docs: add RFC 9421 request signing guide#3064
Conversation
|
Heads-up: two SDK ergonomics PRs landed on
Specific tightening once the release shipsStep 4 — Express middleware ( createExpressVerifier({
capability: { supported: true, covers_content_digest: 'required', required_for: ['create_media_buy', 'update_media_buy'] },
jwks: new StaticJwksResolver(buyerPublicKeys),
- replayStore: new InMemoryReplayStore(),
- revocationStore: new InMemoryRevocationStore(),
resolveOperation: mcpToolNameResolver,
})Step 4 — Step 3 — Capability-aware signing: the import { createAgentSignedFetch } from '@adcp/client/signing';
export const signedFetch = createAgentSignedFetch({
signing: {
kid: 'my-agent-2026',
alg: 'ed25519',
private_key: privateJwk,
agent_url: 'https://agent.example.com',
},
sellerAgentUri: 'https://seller.example.com',
});Worth keeping the longer No need to wait — happy for this to merge as-is and follow up with a tightening PR after the next |
|
we should also have examples for python and go |
|
SDK ergonomics PRs are now out across all three official SDKs — happy to update this guide once they ship in a release. Posting the cross-SDK status so the docs can cite them in lockstep.
All three land the same security-by-default story:
Once Python and Go merge and release-please cuts new versions, the docs here can:
Happy to send a follow-up tightening PR after the Python/Go releases ship, or to push the rewrite directly into this branch — your call. Either way no need to block this PR on it. cc @benminer |
|
Heads up — three SDK PRs landed (or are in flight) on 1. Step 1.3 "Storing the private key" — add KMS option. adcp-client#1017 (merged) ships
2. Step 3 "Sign outbound requests" — show the
const provider = await createGcpKmsSigningProvider({
versionName: process.env.ADCP_KMS_VERSION!,
kid: 'my-agent-2026',
algorithm: 'ed25519',
client: kmsClient,
});
const signingFetch = buildAgentSigningFetch({
upstream: fetch,
signing: { kind: 'provider', provider, agent_url: 'https://agent.example.com' },
getCapability: () => capabilityCache.get('https://seller.example.com'),
});Wire format unchanged — counterparties can't tell the difference between in-process and KMS-backed signing. 3. Step 4 "Verify inbound signatures" — call out multi-instance verifier deployments. adcp-client#1018 (merged) ships
4. Step 6 "Sign outbound webhooks" — flag the in-process-only caveat.
5. Testing — add adcp-client#1019 (open, all CI green, accumulates into the same 5.20.0 release) ships the signer-side grader: # KMS-backed signer via signing oracle
adcp grade signer https://addie.example.com \
--signer-url https://signer.internal/sign --signer-auth "Bearer ${SIGNER_TOKEN}" \
--kid addie-2026-04 --alg ed25519 \
--jwks-url https://addie.example.com/.well-known/jwks.jsonPairs with My spec-side PR #3255 (docs(security): production key storage subsection for RFC 9421 signing) adds a "Production key storage" subsection to Happy to push these as a follow-up commit on this branch, or land yours as-is and I file a separate guide-update PR after #1019 merges and 5.20.0 publishes — whichever fits your release rhythm. Either order works. cc @bokelley |
…ption
Extends Ben's RFC 9421 guide so it covers all three official SDKs in
parallel rather than being TypeScript-only. Three additions:
1. Multi-language tabs (JS/TS, Python, Go) on every code-bearing step:
- Step 1 programmatic keygen — adcp.signing.generate_signing_keypair,
signing.GenerateKeyForProfile
- Step 3 sign outbound — ADCPClient(signing=...) and sign_request,
signing.NewSigner + RoundTripper
- Step 4 verify inbound — verify_starlette_request /
verify_flask_request, signing.Middleware
- Step 5 verify webhook — verify_webhook_signature,
signing.Middleware with ProfileWebhookSigning
- Step 6 sign webhook — sign_webhook, NewSigner with
ProfileWebhookSigning
- Step 7 capability declaration — capabilities_response and
adcp.RequestSigningCapability
2. KMS as a fourth (preferred) storage option in §1.3. Cloud HSM-backed
keys never leave the boundary; signing happens via the KMS API. Calls
out the TS SDK's createKmsSigner adapter and notes the latency
tradeoff. The other options are reordered most-to-least-secure with
memory-resident risk called out for env-var and secret-manager paths.
3. Up-front <Info> note that all three SDKs implement the same wire
profile against the same conformance vectors — the API surface
differs but the bytes on the wire are identical. Readers in any
language can fall back to the spec + vectors if their SDK isn't
listed.
Closes the cross-language ask from #3064 review comments.
Co-Authored-By: Ben Miner <ben@scope3.com>
|
Pushing the additions from my earlier review comments directly to this branch so this can land:
Total addition: +361 / -10 on Marking ready for review. No structural changes to the existing diff. |
New `docs/building/by-layer/L1/request-signing.mdx` — practical implementation walkthrough complementing the normative spec at `L1/security.mdx` (which covers the wire profile and verifier checklist) and the operator-facing tuning page at `L1/webhook-verifier-tuning.mdx`. Closes the missing third L1 page flagged in `L1/index.mdx`. Coverage: - Step-by-step keygen, JWKS / brand.json publication, signing, verification, webhook signing, and capability declaration. - Multi-language tabs (JS/TS, Python, Go) on every code-bearing step. APIs verified against `adcp-client-python` (`adcp.signing.*`) and `adcp-go` (`adcp/signing.*`) module exports. - Storage section orders options most-to-least-secure: cloud KMS (preferred for spend-committing agents) → secret manager → env var → file. Calls out the TS SDK's `createKmsSigner` adapter (per adcp-client#1017) and notes the latency tradeoff. - Up-front <Info> note that all three SDKs implement the same wire profile against the same conformance vectors — the API surface differs but the bytes on the wire are identical. `docs.json`: adds the page to the L1 nav (both nav variants) and a redirect from the legacy `/docs/building/implementation/request-signing` path so external links to Ben's drafted location resolve. Originally drafted by Ben Miner at `docs/building/implementation/`. Re-ported to the L1 layered IA after the docs reorg, with the multi- language and KMS additions folded in. Co-Authored-By: Ben Miner <ben@scope3.com>
9434434 to
95f33a3
Compare
Summary
Ported documentation from adcontextprotocol/adcp-client#914, which was accidentally opened against the wrong repo.
docs/building/implementation/request-signing.mdx— practical step-by-step guide covering key generation, JWKS/brand.json publication, buyer-side signing, seller-side verification, webhook signing, capability declaration, key rotation, and conformance testingdocs/building/build-an-agent.mdxshowing therequireSignatureWhenPresent+verifySignatureAsAuthenticatorcomposition pattern and webhook signer configrequest-signingto the Implementation Patterns nav indocs.json<Note>in thesecurity.mdxquickstart section pointing to the new guide (framing the spec as the normative source the guide implements)Notes
The normative RFC 9421 spec already lives in
docs/building/implementation/security.mdx. This guide is the approachable complement — what you actually run and configure — pointing back to the spec for the verifier checklist, canonicalization rules, and error taxonomy.