Skip to content

request-signing.mdx documents seven signing error codes that do not exist — implementers who follow it fail all 28 negative vectors #6076

Description

@KonstantinMirin

Summary

docs/building/by-layer/L1/request-signing.mdx § ## Testing### Error codes tells implementers to return 401 with WWW-Authenticate: Signature error="<code>" and then lists seven codes:

missing_signature, invalid_signature, expired_signature,
replayed_nonce, revoked_key, unknown_key, unsupported_algorithm

None of those seven names exists anywhere in the 3.1.1 compliance tree. Every real code is request_signature_*.

This is not a stale count. It is the normative contract being wrong on the primary L1 page that teaches it.

Impact

universal/signed-requests.yaml grades the code byte-for-byte:

Negative vectors MUST produce 401 with WWW-Authenticate: Signature error="<code>", where the <code> matches the vector's expected_outcome.error_code byte-for-byte.

So an implementer who follows this page fails all 28 negative vectors while having correctly implemented what the documentation told them to do — correct 401, correct header, correct rejection reason, wrong string. The docs and the conformance suite describe two different protocols.

The failure mode is expensive precisely because the behaviour is right: nothing in the implementation looks wrong, and the grader gives 28 failures with no hint that the source of the names was the docs.

Verification

Vector codes:

for f in $(git ls-tree -r --name-only v3.1.1 \
    dist/compliance/3.1.1/test-vectors/request-signing/negative/); do
  git show v3.1.1:$f | jq -r .expected_outcome.error_code
done | sort -u

→ 15 distinct codes across 28 negative vectors, all request_signature_*.

None of the seven documented names appears:

git grep -E "\b(missing_signature|invalid_signature|expired_signature|replayed_nonce|unknown_key|unsupported_algorithm)\b" \
  v3.1.1 -- 'dist/compliance/3.1.1/*'
# no output

(revoked_key matches only as a substring of pre_revoked_keyid / revoked_kids, never as an error code.)

What the page should have said:

Documented Actually graded
missing_signature request_signature_required
invalid_signature request_signature_invalid
expired_signature request_signature_window_invalid
replayed_nonce request_signature_replayed
revoked_key request_signature_key_revoked
unknown_key request_signature_key_unknown
unsupported_algorithm request_signature_alg_not_allowed

The canonical set is larger than seven

docs/building/by-layer/L1/security.mdx carries the authoritative taxonomy in two places — #transport-error-taxonomy (20 rows) and #discovering-an-agents-signing-keys-via-brand_json_url (the discovery-phase codes). Together they define 27 concrete request_signature_* codes, of which the negative vectors currently exercise 15.

Note the transport table also carries two codes that are not request_signature_*request_target_uri_malformed and request_body_malformed — so "all signing errors are request_signature_*" is not quite a rule.

The protocol error-code enum is not the source here. dist/schemas/3.1.1/enums/error-code.json has 92 values and zero request_signature_*: these are HTTP transport-layer codes carried in WWW-Authenticate, not AdCP protocol error codes. The only schema that names any of them is get-adcp-capabilities-response.json (3 of them, in prose). Schema, vectors, and security.mdx do not disagree — they have different scopes, and security.mdx is the only complete list.

Why no guard caught it

scripts/lint-error-codes.cjs and scripts/lint-error-code-drift.cjs scan static/compliance/source/ and static/schemas/source/enums/error-code.json. Neither scans docs/. No check validates an error code named in prose against anything. That structural gap is #6075; this issue is the instance.

Fix

PR incoming: replace the table with the 15 codes the negative vectors actually grade, worded to match the canonical security.mdx rows, ordered by the verifier checklist, and pointing at both canonical sections for the remaining 12.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingclaude-triagedIssue has been triaged by the Claude Code triage routine. Remove to re-triage.compliance-suitedocumentationImprovements or additions to documentationpriority:P0Immediate priority: user/revenue/security/reliability bug to work now

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions