Part 2 of 4 for #159 (see the design review). Re-scoped 2026-07-09: CIMD-first, DCR demoted to optional back-compat — the MCP draft spec marks DCR deprecated and CIMD SHOULD-support (#166), and #167 explicitly defers private_key_jwt activation to this work. The original "extend DCR + initialAccessToken gate" plan solved a problem CIMD dissolves: agents don't register — the fleet hosts a metadata document per agent (client_id = its HTTPS URL) carrying the Ed25519 JWKS.
Scope
Client resolution & validation (builds on #167's resolveClient() / shared clientValidator):
- Accept CIMD documents describing headless agents:
grant_types: ["client_credentials"], token_endpoint_auth_method: "private_key_jwt", jwks = JWK Set of public OKP/Ed25519 keys only (reject any key carrying private d; reject empty sets and non-OKP/Ed25519 keys).
- Conditional shape for client_credentials-only clients: no
redirect_uris, no response_types. ⚠️ Spec check at implementation time: the CIMD draft's required-fields list includes redirect_uris — confirm whether non-interactive clients have a carve-out or document our deviation explicitly.
- Reject
client_credentials combined with refresh_token.
Gate (security-critical): for client_credentials via CIMD, clientIdMetadataDocuments.allowedHosts MUST be configured and the client_id URL's host MUST match — merely hosting a reachable document must never suffice to mint tokens. Fail closed (config error) when the grant is enabled without an allowlist. (This replaces the re-scoped-away initialAccessToken DCR gate; enforcement is server-side policy, not document self-assertion.)
Key rotation / revocation semantics: document cache-TTL-bounded staleness — pulling a fleet key from the document takes effect within the CIMD cache TTL; bounded further by the ≤60s assertion window + short access-token TTL. Belongs in the threat notes, not new mechanism.
DCR back-compat (optional, may drop from v1): since validators are shared, DCR registration of private_key_jwt clients may come nearly free — if kept, the original initialAccessToken-required gate applies. Not required for the Flair fleet path.
Tests
CIMD document for a client_credentials agent resolves and validates (valid Ed25519 JWK Set); private-d / RSA / empty jwks rejected; missing-allowlist fails closed; off-allowlist document host rejected; client_credentials+refresh_token rejected; redirect_uris still required for interactive clients; interactive CIMD clients unaffected.
Dependencies
#167 (CIMD resolution layer) and #160 (merged). #162 depends on this. Small enough that folding into #162 is a fair call for whoever implements.
Part 2 of 4 for #159 (see the design review). Re-scoped 2026-07-09: CIMD-first, DCR demoted to optional back-compat — the MCP draft spec marks DCR deprecated and CIMD SHOULD-support (#166), and #167 explicitly defers
private_key_jwtactivation to this work. The original "extend DCR + initialAccessToken gate" plan solved a problem CIMD dissolves: agents don't register — the fleet hosts a metadata document per agent (client_id= its HTTPS URL) carrying the Ed25519 JWKS.Scope
Client resolution & validation (builds on #167's
resolveClient()/ sharedclientValidator):grant_types: ["client_credentials"],token_endpoint_auth_method: "private_key_jwt",jwks= JWK Set of public OKP/Ed25519 keys only (reject any key carrying privated; reject empty sets and non-OKP/Ed25519 keys).redirect_uris, noresponse_types.redirect_uris— confirm whether non-interactive clients have a carve-out or document our deviation explicitly.client_credentialscombined withrefresh_token.Gate (security-critical): for
client_credentialsvia CIMD,clientIdMetadataDocuments.allowedHostsMUST be configured and theclient_idURL's host MUST match — merely hosting a reachable document must never suffice to mint tokens. Fail closed (config error) when the grant is enabled without an allowlist. (This replaces the re-scoped-awayinitialAccessTokenDCR gate; enforcement is server-side policy, not document self-assertion.)Key rotation / revocation semantics: document cache-TTL-bounded staleness — pulling a fleet key from the document takes effect within the CIMD cache TTL; bounded further by the ≤60s assertion window + short access-token TTL. Belongs in the threat notes, not new mechanism.
DCR back-compat (optional, may drop from v1): since validators are shared, DCR registration of
private_key_jwtclients may come nearly free — if kept, the originalinitialAccessToken-required gate applies. Not required for the Flair fleet path.Tests
CIMD document for a client_credentials agent resolves and validates (valid Ed25519 JWK Set); private-
d/ RSA / emptyjwksrejected; missing-allowlist fails closed; off-allowlist document host rejected;client_credentials+refresh_tokenrejected; redirect_uris still required for interactive clients; interactive CIMD clients unaffected.Dependencies
#167 (CIMD resolution layer) and #160 (merged). #162 depends on this. Small enough that folding into #162 is a fair call for whoever implements.