Skip to content

test(identityharness): re-cut AS-1 to the generic grant - #2589

Merged
ChrisJBurns merged 2 commits into
mainfrom
feat/identitybroker-generic-grant-harness
Oct 28, 2026
Merged

ChrisJBurns merged 2 commits into
mainfrom
feat/identitybroker-generic-grant-harness

Conversation

@ChrisJBurns

@ChrisJBurns ChrisJBurns commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

First step of #2492: brings the merged identity broker code to the current design. Design PR #2575 made AS-1's grants generic after #2494 and #2489 merged. No broker behaviour changes; the broker side of session open follows in its own PR.

  • Offline harness AS-1 (internal/testutil/identityharness): session open is now the exchange for a generic grant, as Refresh tokens through token exchange, as generic grants toolhive#6897 builds it.
    • One exchange-grant entry listing only id-jag. Its optional expires_at is capped at AS-1's maximum (Options.GrantMaxLifetime) and echoed.
    • One grant per access-token jti, with no retry exception.
    • No session, owner, replacement, or closed-session logic at AS-1.
    • A refused access token gets no reason.
    • resource and audience are refused with invalid_target, and unknown entry members are refused.
    • invalid_authorization_details carries ToolHive's sub-reasons.
    • Revoking a grant's refresh token marks the grant revoked.
    • A new fault, DropNextExchange, drops a request before AS-1 processes it, beside LoseNextExchangeResponse for one it processed. Replay-revoke (Revoke the grant a reused subject token created toolhive#6973) is phase 2, so a reused jti is refused but revokes nothing.
  • knownReasons (internal/identitybroker/serverrefusal.go): adds revoked, parent_revoked, and not_issuable and drops superseded, so a revoked grant is not reported as a configuration fault.
  • Classifier notes: session open maps a reasonless invalid_request to subject_invalid before IsConfigurationFault. Following design PR docs(agent-identity): reconcile the ToolHive work list and settle the lost-response rule #2587, ErrNoResponse's "retry once" note applies at session open: the resend carries the same access token, and a token_used refusal means the client must refresh and open again.
  • authserverclient tests: use the exchange-grant entry. After a lost response, a resend of a request AS-1 processed gets token_used and a fresh token converts; a resend of a request it never processed converts. A refused access token gets no reason.

Not in this PR: child grants. The harness can't yet produce parent_revoked; that comes with ID-JAG issuance and #2569.

Issue relationship

Part of #2492

API compatibility

None. Test harness and internal classification only: no protobuf, server, or client change. Production code receives none of the new reasons yet, because nothing wires AS-1 into the broker.

Test plan

  • go test -race on internal/testutil/identityharness, internal/identitybroker/..., cmd/mecak8s, and internal/adapter/clientauth
  • Mutation check: a retry exception at AS-1, revoked removed from knownReasons, and a dropped request that AS-1 processes anyway each fail the new tests
  • task lint: clean except a pre-existing gosec finding in environment/microvm/launch_ownership_darwin.go (untouched)
  • task test:race: failures in cmd/mecated, cmd/mecatui, environment/microvm/gitexec, internal/app, and internal/adapter/server all reproduce on unmodified origin/main on this machine
  • Offline demo (go run ./cmd/mecademo)

ChrisJBurns and others added 2 commits October 28, 2026 18:46
Bring the merged identity broker code to the current design, where AS-1
issues generic grants bound to the client and the user (design PR #2575).

The offline harness's AS-1 now exchanges an access token for a grant
that issues only ID-JAGs: one exchange-grant entry with a capped, echoed
expires_at, one grant per access-token jti with no retry exception, no
session, owner, or replacement logic, and no reason for a refused access
token. knownReasons gains revoked, parent_revoked, and not_issuable and
drops superseded, so a revoked grant is not taken for a configuration
fault.

Part of #2492.

Co-authored-by: Mecatl <noreply@mecatl.dev>
Design PR #2587 makes the broker resend a lost session-open request once,
with the same access token and a new client assertion. The ErrNoResponse
note applies at session open again, and the lost-response tests become
two cases: a resend after a processed request gets token_used, and a
resend of a request AS-1 never processed converts. DropNextExchange
injects the second case.

Co-authored-by: Mecatl <noreply@mecatl.dev>
@ChrisJBurns
ChrisJBurns requested a review from jhrozek October 28, 2026 19:29
@ChrisJBurns
ChrisJBurns merged commit 0a3f8c0 into main Oct 28, 2026
37 checks passed
@ChrisJBurns
ChrisJBurns deleted the feat/identitybroker-generic-grant-harness branch October 28, 2026 20:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant