You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Companion to #4205 — taking the storyboard / SDK skill on-ramp pass I self-pledged ("inventory which currently reference HMAC vs RFC 9421 and file a follow-up issue").
Framing
Per @bokelley's reframe in #4205: the right metric isn't "% migrated" against the installed base (which is ~empty). It's "no new HMAC implementers after date X," enforced via four on-ramp surfaces:
This issue covers surface 4. Where SDK-bundled skills + storyboard-adjacent compliance / schema docs frame webhook auth, do they steer new buyers toward 9421 or do they leave HMAC as the path of least resistance?
Inventory (against adcp-3.0.8)
✅ Already well-framed (no action)
Surface
Treatment
compliance/universal/webhook-emission.yaml
Calls HMAC "deprecated fallback"; grades 9421 as default; legacy buyers graded only on idempotency phases.
compliance/universal/signed-requests.yaml
RFC 9421 only; no HMAC mention.
compliance/test-vectors/webhook-signing/README.md
RFC 9421 throughout; production keys MUST be minted under own jwks_uri.
schemas/3.0.8/core/push-notification-config.json
"By default, webhooks are signed with the AdCP RFC 9421 profile"; auth block is the deprecated fallback, removed in 4.0. Best-in-class framing.
🟡 Stale framing — actively recommends HMAC
schemas/3.0.8/core/reporting-webhook.json
Line 24 description on the authentication block:
Supported: ['Bearer'] for simple token auth, ['HMAC-SHA256'] for signature verification (recommended for production)
This contradicts push-notification-config.json's framing (HMAC is the deprecated fallback there). Two adjacent webhook config schemas tell new buyers different things. Worse, on this schema authentication is required (line 63) — there is no path to opt into 9421 for reporting webhooks at all.
Suggested fix: align with push-notification-config.json's description; make authentication optional and document that omitting it selects the default 9421 profile (or document why reporting webhooks are different and intentionally locked to legacy).
schemas/3.0.8/enums/auth-scheme.json
Enum is [\"Bearer\", \"HMAC-SHA256\"] with a description that doesn't mention deprecation. A buyer reading this enum in isolation has no signal these are legacy options. Suggested fix: extend the description to note these are legacy auth-block options for buyers who haven't adopted the default 9421 webhook profile.
🔴 Silent — agent on-ramp skills don't mention webhook auth at all
The skills/*/SKILL.md files are what SDKs ship to teach LLM agents the wire contract. They cover idempotency_key, the oneOfaccount discriminator, async status:'submitted' polling, error recovery from adcp_error.issues[] — but none of them mention webhook signing:
skills/call-adcp-agent/SKILL.md (cross-cutting buyer-side basics) — zero webhook auth references
skills/adcp-signals/SKILL.md — only "Poll or use webhooks to check completion status" (line 178); no auth guidance
skills/adcp-media-buy/SKILL.md — only "Poll or use webhooks to check completion status" (line 392); no auth guidance
skills/adcp-creative/SKILL.md — no webhook references
skills/adcp-governance/SKILL.md — no webhook references
A new buyer agent built from these skills will reach for push_notification_config.authentication (the visible field in the schema) before learning that omitting it selects the modern path. The on-ramp surface that matters most for "no new HMAC implementers" is silent on the choice.
Suggested fix: a short section in call-adcp-agent/SKILL.md (cross-cutting, all buyer agents load this first) titled e.g. "Webhook signing — default to RFC 9421":
Default behavior: omit push_notification_config.authentication → seller signs with 9421 against the JWKS published at its brand.jsonagents[].jwks_uri
Buyer verifies via the published JWKS; no shared secret crosses the wire
Legacy authentication block (Bearer / HMAC-SHA256) is the deprecated fallback for receivers that haven't adopted 9421; removed in AdCP 4.0
Link to docs/building/implementation/security.mdx#webhook-callbacks for full profile + verifier checklist
That single section closes the silent-default trap across all five protocol skills, since they all > Buyer-side basics ... live in skills/call-adcp-agent/SKILL.md.
Out of scope
schemas/core/assets/webhook-asset.json (DCO outbound webhook, separate auth model — webhook-security-method.json enum: hmac_sha256/api_key/none). Different surface, not part of buyer push-notification webhooks.
Live docs at adcontextprotocol.org/docs/building/implementation/security.mdx — those are tracked under docs: add RFC 9421 request signing guide #3064 (docs default to RFC 9421) and out of scope here. This issue scoped to bundled storyboard / SDK skill / schema descriptions only.
Suggested resolution
Two-PR shape:
Schema PR — fix reporting-webhook.json description (and consider making authentication optional with 9421 default); add a deprecation hint in auth-scheme.json enum description.
SDK skill PR — add a webhook-signing section to skills/call-adcp-agent/SKILL.md so all five protocol skills inherit the framing.
Happy to take a first pass on either if a maintainer wants to triage rough scope first.
Companion to #4205 — taking the storyboard / SDK skill on-ramp pass I self-pledged ("inventory which currently reference HMAC vs RFC 9421 and file a follow-up issue").
Framing
Per @bokelley's reframe in #4205: the right metric isn't "% migrated" against the installed base (which is ~empty). It's "no new HMAC implementers after date X," enforced via four on-ramp surfaces:
This issue covers surface 4. Where SDK-bundled skills + storyboard-adjacent compliance / schema docs frame webhook auth, do they steer new buyers toward 9421 or do they leave HMAC as the path of least resistance?
Inventory (against
adcp-3.0.8)✅ Already well-framed (no action)
compliance/universal/webhook-emission.yamlcompliance/universal/signed-requests.yamlcompliance/test-vectors/webhook-signing/README.mdjwks_uri.schemas/3.0.8/core/push-notification-config.json🟡 Stale framing — actively recommends HMAC
schemas/3.0.8/core/reporting-webhook.jsonLine 24 description on the
authenticationblock:This contradicts push-notification-config.json's framing (HMAC is the deprecated fallback there). Two adjacent webhook config schemas tell new buyers different things. Worse, on this schema
authenticationisrequired(line 63) — there is no path to opt into 9421 for reporting webhooks at all.Suggested fix: align with push-notification-config.json's description; make
authenticationoptional and document that omitting it selects the default 9421 profile (or document why reporting webhooks are different and intentionally locked to legacy).schemas/3.0.8/enums/auth-scheme.jsonEnum is
[\"Bearer\", \"HMAC-SHA256\"]with a description that doesn't mention deprecation. A buyer reading this enum in isolation has no signal these are legacy options. Suggested fix: extend the description to note these are legacy auth-block options for buyers who haven't adopted the default 9421 webhook profile.🔴 Silent — agent on-ramp skills don't mention webhook auth at all
The
skills/*/SKILL.mdfiles are what SDKs ship to teach LLM agents the wire contract. They cover idempotency_key, theoneOfaccountdiscriminator, asyncstatus:'submitted'polling, error recovery fromadcp_error.issues[]— but none of them mention webhook signing:skills/call-adcp-agent/SKILL.md(cross-cutting buyer-side basics) — zero webhook auth referencesskills/adcp-signals/SKILL.md— only "Poll or use webhooks to check completion status" (line 178); no auth guidanceskills/adcp-media-buy/SKILL.md— only "Poll or use webhooks to check completion status" (line 392); no auth guidanceskills/adcp-creative/SKILL.md— no webhook referencesskills/adcp-governance/SKILL.md— no webhook referencesA new buyer agent built from these skills will reach for
push_notification_config.authentication(the visible field in the schema) before learning that omitting it selects the modern path. The on-ramp surface that matters most for "no new HMAC implementers" is silent on the choice.Suggested fix: a short section in
call-adcp-agent/SKILL.md(cross-cutting, all buyer agents load this first) titled e.g. "Webhook signing — default to RFC 9421":push_notification_config.authentication→ seller signs with 9421 against the JWKS published at itsbrand.jsonagents[].jwks_uriauthenticationblock (Bearer / HMAC-SHA256) is the deprecated fallback for receivers that haven't adopted 9421; removed in AdCP 4.0docs/building/implementation/security.mdx#webhook-callbacksfor full profile + verifier checklistThat single section closes the silent-default trap across all five protocol skills, since they all
> Buyer-side basics ... live in skills/call-adcp-agent/SKILL.md.Out of scope
schemas/core/assets/webhook-asset.json(DCO outbound webhook, separate auth model —webhook-security-method.jsonenum:hmac_sha256/api_key/none). Different surface, not part of buyer push-notification webhooks.adcontextprotocol.org/docs/building/implementation/security.mdx— those are tracked under docs: add RFC 9421 request signing guide #3064 (docs default to RFC 9421) and out of scope here. This issue scoped to bundled storyboard / SDK skill / schema descriptions only.Suggested resolution
Two-PR shape:
reporting-webhook.jsondescription (and consider makingauthenticationoptional with 9421 default); add a deprecation hint inauth-scheme.jsonenum description.skills/call-adcp-agent/SKILL.mdso all five protocol skills inherit the framing.Happy to take a first pass on either if a maintainer wants to triage rough scope first.
References
@adcp/sdk5.25.0)Filed by an agent vendor consuming the bundled
adcp-3.0.8skills + schemas; happy to discuss what "agent on-ramp" reads like from the consumer side.