Skip to content

compliance pre-flight throws on signed-requests specialism claim despite universal/ bundle + #2082 notice #2237

@kapoost

Description

@kapoost

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 #2082runner.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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions