@adcp/sdk 6.9.0 → 6.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adcp.js +285 -5
- package/compliance/cache/3.0.6.previous/domains/brand/index.yaml +163 -0
- package/compliance/cache/3.0.6.previous/domains/creative/index.yaml +412 -0
- package/compliance/cache/3.0.6.previous/domains/governance/index.yaml +683 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/creative-reception.yaml +247 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/index.yaml +769 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/create_media_buy_async.yaml +232 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/creative_fate_after_cancellation.yaml +414 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/delivery_reporting.yaml +205 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/governance_approved.yaml +211 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/governance_conditions.yaml +196 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/governance_denied.yaml +192 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/governance_denied_recovery.yaml +244 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/invalid_transitions.yaml +284 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/inventory_list_no_match.yaml +143 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/inventory_list_targeting.yaml +271 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/measurement_terms_rejected.yaml +195 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/pending_creatives_to_start.yaml +250 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/proposal_finalize.yaml +243 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/scenarios/refine_products.yaml +148 -0
- package/compliance/cache/3.0.6.previous/domains/media-buy/state-machine.yaml +442 -0
- package/compliance/cache/3.0.6.previous/domains/signals/index.yaml +266 -0
- package/compliance/cache/3.0.6.previous/domains/sponsored-intelligence/index.yaml +256 -0
- package/compliance/cache/3.0.6.previous/index.json +324 -0
- package/compliance/cache/3.0.6.previous/protocols/brand/index.yaml +163 -0
- package/compliance/cache/3.0.6.previous/protocols/creative/index.yaml +412 -0
- package/compliance/cache/3.0.6.previous/protocols/governance/index.yaml +683 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/creative-reception.yaml +247 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/index.yaml +769 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/create_media_buy_async.yaml +232 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/creative_fate_after_cancellation.yaml +414 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/delivery_reporting.yaml +205 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/governance_approved.yaml +211 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/governance_conditions.yaml +196 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/governance_denied.yaml +192 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/governance_denied_recovery.yaml +244 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/invalid_transitions.yaml +284 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/inventory_list_no_match.yaml +143 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/inventory_list_targeting.yaml +271 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/measurement_terms_rejected.yaml +195 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/pending_creatives_to_start.yaml +250 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/proposal_finalize.yaml +243 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/scenarios/refine_products.yaml +148 -0
- package/compliance/cache/3.0.6.previous/protocols/media-buy/state-machine.yaml +442 -0
- package/compliance/cache/3.0.6.previous/protocols/signals/index.yaml +266 -0
- package/compliance/cache/3.0.6.previous/protocols/sponsored-intelligence/index.yaml +256 -0
- package/compliance/cache/3.0.6.previous/specialisms/audience-sync/index.yaml +280 -0
- package/compliance/cache/3.0.6.previous/specialisms/brand-rights/index.yaml +350 -0
- package/compliance/cache/3.0.6.previous/specialisms/brand-rights/scenarios/governance_denied.yaml +204 -0
- package/compliance/cache/3.0.6.previous/specialisms/collection-lists/index.yaml +359 -0
- package/compliance/cache/3.0.6.previous/specialisms/content-standards/index.yaml +572 -0
- package/compliance/cache/3.0.6.previous/specialisms/creative-ad-server/index.yaml +383 -0
- package/compliance/cache/3.0.6.previous/specialisms/creative-generative/generative-seller.yaml +758 -0
- package/compliance/cache/3.0.6.previous/specialisms/creative-generative/index.yaml +746 -0
- package/compliance/cache/3.0.6.previous/specialisms/creative-template/index.yaml +413 -0
- package/compliance/cache/3.0.6.previous/specialisms/governance-aware-seller/index.yaml +136 -0
- package/compliance/cache/3.0.6.previous/specialisms/governance-delivery-monitor/index.yaml +441 -0
- package/compliance/cache/3.0.6.previous/specialisms/governance-spend-authority/denied.yaml +221 -0
- package/compliance/cache/3.0.6.previous/specialisms/governance-spend-authority/index.yaml +330 -0
- package/compliance/cache/3.0.6.previous/specialisms/property-lists/index.yaml +482 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-broadcast-tv/index.yaml +689 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-catalog-driven/index.yaml +779 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-guaranteed/index.yaml +504 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-non-guaranteed/index.yaml +428 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-proposal-mode/index.yaml +520 -0
- package/compliance/cache/3.0.6.previous/specialisms/sales-social/index.yaml +584 -0
- package/compliance/cache/3.0.6.previous/specialisms/signal-marketplace/index.yaml +415 -0
- package/compliance/cache/3.0.6.previous/specialisms/signal-marketplace/scenarios/governance_denied.yaml +207 -0
- package/compliance/cache/3.0.6.previous/specialisms/signal-owned/index.yaml +316 -0
- package/compliance/cache/3.0.6.previous/test-kits/acme-outdoor.yaml +210 -0
- package/compliance/cache/3.0.6.previous/test-kits/bistro-oranje.yaml +126 -0
- package/compliance/cache/3.0.6.previous/test-kits/nova-motors.yaml +262 -0
- package/compliance/cache/3.0.6.previous/test-kits/osei-natural.yaml +126 -0
- package/compliance/cache/3.0.6.previous/test-kits/signed-requests-runner.yaml +155 -0
- package/compliance/cache/3.0.6.previous/test-kits/substitution-observer-runner.yaml +690 -0
- package/compliance/cache/3.0.6.previous/test-kits/summit-foods.yaml +125 -0
- package/compliance/cache/3.0.6.previous/test-kits/webhook-receiver-runner.yaml +265 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/001-minimal-plan.json +43 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/002-full-plan.json +217 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/003-bookkeeping-stripped.json +60 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/004a-human-review-omitted.json +43 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/004b-human-review-explicit-null.json +49 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/005a-policy-categories-order-1.json +53 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/005b-policy-categories-order-2.json +57 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/006a-ext-trace-v1.json +49 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/006b-ext-trace-v2.json +53 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/007-unicode-objectives.json +43 -0
- package/compliance/cache/3.0.6.previous/test-vectors/plan-hash/008-numeric-canonicalization.json +65 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/README.md +219 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/canonicalization.json +241 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/keys.json +60 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/001-no-signature-header.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/002-wrong-tag.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/003-expired-signature.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/004-window-too-long.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/005-alg-not-allowed.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/006-missing-covered-component.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/007-missing-content-digest.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/008-unknown-keyid.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/009-key-ops-missing-verify.json +27 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/010-content-digest-mismatch.json +33 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/011-malformed-header.json +27 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/012-missing-expires-param.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/013-expires-le-created.json +27 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/014-missing-nonce-param.json +27 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/015-signature-invalid.json +28 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/016-replayed-nonce.json +35 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/017-key-revoked.json +38 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/018-digest-covered-when-forbidden.json +28 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/019-signature-without-signature-input.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/020-rate-abuse.json +34 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/021-duplicate-signature-input-label.json +31 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/022-multi-valued-content-type.json +31 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/023-multi-valued-content-digest.json +32 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/024-unquoted-string-param.json +31 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/025-jwk-alg-crv-mismatch.json +43 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/026-non-ascii-host.json +31 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/027-webhook-registration-authentication-unsigned.json +25 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/001-basic-post.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/002-post-with-content-digest.json +31 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/003-es256-post.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/004-multiple-signature-labels.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/005-default-port-stripped.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/006-dot-segment-path.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/007-query-byte-preserved.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/008-percent-encoded-path.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/009-percent-encoded-unreserved-decoded.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/010-percent-encoded-slash-preserved.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/011-ipv6-authority.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/request-signing/positive/012-ipv6-authority-default-port-stripped.json +30 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/README.md +211 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/keys.json +61 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/001-wrong-tag.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/002-expired-signature.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/003-window-too-long.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/004-alg-not-allowed.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/005-missing-authority-component.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/006-missing-content-digest.json +25 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/007-unknown-keyid.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/008-wrong-adcp-use.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/009-content-digest-mismatch.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/010-malformed-signature-input.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/011-signature-without-input.json +25 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/012-missing-expires-param.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/013-expires-le-created.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/014-missing-nonce-param.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/015-signature-invalid.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/016-replayed-nonce.json +37 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/017-key-revoked.json +32 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/018-rate-abuse.json +33 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/019-revocation-stale.json +32 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/020-key-ops-missing-verify.json +41 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/negative/021-base64-alphabet-mixing.json +26 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/001-basic-post.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/002-es256-post.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/003-multiple-signature-labels.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/004-default-port-stripped.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/005-percent-encoded-path.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/006-query-byte-preserved.json +24 -0
- package/compliance/cache/3.0.6.previous/test-vectors/webhook-signing/positive/007-body-without-idempotency-key.json +25 -0
- package/compliance/cache/3.0.6.previous/universal/capability-discovery.yaml +125 -0
- package/compliance/cache/3.0.6.previous/universal/collection-lists-pagination-integrity.yaml +306 -0
- package/compliance/cache/3.0.6.previous/universal/content-standards-pagination-integrity.yaml +326 -0
- package/compliance/cache/3.0.6.previous/universal/deterministic-testing.yaml +1343 -0
- package/compliance/cache/3.0.6.previous/universal/error-compliance.yaml +474 -0
- package/compliance/cache/3.0.6.previous/universal/fictional-entities.yaml +307 -0
- package/compliance/cache/3.0.6.previous/universal/get-media-buys-pagination-integrity.yaml +160 -0
- package/compliance/cache/3.0.6.previous/universal/get-signals-pagination-integrity.yaml +211 -0
- package/compliance/cache/3.0.6.previous/universal/idempotency.yaml +593 -0
- package/compliance/cache/3.0.6.previous/universal/pagination-integrity-creative-formats.yaml +258 -0
- package/compliance/cache/3.0.6.previous/universal/pagination-integrity-list-accounts.yaml +262 -0
- package/compliance/cache/3.0.6.previous/universal/pagination-integrity.yaml +263 -0
- package/compliance/cache/3.0.6.previous/universal/property-lists-pagination-integrity.yaml +307 -0
- package/compliance/cache/3.0.6.previous/universal/runner-output-contract.yaml +358 -0
- package/compliance/cache/3.0.6.previous/universal/schema-validation.yaml +526 -0
- package/compliance/cache/3.0.6.previous/universal/security.yaml +431 -0
- package/compliance/cache/3.0.6.previous/universal/signed-requests.yaml +205 -0
- package/compliance/cache/3.0.6.previous/universal/storyboard-schema.yaml +1176 -0
- package/compliance/cache/3.0.6.previous/universal/v3-envelope-integrity.yaml +106 -0
- package/compliance/cache/3.0.6.previous/universal/webhook-emission.yaml +337 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/create-adcp-server.d.ts +33 -0
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +127 -1
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/credential-policy.d.ts +221 -0
- package/dist/lib/server/credential-policy.d.ts.map +1 -0
- package/dist/lib/server/credential-policy.js +260 -0
- package/dist/lib/server/credential-policy.js.map +1 -0
- package/dist/lib/server/decisioning/async-outcome.d.ts +17 -0
- package/dist/lib/server/decisioning/async-outcome.d.ts.map +1 -1
- package/dist/lib/server/decisioning/async-outcome.js +23 -18
- package/dist/lib/server/decisioning/async-outcome.js.map +1 -1
- package/dist/lib/server/decisioning/context.d.ts +8 -2
- package/dist/lib/server/decisioning/context.d.ts.map +1 -1
- package/dist/lib/server/decisioning/index.d.ts +1 -0
- package/dist/lib/server/decisioning/index.d.ts.map +1 -1
- package/dist/lib/server/decisioning/index.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +6 -4
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +5 -2
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts +5 -0
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.js +4 -1
- package/dist/lib/server/decisioning/runtime/task-registry.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.js +10 -2
- package/dist/lib/server/decisioning/runtime/to-context.js.map +1 -1
- package/dist/lib/server/dynamic-registry.d.ts +219 -0
- package/dist/lib/server/dynamic-registry.d.ts.map +1 -0
- package/dist/lib/server/dynamic-registry.js +245 -0
- package/dist/lib/server/dynamic-registry.js.map +1 -0
- package/dist/lib/server/index.d.ts +8 -0
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js +15 -4
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/operational-platform.d.ts +239 -0
- package/dist/lib/server/operational-platform.d.ts.map +1 -0
- package/dist/lib/server/operational-platform.js +94 -0
- package/dist/lib/server/operational-platform.js.map +1 -0
- package/dist/lib/server/test-controller.d.ts +2 -0
- package/dist/lib/server/test-controller.d.ts.map +1 -1
- package/dist/lib/server/test-controller.js +6 -11
- package/dist/lib/server/test-controller.js.map +1 -1
- package/dist/lib/server/wire-safe.d.ts +211 -0
- package/dist/lib/server/wire-safe.d.ts.map +1 -0
- package/dist/lib/server/wire-safe.js +231 -0
- package/dist/lib/server/wire-safe.js.map +1 -0
- package/dist/lib/server/wire-spec-fields.generated.d.ts +168 -0
- package/dist/lib/server/wire-spec-fields.generated.d.ts.map +1 -0
- package/dist/lib/server/wire-spec-fields.generated.js +172 -0
- package/dist/lib/server/wire-spec-fields.generated.js.map +1 -0
- package/dist/lib/testing/compliance/index.d.ts +2 -0
- package/dist/lib/testing/compliance/index.d.ts.map +1 -1
- package/dist/lib/testing/compliance/index.js +6 -1
- package/dist/lib/testing/compliance/index.js.map +1 -1
- package/dist/lib/testing/compliance/summary.d.ts +77 -0
- package/dist/lib/testing/compliance/summary.d.ts.map +1 -0
- package/dist/lib/testing/compliance/summary.js +176 -0
- package/dist/lib/testing/compliance/summary.js.map +1 -0
- package/dist/lib/testing/comply-controller.d.ts +2 -0
- package/dist/lib/testing/comply-controller.d.ts.map +1 -1
- package/dist/lib/testing/comply-controller.js.map +1 -1
- package/dist/lib/testing/storyboard/compliance.d.ts +26 -0
- package/dist/lib/testing/storyboard/compliance.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/compliance.js +51 -0
- package/dist/lib/testing/storyboard/compliance.js.map +1 -1
- package/dist/lib/testing/storyboard/index.d.ts +2 -2
- package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/index.js +4 -2
- package/dist/lib/testing/storyboard/index.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +58 -5
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.d.ts.map +1 -1
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Signature alg is rsa-pss-sha512, not in AdCP allowlist",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 4",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"AAAAAAAAAAAAAAAAAAAAAA\";keyid=\"test-ed25519-2026\";alg=\"rsa-pss-sha512\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
21
|
+
"expected_outcome": {
|
|
22
|
+
"success": false,
|
|
23
|
+
"error_code": "request_signature_alg_not_allowed",
|
|
24
|
+
"failed_step": 4
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Covered components missing @authority",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 6",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"AAAAAAAAAAAAAAAAAAAAAA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
21
|
+
"expected_outcome": {
|
|
22
|
+
"success": false,
|
|
23
|
+
"error_code": "request_signature_components_incomplete",
|
|
24
|
+
"failed_step": 6
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Verifier requires content-digest coverage but signature omits it",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 6",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"AAAAAAAAAAAAAAAAAAAAAA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "required",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
21
|
+
"expected_outcome": {
|
|
22
|
+
"success": false,
|
|
23
|
+
"error_code": "request_signature_components_incomplete",
|
|
24
|
+
"failed_step": 6
|
|
25
|
+
}
|
|
26
|
+
}
|
package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/008-unknown-keyid.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "keyid does not match any entry in the signer's JWKS",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 7",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"AAAAAAAAAAAAAAAAAAAAAA\";keyid=\"not-a-real-kid\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
21
|
+
"expected_outcome": {
|
|
22
|
+
"success": false,
|
|
23
|
+
"error_code": "request_signature_key_unknown",
|
|
24
|
+
"failed_step": 7
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Presented JWK is scoped to governance signing (adcp_use != request-signing)",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 8",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"AAAAAAAAAAAAAAAAAAAAAA\";keyid=\"test-gov-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-gov-2026"],
|
|
21
|
+
"expected_outcome": {
|
|
22
|
+
"success": false,
|
|
23
|
+
"error_code": "request_signature_key_purpose_invalid",
|
|
24
|
+
"failed_step": 8
|
|
25
|
+
},
|
|
26
|
+
"$comment": "The keyid test-gov-2026 resolves to a JWK in keys.json with adcp_use='governance-signing'. Per spec step 8, verifier MUST reject because adcp_use is not 'request-signing'. This exercises the cross-purpose key reuse prevention: a single JWK declares one purpose, and verifiers enforce locally without cross-JWKS lookup."
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Content-Digest header does not match SHA-256 of received body",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 11",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Content-Digest": "sha-256=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=:",
|
|
11
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\" \"content-digest\");created=1776520800;expires=1776521100;nonce=\"AAAAAAAAAAAAAAAAAAAAAA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
12
|
+
"Signature": "sig1=:2p3oUaH5wK2ORtjDicHj69JEe6MDkrDUha0gIp8lw9qG2W1dQHSDvU4NkAwSeIIf8ieLaPGlE7X_yGu9enllAQ:"
|
|
13
|
+
},
|
|
14
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
15
|
+
},
|
|
16
|
+
"verifier_capability": {
|
|
17
|
+
"supported": true,
|
|
18
|
+
"covers_content_digest": "required",
|
|
19
|
+
"required_for": [
|
|
20
|
+
"create_media_buy"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"jwks_ref": [
|
|
24
|
+
"test-ed25519-2026"
|
|
25
|
+
],
|
|
26
|
+
"expected_outcome": {
|
|
27
|
+
"success": false,
|
|
28
|
+
"error_code": "request_signature_digest_mismatch",
|
|
29
|
+
"failed_step": 11
|
|
30
|
+
},
|
|
31
|
+
"$comment": "The Content-Digest header asserts sha-256 of 32 zero bytes, which is a value that is not the SHA-256 of the request body (the body hashes to something non-zero). The signature IS valid over the base that includes the Content-Digest header value as-is — step 10 passes. Step 11 recomputes the body's actual SHA-256 and compares against the header value, producing a mismatch. Verifiers MUST reject with request_signature_digest_mismatch at step 11; rejecting earlier with request_signature_invalid is non-conformant for this vector.",
|
|
32
|
+
"expected_signature_base": "\"@method\": POST\n\"@target-uri\": https://seller.example.com/adcp/create_media_buy\n\"@authority\": seller.example.com\n\"content-type\": application/json\n\"content-digest\": sha-256=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=:\n\"@signature-params\": (\"@method\" \"@target-uri\" \"@authority\" \"content-type\" \"content-digest\");created=1776520800;expires=1776521100;nonce=\"AAAAAAAAAAAAAAAAAAAAAA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\""
|
|
33
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Signature-Input present but syntactically invalid (downgrade protection)",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests pre-check (malformed header, no bearer fallback)",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/sync_creatives",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "this-is-not-a-valid-rfc-9421-signature-input",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
21
|
+
"expected_outcome": {
|
|
22
|
+
"success": false,
|
|
23
|
+
"error_code": "request_signature_header_malformed",
|
|
24
|
+
"failed_step": 1
|
|
25
|
+
},
|
|
26
|
+
"$comment": "Operation (sync_creatives) is NOT in required_for. Spec mandates that malformed signatures reject even for non-required ops — silent fallback to bearer-only authentication would enable downgrade attacks. Verifier MUST reject with request_signature_header_malformed, not accept-as-unsigned."
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Signature-Input is missing the required 'expires' parameter",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 2",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;nonce=\"AAAAAAAAAAAAAAAAAAAAAA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
21
|
+
"expected_outcome": {
|
|
22
|
+
"success": false,
|
|
23
|
+
"error_code": "request_signature_params_incomplete",
|
|
24
|
+
"failed_step": 2
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Signature expires equals created (negative validity window)",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 5",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776520800;nonce=\"AAAAAAAAAAAAAAAAAAAAAA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
21
|
+
"expected_outcome": {
|
|
22
|
+
"success": false,
|
|
23
|
+
"error_code": "request_signature_window_invalid",
|
|
24
|
+
"failed_step": 5
|
|
25
|
+
},
|
|
26
|
+
"$comment": "expires == created yields a zero-length validity window. Spec requires expires > created (strict inequality) to prevent signatures that are simultaneously issued and expired, which would bypass replay dedup — the replay cache entry would immediately be stale."
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Signature-Input is missing the required 'nonce' parameter",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 2",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
21
|
+
"expected_outcome": {
|
|
22
|
+
"success": false,
|
|
23
|
+
"error_code": "request_signature_params_incomplete",
|
|
24
|
+
"failed_step": 2
|
|
25
|
+
},
|
|
26
|
+
"$comment": "Without nonce, replay dedup collapses — the verifier has nothing to deduplicate on within the validity window. Spec requires nonce presence independently of other sig-params so this specific rejection path fires before the verifier reaches step 12's replay check."
|
|
27
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Signature header is well-formed but cryptographically invalid over the signature base",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 10",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"KXYnfEfJ0PBRZXQyVXfVQA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\",\"packages\":[{\"package_id\":\"pkg_1\",\"budget\":{\"amount\":1000,\"currency\":\"USD\"}}]}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
21
|
+
"expected_signature_base": "\"@method\": POST\n\"@target-uri\": https://seller.example.com/adcp/create_media_buy\n\"@authority\": seller.example.com\n\"content-type\": application/json\n\"@signature-params\": (\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"KXYnfEfJ0PBRZXQyVXfVQA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
22
|
+
"expected_outcome": {
|
|
23
|
+
"success": false,
|
|
24
|
+
"error_code": "request_signature_invalid",
|
|
25
|
+
"failed_step": 10
|
|
26
|
+
},
|
|
27
|
+
"$comment": "Signature-Input is identical to positive/001-basic-post.json, but Signature contains 64 zero bytes (base64url: 86 'A's) which is not a valid Ed25519 signature over any base. Verifier passes steps 1–9 and fails at step 10 cryptographic verification. This is the primary canonicalization-bug-catching vector: implementations whose signature base differs from the spec will ALSO fail here, but they'll fail even when given the CORRECT signature from positive/001. Implementations MUST distinguish by running positive/001 first (should succeed) and this vector second (should fail with request_signature_invalid)."
|
|
28
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Second submission of a previously-accepted (keyid, nonce) within the replay window",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 12",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"KXYnfEfJ0PBRZXQyVXfVQA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:U51PJzU9nMJxMAH_u-UDpSecT5SQX1-deSnWE3XpFo-BLT2_2h5FgMltntNCW05chhmFnjZEzkRmaYKeU0UUBw:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\",\"packages\":[{\"package_id\":\"pkg_1\",\"budget\":{\"amount\":1000,\"currency\":\"USD\"}}]}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
21
|
+
"test_harness_state": {
|
|
22
|
+
"$comment": "Pre-populate the replay cache as if positive/001 was just verified. Harness sets replay_cache[(test-ed25519-2026, KXYnfEfJ0PBRZXQyVXfVQA)] = valid-until 1776521100.",
|
|
23
|
+
"replay_cache_entries": [
|
|
24
|
+
{ "keyid": "test-ed25519-2026", "nonce": "KXYnfEfJ0PBRZXQyVXfVQA", "ttl_seconds": 360 }
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"expected_outcome": {
|
|
28
|
+
"success": false,
|
|
29
|
+
"error_code": "request_signature_replayed",
|
|
30
|
+
"failed_step": 12
|
|
31
|
+
},
|
|
32
|
+
"requires_contract": "replay_window",
|
|
33
|
+
"side_effects": "mutating",
|
|
34
|
+
"$comment": "This vector is identical to positive/001-basic-post.json but is submitted after the replay cache has already recorded the (keyid, nonce) pair. White-box harnesses MAY inject the cache entry directly (see test_harness_state). Black-box runners SHOULD send the request twice in sequence per test-kits/signed-requests-runner.yaml → stateful_vector_contract.replay_window; the first submission is accepted as a real create_media_buy and MUST be sent against a sandbox endpoint only (see endpoint_scope in the test-kit), the second MUST be rejected at step 12 with request_signature_replayed without reaching step 13's cache insert. The side_effects: mutating marker is a belt-and-suspenders signal for consumers that read vectors outside the storyboard runner: the black-box path for this vector has a first-request side effect by design."
|
|
35
|
+
}
|
package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/017-key-revoked.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Signing keyid is listed in the revocation list",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 9",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"KXYnfEfJ0PBRZXQyVXfVQA\";keyid=\"test-revoked-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:U51PJzU9nMJxMAH_u-UDpSecT5SQX1-deSnWE3XpFo-BLT2_2h5FgMltntNCW05chhmFnjZEzkRmaYKeU0UUBw:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\",\"packages\":[{\"package_id\":\"pkg_1\",\"budget\":{\"amount\":1000,\"currency\":\"USD\"}}]}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-revoked-2026"],
|
|
21
|
+
"test_harness_state": {
|
|
22
|
+
"$comment": "Pre-populate revocation list with test-revoked-2026 revoked. Harness sets revocation_list = { revoked_kids: ['test-revoked-2026'], revoked_jtis: [], fresh: true, issuer: 'https://seller.example.com', updated: '2026-04-18T14:00:00Z', next_update: '2026-04-18T14:15:00Z' }. Black-box runners rely on the agent having pre-configured this state per test-kits/signed-requests-runner.yaml → stateful_vector_contract.revocation (pre_revoked_keyid: test-revoked-2026).",
|
|
23
|
+
"revocation_list": {
|
|
24
|
+
"issuer": "https://seller.example.com",
|
|
25
|
+
"updated": "2026-04-18T14:00:00Z",
|
|
26
|
+
"next_update": "2026-04-18T14:15:00Z",
|
|
27
|
+
"revoked_kids": ["test-revoked-2026"],
|
|
28
|
+
"revoked_jtis": []
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"expected_outcome": {
|
|
32
|
+
"success": false,
|
|
33
|
+
"error_code": "request_signature_key_revoked",
|
|
34
|
+
"failed_step": 9
|
|
35
|
+
},
|
|
36
|
+
"requires_contract": "revocation",
|
|
37
|
+
"$comment": "Revocation check runs BEFORE cryptographic verify (step 9, before step 10) — this prevents cheap amplification where an attacker replays a revoked key's valid signature and forces the verifier to do an Ed25519/ECDSA verify for every rejection. Verifier MUST reject at step 9 without computing the signature base or running crypto verification. Implementations that defer the revocation check until after crypto verify will fail this vector because the committed Signature bytes are a placeholder copied from positive/001 and do not verify cryptographically against this vector's own signature base (different keyid in @signature-params); a crypto-first verifier will return request_signature_invalid instead of request_signature_key_revoked, which is a graded mismatch. Graders SHOULD surface this specific mismatch (_invalid where _key_revoked was expected) in operator-facing diagnostics as a step-ordering bug (still a graded FAIL) rather than as a generic vector failure — the vector is deliberately designed as a step-ordering canary and a verifier that runs crypto before revocation is exploitable (cheap amplification on revoked-key replay), which is the very failure mode the step-9-before-step-10 ordering exists to prevent. The keyid test-revoked-2026 is a dedicated revoked keypair in keys.json so this vector does not conflict with the purpose-mismatch vector (009) or the runner signing keys (test-ed25519-2026, test-es256-2026)."
|
|
38
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Signature covers content-digest but verifier capability is covers_content_digest='forbidden'",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 6",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Content-Digest": "sha-256=:SNIVma8dgUBx/U1CBaYFQnsJep9S0/tXaNXlQQOdoxQ=:",
|
|
11
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\" \"content-digest\");created=1776520800;expires=1776521100;nonce=\"KXYnfEfJ0PBRZXQyVXfVQA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
12
|
+
"Signature": "sig1=:RiD5mPhxpBWhmaqUL5-vceyPX5jpjzYZhSnteuYCIYhIqdIl0Yxdh5qstCPXwkKL4AZOsPBL7-8ctbPkHunSAw:"
|
|
13
|
+
},
|
|
14
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
15
|
+
},
|
|
16
|
+
"verifier_capability": {
|
|
17
|
+
"supported": true,
|
|
18
|
+
"covers_content_digest": "forbidden",
|
|
19
|
+
"required_for": ["create_media_buy"]
|
|
20
|
+
},
|
|
21
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
22
|
+
"expected_outcome": {
|
|
23
|
+
"success": false,
|
|
24
|
+
"error_code": "request_signature_components_unexpected",
|
|
25
|
+
"failed_step": 6
|
|
26
|
+
},
|
|
27
|
+
"$comment": "Signer covered content-digest, but verifier's capability advertises covers_content_digest='forbidden' (narrow opt-out for legacy infrastructure that cannot preserve body bytes). Verifier MUST reject with request_signature_components_unexpected — distinct error code from the inverse case (signer omits when required → request_signature_components_incomplete). This vector exists so SDKs can distinguish the two failure modes in their typed-error surfaces."
|
|
28
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Signature header present but Signature-Input header absent (downgrade loophole)",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests pre-check (header pair enforcement)",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature": "sig1=:qjngSQ0bgimxQbc6l0aFOmSthQRCdEgD10mOa7OGyUIEMuKwe2h_3l42oxs2Ga5qQCnVpaZHOuwhYu3qJp4HAA:"
|
|
11
|
+
},
|
|
12
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
13
|
+
},
|
|
14
|
+
"verifier_capability": {
|
|
15
|
+
"supported": true,
|
|
16
|
+
"covers_content_digest": "either",
|
|
17
|
+
"required_for": ["create_media_buy"]
|
|
18
|
+
},
|
|
19
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
20
|
+
"expected_outcome": {
|
|
21
|
+
"success": false,
|
|
22
|
+
"error_code": "request_signature_header_malformed",
|
|
23
|
+
"failed_step": 1
|
|
24
|
+
},
|
|
25
|
+
"$comment": "Signature and Signature-Input are a bound pair — one without the other is malformed. A proxy stripping Signature-Input while preserving Signature could otherwise be misread as 'this request is unsigned,' degrading a signed request to bearer-only auth. Verifier MUST reject; MUST NOT fall back to bearer-only authentication. Mirror case (Signature-Input without Signature) is also a reject condition per the spec pre-check — one vector is sufficient to exercise the rule."
|
|
26
|
+
}
|
package/compliance/cache/3.0.6.previous/test-vectors/request-signing/negative/020-rate-abuse.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Per-keyid replay cache entry cap exceeded (abuse or misconfigured signer)",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 9a (per-keyid cap; before crypto verify) and #transport-replay-dedup",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"NEW_NONCE_AFTER_CAP_________\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:U51PJzU9nMJxMAH_u-UDpSecT5SQX1-deSnWE3XpFo-BLT2_2h5FgMltntNCW05chhmFnjZEzkRmaYKeU0UUBw:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": ["create_media_buy"]
|
|
19
|
+
},
|
|
20
|
+
"jwks_ref": ["test-ed25519-2026"],
|
|
21
|
+
"test_harness_state": {
|
|
22
|
+
"$comment": "Pre-populate the replay cache to the per-keyid cap for test-ed25519-2026. Harness simulates the cap by setting a flag or populating with N placeholder entries where N is the verifier's configured cap. The exact mechanism is verifier-implementation-specific; what the vector asserts is the rejection behavior when the cap is hit.",
|
|
23
|
+
"replay_cache_per_keyid_cap_hit": {
|
|
24
|
+
"keyid": "test-ed25519-2026"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"expected_outcome": {
|
|
28
|
+
"success": false,
|
|
29
|
+
"error_code": "request_signature_rate_abuse",
|
|
30
|
+
"failed_step": "9a"
|
|
31
|
+
},
|
|
32
|
+
"requires_contract": "rate_abuse",
|
|
33
|
+
"$comment": "When the per-keyid replay cache has reached its configured cap (recommended: 1M entries), new signatures from that keyid MUST be rejected with request_signature_rate_abuse — not silently evict, not accept. Silent eviction creates replay windows exactly when under attack. The nonce in this vector is fresh (never seen); the rejection is due to the cap, not replay. Verifiers SHOULD alert operators on this condition as a compromised-key or misconfigured-signer signal. The cap check is step 9a of the verifier checklist and runs BEFORE crypto verify (step 10) to prevent amplified Ed25519/ECDSA work on an abusive signer — same rationale as revocation (step 9). Black-box runners target the cap declared in test-kits/signed-requests-runner.yaml → stateful_vector_contract.rate_abuse (grading_target_per_keyid_cap_requests: 100); agents MAY lower their production cap for the test-kit counterparty only. Implementations that defer the cap check until after crypto verify will fail this vector because the committed Signature bytes are a placeholder copied from positive/001 and do not verify cryptographically against this vector's own signature base (different nonce in @signature-params, different body); a crypto-first verifier will return request_signature_invalid instead of request_signature_rate_abuse. Graders SHOULD surface this specific mismatch (_invalid where _rate_abuse was expected) in operator-facing diagnostics as a step-ordering bug (still a graded FAIL) rather than as a generic vector failure — the vector is deliberately designed as a step-ordering canary and a verifier that runs crypto before the per-keyid cap is exploitable (an abusive signer forces Ed25519/ECDSA verify per request), which is the very failure mode the step-9a-before-step-10 ordering exists to prevent."
|
|
34
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Signature-Input header declares label 'sig1' twice (malformed structured dictionary)",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 1 (RFC 9421 §4.1 Signature-Input is a Dictionary; duplicate keys malformed)",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"KXYnfEfJ0PBRZXQyVXfVQA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\", sig1=(\"@method\" \"@target-uri\");created=1776520800;expires=1776521100;nonce=\"AAAAAAAAAAAAAAAAAAAAAA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": [
|
|
19
|
+
"create_media_buy"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"jwks_ref": [
|
|
23
|
+
"test-ed25519-2026"
|
|
24
|
+
],
|
|
25
|
+
"expected_outcome": {
|
|
26
|
+
"success": false,
|
|
27
|
+
"error_code": "request_signature_header_malformed",
|
|
28
|
+
"failed_step": 1
|
|
29
|
+
},
|
|
30
|
+
"$comment": "RFC 8941 §3.2 Dictionaries: 'When parsing, duplicate keys MUST be handled by either rejecting the input or by retaining only the last value.' Per the AdCP profile and downgrade-protection rule at step 1, verifiers MUST reject — silently retaining 'the last value' would let a proxy smuggle a weaker set of covered components past a verifier that read the first. Related cases: 011-malformed-header (unparseable) and 019-signature-without-signature-input (missing pair); this vector is the 'parseable-but-ambiguous' case the two existing vectors don't cover."
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Content-Type header sent as multiple field values (malformed — field covered by signature must be single-valued)",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 1 (covered component fields must be single-valued; RFC 9421 §2.1 derivation rules do not permit concatenation for non-list headers)",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json, text/plain",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"KXYnfEfJ0PBRZXQyVXfVQA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": [
|
|
19
|
+
"create_media_buy"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"jwks_ref": [
|
|
23
|
+
"test-ed25519-2026"
|
|
24
|
+
],
|
|
25
|
+
"expected_outcome": {
|
|
26
|
+
"success": false,
|
|
27
|
+
"error_code": "request_signature_header_malformed",
|
|
28
|
+
"failed_step": 1
|
|
29
|
+
},
|
|
30
|
+
"$comment": "Content-Type is not a List-Structured-Field — it has a single canonical value with optional parameters. RFC 9421 §2.1 says covered field values are the field's canonical in-order concatenation only for fields the HTTP spec treats as list-typed. A proxy inserting a second Content-Type (or a client with a bug emitting two) leaves the field's meaning undefined relative to the signature base. Verifier MUST reject at parse time rather than pick one value and hope for the best."
|
|
31
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Content-Digest header sent as multiple field values (malformed)",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 1 (Content-Digest covered in signature must be single-valued; RFC 9530)",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Content-Digest": "sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:, sha-256=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=:",
|
|
11
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\" \"content-digest\");created=1776520800;expires=1776521100;nonce=\"KXYnfEfJ0PBRZXQyVXfVQA\";keyid=\"test-ed25519-2026\";alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
12
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
13
|
+
},
|
|
14
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
15
|
+
},
|
|
16
|
+
"verifier_capability": {
|
|
17
|
+
"supported": true,
|
|
18
|
+
"covers_content_digest": "required",
|
|
19
|
+
"required_for": [
|
|
20
|
+
"create_media_buy"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"jwks_ref": [
|
|
24
|
+
"test-ed25519-2026"
|
|
25
|
+
],
|
|
26
|
+
"expected_outcome": {
|
|
27
|
+
"success": false,
|
|
28
|
+
"error_code": "request_signature_header_malformed",
|
|
29
|
+
"failed_step": 1
|
|
30
|
+
},
|
|
31
|
+
"$comment": "Content-Digest per RFC 9530 §2 is a Dictionary-Structured-Field where each member is a digest algorithm — duplicates of the same algorithm are ambiguous and undefined for signature coverage. Even if the two sha-256 values happened to be identical, permitting multiple on the wire creates a parser-differential attack: signer and verifier might disagree on which value enters the signature base. Verifier MUST reject. Distinct from 010-content-digest-mismatch (where the single declared digest doesn't match the body)."
|
|
32
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Signature-Input sig-param string value sent unquoted (keyid=foo instead of keyid=\"foo\")",
|
|
3
|
+
"spec_reference": "#verifier-checklist-requests step 1 (RFC 9421 §2.3 sig-params; RFC 8941 §3.3 string values MUST be double-quoted)",
|
|
4
|
+
"reference_now": 1776520800,
|
|
5
|
+
"request": {
|
|
6
|
+
"method": "POST",
|
|
7
|
+
"url": "https://seller.example.com/adcp/create_media_buy",
|
|
8
|
+
"headers": {
|
|
9
|
+
"Content-Type": "application/json",
|
|
10
|
+
"Signature-Input": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-type\");created=1776520800;expires=1776521100;nonce=\"KXYnfEfJ0PBRZXQyVXfVQA\";keyid=test-ed25519-2026;alg=\"ed25519\";tag=\"adcp/request-signing/v1\"",
|
|
11
|
+
"Signature": "sig1=:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
|
|
12
|
+
},
|
|
13
|
+
"body": "{\"plan_id\":\"plan_001\"}"
|
|
14
|
+
},
|
|
15
|
+
"verifier_capability": {
|
|
16
|
+
"supported": true,
|
|
17
|
+
"covers_content_digest": "either",
|
|
18
|
+
"required_for": [
|
|
19
|
+
"create_media_buy"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"jwks_ref": [
|
|
23
|
+
"test-ed25519-2026"
|
|
24
|
+
],
|
|
25
|
+
"expected_outcome": {
|
|
26
|
+
"success": false,
|
|
27
|
+
"error_code": "request_signature_header_malformed",
|
|
28
|
+
"failed_step": 1
|
|
29
|
+
},
|
|
30
|
+
"$comment": "Per RFC 8941 §3.3.3, Structured-Field string values MUST be wrapped in ASCII double-quotes. RFC 9421 §2.3 defines keyid, nonce, and tag as string-typed sig-params, so 'keyid=foo' (bare token) is not a valid string — it would parse as a token-typed value if the grammar allowed tokens there, which it does not. A verifier that tolerantly accepts bare tokens (common bug in hand-rolled parsers) introduces a parser-differential attack: one implementation sees keyid='foo', another sees keyid=undefined, and they disagree on which JWKS entry to resolve. Verifier MUST reject at parse."
|
|
31
|
+
}
|