The binary wire protocol defines the CreatePersonalAccessToken format as [name_len:u8][name:N][expiry:u64_le] the expiry is an 8-byte little-endian uint64 (see create_personal_access_token.rs#L25).
The Go SDK gets this wrong in two ways:
- The
Expiry field is declared as uint32 instead of uint64
MarshalBinary() uses PutUint32(bytes[len(bytes)-4:], c.Expiry) which writes 4 bytes at offset 1 + len(name) + 4 instead of writing 8 bytes at offset 1 + len(name)
This leaves 4 zero bytes between the name and the actual expiry value. The server reads all 8 bytes as a single u64_le, so the expiry ends up in the high 32 bits — effectively value << 32. Any non-zero expiry (e.g. 3600 for 1 hour) gets interpreted as ~490,000 years, making tokens silently never expire.
Fix: In foreign/go/internal/command/access_token.go, change the field type to uint64 and replace the PutUint32 call with PutUint64(bytes[1+len(c.Name):], c.Expiry).