From 829c17e99183e796cc555d100caf01a898999d5d Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 8 May 2026 22:56:15 +0000 Subject: [PATCH 1/2] =?UTF-8?q?fix(schema,skill):=20align=20HMAC=20framing?= =?UTF-8?q?=20to=20RFC=209421=20default=20=E2=80=94=20reporting-webhook,?= =?UTF-8?q?=20auth-scheme,=20call-adcp-agent=20SKILL.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description-only fixes closing the on-ramp framing gap identified in #4270. reporting-webhook.json called HMAC-SHA256 "recommended for production"; auth-scheme.json had no deprecation signal. Both now align with push-notification-config.json's framing. call-adcp-agent/SKILL.md gains a "Webhook signing" section so buyer agents learn to omit authentication (selecting RFC 9421 default) rather than reaching for the visible legacy field. No wire format changes; authentication remains required in 3.x per the existing schema. The optionality change (making authentication optional + defining 9421 default on reporting-webhook) is a signing-profile change routed to 3.1.x — see #4270. https://claude.ai/code/session_01WczUEAGjbrADfTVX2MWEn6 --- .../fix-hmac-framing-skill-9421-default.md | 5 +++++ skills/call-adcp-agent/SKILL.md | 19 +++++++++++++++++++ .../source/core/reporting-webhook.json | 6 +++--- static/schemas/source/enums/auth-scheme.json | 2 +- 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 .changeset/fix-hmac-framing-skill-9421-default.md diff --git a/.changeset/fix-hmac-framing-skill-9421-default.md b/.changeset/fix-hmac-framing-skill-9421-default.md new file mode 100644 index 0000000000..83912813af --- /dev/null +++ b/.changeset/fix-hmac-framing-skill-9421-default.md @@ -0,0 +1,5 @@ +--- +"adcontextprotocol": patch +--- + +Fix stale HMAC-as-recommended framing in reporting-webhook.json and auth-scheme.json; add RFC 9421 default guidance to call-adcp-agent SKILL.md. Description-only fixes aligning these surfaces with the existing push-notification-config.json framing (HMAC is the deprecated fallback, RFC 9421 is the default). No wire format changes. diff --git a/skills/call-adcp-agent/SKILL.md b/skills/call-adcp-agent/SKILL.md index d3da9200f1..c8ae023e6e 100644 --- a/skills/call-adcp-agent/SKILL.md +++ b/skills/call-adcp-agent/SKILL.md @@ -89,6 +89,25 @@ When you see `status: 'submitted'`, the work is NOT complete. Poll via `tasks/ge `budget` is a **number** (not `{amount, currency}` — currency is implied by the pricing option). Required per package: `product_id`, `budget`, `pricing_option_id`. `buyer_ref` is optional but strongly recommended as a buyer-side correlation id across retries and reporting. +### Webhook signing — omit `authentication` for new integrations + +When you include `push_notification_config` in a request, do **not** set `authentication` +unless you are integrating with a legacy receiver. Omitting `authentication` selects the +default: the seller signs each inbound webhook POST with its RFC 9421 +`adcp_use: "webhook-signing"` key, published at the `jwks_uri` in its own `brand.json` +`agents[]` entry. You verify against the seller's JWKS. No shared secret crosses the wire. + +Presence of `authentication` is a **switch, not a fallback** — it opts the seller into +Bearer or HMAC-SHA256 and disables 9421 for that registration. A buyer MUST NOT attempt +"try 9421 first, fall back to HMAC" verification — mode is fixed at registration time. + +The `authentication` block (Bearer / HMAC-SHA256) is deprecated and sellers MAY decline +to support it. It is removed in AdCP 4.0. The `token` field (a correlation token echoed +back in the webhook payload) is separate from `authentication` and is not deprecated. + +See [Webhook callbacks](https://adcontextprotocol.org/docs/building/implementation/security#webhook-callbacks) for the +full verifier checklist and downgrade-resistance rules. + ## Error envelope — read `issues[]` to recover Every validation failure produces: diff --git a/static/schemas/source/core/reporting-webhook.json b/static/schemas/source/core/reporting-webhook.json index cb9a295533..0bc09d5081 100644 --- a/static/schemas/source/core/reporting-webhook.json +++ b/static/schemas/source/core/reporting-webhook.json @@ -17,11 +17,11 @@ }, "authentication": { "type": "object", - "description": "Authentication configuration for webhook delivery (A2A-compatible)", + "description": "Legacy authentication configuration for webhook delivery (A2A-compatible). Opts the receiver into Bearer or HMAC-SHA256 signing. Both schemes are deprecated; the preferred signing profile for new integrations is RFC 9421, where the seller signs with a key published at its brand.json agents[] entry and the buyer verifies against the seller's JWKS — no shared secret crosses the wire (see docs/building/implementation/security.mdx#webhook-callbacks). This field is required in AdCP 3.x; the requirement is removed in AdCP 4.0 when the default RFC 9421 path becomes the only path.", "properties": { "schemes": { "type": "array", - "description": "Array of authentication schemes. Supported: ['Bearer'] for simple token auth, ['HMAC-SHA256'] for signature verification (recommended for production)", + "description": "Array of authentication schemes. ['Bearer'] for simple token auth, ['HMAC-SHA256'] for legacy shared-secret signing. Both are deprecated; new integrations SHOULD use the RFC 9421 webhook signing profile instead.", "items": { "$ref": "/schemas/enums/auth-scheme.json" }, @@ -30,7 +30,7 @@ }, "credentials": { "type": "string", - "description": "Credentials for authentication. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.", + "description": "Credentials for the legacy scheme. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.", "minLength": 32 } }, diff --git a/static/schemas/source/enums/auth-scheme.json b/static/schemas/source/enums/auth-scheme.json index 1ae1063f76..af841d9d0e 100644 --- a/static/schemas/source/enums/auth-scheme.json +++ b/static/schemas/source/enums/auth-scheme.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/schemas/enums/auth-scheme.json", "title": "Authentication Scheme", - "description": "Authentication schemes for push notification endpoints", + "description": "Legacy authentication schemes for the webhook auth block. Bearer: token sent in Authorization header. HMAC-SHA256: legacy shared-secret signing. Both are deprecated; new integrations SHOULD omit the authentication block and use the RFC 9421 webhook signing profile (applicable on schemas where authentication is optional). Removed in AdCP 4.0.", "type": "string", "enum": [ "Bearer", From ab355fd808104584cf4fa654a365a9a563155ebd Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sat, 9 May 2026 09:32:49 -0400 Subject: [PATCH 2/2] fix(schema): align artifact_webhook HMAC framing to RFC 9421 default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same description-only fix applied to artifact_webhook in create-media-buy-request.json — drops "recommended for production" on HMAC-SHA256, labels the authentication block as legacy, points new integrations at the RFC 9421 webhook signing profile. Mirrors the push-notification-config.json and reporting-webhook.json framing. Closes the last on-ramp surface from #4270. --- .changeset/fix-hmac-framing-skill-9421-default.md | 2 +- .../schemas/source/media-buy/create-media-buy-request.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.changeset/fix-hmac-framing-skill-9421-default.md b/.changeset/fix-hmac-framing-skill-9421-default.md index 83912813af..6aaf4f9669 100644 --- a/.changeset/fix-hmac-framing-skill-9421-default.md +++ b/.changeset/fix-hmac-framing-skill-9421-default.md @@ -2,4 +2,4 @@ "adcontextprotocol": patch --- -Fix stale HMAC-as-recommended framing in reporting-webhook.json and auth-scheme.json; add RFC 9421 default guidance to call-adcp-agent SKILL.md. Description-only fixes aligning these surfaces with the existing push-notification-config.json framing (HMAC is the deprecated fallback, RFC 9421 is the default). No wire format changes. +Fix stale HMAC-as-recommended framing in reporting-webhook.json, auth-scheme.json, and create-media-buy-request.json's artifact_webhook; add RFC 9421 default guidance to call-adcp-agent SKILL.md. Description-only fixes aligning these surfaces with the existing push-notification-config.json framing (HMAC is the deprecated fallback, RFC 9421 is the default). No wire format changes. diff --git a/static/schemas/source/media-buy/create-media-buy-request.json b/static/schemas/source/media-buy/create-media-buy-request.json index fa5e2607ea..dccf332c7b 100644 --- a/static/schemas/source/media-buy/create-media-buy-request.json +++ b/static/schemas/source/media-buy/create-media-buy-request.json @@ -145,11 +145,11 @@ }, "authentication": { "type": "object", - "description": "Authentication configuration for webhook delivery (A2A-compatible)", + "description": "Legacy authentication configuration for webhook delivery (A2A-compatible). Opts the receiver into Bearer or HMAC-SHA256 signing. Both schemes are deprecated; the preferred signing profile for new integrations is RFC 9421, where the seller signs with a key published at its brand.json agents[] entry and the buyer verifies against the seller's JWKS — no shared secret crosses the wire (see docs/building/implementation/security.mdx#webhook-callbacks). This field is required in AdCP 3.x; the requirement is removed in AdCP 4.0 when the default RFC 9421 path becomes the only path.", "properties": { "schemes": { "type": "array", - "description": "Array of authentication schemes. Supported: ['Bearer'] for simple token auth, ['HMAC-SHA256'] for signature verification (recommended for production)", + "description": "Array of authentication schemes. ['Bearer'] for simple token auth, ['HMAC-SHA256'] for legacy shared-secret signing. Both are deprecated; new integrations SHOULD use the RFC 9421 webhook signing profile instead.", "items": { "$ref": "/schemas/enums/auth-scheme.json" }, @@ -158,7 +158,7 @@ }, "credentials": { "type": "string", - "description": "Credentials for authentication. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.", + "description": "Credentials for the legacy scheme. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.", "minLength": 32 } },