Problem
Two SDK code paths contradict each other on the deprecated signed-requests specialism claim:
1. createAdcpServer (require the claim):
src/lib/server/create-adcp-server.ts (around the claimsSignedRequests guard) hard-throws when signedRequests: {...} is configured but capabilities.specialisms does not include signed-requests:
Error: createAdcpServer: `signedRequests` is configured but `capabilities.specialisms`
does not include "signed-requests". Add "signed-requests" to the specialisms list...
2. resolveStoryboardsForCapabilities (throw on the claim):
src/lib/testing/storyboard/compliance.ts iterates caps.specialisms, looks up index.specialisms, throws unknown_specialism if missing. signed-requests is in universal/signed-requests.yaml, not specialisms/signed-requests/, so the lookup misses and the entire compliance run is blocked:
CapabilityResolutionError: Agent declared specialism "signed-requests" but no bundle
exists at .../compliance/cache/3.1.0-rc.10/specialisms/signed-requests. Known
specialisms: audience-sync, brand-rights, ...
Reproduces against @adcp/sdk@9.0.0-beta.27 bundling 3.1.0-rc.10.
What the spec says
compliance/cache/3.1.0-rc.10/universal/signed-requests.yaml is explicit about backward-compat:
Backward-compatible specialism claims. The deprecated signed-requests specialism
enum value remains in the schema for back-compat (see adcp#3075). Agents that still
advertise specialisms: ["signed-requests"] are graded via this universal storyboard;
the runner SHOULD emit the signed_requests_specialism_deprecated notice [...]
The notice itself was shipped via #2082 — runner.ts collectCapabilityNotices() emits it correctly when the deprecated claim is present alongside request_signing.supported: true. But the pre-flight throws before any storyboard executes, so the notice never fires.
Reproduction
Minimal seller wiring (Bun, @adcp/sdk@9.0.0-beta.27):
// platform.ts
export const platform = definePlatform({
capabilities: { specialisms: ['sales-non-guaranteed', 'signed-requests'] as const, ... },
...
});
// index.ts
createAdcpServerFromPlatform(platform, {
...,
signedRequests: { jwks, replayStore, revocationStore },
});
Without 'signed-requests' in specialisms → createAdcpServer throws.
With it → boot succeeds, but adcp storyboard run <agent> fails pre-flight:
STORYBOARD-FAIL 1 step(s):
- pre-flight/comply [core]: Agent declared specialism "signed-requests" but
no bundle exists at .../specialisms/signed-requests. ...
The full suite never runs. (Workaround: drop both the specialism claim and the signedRequests config, but then we lose the verifier the spec asks us to expose.)
Proposed fix
resolveStoryboardsForCapabilities should special-case deprecated specialism aliases that resolve to a universal/ bundle:
- When iterating
declaredSpecialisms, before throwing unknown_specialism, check universal/<id>.yaml. If found AND the id is on a known deprecation list (or has a deprecation_alias_universal: <id> field in the universal bundle), push it as a universal storyboard target instead of throwing.
- The deprecation notice already fires from
runner.ts once the storyboard executes, satisfying the YAML contract.
Parallel cleanup (separate concern, may want its own issue):
createAdcpServer's guard should accept either path: deprecated specialisms: ['signed-requests'] OR capabilities.request_signing.supported === true (the canonical 3.1+ surface). Today it requires the deprecated claim, which is the inverse of what the spec encourages.
Why this matters
Adopters wiring 3.1 signed-requests against current SDK 9.x are blocked from running the full storyboard suite — unknown_specialism aborts pre-flight before any other storyboard can grade. This pushes adopters toward dropping the verifier (loses spec value) or hand-patching the SDK locally (loses upgrade path). Closing this unblocks signed-requests adopters today and removes a paper cut in the 3.1 → 4.0 deprecation runway.
Context
- Found while wiring signed-requests on a production seller (purrsonality-seller-agent, kapoost) against
@adcp/sdk@9.0.0-beta.27.
adcp grade request-signing (the dedicated grader) works fine — bypasses the pre-flight path entirely.
- The seller's e2e suite verifies that the auto-wired verifier correctly rejects unsigned mutating requests, so the SDK plumbing itself is sound. Only the storyboard-runner discovery path is wrong.
Related
Problem
Two SDK code paths contradict each other on the deprecated
signed-requestsspecialism claim:1.
createAdcpServer(require the claim):src/lib/server/create-adcp-server.ts(around theclaimsSignedRequestsguard) hard-throws whensignedRequests: {...}is configured butcapabilities.specialismsdoes not includesigned-requests:2.
resolveStoryboardsForCapabilities(throw on the claim):src/lib/testing/storyboard/compliance.tsiteratescaps.specialisms, looks upindex.specialisms, throwsunknown_specialismif missing.signed-requestsis inuniversal/signed-requests.yaml, notspecialisms/signed-requests/, so the lookup misses and the entire compliance run is blocked:Reproduces against
@adcp/sdk@9.0.0-beta.27bundling 3.1.0-rc.10.What the spec says
compliance/cache/3.1.0-rc.10/universal/signed-requests.yamlis explicit about backward-compat:The notice itself was shipped via #2082 —
runner.tscollectCapabilityNotices()emits it correctly when the deprecated claim is present alongsiderequest_signing.supported: true. But the pre-flight throws before any storyboard executes, so the notice never fires.Reproduction
Minimal seller wiring (Bun,
@adcp/sdk@9.0.0-beta.27):Without
'signed-requests'in specialisms →createAdcpServerthrows.With it → boot succeeds, but
adcp storyboard run <agent>fails pre-flight:The full suite never runs. (Workaround: drop both the specialism claim and the
signedRequestsconfig, but then we lose the verifier the spec asks us to expose.)Proposed fix
resolveStoryboardsForCapabilitiesshould special-case deprecated specialism aliases that resolve to auniversal/bundle:declaredSpecialisms, before throwingunknown_specialism, checkuniversal/<id>.yaml. If found AND the id is on a known deprecation list (or has adeprecation_alias_universal: <id>field in the universal bundle), push it as auniversalstoryboard target instead of throwing.runner.tsonce the storyboard executes, satisfying the YAML contract.Parallel cleanup (separate concern, may want its own issue):
createAdcpServer's guard should accept either path: deprecatedspecialisms: ['signed-requests']ORcapabilities.request_signing.supported === true(the canonical 3.1+ surface). Today it requires the deprecated claim, which is the inverse of what the spec encourages.Why this matters
Adopters wiring 3.1 signed-requests against current SDK 9.x are blocked from running the full storyboard suite —
unknown_specialismaborts pre-flight before any other storyboard can grade. This pushes adopters toward dropping the verifier (loses spec value) or hand-patching the SDK locally (loses upgrade path). Closing this unblocks signed-requests adopters today and removes a paper cut in the 3.1 → 4.0 deprecation runway.Context
@adcp/sdk@9.0.0-beta.27.adcp grade request-signing(the dedicated grader) works fine — bypasses the pre-flight path entirely.Related