Skip to content

Migrate revocation channel to SET delivery (RFC 8417/8935)#9

Merged
m0tzy merged 5 commits into
mainfrom
madison/secevent
Jun 4, 2026
Merged

Migrate revocation channel to SET delivery (RFC 8417/8935)#9
m0tzy merged 5 commits into
mainfrom
madison/secevent

Conversation

@m0tzy
Copy link
Copy Markdown
Collaborator

@m0tzy m0tzy commented Jun 3, 2026

  • I have QA'd the changes

Stack

  1. Split credentials into a separate endpoint #8
  2. Migrate revocation channel to SET delivery (RFC 8417/8935) #9 ← you are here
  3. Invert the claim flow to mirror device auth #10
  4. ID-JAG step-up + auth_time freshness #11
  5. Claim anonymous registration via ID-JAG #12

Summary

Switch the provider-driven invalidation channel from a logout-token at agent_auth.revocation_uri to a Security Event Token (RFC 8417) delivered via push (RFC 8935) at agent_auth.events_endpoint. The discovery field, endpoint path, JWT typ, content-type, and response shape all switch together.

  • Discovery: agent_auth.revocation_uriagent_auth.events_endpoint
  • Endpoint: /agent/auth/revoke/agent/event/notify
  • JWT typ: logout+jwtsecevent+jwt; Content-Type: application/logout+jwtapplication/secevent+jwt
  • Receiver responses follow RFC 8935 §2.4: 202 Accepted on success (no body), 400 with { "err": "<code>", "description": "..." } on failure with codes from §2.4 (invalid_request, invalid_key, invalid_issuer, invalid_audience, authentication_failed)
  • Provider side: mintLogoutJwtmintSecEventJwt; grant input field revocation_urievents_uri
  • Docs + demos updated end to end

The top-level OAuth revocation_endpoint (/oauth2/revoke, RFC 7009) is unrelated and stays as-is.

@m0tzy
Copy link
Copy Markdown
Collaborator Author

m0tzy commented Jun 3, 2026

@greptile

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Jun 3, 2026

Greptile Summary

This PR migrates the provider-driven invalidation channel from OIDC Back-Channel Logout tokens to RFC 8417 Security Event Token push delivery (RFC 8935), touching the endpoint path, JWT typ, Content-Type, discovery field, and response shape consistently across both packages.

  • Receiver (/agent/event/notify): validates the events claim is a non-empty object (RFC 8417 §2.1), dispatches on schema URIs so unknown event types are silently ignored (§2.2), returns 202 on success and RFC 8935 §2.4 { err, description } on failure with correctly mapped error codes.
  • Sender (mintSecEventJwt): switches typ to secevent+jwt, populates the events claim with the identity-assertion-revoked schema URI.
  • Discovery (well-known.ts): swaps revocation_uri for events_endpoint; events_supported now references IDENTITY_ASSERTION_REVOKED_SCHEMA rather than a raw string.

Confidence Score: 5/5

Safe to merge — the migration is internally consistent and the previously missing events-claim validation is now correctly implemented.

All seven changed layers (endpoint path, JWT typ, Content-Type, discovery field, response shape, events-claim dispatch, and error-code mapping) are updated in lock-step. The verifySecEventJwt path now validates iss, aud, jti, sub, and the events object before any state mutation, and the response codes match RFC 8935 §2.4. No sensitive fields are logged and no TLS validation is bypassed.

No files require special attention; the two style notes are about code organization and an inline comment, neither of which affects correctness.

Important Files Changed

Filename Overview
agent-services/src/verify.ts Renames LogoutClaims→SecEventClaims and verifyLogoutJwt→verifySecEventJwt; adds RFC 8417 §2.1 validation of the events claim (non-empty object); adds typed error codes for expired/audience from jose exceptions. Previously flagged missing events validation is now addressed.
agent-services/src/routes/agent-auth.ts Switches endpoint to /agent/event/notify with application/secevent+jwt body; dispatches on events schema URI; returns 202 on success and RFC 8935 §2.4 {err, description} on failure. IDENTITY_ASSERTION_REVOKED_SCHEMA is declared after its first use (safe at runtime, minor style concern).
agent-providers/src/jwts.ts Renames mintLogoutJwt→mintSecEventJwt, switches typ to secevent+jwt, correctly sets events claim with the schema URI. No exp claim is set (intentional — RFC 8417 makes exp optional for SETs; sign() adds iat automatically).
agent-providers/src/routes/grants.ts Renames field from revocation_uri/revocationUri to events_uri/eventsUri and switches to mintSecEventJwt + application/secevent+jwt content-type; any non-2xx response is treated as delivery failure and the grant is retained.
agent-services/src/routes/well-known.ts Swaps revocation_uri for events_endpoint in the discovery document and de-duplicates the schema URI string by referencing IDENTITY_ASSERTION_REVOKED_SCHEMA from agent-auth.ts.
agent-providers/src/schemas.ts Renames revocation_uri to events_uri in the Zod createGrantBody schema — straightforward field rename.
agent-providers/src/store.ts Renames revocation_uri/revocationUri to events_uri/eventsUri on the Grant type and upsertGrant input — clean rename with JSDoc added.
agent-services/src/config.ts Renames revocationUriPath to eventsEndpointPath and updates the path value from /agent/auth/revoke to /agent/event/notify.

Sequence Diagram

sequenceDiagram
    participant P as Agent Provider
    participant S as Agent Service /agent/event/notify

    P->>P: "mintSecEventJwt(user, audience) typ=secevent+jwt"
    P->>S: POST /agent/event/notify Content-Type: application/secevent+jwt

    S->>S: verifySecEventJwt(token) 1. isTrustedIssuer(iss) 2. jwtVerify(sig,iss,aud,typ) 3. jti+sub present 4. events non-empty RFC8417 5. jti replay check

    alt Verification failure
        S-->>P: "400 { err, description } RFC 8935 2.4"
    else Verification success
        S->>S: dispatch on events schema URIs
        alt identity-assertion-revoked in events
            S->>S: revokeForDelegation(iss, sub, aud)
        else unknown schemas only
            S->>S: no-op RFC 8417 2.2
        end
        S-->>P: 202 Accepted no body
    end
Loading

Reviews (7): Last reviewed commit: "Re-date v0.3.0 to 2026-06-03" | Re-trigger Greptile

Comment thread agent-providers/src/routes/grants.ts
@m0tzy
Copy link
Copy Markdown
Collaborator Author

m0tzy commented Jun 3, 2026

@greptile

Base automatically changed from madison/separate-identity-and-tokens to main June 4, 2026 00:00
m0tzy added 2 commits June 3, 2026 17:06
Switch from logout-token to RFC 8417 Security Event Tokens delivered per
RFC 8935 push. The endpoint, discovery field, and grant field rename to
match what the channel is actually doing — delivering security events, not
just revocations.

Service side
- Rename agent_auth.revocation_uri → agent_auth.events_endpoint
- Rename /agent/auth/revoke → /agent/event/notify
- Receiver accepts application/secevent+jwt and the JWT typ "secevent+jwt"
- Success returns 202 Accepted (RFC 8935 §2.4); errors return
  { "err": "<code>", "description": "..." } with codes from §2.4
  (invalid_request, invalid_key, invalid_issuer, invalid_audience,
  authentication_failed)
- Rename verifyLogoutJwt → verifySecEventJwt

Provider side
- mintLogoutJwt → mintSecEventJwt (typ: secevent+jwt)
- Grant field revocation_uri → events_uri; create-grant body renamed
- Outbound POST sends Content-Type: application/secevent+jwt

Docs + demos
- Update both READMEs, AUTH.md, and both home.ts demos to describe SET
  delivery, the new path, and the RFC 8935 response shape
@m0tzy m0tzy force-pushed the madison/secevent branch from 983ace1 to 11ef73d Compare June 4, 2026 00:06
m0tzy and others added 2 commits June 3, 2026 17:11
verifySecEventJwt was collapsing every jose error into invalid_signature,
which left the invalid_audience branch in mapSecEventError unreachable —
providers got authentication_failed back on aud mismatch instead of the
RFC 8935 §2.4 invalid_audience code. Mirror what verifyIdJag does and
pick out expired and audience errors before the catch-all.

Also extend the v0.2.0 changelog entry to describe the SET migration
end-to-end (endpoint/discovery/typ/Content-Type/response-shape) and bump
the release date to 2026-06-04.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each PR in this stack ships as a separate merge to main, so each gets
its own version. Move the SET migration items out of v0.2.0 and into a
fresh v0.3.0 entry; restore v0.2.0 to the identity/credential-split
scope it actually had.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@m0tzy
Copy link
Copy Markdown
Collaborator Author

m0tzy commented Jun 4, 2026

@greptile

@m0tzy m0tzy marked this pull request as ready for review June 4, 2026 00:16
Comment thread agent-providers/README.md
Comment thread agent-services/README.md
@m0tzy m0tzy marked this pull request as draft June 4, 2026 03:43
@m0tzy m0tzy marked this pull request as ready for review June 4, 2026 03:43
@m0tzy m0tzy force-pushed the madison/secevent branch from d2f122d to 504e4ab Compare June 4, 2026 03:43
Aligning with the actual merge date.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@m0tzy m0tzy merged commit 4ff01ab into main Jun 4, 2026
2 checks passed
@m0tzy m0tzy deleted the madison/secevent branch June 4, 2026 03:51
@m0tzy m0tzy mentioned this pull request Jun 4, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants