Skip to content

AAuth -11: correct token recitals, PS discovery, and the JWT claims registry - #93

Merged
dickhardt merged 1 commit into
mainfrom
aauth-11/wp0-spec
Aug 13, 2026
Merged

AAuth -11: correct token recitals, PS discovery, and the JWT claims registry#93
dickhardt merged 1 commit into
mainfrom
aauth-11/wp0-spec

Conversation

@dickhardt

@dickhardt dickhardt commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Editorial corrections to the two drafts, bringing R3 -02's recitals and the protocol's registry into line with what -11 actually says. No new normative behaviour — the normative changes for -11 already landed on main (issues #75#81, #84). This is the cleanup pass that the eleven implementation PRs were written against, plus six new issues raised by implementing it.

What changed

R3 (draft-hardt-aauth-r3.md) — its base-claim recitals for the resource token and the auth token still described AAuth Protocol -09:

  • The agent claim is gone from both. A resource token carries ps, sub, person_token_jti; an auth token carries ps and a REQUIRED directed sub plus an OPTIONAL mission_s256. Both lists and both JSON examples updated — including the auth-token example's sub, which showed an email address where the value is an opaque directed identifier.
  • AS Processing step 4 required the AS to log "the agent identifier" against a resource token that no longer carries one. It now names ps, sub and agent_jkt from the resource token, and says the agent identifier comes from the agent_token the PS sends on the PS-to-AS request.
  • R3 Document Access Restriction identified the entitled PS by the agent token's OPTIONAL ps claim. Under -11 the agent presents a person token at the authorization endpoint; the entitled PS is the issuer of that person token, which the resource recorded as the resource token's REQUIRED ps.

Protocol (draft-hardt-oauth-aauth-protocol.md):

  • Three places said a resource discovers the agent's PS from the agent token's ps claim — contradicting the draft's own Design Rationale. ps on an agent token is the advance signal that the agent has a person server at all, which is what lets a resource decide to challenge for a person token. The PS of an issued authorization is the iss of the person token the resource verified.
  • The JWT Claims Registrations table registered ps twice, still registered agent (now only a mission-blob member, not a JWT claim), and omitted person_token_jti, account and interaction.

Six issues filed while implementing -11

Implementation proceeds without resolutions for all of them; each is recorded so the text catches up.

#87 The PS's person-token retention obligation is implied by §Resource Token Verification step 6 but never stated.
#88 Nothing selects the tenant for a person token when a person holds a personal context plus several managed ones. proxy-mcp's binding-set model depends on the answer. Provisionally closed by accepting tenant at the person token endpoint.
#89 No conformant way to convey capabilities to the person token endpoint, which can return 202 requirement=interaction. @aauth/agent currently sends AAuth-Capabilities there, contradicting §AAuth-Capabilities — deliberate, and pending this decision.
#90 (closed) The mirror of #87 on the resource side. A step-up or r3_per_call challenge fires on a request carrying an auth token, which has ps and sub but no person_token_jti — yet the resource token it must issue makes that claim REQUIRED, so every resource must retain the person tokens it verified. notes implements the retention reading: a record per (ps, sub, agent key, mission), TTL = the person token's exp. Whatever text resolves this should specify the retained record as the whole tuple, not the jti alone — keeping the jti while losing its mission fails safe, but picking the wrong record among several produces a spurious rejection.
#91 R3 operation access annotations cannot express two common cases.
#92 Per-call authorization: let a resource defer with 202, and make the grant single-use.

This is one coordinated wave

Twelve PRs across twelve repositories implement AAuth -11 and R3 -02. They were built in parallel worktrees that could not see each other, against a pinned interface contract, and reconciled in one integration pass.

Merging any one alone breaks the others. For this repo the coupling runs the other way from the code repos: this is only text, so merging it early is harmless in itself — but the published editor's copy would then describe a protocol that person.hello.coop and the whole resource fleet do not yet speak, and the walkthrough and diagrams in aauth-dev/www would contradict the live services. Merging the implementations without this leaves the normative recitals describing -09.

The twelve PRs

Repo PR What it is
hellocoop/mockin #6 The reference PS. The only thing issuing -11 person tokens — the gate on verifying everything else.
dickhardt/AAuth #93 The specs: editorial corrections, plus six issues filed.
aauth-dev/packages-js #16 The npm surface. @aauth/protocol 1.0.0 (new), @aauth/agent 3.0.0, @aauth/resource 2.0.0, five more.
aauth-dev/proxy #2 @aauth/proxy 1.0.0 — the agent-proxy core.
hellocoop/aauth-proxy #33 The 38-proxy fleet. Carries the flag day. Merging deploys.
hellocoop/proxy-mcp #1 Tracks @aauth/proxy ^1.0.0; AP metadata cleanup.
aauth-dev/notes #2 Reference R3 resource; implements the #90 retention pattern.
aauth-dev/whoami #1 Agent identity + the new person-identity path.
aauth-dev/web-agent-demo (playground) #5 Browser walkthrough; handles the 202 deferred path.
aauth-dev/playground-popup #2 Popup-flow variant.
aauth-dev/registry #6 Five access modes; three-rung login.
aauth-dev/www #7 Six access-mode diagrams.

Related and already open: aauth-dev/explorer #5 reworks the explorer for -11 / R3 -02.

Background: AAUTH-11-INTEGRATION.md (the integration ledger) and AAUTH-11-PACKAGE-CONTRACT.md (the pinned interface contract the parallel work packages were built against).

Ordering constraints for the wave

  1. @aauth/protocol 1.0.0 needs a manual first publish. npm will not accept a trusted publisher for a name that does not exist in the registry, so release.yml cannot publish it until someone runs npm publish --access public by hand and then registers the publisher.
  2. @aauth/proxy 1.0.0 must publish before the fleet serves person-token. 0.4.0 hard-fails on an unrecognized access_mode (invalid access_mode person-token).
  3. HelloCoop/Wallet svr/issuer/sign.js:32 must ship Ed25519 in the same window. It reads const alg = useEdDSA ? 'EdDSA' : 'RS256' with useEdDSA = isAAuthType(typ), so every aa-auth+jwt and aa-person+jwt person.hello.coop issues today carries alg: EdDSA. Every verifier in this wave rejects EdDSA — -10 allows no transition. If that line does not ship, every resource rejects every token the live PS issues. RS256 stays for OIDC.

Not covered

This PR is prose; there is no test suite. Two things a reader should know about the wave it documents:

  • -11 is not on the datatracker (404; -10 is latest), so llms.txt in aauth-dev/www points at the document page and the editor's copy rather than pinning a revision.
  • mission_endpoint is unimplemented by agreement across the whole wave. mission_s256 is accepted, stamped, copied and compared everywhere, but the reference PS accepts any value as a mission hash — there is no mission to look up. §Resource Token Verification step 7 (mission active, current time before expires_at) is therefore never exercised, and every expires_at clamp in the fleet is untested.

What a reviewer should check

  • The claims registry table now lists ps once, does not list agent, and does list person_token_jti, account and interaction.
  • No remaining text tells a resource to read the agent's PS from the agent token's ps claim.
  • The auth-token example's sub reads as an opaque directed identifier, not an email address.

R3's base-claim recitals for the resource token and the auth token still
described AAuth Protocol -09. The `agent` claim is gone from both tokens:
a resource token carries `ps`, `sub`, and `person_token_jti`, an auth
token carries `ps` and a REQUIRED directed `sub` plus an OPTIONAL
`mission_s256`. Updated both lists and both JSON examples, including the
auth token example's `sub`, which showed an email address where the value
is an opaque directed identifier.

Two other places in R3 named parties or claims that -11 removed. AS
Processing step 4 required the AS to log "the agent identifier" against a
resource token that no longer carries one; it now names `ps`, `sub`, and
`agent_jkt` from the resource token, and the text says the agent
identifier comes from the `agent_token` the PS sends on the PS-to-AS
request. R3 Document Access Restriction identified the entitled PS by the
agent token's OPTIONAL `ps` claim, but under -11 the agent presents a
person token in place of its agent token at the authorization endpoint;
the entitled PS is the issuer of that person token, which the resource
recorded as the resource token's REQUIRED `ps`.

The protocol said in three places that a resource discovers the agent's
PS from the agent token's `ps` claim, contradicting its own Design
Rationale. That claim is the advance signal that the agent has a person
server at all, which is what lets a resource decide to challenge for a
person token; the PS of an issued authorization is the `iss` of the
person token the resource verified.

The protocol's JWT Claims Registrations table registered `ps` twice, still
registered `agent` (now only a mission blob member, not a JWT claim), and
omitted `person_token_jti`, `account`, and `interaction`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FmiCqDjRUSx6zb1N4gZPXE
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