Add Jurisdictional Token Flag to Auth Command · Entire

We have entire auth token add a flag to output a jurisdictional token so that I can use it on e.g. https://aws-us-east-2.api.entire.io/api/v1. I should be able to specify the jurisdiction.

Plan: add --jurisdiction to entire auth token

The key finding: the entire jurisdictional-token exchange pipeline already exists in cmd/entire/cli/auth/cell_data_api.go (exchangeJurisdictionToken, jurisdictionAudience, jurisdictionCoreURL, targetJurisdiction). It's consumed by NewEntireAPICellClient, which returns a wrapped *api.Client instead of the raw token. So this is mostly exposing existing, already-audited logic rather than writing new exchange/security code.

The change, in three parts:

  1. Expose the token — a new auth.JurisdictionToken(ctx, insecureHTTP, jurisdiction) that runs the same discover → resolve-subject → RFC 8693 exchange flow but returns the token string (skipping the cell-URL resolution only a client needs). Honoring your two decisions: flag value is a slug (us, eu), and ENTIRE_TOKEN is used as the exchange subject_token when set. Minor refactors keep NewEntireAPICellClient's behavior identical.
  2. Wire the flag — --jurisdiction on newAuthTokenCmd; when non-empty it mints & prints the jurisdictional token (stdout stays clean for $(...)), otherwise the current control-plane behavior is untouched.
  3. Docs — CLAUDE.md auth bullet + CHANGELOG.md.

Result:curl -H "Authorization: Bearer $(entire auth token --jurisdiction us)" https://aws-us-east-2.api.entire.io/api/v1/... works.

Tests reuse the existing SetResolveContextForCellAPIForTest / SetCellExchangeTransportForTest httptest seams, covering both the stored-login and ENTIRE_TOKEN subject paths, plus a command-level test.

Base directory for this skill: /Users/georgf/.claude/skills/grill-me

Question 1 — Input contract & discoverability. The token's aud is the jurisdiction host (https://us.entire.io), not the cell host. So the flag value is a jurisdiction slug like us, and that one token works against any cell in that jurisdiction (including your example aws-us-east-2.api.entire.io). But a user staring at aws-us-east-2.api.entire.io/api/v1 has no CLI-supported way to learn that its slug is us — auth status doesn't print it, and the only slug UI is the interactive mirror wizard.

So: how should a user discover the value, and should the flag accept anything beyond a bare slug?

My recommendation: Keep --jurisdiction accepting only a lowercase slug (crisp contract, matches the internal jurisdictionLabelPattern and the existing --region values). To close the discovery gap, also print the home jurisdiction in entire auth status (one line, e.g. Region: us) as part of this change.

Question 2 — ENTIRE_TOKEN exchange: environment detection & the "must be a login JWT" limitation. You chose to honor ENTIRE_TOKEN as the exchange subject_token. Tracing the exchange path surfaces two things worth nailing down:

  1. Environment auto-detection. The shared helpers pick prod-vs-staging from environmentFamily(dataOrigin, discoveredCore), and dataOrigin defaults to https://entire.io ( prod) unless ENTIRE_API_BASE_URL is set. A CI job that only exports ENTIRE_TOKEN (the common case) — especially a staging token — would otherwise get mis-templated to prod cores. The env token's own aud (via ParseEnvToken) unambiguously encodes its environment.
  2. Exchange happens at the target jurisdiction's core (https://{j}.auth.<family>/oauth/token), not the token's home core — this is the existing cross-jurisdiction identity flow. It only works if ENTIRE_TOKEN is a login JWT (subject-capable); an already-exchanged cell/foreign token gets rejected (the server refuses chained exchanges).

My recommendation:

Question 3 — Slug normalization. resolveJurisdiction validates the value against jurisdictionLabelPattern, which is lowercase-only ([a-z0-9-]). The existing --region flag on org/project passes its value verbatim to the server (no client normalization). But our path validates client-side, so entire auth token --jurisdiction US would fail with "US" is not a valid label — a jarring error for something that unambiguously means us.

My recommendation: normalize the explicit slug (strings.TrimSpace + strings.ToLower) inside resolveJurisdiction's override branch before the pattern check, so --jurisdiction US / " us " / us all work. Slugs are lowercase DNS labels — there's no valid uppercase variant that means something else — so lowercasing can't mask a real distinction, and the pattern still guards against injection. (The home-fallback branch reads an already-lowercase claim, so it's unaffected.)

Question 4 — Should the flag have a "home jurisdiction" shortcut, or always require a slug? JurisdictionToken already falls back to the subject token's home_jurisdiction claim when the slug is empty. That opens a design choice for the command surface:

My recommendation: (A), slug always required. It matches your original ask ("specify the jurisdiction"), keeps the flag's contract unambiguous (a string flag that sometimes takes no value is a papercut), and the home case is no longer opaque now that auth status prints the slug. The home-fallback stays in the library function for internal reuse but isn't surfaced on the flag.

Question 5 — Any stderr diagnostics on success, or token-only? The minted token goes to stdout. The token's aud (jurisdiction host, e.g. https://us.entire.io) differs from the cell URL the user curls (https://aws-us-east-2.api.entire.io/api/v1). We could echo the resolved audience/exchange-core to stderr as a debugging aid.

My recommendation: token-only, no success chatter. It matches today's auth token contract (only the token on stdout, only errors on stderr, so $(entire auth token --jurisdiction us) stays clean), and the user already knows the cell URL they're targeting. Diagnostics on failure still surface via the wrapped exchange error. If deeper tracing is ever needed, the existing --insecure-http-auth/debug-logging paths cover it.

Done. Here's what shipped.

entire auth token --jurisdiction <slug>

Feature — entire auth token --jurisdiction us now mints and prints a jurisdictional identity token (RFC 8693 exchange, scope=openid, aud=<jurisdiction host>) for use against that jurisdiction's entire-api cells like https://aws-us-east-2.api.entire.io/api/v1, which reject the control-plane bearer. Bare entire auth token is unchanged.

Implementation (per the grilled plan):

Tests — JurisdictionToken stored-context + ENTIRE_TOKEN paths (asserting subject_token, scope=openid, audience), the --jurisdiction command path (env-token success + not-logged-in), and the auth status slug line.