You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implement jotsmith token mint with standard claims only (--sub, --aud, --exp, --iat, --nbf, --jti, --verbose). This is the slice that finally proves the full minting story: client-side header + payload assembly, SHA-256 digest of the signing input, Azure Key Vault Sign("RS256", digest), base64url-encode the returned signature, emit the compact JWT to stdout. Custom-claim plumbing comes in #8.
The iss claim always comes from config — there is no --iss flag and there must never be one (PRD hard invariant; faking iss defeats the trust model).
Acceptance criteria
--sub required; absence → exit 2 with clear stderr error
--aud optional; single occurrence → JSON string; multiple → JSON array of strings; absent → omitted from payload
--exp accepts a Go time.Duration (15m, 1h, 24h) relative to iat, or an RFC3339 absolute timestamp; default 15m
--iat defaults to wall-clock now(); --nbf defaults to iat; --jti defaults to a fresh UUID v4
iss is read from config; no --iss flag exists, and attempting --iss fails as an unknown flag
Header is canonical JSON {"alg":"RS256","typ":"JWT","kid":"<thumbprint>"} with no whitespace
Payload is canonical JSON of the assembled claims with no whitespace
Signing flow: compute digest = SHA-256(base64url(header) + "." + base64url(payload)) client-side, then call KV Sign("RS256", digest); base64url-encode the returned signature; concatenate signing_input + "." + signature into the compact JWT
No private key material ever touches the CLI process — verified by code review
Stdout receives exactly the compact JWT followed by \n; nothing else, ever, on stdout from this command (smoke test asserts byte exactness)
--verbose pretty-prints decoded header, payload, and metadata to stderr after the JWT is on stdout
Exit 0 on success; non-zero on validation or KV signing failure
--exp > 24h is refused by default with a clear stderr error; --allow-long-lived overrides (resolves PRD §10 OQ Slice 3: jotsmith token decode #3)
What to build
Implement
jotsmith token mintwith standard claims only (--sub,--aud,--exp,--iat,--nbf,--jti,--verbose). This is the slice that finally proves the full minting story: client-side header + payload assembly, SHA-256 digest of the signing input, Azure Key VaultSign("RS256", digest), base64url-encode the returned signature, emit the compact JWT to stdout. Custom-claim plumbing comes in #8.The
issclaim always comes from config — there is no--issflag and there must never be one (PRD hard invariant; fakingissdefeats the trust model).Acceptance criteria
--subrequired; absence → exit 2 with clear stderr error--audoptional; single occurrence → JSON string; multiple → JSON array of strings; absent → omitted from payload--expaccepts a Gotime.Duration(15m,1h,24h) relative toiat, or an RFC3339 absolute timestamp; default15m--iatdefaults to wall-clocknow();--nbfdefaults toiat;--jtidefaults to a fresh UUID v4issis read from config; no--issflag exists, and attempting--issfails as an unknown flag{"alg":"RS256","typ":"JWT","kid":"<thumbprint>"}with no whitespacedigest = SHA-256(base64url(header) + "." + base64url(payload))client-side, then call KVSign("RS256", digest); base64url-encode the returned signature; concatenatesigning_input + "." + signatureinto the compact JWT\n; nothing else, ever, on stdout from this command (smoke test asserts byte exactness)--verbosepretty-prints decoded header, payload, and metadata to stderr after the JWT is on stdout--exp> 24h is refused by default with a clear stderr error;--allow-long-livedoverrides (resolves PRD §10 OQ Slice 3: jotsmith token decode #3)//go:build integrationmints a token and asserts compact-form parsingBlocked by
setupOriginally created in OpenCode session ID: ses_17ca8efd8ffexLcFSysAMDVNBQ