@adcp/sdk 7.11.0 → 7.11.1
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/compliance/cache/3.1.0-rc.2/domains/brand/index.yaml +160 -0
- package/compliance/cache/3.1.0-rc.2/domains/brand/scenarios/distributed_brand_resolution.yaml +415 -0
- package/compliance/cache/3.1.0-rc.2/domains/brand/scenarios/single_side_trust_extension.yaml +454 -0
- package/compliance/cache/3.1.0-rc.2/domains/creative/index.yaml +339 -0
- package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/billing_out_of_band.yaml +153 -0
- package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/canonical_supported_formats.yaml +212 -0
- package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/creative_lifecycle_webhooks.yaml +389 -0
- package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/native_in_feed.yaml +543 -0
- package/compliance/cache/3.1.0-rc.2/domains/governance/index.yaml +682 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/index.yaml +789 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/audience_buy_flow.yaml +380 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/available_actions.yaml +565 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/billing_finality_delivery.yaml +354 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/canonical_formats.yaml +861 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/clicks_buy_flow.yaml +264 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/completed_views_buy_flow.yaml +344 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/create_media_buy_async.yaml +234 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/creative_fate_after_cancellation.yaml +419 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/creative_reception.yaml +247 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/delivery_reporting.yaml +357 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/dependency_impairment.yaml +633 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/dependency_impairment_cardinality.yaml +800 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/event_dedup_flow.yaml +399 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/frequency_cap_enforcement.yaml +309 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_approved.yaml +214 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_conditions.yaml +199 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_denied.yaml +204 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_denied_recovery.yaml +252 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/invalid_transitions.yaml +289 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/inventory_list_no_match.yaml +148 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/inventory_list_targeting.yaml +276 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/measurement_accountability.yaml +244 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/measurement_terms_rejected.yaml +203 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/package_correlation_legacy_fallback.yaml +113 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/pending_creatives_to_start.yaml +292 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/per_creative_conversion_attribution.yaml +500 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/performance_buy_flow.yaml +428 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/performance_buy_flow_roas.yaml +470 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/product_signal_targeting.yaml +373 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/proposal_finalize.yaml +399 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/proposal_finalize_asap_timing.yaml +264 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/proposal_not_found_errors.yaml +257 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/provenance_audit_observation.yaml +333 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/provenance_enforcement.yaml +517 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/provenance_truth_of_claim.yaml +294 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/reach_buy_flow.yaml +823 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/refine_finalize_exclusivity.yaml +360 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/refine_products.yaml +148 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/vendor_metric_accountability.yaml +293 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +307 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/vendor_metric_optimization_flow.yaml +576 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/state-machine.yaml +442 -0
- package/compliance/cache/3.1.0-rc.2/domains/signals/index.yaml +266 -0
- package/compliance/cache/3.1.0-rc.2/domains/sponsored-intelligence/index.yaml +256 -0
- package/compliance/cache/3.1.0-rc.2/index.json +356 -0
- package/compliance/cache/3.1.0-rc.2/protocols/brand/index.yaml +160 -0
- package/compliance/cache/3.1.0-rc.2/protocols/brand/scenarios/distributed_brand_resolution.yaml +415 -0
- package/compliance/cache/3.1.0-rc.2/protocols/brand/scenarios/single_side_trust_extension.yaml +454 -0
- package/compliance/cache/3.1.0-rc.2/protocols/creative/index.yaml +339 -0
- package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/billing_out_of_band.yaml +153 -0
- package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/canonical_supported_formats.yaml +212 -0
- package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/creative_lifecycle_webhooks.yaml +389 -0
- package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/native_in_feed.yaml +543 -0
- package/compliance/cache/3.1.0-rc.2/protocols/governance/index.yaml +682 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/index.yaml +789 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/audience_buy_flow.yaml +380 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/available_actions.yaml +565 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/billing_finality_delivery.yaml +354 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/canonical_formats.yaml +861 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/clicks_buy_flow.yaml +264 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/completed_views_buy_flow.yaml +344 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/create_media_buy_async.yaml +234 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/creative_fate_after_cancellation.yaml +419 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/creative_reception.yaml +247 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/delivery_reporting.yaml +357 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/dependency_impairment.yaml +633 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/dependency_impairment_cardinality.yaml +800 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/event_dedup_flow.yaml +399 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/frequency_cap_enforcement.yaml +309 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_approved.yaml +214 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_conditions.yaml +199 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_denied.yaml +204 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_denied_recovery.yaml +252 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/invalid_transitions.yaml +289 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/inventory_list_no_match.yaml +148 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/inventory_list_targeting.yaml +276 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/measurement_accountability.yaml +244 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/measurement_terms_rejected.yaml +203 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/package_correlation_legacy_fallback.yaml +113 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/pending_creatives_to_start.yaml +292 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/per_creative_conversion_attribution.yaml +500 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/performance_buy_flow.yaml +428 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/performance_buy_flow_roas.yaml +470 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/product_signal_targeting.yaml +373 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/proposal_finalize.yaml +399 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/proposal_finalize_asap_timing.yaml +264 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/proposal_not_found_errors.yaml +257 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/provenance_audit_observation.yaml +333 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/provenance_enforcement.yaml +517 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/provenance_truth_of_claim.yaml +294 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/reach_buy_flow.yaml +823 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/refine_finalize_exclusivity.yaml +360 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/refine_products.yaml +148 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/vendor_metric_accountability.yaml +293 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +307 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/vendor_metric_optimization_flow.yaml +576 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/state-machine.yaml +442 -0
- package/compliance/cache/3.1.0-rc.2/protocols/signals/index.yaml +266 -0
- package/compliance/cache/3.1.0-rc.2/protocols/sponsored-intelligence/index.yaml +256 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/audience-sync/index.yaml +313 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/brand-rights/index.yaml +350 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/brand-rights/scenarios/governance_denied.yaml +226 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/collection-lists/index.yaml +359 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/content-standards/index.yaml +572 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/creative-ad-server/index.yaml +409 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/creative-generative/generative-seller.yaml +807 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/creative-generative/index.yaml +758 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/creative-template/index.yaml +510 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/governance-aware-seller/index.yaml +143 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/governance-aware-seller/scenarios/governance_multi_agent_rejected.yaml +117 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/governance-delivery-monitor/index.yaml +441 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/governance-spend-authority/denied.yaml +221 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/governance-spend-authority/index.yaml +330 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/property-lists/index.yaml +482 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-broadcast-tv/index.yaml +738 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-catalog-driven/index.yaml +840 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-guaranteed/index.yaml +601 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-non-guaranteed/index.yaml +546 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-proposal-mode/index.yaml +586 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-social/index.yaml +919 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/signal-marketplace/index.yaml +424 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/signal-marketplace/scenarios/governance_denied.yaml +210 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/signal-owned/index.yaml +317 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sponsored-intelligence/index.yaml +59 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/acme-outdoor-live.yaml +78 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/acme-outdoor.yaml +223 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/billing-gate-runner.yaml +115 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/bistro-oranje.yaml +126 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/distributed-brand-runner.yaml +281 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/nova-motors.yaml +262 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/osei-natural.yaml +126 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/parallel-dispatch-runner.yaml +196 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/rate-limit-trip-runner.yaml +172 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/signed-requests-runner.yaml +155 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/single-side-trust-runner.yaml +294 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/substitution-observer-runner.yaml +688 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/summit-foods.yaml +125 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/webhook-receiver-runner.yaml +265 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/001-minimal-plan.json +43 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/002-full-plan.json +217 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/003-bookkeeping-stripped.json +60 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/004a-human-review-omitted.json +43 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/004b-human-review-explicit-null.json +49 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/005a-policy-categories-order-1.json +53 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/005b-policy-categories-order-2.json +57 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/006a-ext-trace-v1.json +49 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/006b-ext-trace-v2.json +53 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/007-unicode-objectives.json +43 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/008-numeric-canonicalization.json +65 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/README.md +220 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/canonicalization.json +241 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/keys.json +60 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/001-no-signature-header.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/002-wrong-tag.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/003-expired-signature.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/004-window-too-long.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/005-alg-not-allowed.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/006-missing-covered-component.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/007-missing-content-digest.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/008-unknown-keyid.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/009-key-ops-missing-verify.json +27 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/010-content-digest-mismatch.json +33 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/011-malformed-header.json +27 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/012-missing-expires-param.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/013-expires-le-created.json +27 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/014-missing-nonce-param.json +27 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/015-signature-invalid.json +28 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/016-replayed-nonce.json +35 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/017-key-revoked.json +38 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/018-digest-covered-when-forbidden.json +28 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/019-signature-without-signature-input.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/020-rate-abuse.json +34 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/021-duplicate-signature-input-label.json +31 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/022-multi-valued-content-type.json +31 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/023-multi-valued-content-digest.json +32 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/024-unquoted-string-param.json +31 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/025-jwk-alg-crv-mismatch.json +43 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/026-non-ascii-host.json +31 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/027-webhook-registration-authentication-unsigned.json +25 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/028-unsigned-protocol-method-required.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/001-basic-post.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/002-post-with-content-digest.json +31 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/003-es256-post.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/004-multiple-signature-labels.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/005-default-port-stripped.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/006-dot-segment-path.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/007-query-byte-preserved.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/008-percent-encoded-path.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/009-percent-encoded-unreserved-decoded.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/010-percent-encoded-slash-preserved.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/011-ipv6-authority.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/012-ipv6-authority-default-port-stripped.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/README.md +211 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/keys.json +61 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/001-wrong-tag.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/002-expired-signature.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/003-window-too-long.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/004-alg-not-allowed.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/005-missing-authority-component.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/006-missing-content-digest.json +25 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/007-unknown-keyid.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/008-wrong-adcp-use.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/009-content-digest-mismatch.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/010-malformed-signature-input.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/011-signature-without-input.json +25 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/012-missing-expires-param.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/013-expires-le-created.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/014-missing-nonce-param.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/015-signature-invalid.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/016-replayed-nonce.json +37 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/017-key-revoked.json +32 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/018-rate-abuse.json +33 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/019-revocation-stale.json +32 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/020-key-ops-missing-verify.json +41 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/021-base64-alphabet-mixing.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/001-basic-post.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/002-es256-post.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/003-multiple-signature-labels.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/004-default-port-stripped.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/005-percent-encoded-path.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/006-query-byte-preserved.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/007-body-without-idempotency-key.json +25 -0
- package/compliance/cache/3.1.0-rc.2/universal/billing-gate-dispatch.yaml +450 -0
- package/compliance/cache/3.1.0-rc.2/universal/canonical-format-validate-input.yaml +640 -0
- package/compliance/cache/3.1.0-rc.2/universal/capability-discovery.yaml +125 -0
- package/compliance/cache/3.1.0-rc.2/universal/collection-lists-pagination-integrity.yaml +306 -0
- package/compliance/cache/3.1.0-rc.2/universal/comply-controller-mode-gate.yaml +141 -0
- package/compliance/cache/3.1.0-rc.2/universal/content-standards-pagination-integrity.yaml +326 -0
- package/compliance/cache/3.1.0-rc.2/universal/deterministic-testing.yaml +1430 -0
- package/compliance/cache/3.1.0-rc.2/universal/error-compliance-signals.yaml +377 -0
- package/compliance/cache/3.1.0-rc.2/universal/error-compliance.yaml +528 -0
- package/compliance/cache/3.1.0-rc.2/universal/fictional-entities.yaml +307 -0
- package/compliance/cache/3.1.0-rc.2/universal/get-media-buys-pagination-integrity.yaml +160 -0
- package/compliance/cache/3.1.0-rc.2/universal/get-signals-pagination-integrity.yaml +210 -0
- package/compliance/cache/3.1.0-rc.2/universal/idempotency.yaml +861 -0
- package/compliance/cache/3.1.0-rc.2/universal/notification-config-event-scope.yaml +119 -0
- package/compliance/cache/3.1.0-rc.2/universal/notification-config-lifecycle.yaml +337 -0
- package/compliance/cache/3.1.0-rc.2/universal/notification-config-rejections.yaml +107 -0
- package/compliance/cache/3.1.0-rc.2/universal/pagination-integrity-creative-formats.yaml +265 -0
- package/compliance/cache/3.1.0-rc.2/universal/pagination-integrity-list-accounts.yaml +245 -0
- package/compliance/cache/3.1.0-rc.2/universal/pagination-integrity.yaml +263 -0
- package/compliance/cache/3.1.0-rc.2/universal/property-lists-pagination-integrity.yaml +307 -0
- package/compliance/cache/3.1.0-rc.2/universal/read-tool-idempotency.yaml +405 -0
- package/compliance/cache/3.1.0-rc.2/universal/runner-output-contract.yaml +1285 -0
- package/compliance/cache/3.1.0-rc.2/universal/schema-validation-signals.yaml +181 -0
- package/compliance/cache/3.1.0-rc.2/universal/schema-validation.yaml +548 -0
- package/compliance/cache/3.1.0-rc.2/universal/security.yaml +539 -0
- package/compliance/cache/3.1.0-rc.2/universal/signed-requests.yaml +217 -0
- package/compliance/cache/3.1.0-rc.2/universal/stale-response-advisory.yaml +295 -0
- package/compliance/cache/3.1.0-rc.2/universal/storyboard-schema.yaml +2194 -0
- package/compliance/cache/3.1.0-rc.2/universal/v3-envelope-integrity.yaml +117 -0
- package/compliance/cache/3.1.0-rc.2/universal/version-negotiation.yaml +130 -0
- package/compliance/cache/3.1.0-rc.2/universal/webhook-emission.yaml +411 -0
- package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-bulk-webhooks.yaml +82 -0
- package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-product-webhooks.yaml +83 -0
- package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-products.yaml +151 -0
- package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-signal-webhooks.yaml +83 -0
- package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-signals.yaml +149 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/testing/storyboard/default-invariants.js +23 -0
- package/dist/lib/testing/storyboard/default-invariants.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +84 -21
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/testing/storyboard/types.d.ts +21 -0
- package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/types.js.map +1 -1
- package/dist/lib/testing/types.d.ts +9 -0
- package/dist/lib/testing/types.d.ts.map +1 -1
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/package.json +1 -1
|
@@ -0,0 +1,1285 @@
|
|
|
1
|
+
# Runner Output Contract
|
|
2
|
+
#
|
|
3
|
+
# Defines the failure-result shape that any AdCP compliance runner MUST emit
|
|
4
|
+
# when it reports storyboard results to a user or coding agent. Applies to
|
|
5
|
+
# evaluate_agent_quality, `@adcp/client storyboard run`, and any other harness
|
|
6
|
+
# that executes the storyboards published under /compliance/{version}/.
|
|
7
|
+
#
|
|
8
|
+
# Rationale
|
|
9
|
+
# ---------
|
|
10
|
+
# A failing validation is only actionable if the implementor can see:
|
|
11
|
+
# 1. The exact request the runner sent.
|
|
12
|
+
# 2. The exact response the agent returned.
|
|
13
|
+
# 3. Which field failed (as an RFC 6901 JSON Pointer).
|
|
14
|
+
# 4. What the runner expected vs. what it observed.
|
|
15
|
+
# 5. The identity of the schema applied (so the implementor can re-validate
|
|
16
|
+
# locally against the same artifact).
|
|
17
|
+
#
|
|
18
|
+
# Without these, a buyer building an agent cannot diagnose failures even when
|
|
19
|
+
# their own local validation passes — a mismatch between the schema they tested
|
|
20
|
+
# against and the schema the runner used is indistinguishable from a genuine
|
|
21
|
+
# agent bug.
|
|
22
|
+
#
|
|
23
|
+
# Storyboard AUTHORING is covered in storyboard-schema.yaml. This contract
|
|
24
|
+
# covers runner OUTPUT.
|
|
25
|
+
#
|
|
26
|
+
# --- Schema definition ---
|
|
27
|
+
|
|
28
|
+
id: runner_output_contract
|
|
29
|
+
version: "2.4.0"
|
|
30
|
+
title: "Runner output contract"
|
|
31
|
+
summary: "Required failure-detail shape that AdCP storyboard runners MUST emit so implementors can self-diagnose validation failures."
|
|
32
|
+
|
|
33
|
+
# Single source of truth for the storyboard-authored check enum.
|
|
34
|
+
# Storyboards MUST only declare step.validations[].check values from this
|
|
35
|
+
# list. Synthesized codes (capture_path_not_resolvable,
|
|
36
|
+
# unresolved_substitution) are emitted by the runner — not authored — and
|
|
37
|
+
# MUST NOT appear here. The build-time lint
|
|
38
|
+
# `scripts/lint-storyboard-check-enum.cjs` reads this field and rejects any
|
|
39
|
+
# storyboard that declares an unknown check kind, complementing the runtime
|
|
40
|
+
# forward-compat default (which exists for cross-version skew between
|
|
41
|
+
# storyboard and runner, not for catching typos at publish time).
|
|
42
|
+
authored_check_kinds:
|
|
43
|
+
- response_schema
|
|
44
|
+
- field_present
|
|
45
|
+
- field_absent
|
|
46
|
+
- envelope_field_present
|
|
47
|
+
- envelope_field_absent
|
|
48
|
+
- field_value
|
|
49
|
+
- field_value_or_absent
|
|
50
|
+
- status_code
|
|
51
|
+
- http_status
|
|
52
|
+
- http_status_in
|
|
53
|
+
- error_code
|
|
54
|
+
- on_401_require_header
|
|
55
|
+
- resource_equals_agent_url
|
|
56
|
+
- any_of
|
|
57
|
+
- refs_resolve
|
|
58
|
+
- a2a_submitted_artifact
|
|
59
|
+
- a2a_context_continuity
|
|
60
|
+
- field_less_than
|
|
61
|
+
- field_equals_context
|
|
62
|
+
- upstream_traffic
|
|
63
|
+
- canonical_format_satisfaction
|
|
64
|
+
|
|
65
|
+
# Cross-response check kinds — applied across the response set of a
|
|
66
|
+
# step that dispatches multiple requests under a runner contract that
|
|
67
|
+
# produces a structured multi-response observation, today either
|
|
68
|
+
# `parallel_dispatch_runner` (N parallel dispatches with the same
|
|
69
|
+
# idempotency_key) or `rate_limit_trip_runner` (sequential burst +
|
|
70
|
+
# replay). These kinds are NOT applicable to single-dispatch steps: a
|
|
71
|
+
# runner that applies them per-response produces nonsense (a single
|
|
72
|
+
# response trivially has cardinality 1 on any field). Runners MUST gate
|
|
73
|
+
# dispatch of these checks on the step declaring the appropriate
|
|
74
|
+
# `requires_contract:` and its accompanying parameter block
|
|
75
|
+
# (`parallel_dispatch:` or `rate_limit_trip:`); otherwise grade the
|
|
76
|
+
# validation `not_applicable` per the forward-compat clause.
|
|
77
|
+
#
|
|
78
|
+
# The `lint-storyboard-check-enum.cjs` lint reads BOTH this list and
|
|
79
|
+
# `authored_check_kinds` as the canonical published-time enum, so
|
|
80
|
+
# storyboards declaring either kind pass the typo gate.
|
|
81
|
+
cross_response_check_kinds:
|
|
82
|
+
- cross_response_field_equal
|
|
83
|
+
- cross_response_count_distinct
|
|
84
|
+
- replay_not_cached_rate_limit
|
|
85
|
+
|
|
86
|
+
# Conforming implementation: adcp-client PR #611
|
|
87
|
+
# (src/lib/testing/storyboard/types.ts — RunnerRequestRecord,
|
|
88
|
+
# RunnerResponseRecord, ValidationResult, RunnerSkipResult, etc.).
|
|
89
|
+
# The concrete shapes, redaction pattern, and header allowlist below are
|
|
90
|
+
# taken from that implementation.
|
|
91
|
+
|
|
92
|
+
# A storyboard step result is produced per step the runner executes. Each
|
|
93
|
+
# step result carries zero or more validation results — one per `check` in
|
|
94
|
+
# the storyboard's step.validations array, plus any transport-level check
|
|
95
|
+
# the runner performs (e.g., extraction path).
|
|
96
|
+
|
|
97
|
+
step_result:
|
|
98
|
+
description: |
|
|
99
|
+
Runners MUST emit one step result per executed step. Skipped steps MUST
|
|
100
|
+
include a skip result block. Failed steps MUST include at least one
|
|
101
|
+
validation result with passed: false. Not-selected steps are not step
|
|
102
|
+
results; they are reported in run_summary.not_selected with
|
|
103
|
+
selection_result records.
|
|
104
|
+
required_fields:
|
|
105
|
+
- storyboard_id # e.g. "capability_discovery"
|
|
106
|
+
- phase_id # e.g. "protocol_discovery"
|
|
107
|
+
- step_id # e.g. "get_capabilities"
|
|
108
|
+
- task # AdCP task name invoked, e.g. "get_adcp_capabilities"
|
|
109
|
+
- passed # boolean — all required validations passed
|
|
110
|
+
- duration_ms # wall-clock time for this step
|
|
111
|
+
- validations # array of validation_result objects (see below)
|
|
112
|
+
- extraction # transport extraction record (see below)
|
|
113
|
+
optional_fields:
|
|
114
|
+
- skip # skip_result block when the step was not run
|
|
115
|
+
# after being selected for this run
|
|
116
|
+
- error # transport-level error (no validations attempted)
|
|
117
|
+
- request # exact request the runner sent (see request block)
|
|
118
|
+
- response # exact response observed (see response block)
|
|
119
|
+
- notices # array of notice objects attached to this step's
|
|
120
|
+
# result — informational signals that MUST NOT
|
|
121
|
+
# change `passed`. See the notice block below for
|
|
122
|
+
# the field shape and the canonical first-day codes.
|
|
123
|
+
|
|
124
|
+
validation_result:
|
|
125
|
+
description: |
|
|
126
|
+
Every validation result — whether passed or failed — MUST carry the fields
|
|
127
|
+
below. Failed validations MUST include request, response, json_pointer,
|
|
128
|
+
expected, and actual unless the failure is transport-level (in which case
|
|
129
|
+
json_pointer, expected, and actual MAY be null and the step-level error
|
|
130
|
+
field carries the transport failure).
|
|
131
|
+
|
|
132
|
+
Forward compatibility: when a runner encounters an authored `check` value
|
|
133
|
+
it does not recognize (e.g., a storyboard declares a check type added in a
|
|
134
|
+
later spec minor version than the runner implements), the runner MUST emit
|
|
135
|
+
a validation_result with passed: true, check: <the unrecognized value>,
|
|
136
|
+
description: copied from the storyboard, and a `note` field describing the
|
|
137
|
+
coverage gap (e.g., "runner does not implement check type
|
|
138
|
+
'upstream_traffic' — graded as not_applicable to preserve forward
|
|
139
|
+
compatibility"). The result MUST contribute to a per-step `not_applicable`
|
|
140
|
+
counter the runner exposes alongside steps_passed/failed/skipped/not_selected, so
|
|
141
|
+
consumers can distinguish "runner is older than the storyboard" from
|
|
142
|
+
"storyboard validations passed cleanly." Runners MUST NOT fail steps
|
|
143
|
+
on unrecognized check values — additive check-type extensions are
|
|
144
|
+
explicitly part of the spec evolution model.
|
|
145
|
+
required_fields:
|
|
146
|
+
- check # Validation kind. For storyboard-authored checks,
|
|
147
|
+
# mirrors the storyboard's step.validations[].check:
|
|
148
|
+
# response_schema | field_present |
|
|
149
|
+
# field_absent | envelope_field_present |
|
|
150
|
+
# envelope_field_absent | field_value |
|
|
151
|
+
# field_value_or_absent | status_code | http_status |
|
|
152
|
+
# http_status_in | error_code | on_401_require_header |
|
|
153
|
+
# resource_equals_agent_url | any_of | refs_resolve |
|
|
154
|
+
# a2a_submitted_artifact | field_less_than |
|
|
155
|
+
# field_equals_context | upstream_traffic |
|
|
156
|
+
# canonical_format_satisfaction |
|
|
157
|
+
# cross_response_field_equal |
|
|
158
|
+
# cross_response_count_distinct (the last two are
|
|
159
|
+
# cross-response checks; see cross_response_check_kinds
|
|
160
|
+
# above and storyboard-schema.yaml > Cross-response
|
|
161
|
+
# assertions for semantics).
|
|
162
|
+
#
|
|
163
|
+
# For runner-synthesized grading (not authored in the
|
|
164
|
+
# storyboard validations array, generated by the runner
|
|
165
|
+
# after the authored checks complete):
|
|
166
|
+
# capture_path_not_resolvable | unresolved_substitution
|
|
167
|
+
#
|
|
168
|
+
# See storyboard-schema.yaml > "Runner grading codes"
|
|
169
|
+
# for the semantics of each synthesized code, and
|
|
170
|
+
# storyboard-schema.yaml > "upstream_traffic" for the
|
|
171
|
+
# authored upstream-side-effect check.
|
|
172
|
+
- passed # boolean
|
|
173
|
+
- description # human-readable description copied from the
|
|
174
|
+
# storyboard validation entry (so the implementor
|
|
175
|
+
# sees the same text the author wrote).
|
|
176
|
+
# For synthesized checks, the runner MUST generate
|
|
177
|
+
# a descriptive string naming the affected path or
|
|
178
|
+
# substitution token.
|
|
179
|
+
required_on_failure:
|
|
180
|
+
- request # exact request the runner sent (see request block).
|
|
181
|
+
# NULL for unresolved_substitution — the request was
|
|
182
|
+
# never sent (pre-wire failure).
|
|
183
|
+
# For upstream_traffic: the comply_test_controller
|
|
184
|
+
# query_upstream_traffic request the runner issued,
|
|
185
|
+
# not the storyboard step's AdCP request.
|
|
186
|
+
- response # exact response observed (see response block).
|
|
187
|
+
# NULL for unresolved_substitution — no response
|
|
188
|
+
# exists (pre-wire failure).
|
|
189
|
+
# For upstream_traffic: the query_upstream_traffic
|
|
190
|
+
# response carrying the recorded_calls array.
|
|
191
|
+
- json_pointer # RFC 6901 pointer to the failing field in the
|
|
192
|
+
# response, or the request for input-level
|
|
193
|
+
# failures. Null when the failure is transport-level
|
|
194
|
+
# and no payload was returned. Also null for
|
|
195
|
+
# unresolved_substitution (pre-wire; no response
|
|
196
|
+
# path implicated) — see notes.synthesized_checks.
|
|
197
|
+
# For upstream_traffic, points into the recorded_calls
|
|
198
|
+
# array (e.g., "/recorded_calls/0/payload") when a
|
|
199
|
+
# specific call's payload failed payload_must_contain;
|
|
200
|
+
# null when the failure is a count mismatch
|
|
201
|
+
# (no specific call implicated).
|
|
202
|
+
- expected # machine-readable expected value:
|
|
203
|
+
# response_schema → schema $id that was applied
|
|
204
|
+
# field_value → expected value (any JSON type)
|
|
205
|
+
# field_value_or_absent → value or allowed_values array
|
|
206
|
+
# from the storyboard validation
|
|
207
|
+
# field_present → the path that should resolve
|
|
208
|
+
# field_absent → null (the field must not be present)
|
|
209
|
+
# envelope_field_present → the path that should resolve
|
|
210
|
+
# in the protocol envelope
|
|
211
|
+
# envelope_field_absent → null (the envelope field must
|
|
212
|
+
# not be present)
|
|
213
|
+
# status_code → expected status
|
|
214
|
+
# error_code → expected error code
|
|
215
|
+
# any_of → array of acceptable forms
|
|
216
|
+
# field_less_than → comparand the field MUST be
|
|
217
|
+
# strictly less than. When the
|
|
218
|
+
# comparand was resolved from
|
|
219
|
+
# `context_key`, the runtime
|
|
220
|
+
# value (a finite number) is
|
|
221
|
+
# captured here; when from a
|
|
222
|
+
# literal `value`, that literal.
|
|
223
|
+
# field_equals_context → comparand the field MUST
|
|
224
|
+
# deep-equal. The runtime value
|
|
225
|
+
# resolved from
|
|
226
|
+
# `validation.context_key` in the
|
|
227
|
+
# storyboard accumulator.
|
|
228
|
+
# capture_path_not_resolvable → the context_outputs path
|
|
229
|
+
# string that failed to resolve
|
|
230
|
+
# (e.g. "signals[0].signal_agent_segment_id")
|
|
231
|
+
# unresolved_substitution → the unresolved token string
|
|
232
|
+
# (e.g. "$context.first_signal_agent_segment_id"
|
|
233
|
+
# or "{{prior_step.search.id}}")
|
|
234
|
+
# upstream_traffic → object with the declared
|
|
235
|
+
# assertion: { min_count,
|
|
236
|
+
# endpoint_pattern, payload_must_contain,
|
|
237
|
+
# identifier_paths, purpose_filter,
|
|
238
|
+
# since, attestation_mode_required } —
|
|
239
|
+
# whichever fields the storyboard set.
|
|
240
|
+
# canonical_format_satisfaction
|
|
241
|
+
# → object { accepted, local_satisfied }
|
|
242
|
+
# where accepted is the boolean value
|
|
243
|
+
# from the storyboard validation and
|
|
244
|
+
# local_satisfied mirrors the expected
|
|
245
|
+
# local package/product satisfaction
|
|
246
|
+
# verdict.
|
|
247
|
+
# cross_response_field_equal
|
|
248
|
+
# → object { path } — the JSON path
|
|
249
|
+
# asserted equal across every
|
|
250
|
+
# resolved response in the step's
|
|
251
|
+
# dispatch set.
|
|
252
|
+
# cross_response_count_distinct
|
|
253
|
+
# → object { path, allowed_values } —
|
|
254
|
+
# the path scanned, plus the
|
|
255
|
+
# permitted cardinalities of
|
|
256
|
+
# distinct values observed at
|
|
257
|
+
# that path across the resolved
|
|
258
|
+
# response set (typically [1]
|
|
259
|
+
# for rule-9 tests).
|
|
260
|
+
- actual # machine-readable actual value observed:
|
|
261
|
+
# response_schema → array of schema errors
|
|
262
|
+
# (each { instance_path,
|
|
263
|
+
# schema_path, keyword,
|
|
264
|
+
# message })
|
|
265
|
+
# field_value → actual value (any JSON type)
|
|
266
|
+
# field_value_or_absent → actual value (any JSON type);
|
|
267
|
+
# null when the field was absent
|
|
268
|
+
# field_present → null (the field was missing)
|
|
269
|
+
# or the observed non-object
|
|
270
|
+
# value
|
|
271
|
+
# field_absent → observed value at path (any JSON
|
|
272
|
+
# type); emitted only on failure
|
|
273
|
+
# envelope_field_present → null (the field was missing)
|
|
274
|
+
# or the observed non-object
|
|
275
|
+
# value (scoped to envelope)
|
|
276
|
+
# envelope_field_absent → observed value at path (any JSON
|
|
277
|
+
# type); emitted only on failure
|
|
278
|
+
# and scoped to envelope
|
|
279
|
+
# field_less_than → the observed value at `path`
|
|
280
|
+
# (number when resolvable, null
|
|
281
|
+
# when the field was missing).
|
|
282
|
+
# field_equals_context → the observed value at `path`
|
|
283
|
+
# (any JSON type, null when the
|
|
284
|
+
# field was missing).
|
|
285
|
+
# capture_path_not_resolvable → the value that was
|
|
286
|
+
# resolved at the path, or null
|
|
287
|
+
# when the path did not exist.
|
|
288
|
+
# Runners MUST treat null, "",
|
|
289
|
+
# and structurally-absent paths
|
|
290
|
+
# as equally non-resolvable for
|
|
291
|
+
# this check — capture of a null
|
|
292
|
+
# or empty-string value produces
|
|
293
|
+
# fabricated state and is as
|
|
294
|
+
# incorrect as a missing path.
|
|
295
|
+
# unresolved_substitution → null (no response payload
|
|
296
|
+
# available at substitution time)
|
|
297
|
+
# upstream_traffic → object summarizing what was
|
|
298
|
+
# observed: { matched_count,
|
|
299
|
+
# total_calls, missing_payload_paths,
|
|
300
|
+
# missing_identifier_values }.
|
|
301
|
+
# The full recorded_calls array
|
|
302
|
+
# lives in `response.payload`;
|
|
303
|
+
# canonical_format_satisfaction
|
|
304
|
+
# → object { accepted, local_satisfied,
|
|
305
|
+
# rejection? } where accepted is the
|
|
306
|
+
# observed task success boolean,
|
|
307
|
+
# local_satisfied is the runner's
|
|
308
|
+
# package/product satisfaction verdict,
|
|
309
|
+
# and rejection summarizes format-related
|
|
310
|
+
# rejection evidence when the task failed.
|
|
311
|
+
# cross_response_field_equal
|
|
312
|
+
# → object { observed_values: [...] } —
|
|
313
|
+
# the values observed at `path` on
|
|
314
|
+
# each resolved response, in dispatch
|
|
315
|
+
# order. Empty when no response
|
|
316
|
+
# carried the path.
|
|
317
|
+
# cross_response_count_distinct
|
|
318
|
+
# → object { observed_cardinality,
|
|
319
|
+
# observed_values: [...] } — the
|
|
320
|
+
# number of distinct values seen at
|
|
321
|
+
# `path` across the resolved response
|
|
322
|
+
# set, plus the values themselves.
|
|
323
|
+
# `actual` is the diagnostic summary.
|
|
324
|
+
- schema_id # $id of the response schema applied. Required
|
|
325
|
+
# when check == response_schema, null otherwise.
|
|
326
|
+
# MUST be null for capture_path_not_resolvable,
|
|
327
|
+
# unresolved_substitution, upstream_traffic, and
|
|
328
|
+
# canonical_format_satisfaction.
|
|
329
|
+
- schema_url # Resolvable URL the implementor can fetch to
|
|
330
|
+
# validate locally. Required when
|
|
331
|
+
# check == response_schema, null otherwise.
|
|
332
|
+
# MUST be null for capture_path_not_resolvable,
|
|
333
|
+
# unresolved_substitution, upstream_traffic, and
|
|
334
|
+
# canonical_format_satisfaction.
|
|
335
|
+
notes:
|
|
336
|
+
synthesized_checks: |
|
|
337
|
+
capture_path_not_resolvable and unresolved_substitution are emitted by
|
|
338
|
+
the runner after storyboard-authored checks complete. They MUST appear in
|
|
339
|
+
the step's validations array so the "failed steps MUST include at least
|
|
340
|
+
one validation result with passed: false" invariant is satisfied.
|
|
341
|
+
For capture_path_not_resolvable, json_pointer MUST be the RFC 6901 form
|
|
342
|
+
of the context_outputs path that failed to resolve (e.g. "/signals/0/
|
|
343
|
+
signal_agent_segment_id"). For unresolved_substitution, json_pointer MUST
|
|
344
|
+
be null (the substitution is pre-wire and no response path is implicated).
|
|
345
|
+
cross_step_comparison_checks: |
|
|
346
|
+
field_less_than and field_equals_context are authored checks that compare
|
|
347
|
+
a field on this step's response against a value from the storyboard
|
|
348
|
+
accumulator (populated by prior steps' `context_outputs`). Three
|
|
349
|
+
consumer-facing rendering rules runners MUST follow:
|
|
350
|
+
|
|
351
|
+
1. `expected` carries the RESOLVED RUNTIME comparand, not the storyboard's
|
|
352
|
+
`context_key` string. A consumer diffing `validation_result.expected`
|
|
353
|
+
across two storyboard runs will see different values when the prior
|
|
354
|
+
step's response differed — that's load-bearing for diagnosing
|
|
355
|
+
filtered-vs-baseline regressions. The `context_key` field on the
|
|
356
|
+
storyboard validation is authoring-time metadata; it is NOT echoed
|
|
357
|
+
into validation_result.
|
|
358
|
+
|
|
359
|
+
2. `context_key_absent` observation: when the storyboard sets
|
|
360
|
+
`context_key` and the named entry is missing from the accumulator
|
|
361
|
+
(the prior capturing step was legitimately skipped on a branch-set
|
|
362
|
+
path), the validation_result MUST carry `passed: true` with an
|
|
363
|
+
`observations: [<descriptive string>]` entry naming the absent key.
|
|
364
|
+
`expected` and `actual` MAY be omitted in this path. A genuinely
|
|
365
|
+
missing capture (prior step ran but its capture path didn't resolve)
|
|
366
|
+
is NOT this case — that grades `capture_path_not_resolvable` ON THE
|
|
367
|
+
PRIOR STEP per the synthesized_checks rule.
|
|
368
|
+
|
|
369
|
+
3. Step-ordering dependency: cross-step comparison checks read from the
|
|
370
|
+
accumulator built up over prior step executions. Runners that
|
|
371
|
+
parallelize step execution MUST honour the storyboard's declared
|
|
372
|
+
ordering for any step that names a `context_key` referencing an
|
|
373
|
+
earlier step's `context_outputs`.
|
|
374
|
+
upstream_traffic_check: |
|
|
375
|
+
upstream_traffic is an authored check (declared in the storyboard's
|
|
376
|
+
step.validations array) that asserts side-effects against a sandbox the
|
|
377
|
+
adopter exposes through the comply_test_controller tool's
|
|
378
|
+
query_upstream_traffic scenario. The runner queries the controller after
|
|
379
|
+
the step completes, scoped to traffic recorded since the step's request
|
|
380
|
+
timestamp, and applies the assertion. Adopters who do not advertise
|
|
381
|
+
query_upstream_traffic in list_scenarios grade the check
|
|
382
|
+
not_applicable (skip_result.reason: missing_test_controller with detail
|
|
383
|
+
naming the scenario) — the contract is opt-in by adopter capability.
|
|
384
|
+
See storyboard-schema.yaml > "upstream_traffic" for the authored shape
|
|
385
|
+
and comply-test-controller-request.json > query_upstream_traffic for
|
|
386
|
+
the controller-side query contract.
|
|
387
|
+
upstream_traffic_timestamp_boundary: |
|
|
388
|
+
The runner's lower-bound timestamp for query_upstream_traffic MUST be
|
|
389
|
+
the runner's own wall-clock at the moment it issued the storyboard
|
|
390
|
+
step's AdCP request (or the prior step's request timestamp when the
|
|
391
|
+
storyboard declares `since: <prior_step_id>`). The bound is INCLUSIVE.
|
|
392
|
+
Runners SHOULD subtract a clock-skew tolerance (50ms minimum, 250ms
|
|
393
|
+
recommended) before sending the bound to the controller, so a recorded
|
|
394
|
+
call timestamped microseconds before the runner's clock measurement is
|
|
395
|
+
not silently excluded. Controllers MUST emit recorded_calls timestamps
|
|
396
|
+
matching the wall clock at outbound-request-send time (not log-flush
|
|
397
|
+
time) and MUST order them monotonically non-decreasing. Runners MUST
|
|
398
|
+
attribute calls to a step using their own clock-bracket of when they
|
|
399
|
+
issued and received the AdCP request, not the controller's
|
|
400
|
+
since_timestamp echo (which is informational only — see
|
|
401
|
+
comply-test-controller-response.json > UpstreamTrafficSuccess >
|
|
402
|
+
since_timestamp).
|
|
403
|
+
upstream_traffic_threat_model: |
|
|
404
|
+
upstream_traffic raises the bar against UNINTENTIONAL façades —
|
|
405
|
+
adapters that satisfy AdCP schema requirements with synthetic
|
|
406
|
+
placeholders without forwarding payloads upstream. It is NOT an
|
|
407
|
+
adversarial integrity check. Adopters self-report their own traffic
|
|
408
|
+
through query_upstream_traffic; a determined façade can fabricate
|
|
409
|
+
recorded_calls entries. Spec consumers — compliance dashboards,
|
|
410
|
+
adapter directories, conformance-tier UIs — MUST NOT present
|
|
411
|
+
upstream_traffic passing as cryptographic proof of adapter behavior.
|
|
412
|
+
The conformance value is "unintentional façades fail this check"; an
|
|
413
|
+
adversarial-integrity attestation path (signed traffic-summary
|
|
414
|
+
endpoint, agent-side telemetry digest, etc.) is its own future RFC,
|
|
415
|
+
not this contract.
|
|
416
|
+
upstream_traffic_digest_mode: |
|
|
417
|
+
Recorded calls returned in `attestation_mode: digest` (see
|
|
418
|
+
comply-test-controller-response.json > UpstreamTrafficSuccess >
|
|
419
|
+
recorded_calls > DigestAttestation) swap raw payload introspection
|
|
420
|
+
for digest-based echo verification:
|
|
421
|
+
- `recorded_calls[].payload_length` MUST be the byte length of the
|
|
422
|
+
exact payload bytes covered by `payload_digest_sha256`: RFC 8785
|
|
423
|
+
(JCS) canonical bytes for JSON-shaped content after redaction, or
|
|
424
|
+
post-redaction raw body bytes for non-JSON content. It is not the
|
|
425
|
+
original outbound body length before JSON parsing, redaction, or
|
|
426
|
+
canonicalization.
|
|
427
|
+
- The runner verifies `identifier_paths` by computing SHA-256 of each
|
|
428
|
+
resolved identifier value, sending the digests in the controller
|
|
429
|
+
query's `params.identifier_value_digests`, and reading the
|
|
430
|
+
per-digest `found: true | false` proof from
|
|
431
|
+
`recorded_calls[].identifier_match_proofs[]`. Plaintext
|
|
432
|
+
identifiers never reach the controller in this path.
|
|
433
|
+
- `payload_must_contain` arbitrary path assertions are NOT
|
|
434
|
+
supported in digest mode — the runner emits a per-affected-entry
|
|
435
|
+
validation_result with `passed: true`, `check: payload_must_contain`,
|
|
436
|
+
and a `note` field explaining the mode constraint, contributing
|
|
437
|
+
to `validations_not_applicable` on run_summary (NOT
|
|
438
|
+
steps_failed). The same validation continues to grade against
|
|
439
|
+
recorded_calls returned in raw mode, so a mixed-mode response
|
|
440
|
+
(some calls raw, some digest) produces partial coverage rather
|
|
441
|
+
than blanket not_applicable.
|
|
442
|
+
- If the controller cannot produce a digest-mode upstream_traffic
|
|
443
|
+
response because the parsed JSON-like value tree contains a
|
|
444
|
+
non-finite numeric value (`NaN`, `+Infinity`, or `-Infinity`),
|
|
445
|
+
it MUST NOT coerce that value to `null`, a string, or any other
|
|
446
|
+
placeholder for digest computation; it returns ControllerError
|
|
447
|
+
with error code `JCS_NON_FINITE_NUMBER`. The runner emits the affected
|
|
448
|
+
upstream_traffic validation_result with `passed: true` and a
|
|
449
|
+
`note` citing the RFC 8785/JCS non-finite-number constraint,
|
|
450
|
+
contributing to `validations_not_applicable` on run_summary
|
|
451
|
+
(NOT steps_failed).
|
|
452
|
+
- `min_count` and `endpoint_pattern` are unchanged — count and URL
|
|
453
|
+
matching work identically in both modes.
|
|
454
|
+
Storyboards that strictly require raw introspection set
|
|
455
|
+
`attestation_mode_required: "raw"` on the storyboard upstream_traffic
|
|
456
|
+
check; runners then grade calls returned in digest mode as
|
|
457
|
+
not_applicable for the entire check (not just per-assertion). Use
|
|
458
|
+
sparingly — see storyboard-schema.yaml > "upstream_traffic" >
|
|
459
|
+
`attestation_mode_required` for the rationale.
|
|
460
|
+
response_schema_validator_semantics: |
|
|
461
|
+
Runners MUST apply the referenced JSON schema using a JSON Schema
|
|
462
|
+
draft-07 compliant validator configured to honour the schema's own
|
|
463
|
+
`additionalProperties` declaration without global override. When a
|
|
464
|
+
schema or any sub-schema reached via `$ref`, `allOf`, `oneOf`, or
|
|
465
|
+
`anyOf` declares `"additionalProperties": true` (explicitly or by
|
|
466
|
+
omission — draft-07 default is `true`), the runner MUST NOT fail a
|
|
467
|
+
response that includes fields beyond those enumerated in `properties`.
|
|
468
|
+
In draft-07, `oneOf` branch-selection does not grant a validator
|
|
469
|
+
licence to apply stricter `additionalProperties` constraints than
|
|
470
|
+
those declared on the selected branch.
|
|
471
|
+
|
|
472
|
+
Configuring the validator in a way that contradicts the schema's own
|
|
473
|
+
`additionalProperties` declaration is a conformance violation of this
|
|
474
|
+
contract (e.g., AJV `removeAdditional: 'all'` or a schema-level
|
|
475
|
+
`additionalProperties: false` override; Zod `.strict()` on a derived
|
|
476
|
+
schema object). A seller returning a spec-valid response with optional
|
|
477
|
+
or newly-added fields (such as `authorization` or `sandbox` on
|
|
478
|
+
sync-accounts items) is conformant. A runner that fails such a
|
|
479
|
+
response because its internal schema representation is stricter than
|
|
480
|
+
the canonical JSON Schema produces a false negative that blocks
|
|
481
|
+
legitimate conformance progress.
|
|
482
|
+
|
|
483
|
+
The AdCP spec-side lint (`scripts/lint-storyboard-response-schema.cjs`,
|
|
484
|
+
AJV `strict: false`, no `removeAdditional`) sets the precedent. This
|
|
485
|
+
clause makes the same requirement normative for all conforming runners.
|
|
486
|
+
Any runner correctly implementing draft-07 JSON Schema validation
|
|
487
|
+
already satisfies it.
|
|
488
|
+
optional_fields:
|
|
489
|
+
- remediation # runner-suggested fix when the failure maps to
|
|
490
|
+
# a well-known cause (e.g., "agent did not echo
|
|
491
|
+
# context.correlation_id — see
|
|
492
|
+
# docs/building/implementation/task-lifecycle")
|
|
493
|
+
- severity # "required" | "advisory" — copied from the
|
|
494
|
+
# storyboard validation entry's severity field
|
|
495
|
+
# (default: "required"). When "advisory", a
|
|
496
|
+
# passed: false validation_result MUST NOT
|
|
497
|
+
# cause its step to grade as failed; the step
|
|
498
|
+
# grades on its remaining required validations.
|
|
499
|
+
# Advisory failures contribute to
|
|
500
|
+
# validations_advisory_failed on run_summary
|
|
501
|
+
# and MUST NOT contribute to steps_failed,
|
|
502
|
+
# validations_failed, or any other
|
|
503
|
+
# required-failure counter — the two counter
|
|
504
|
+
# surfaces are deliberately separate so a
|
|
505
|
+
# consumer aggregating "passed: false" across
|
|
506
|
+
# validations_failed never double-counts
|
|
507
|
+
# advisory results.
|
|
508
|
+
#
|
|
509
|
+
# Rendered-output rule: when a runner emits
|
|
510
|
+
# advisory results to a human-facing surface
|
|
511
|
+
# (chat transcripts, markdown reports,
|
|
512
|
+
# compliance dashboards, LLM summaries),
|
|
513
|
+
# advisory entries MUST be visually
|
|
514
|
+
# distinguished from required failures —
|
|
515
|
+
# prefix with the literal `[ADVISORY]`,
|
|
516
|
+
# render in a muted style, or section them
|
|
517
|
+
# under a separate "advisory findings"
|
|
518
|
+
# header. The machine-readable step_result
|
|
519
|
+
# carries severity verbatim for programmatic
|
|
520
|
+
# consumers; this rule applies only to
|
|
521
|
+
# rendered surfaces. Without this, a façade
|
|
522
|
+
# that declares its anti-façade validations
|
|
523
|
+
# as advisory produces a stream of
|
|
524
|
+
# `passed: false` entries indistinguishable
|
|
525
|
+
# from required failures, eroding the
|
|
526
|
+
# conformance signal.
|
|
527
|
+
#
|
|
528
|
+
# See storyboard-schema.yaml > "Validation"
|
|
529
|
+
# for the author-side semantics and use case
|
|
530
|
+
# (rollout gating during runner adoption
|
|
531
|
+
# windows).
|
|
532
|
+
- severity_promoted_from_advisory
|
|
533
|
+
# boolean | absent. Tri-state contract:
|
|
534
|
+
# true — storyboard declared
|
|
535
|
+
# expires_after_version AND
|
|
536
|
+
# runner_capability_version >=
|
|
537
|
+
# that value, so the runner
|
|
538
|
+
# promoted severity to "required"
|
|
539
|
+
# at execution time. `severity`
|
|
540
|
+
# MUST also be "required" (the
|
|
541
|
+
# promoted value).
|
|
542
|
+
# false — storyboard declared
|
|
543
|
+
# expires_after_version but
|
|
544
|
+
# runner_capability_version is
|
|
545
|
+
# older, so promotion did not fire.
|
|
546
|
+
# `severity` is the storyboard's
|
|
547
|
+
# declared advisory.
|
|
548
|
+
# absent — storyboard did not declare
|
|
549
|
+
# expires_after_version (severity
|
|
550
|
+
# applied verbatim) OR the check
|
|
551
|
+
# grades not_applicable due to
|
|
552
|
+
# forward-compat (no grading
|
|
553
|
+
# occurred, so no promotion was
|
|
554
|
+
# evaluated; per
|
|
555
|
+
# storyboard-schema.yaml >
|
|
556
|
+
# expires_after_version
|
|
557
|
+
# forward-compat ordering rule).
|
|
558
|
+
# The tri-state is required so consumers can
|
|
559
|
+
# distinguish "promoted" from "not promoted
|
|
560
|
+
# because runner is too old" from "not
|
|
561
|
+
# applicable" without re-reading the
|
|
562
|
+
# storyboard. Reports SHOULD render the
|
|
563
|
+
# promotion provenance on the true case —
|
|
564
|
+
# e.g., "[REQUIRED — was advisory through
|
|
565
|
+
# capability v{expires_after_version};
|
|
566
|
+
# promoted at v{runner_capability_version}]".
|
|
567
|
+
|
|
568
|
+
request:
|
|
569
|
+
description: |
|
|
570
|
+
Exact request the runner sent, per transport. Runners MUST redact secrets
|
|
571
|
+
before emission — see the `security` block below.
|
|
572
|
+
required_fields:
|
|
573
|
+
- transport # "mcp" | "a2a" | "http"
|
|
574
|
+
- operation # task/tool/skill name actually invoked (matches
|
|
575
|
+
# step.task after any test-kit interpolation)
|
|
576
|
+
- payload # fully-resolved JSON payload after test-kit
|
|
577
|
+
# substitution and context injection, with
|
|
578
|
+
# secret-bearing fields replaced per the
|
|
579
|
+
# redaction policy in the security block.
|
|
580
|
+
optional_fields:
|
|
581
|
+
- headers # Runners SHOULD NOT populate this field by
|
|
582
|
+
# default — see security.request_headers. The
|
|
583
|
+
# field exists for future auth-override captures
|
|
584
|
+
# that carry a fully-redacted form.
|
|
585
|
+
- url # full URL for http/a2a; omit for stdio MCP
|
|
586
|
+
|
|
587
|
+
response:
|
|
588
|
+
description: |
|
|
589
|
+
Exact response observed from the agent, per transport.
|
|
590
|
+
required_fields:
|
|
591
|
+
- transport # "mcp" | "a2a" | "http"
|
|
592
|
+
- payload # MCP: { isError, structuredContent, content }
|
|
593
|
+
# A2A: the Task object — record task.status.state
|
|
594
|
+
# alongside payload. Extract from
|
|
595
|
+
# task.artifacts[0].parts[] DataPart for final
|
|
596
|
+
# states and task.status.message.parts[] for
|
|
597
|
+
# interim states (per
|
|
598
|
+
# docs/building/implementation/a2a-response-extraction.mdx).
|
|
599
|
+
# http: parsed body
|
|
600
|
+
optional_fields:
|
|
601
|
+
- status # HTTP status where applicable
|
|
602
|
+
- headers # observed response headers, filtered through
|
|
603
|
+
# the allowlist in security.response_headers
|
|
604
|
+
- duration_ms # wall-clock time for this request
|
|
605
|
+
|
|
606
|
+
extraction:
|
|
607
|
+
description: |
|
|
608
|
+
Runners MUST follow the MCP response-extraction algorithm at
|
|
609
|
+
docs/building/implementation/mcp-response-extraction.mdx and the A2A
|
|
610
|
+
equivalent. When both structuredContent and content[].text are present,
|
|
611
|
+
structuredContent wins. Recording the path that was actually used lets
|
|
612
|
+
the implementor distinguish a runner extraction bug from an agent bug.
|
|
613
|
+
required_fields:
|
|
614
|
+
- path # "structured_content" | "text_fallback" |
|
|
615
|
+
# "error" | "none"
|
|
616
|
+
optional_fields:
|
|
617
|
+
- note # e.g. "structuredContent contained only
|
|
618
|
+
# adcp_error — treated as error"
|
|
619
|
+
|
|
620
|
+
security:
|
|
621
|
+
description: |
|
|
622
|
+
Runner output is consumed in compliance reports, chat transcripts, and
|
|
623
|
+
shared dashboards where credentials or breadcrumbs a hostile agent plants
|
|
624
|
+
in a response must not surface. A runner claiming contract conformance
|
|
625
|
+
without the rules below could leak tokens through a compliant-looking
|
|
626
|
+
report — defeating the contract's purpose. These rules are normative.
|
|
627
|
+
|
|
628
|
+
payload_redaction:
|
|
629
|
+
description: |
|
|
630
|
+
Runners MUST recursively redact key-value pairs from request.payload
|
|
631
|
+
and response.payload before emitting the step result. Values at keys
|
|
632
|
+
matching the pattern below are replaced with the literal string
|
|
633
|
+
"[redacted]". Matching is case-insensitive and applies at any depth.
|
|
634
|
+
pattern: |
|
|
635
|
+
^(authorization|credentials?|token|api[_-]?key|password|secret|
|
|
636
|
+
client[_-]secret|refresh[_-]token|access[_-]token|bearer|
|
|
637
|
+
session[_-]token|offering[_-]token|cookie|set[_-]cookie)$
|
|
638
|
+
notes: |
|
|
639
|
+
The pattern above is the MINIMUM floor taken from the adcp-client#611
|
|
640
|
+
conforming implementation. Runners MAY extend it for operator-
|
|
641
|
+
specific key names (e.g., internal vendor headers) but MUST NOT
|
|
642
|
+
narrow it. Redaction happens after the payload is serialized for
|
|
643
|
+
the report, not at transport time — the wire request carries real
|
|
644
|
+
credentials; the emitted record does not.
|
|
645
|
+
|
|
646
|
+
response_headers:
|
|
647
|
+
description: |
|
|
648
|
+
Response headers MUST pass through an allowlist before emission. Any
|
|
649
|
+
header not in the allowlist MUST be dropped (not redacted — absent).
|
|
650
|
+
Dropping rather than redacting avoids publishing the set of header
|
|
651
|
+
names a hostile agent added, which itself can be a breadcrumb.
|
|
652
|
+
allowlist:
|
|
653
|
+
- content-type
|
|
654
|
+
- content-length
|
|
655
|
+
- content-encoding
|
|
656
|
+
- www-authenticate
|
|
657
|
+
- location
|
|
658
|
+
- retry-after
|
|
659
|
+
- x-request-id
|
|
660
|
+
- x-correlation-id
|
|
661
|
+
notes: |
|
|
662
|
+
www-authenticate is retained because it's load-bearing for auth-probe
|
|
663
|
+
validations (on_401_require_header). Matching is case-insensitive.
|
|
664
|
+
|
|
665
|
+
request_headers:
|
|
666
|
+
description: |
|
|
667
|
+
Runners SHOULD NOT populate request.headers. A runner that builds
|
|
668
|
+
`Authorization: Bearer <token>` headers in-flight would leak the token
|
|
669
|
+
by echoing the observed request into a shared report. When a runner
|
|
670
|
+
does populate request.headers (e.g., for auth-override probes that
|
|
671
|
+
intentionally send bogus credentials), values at keys matching the
|
|
672
|
+
payload_redaction pattern MUST be replaced with "[redacted]" and all
|
|
673
|
+
other headers MUST pass through the response_headers allowlist.
|
|
674
|
+
|
|
675
|
+
rendered_output_fencing:
|
|
676
|
+
description: |
|
|
677
|
+
Several validation_result and skip_result fields carry strings whose
|
|
678
|
+
origin is not the runner: the agent under test, the storyboard author,
|
|
679
|
+
or an adopter-supplied test controller. When a runner renders these
|
|
680
|
+
into a shared surface (chat transcript, markdown report, summary fed
|
|
681
|
+
to another LLM), the strings MUST be fenced with a nonce or otherwise
|
|
682
|
+
isolated so a hostile message cannot inject instructions into a
|
|
683
|
+
downstream summarizer. This applies to rendered output, not to the
|
|
684
|
+
machine-readable step_result — raw strings stay in the JSON for
|
|
685
|
+
programmatic consumers.
|
|
686
|
+
|
|
687
|
+
Load-bearing fields that MUST be fenced when rendered:
|
|
688
|
+
- validation_result.error (transport-level errors,
|
|
689
|
+
agent-controlled when the
|
|
690
|
+
error message is echoed)
|
|
691
|
+
- validation_result.actual (agent-controlled response
|
|
692
|
+
values, including string
|
|
693
|
+
forms)
|
|
694
|
+
- validation_result.description (storyboard-author-controlled
|
|
695
|
+
— copied verbatim from the
|
|
696
|
+
storyboard validation entry)
|
|
697
|
+
- validation_result.note (runner-generated but
|
|
698
|
+
interpolates the
|
|
699
|
+
storyboard's unrecognized
|
|
700
|
+
check value verbatim — see
|
|
701
|
+
forward-compat clause above)
|
|
702
|
+
- skip_result.detail (runner-generated but
|
|
703
|
+
interpolates storyboard
|
|
704
|
+
IDs and adopter-supplied
|
|
705
|
+
strings)
|
|
706
|
+
- response.payload (for upstream_traffic checks)
|
|
707
|
+
(carries recorded_calls[]
|
|
708
|
+
where url, payload, and
|
|
709
|
+
endpoint are all
|
|
710
|
+
agent-controlled — a
|
|
711
|
+
hostile adapter that hits
|
|
712
|
+
an attacker-controlled URL
|
|
713
|
+
plants the URL string in
|
|
714
|
+
the payload, and a
|
|
715
|
+
hostile adopter controller
|
|
716
|
+
returns whatever it wants)
|
|
717
|
+
|
|
718
|
+
Inversion rule: any field whose value is copied from storyboard input,
|
|
719
|
+
agent-under-test output, or an adopter-supplied test controller MUST be
|
|
720
|
+
fenced when rendered. Runner-generated identifiers (step_id, schema_id,
|
|
721
|
+
check enum values from the spec's known list) are exempt.
|
|
722
|
+
|
|
723
|
+
Advisory-severity differentiation: validation_result entries with
|
|
724
|
+
severity: advisory MUST render visually distinct from required-severity
|
|
725
|
+
results (literal `[ADVISORY]` prefix, muted style, or grouped under a
|
|
726
|
+
separate "advisory findings" section). This is orthogonal to fencing —
|
|
727
|
+
both rules apply to advisory results that carry agent- or
|
|
728
|
+
storyboard-controlled strings. See validation_result.severity above for
|
|
729
|
+
the rationale (façade-resistance: a façade declaring its anti-façade
|
|
730
|
+
validations as advisory must not blend visually into required failures).
|
|
731
|
+
|
|
732
|
+
Promotion-provenance rendering: when a renderer constructs human
|
|
733
|
+
copy describing severity_promoted_from_advisory: true (e.g., "was
|
|
734
|
+
advisory through capability v{expires_after_version}; promoted at
|
|
735
|
+
v{runner_capability_version}"), the storyboard-supplied
|
|
736
|
+
expires_after_version value MUST be fenced. The semver lint rejects
|
|
737
|
+
malformed values at publish time, but defense-in-depth treats the
|
|
738
|
+
string as untrusted-author input when interpolated into LLM-rendered
|
|
739
|
+
surfaces. permanent_advisory.reason is also storyboard-author-controlled
|
|
740
|
+
and MUST be fenced when rendered.
|
|
741
|
+
|
|
742
|
+
skip_result:
|
|
743
|
+
description: |
|
|
744
|
+
When a track, storyboard, phase, or step is skipped, runners MUST
|
|
745
|
+
distinguish between the reasons below so an implementor knows whether
|
|
746
|
+
the skip is informative (the agent did not claim the protocol) or
|
|
747
|
+
masking (the runner could not apply the storyboard even though the
|
|
748
|
+
agent claimed the protocol).
|
|
749
|
+
|
|
750
|
+
Selection is separate from skipping. If the caller asks for a narrower
|
|
751
|
+
suite or run mode (for example, "Sandbox only") and the runner excludes
|
|
752
|
+
live-only storyboards before execution, those items are `not_selected`,
|
|
753
|
+
not `skipped`. A `skip_result` is emitted only after an item was selected
|
|
754
|
+
for this run and the runner could not execute it because an applicability
|
|
755
|
+
gate, required tool, test controller, prerequisite, or harness contract
|
|
756
|
+
was unavailable.
|
|
757
|
+
required_fields:
|
|
758
|
+
- reason # not_applicable | no_phases |
|
|
759
|
+
# prerequisite_failed | missing_tool |
|
|
760
|
+
# missing_test_controller |
|
|
761
|
+
# unsatisfied_contract | peer_branch_taken |
|
|
762
|
+
# peer_substituted | requirement_unmet
|
|
763
|
+
- detail # human-readable explanation citing the
|
|
764
|
+
# declared supported_protocols / specialisms
|
|
765
|
+
# and, if relevant, the missing tool,
|
|
766
|
+
# prerequisite step id, or contract key.
|
|
767
|
+
reasons:
|
|
768
|
+
not_applicable: |
|
|
769
|
+
The item was selected for this run, but an applicability gate evaluated
|
|
770
|
+
false. Examples: the agent did not declare the protocol or specialism
|
|
771
|
+
this storyboard targets, or a scenario's requires_capability check found
|
|
772
|
+
an optional capability set to false. detail MUST cite the failed gate
|
|
773
|
+
and the agent's relevant declared supported_protocols, specialisms, or
|
|
774
|
+
capability value.
|
|
775
|
+
|
|
776
|
+
When the runner excludes an item before execution because it is outside
|
|
777
|
+
the caller's requested suite, run mode, AdCP version, or verification
|
|
778
|
+
profile, use selection_result instead. Do not report run-mode exclusions
|
|
779
|
+
as not_applicable skips.
|
|
780
|
+
|
|
781
|
+
Branch-set grading uses `peer_branch_taken` (see below), not this
|
|
782
|
+
reason — keeping the two distinct lets dashboards filter coverage
|
|
783
|
+
gaps (not_applicable) separately from runtime branch routing
|
|
784
|
+
(peer_branch_taken).
|
|
785
|
+
no_phases: |
|
|
786
|
+
The storyboard is a placeholder with no phases to run (e.g., a
|
|
787
|
+
protocol baseline that has not been populated yet). detail MUST cite
|
|
788
|
+
the storyboard id and version.
|
|
789
|
+
prerequisite_failed: |
|
|
790
|
+
A prior step this one depends on did not pass. detail MUST cite the
|
|
791
|
+
prerequisite step id.
|
|
792
|
+
missing_tool: |
|
|
793
|
+
The agent declared the protocol or specialism but does not expose a
|
|
794
|
+
required tool. detail MUST cite the tool name declared in the
|
|
795
|
+
storyboard's required_tools and the agent's advertised tool list.
|
|
796
|
+
missing_test_controller: |
|
|
797
|
+
The storyboard requires comply_test_controller and the agent did not
|
|
798
|
+
advertise it. Applies only to deterministic_testing phases.
|
|
799
|
+
unsatisfied_contract: |
|
|
800
|
+
A test-kit harness contract (e.g., signed-requests-runner) is not in
|
|
801
|
+
scope for this grading run. detail MUST cite the contract key. Per
|
|
802
|
+
the signed-requests-runner contract, unsatisfied contracts grade as
|
|
803
|
+
FAIL, not SKIP, for the storyboards that declare them — this reason
|
|
804
|
+
applies only where the contract explicitly permits SKIP.
|
|
805
|
+
peer_branch_taken: |
|
|
806
|
+
The step is part of an `any_of` branch set (see storyboard-schema.yaml
|
|
807
|
+
> "Branch sets") whose `branch_set.id` was already contributed by a
|
|
808
|
+
peer optional phase, making this non-chosen branch moot. detail MUST
|
|
809
|
+
follow the shape
|
|
810
|
+
"<branch_set.id> contributed by <peer_phase_id>.<peer_step_id> —
|
|
811
|
+
<this_phase_id> is moot" so downstream tooling can parse which peer
|
|
812
|
+
carried the contribution. Kept distinct from not_applicable: coverage
|
|
813
|
+
gaps (agent doesn't support a protocol) and runtime branch routing
|
|
814
|
+
(agent took the other path) are different signals and must not be
|
|
815
|
+
conflated in dashboards or summaries.
|
|
816
|
+
peer_substituted: |
|
|
817
|
+
The step would otherwise grade `missing_tool` or
|
|
818
|
+
`missing_test_controller`, but a same-phase peer step declared
|
|
819
|
+
`provides_state_for: <this_step_id>` (see storyboard-schema.yaml >
|
|
820
|
+
`provides_state_for`) and passed — the substitute established
|
|
821
|
+
equivalent state for downstream stateful steps, so the cascade is
|
|
822
|
+
waived. detail MUST follow the shape
|
|
823
|
+
"<this_step_id> state provided by <peer_phase_id>.<peer_step_id>"
|
|
824
|
+
so downstream tooling can parse which substitute carried the state.
|
|
825
|
+
Kept distinct from peer_branch_taken (branch-set routing for
|
|
826
|
+
mutually exclusive behaviors) and not_applicable (coverage gap):
|
|
827
|
+
this signal indicates the agent did declare the specialism but
|
|
828
|
+
offers an interchangeable tool that the storyboard accepts as an
|
|
829
|
+
equivalent state contract.
|
|
830
|
+
requirement_unmet: |
|
|
831
|
+
A storyboard-level load-time precondition was not satisfied. Two
|
|
832
|
+
storyboard-schema fields produce this reason, distinguished by the
|
|
833
|
+
`detail` sub-reason prefix so dashboards can aggregate independently:
|
|
834
|
+
|
|
835
|
+
requires: — runtime context gates
|
|
836
|
+
(see storyboard-schema.yaml > `requires`).
|
|
837
|
+
detail names the unmet requirement value
|
|
838
|
+
directly, e.g. "controller",
|
|
839
|
+
"seeded_state", or an unrecognized
|
|
840
|
+
forward-compat value. This legacy form
|
|
841
|
+
is BARE — no `requires:` prefix is
|
|
842
|
+
synthesized — and remains the canonical
|
|
843
|
+
wire shape for single-gate `requires:`
|
|
844
|
+
failures.
|
|
845
|
+
|
|
846
|
+
required_any_of_tools: — tool-family advertisement gates
|
|
847
|
+
(see storyboard-schema.yaml >
|
|
848
|
+
`required_any_of_tools`). detail
|
|
849
|
+
carries the canonical sub-reason prefix
|
|
850
|
+
"missing_required_tool_family:" followed
|
|
851
|
+
by " needs <tool_a> or <tool_b>[ or
|
|
852
|
+
<tool_c>...]" and, when a rationale was
|
|
853
|
+
declared, a trailing " (<rationale>)"
|
|
854
|
+
parenthetical. Canonical single-line
|
|
855
|
+
example:
|
|
856
|
+
`missing_required_tool_family: needs list_accounts or sync_accounts (AdCP 3.0.9 §accounts/overview)`
|
|
857
|
+
|
|
858
|
+
Family-list separator. When a family contains more than two tools,
|
|
859
|
+
runners MUST join names with the literal three-character " or "
|
|
860
|
+
separator (no Oxford comma; no list-style punctuation). Dashboards
|
|
861
|
+
that parse the family list MAY split on " or " safely. Tool names
|
|
862
|
+
are constrained by the spec's tool-name charset and do not contain
|
|
863
|
+
the literal " or " substring.
|
|
864
|
+
|
|
865
|
+
Wire-shape posture for aggregation. Runners SHOULD emit a single
|
|
866
|
+
sub-reason in `detail` even when multiple gates are unmet —
|
|
867
|
+
surfacing the first-evaluated gate is the canonical wire shape and
|
|
868
|
+
keeps `detail` programmatically parseable. When a runner aggregates
|
|
869
|
+
multiple unmet gates into one `detail` string for human display,
|
|
870
|
+
it MUST use "; " (semicolon + space) as the sub-reason separator
|
|
871
|
+
and MUST preserve each sub-reason's standalone form (the bare
|
|
872
|
+
`requires:` legacy value, or the prefixed `missing_required_tool_family:
|
|
873
|
+
…` shape). Example multi-gate aggregation:
|
|
874
|
+
`controller; missing_required_tool_family: needs list_accounts or sync_accounts (AdCP 3.0.9 §accounts/overview)`.
|
|
875
|
+
|
|
876
|
+
Automated consumers SHOULD parse only the first sub-reason from
|
|
877
|
+
aggregated `detail` (everything up to the first "; ") and surface
|
|
878
|
+
multi-gate state through a separate UI affordance rather than
|
|
879
|
+
treating `detail` as a structured list.
|
|
880
|
+
|
|
881
|
+
The sub-reason prefix is the canonical attribution string —
|
|
882
|
+
dashboards and skip-cause aggregators MUST switch on the prefix to
|
|
883
|
+
separate tool-family gates from `requires:` gates when summarizing
|
|
884
|
+
the first sub-reason.
|
|
885
|
+
|
|
886
|
+
Distinct from missing_test_controller (which fires mid-run at a
|
|
887
|
+
specific step when comply_test_controller is absent) — this reason
|
|
888
|
+
fires at load time for the whole storyboard, before any step
|
|
889
|
+
executes. When `requires: [controller]` is set, the runner MUST
|
|
890
|
+
emit this reason at storyboard scope, not missing_test_controller
|
|
891
|
+
at step scope.
|
|
892
|
+
|
|
893
|
+
Distinct from missing_tool (which fires at step scope when a tool
|
|
894
|
+
declared in the storyboard's `required_tools` is absent — a coverage
|
|
895
|
+
skip). `required_any_of_tools` is a load-time gate on tool
|
|
896
|
+
advertisement, not a per-step coverage signal.
|
|
897
|
+
|
|
898
|
+
Forward compatibility: runners that encounter a `requires` value
|
|
899
|
+
they do not recognize MUST emit this reason with the unrecognized
|
|
900
|
+
value in detail, rather than fail-loading the storyboard. Using
|
|
901
|
+
requirement_unmet (not not_applicable) correctly signals "an unmet
|
|
902
|
+
gate" vs. "agent did not claim the protocol" — the two are distinct
|
|
903
|
+
signals for dashboards and summaries.
|
|
904
|
+
description: |
|
|
905
|
+
Runners MAY internally track narrower skip reasons (e.g., a grader
|
|
906
|
+
distinguishing `rate_abuse_opt_out` from `live_side_effect_opt_in_required`).
|
|
907
|
+
Such runners MUST still populate `reason` with one of the canonical
|
|
908
|
+
values above and encode the narrower cause in `detail`. Machine-
|
|
909
|
+
readable consumers can then switch on a stable enum; human-readable
|
|
910
|
+
consumers still see the specific cause. See
|
|
911
|
+
DETAILED_SKIP_TO_CANONICAL in the conforming implementation for a
|
|
912
|
+
concrete mapping.
|
|
913
|
+
|
|
914
|
+
selection_result:
|
|
915
|
+
description: |
|
|
916
|
+
When a track, storyboard, phase, or step is outside the run the caller
|
|
917
|
+
requested, runners MUST report it as not_selected rather than skipped.
|
|
918
|
+
Not-selected items are not attempted, do not imply an agent capability
|
|
919
|
+
gap, and MUST NOT contribute to steps_skipped or any skip-by-reason
|
|
920
|
+
counter.
|
|
921
|
+
|
|
922
|
+
This distinction is load-bearing for Sandbox verification and buyer
|
|
923
|
+
dashboards. "Sandbox only" means live-only probes are excluded by the
|
|
924
|
+
selected suite; it does not mean the seller skipped or failed those
|
|
925
|
+
probes. By contrast, a selected storyboard that cannot run because the
|
|
926
|
+
seller did not advertise an optional capability, omitted
|
|
927
|
+
comply_test_controller, or lacks a required tool remains a skip_result
|
|
928
|
+
with its own reason.
|
|
929
|
+
required_fields:
|
|
930
|
+
- reason # run_mode_excluded | explicit_scope_excluded |
|
|
931
|
+
# version_excluded | profile_excluded
|
|
932
|
+
- detail # human-readable explanation citing the
|
|
933
|
+
# selected run mode, explicit storyboard scope,
|
|
934
|
+
# AdCP version, or verification profile rule
|
|
935
|
+
# that excluded the item.
|
|
936
|
+
reasons:
|
|
937
|
+
run_mode_excluded: |
|
|
938
|
+
The item is incompatible with the selected run mode. Example:
|
|
939
|
+
a live-only probe is outside a Sandbox-only run. detail MUST cite
|
|
940
|
+
both the selected mode and the excluded mode requirement.
|
|
941
|
+
explicit_scope_excluded: |
|
|
942
|
+
The caller supplied an explicit storyboard, track, protocol, or
|
|
943
|
+
specialism scope that does not include this item. detail MUST cite
|
|
944
|
+
the selected scope.
|
|
945
|
+
version_excluded: |
|
|
946
|
+
The item is not applicable to the AdCP version selected for this run.
|
|
947
|
+
detail MUST cite the selected AdCP version and the item's
|
|
948
|
+
introduced_in or removed_in bound when known.
|
|
949
|
+
profile_excluded: |
|
|
950
|
+
A named verification profile intentionally excludes this item before
|
|
951
|
+
execution. detail MUST cite the profile name and profile rule.
|
|
952
|
+
|
|
953
|
+
notice:
|
|
954
|
+
description: |
|
|
955
|
+
Advisory signal attached to a storyboard step result or run summary.
|
|
956
|
+
Notices are informational — they MUST NOT contribute to steps_failed,
|
|
957
|
+
validations_failed, or any other required-failure counter, and they
|
|
958
|
+
MUST NOT change `step_result.passed` or run-level pass/fail counters.
|
|
959
|
+
|
|
960
|
+
Notices fill the gap between three existing signals:
|
|
961
|
+
- Validation failures (passed: false) — the agent did something wrong.
|
|
962
|
+
- Skip reasons — the runner could not apply the storyboard.
|
|
963
|
+
- Advisory-severity validations — the storyboard author marked a check
|
|
964
|
+
as non-blocking during a runner adoption window.
|
|
965
|
+
|
|
966
|
+
A notice is none of those: it is a forward-looking or migration advisory
|
|
967
|
+
about a passing observation. Examples: an agent still advertising a
|
|
968
|
+
deprecated specialism that the spec recommends dropping; an agent that
|
|
969
|
+
passes today but advertises a capability shape that will be required at
|
|
970
|
+
a named future spec version; an adopter using a legacy fallback that is
|
|
971
|
+
scheduled for removal at a named future version.
|
|
972
|
+
|
|
973
|
+
Spec storyboards that motivate canonical notices SHOULD reference the
|
|
974
|
+
notice `code` (not the prose). The reference adopter currently
|
|
975
|
+
motivating the contract is the `signed_requests_specialism_deprecated`
|
|
976
|
+
notice in `universal/signed-requests.yaml` — the runner SHOULD emit
|
|
977
|
+
this notice when an agent claims the deprecated `signed-requests`
|
|
978
|
+
specialism alongside `request_signing.supported: true`, advising
|
|
979
|
+
the agent to drop the now-redundant specialism claim.
|
|
980
|
+
|
|
981
|
+
Forward compatibility: receivers MUST treat an unknown `code` or
|
|
982
|
+
`severity` value as well-formed and surface the notice verbatim. New
|
|
983
|
+
codes and severities ship additively; rejecting on unknown values
|
|
984
|
+
defeats the contract.
|
|
985
|
+
|
|
986
|
+
required_fields:
|
|
987
|
+
- severity # "info" | "deprecation" | "future_required"
|
|
988
|
+
# info — passing behavior is fine
|
|
989
|
+
# today; advisory context only
|
|
990
|
+
# (e.g., "this agent is using
|
|
991
|
+
# an alternate but supported
|
|
992
|
+
# pathway").
|
|
993
|
+
# deprecation — agent-side claim or behavior
|
|
994
|
+
# is allowed today but the
|
|
995
|
+
# spec recommends migration
|
|
996
|
+
# (e.g., legacy specialism
|
|
997
|
+
# enum values still accepted
|
|
998
|
+
# for back-compat).
|
|
999
|
+
# future_required — capability that is optional
|
|
1000
|
+
# today will be required at a
|
|
1001
|
+
# named future spec version;
|
|
1002
|
+
# agents that do not advertise
|
|
1003
|
+
# it will fail compliance
|
|
1004
|
+
# after the cut. `effective_version`
|
|
1005
|
+
# MUST be populated.
|
|
1006
|
+
- code # stable machine-readable identifier
|
|
1007
|
+
# (SCREAMING_SNAKE-or-lowercase_snake; the
|
|
1008
|
+
# canonical first-day codes below use
|
|
1009
|
+
# lowercase_snake). Runners MUST NOT change
|
|
1010
|
+
# the code for the same advisory across
|
|
1011
|
+
# versions — consumers aggregate by code.
|
|
1012
|
+
# Unknown codes from a forward-compat runner
|
|
1013
|
+
# MUST be surfaced verbatim by receivers, not
|
|
1014
|
+
# rejected.
|
|
1015
|
+
- message # human-readable description. Runners MUST
|
|
1016
|
+
# fence this string when rendering to a
|
|
1017
|
+
# shared LLM-fed surface per the same rules
|
|
1018
|
+
# as skip_result.detail — the storyboard
|
|
1019
|
+
# author controls the substring.
|
|
1020
|
+
optional_fields:
|
|
1021
|
+
- effective_version # When severity is "future_required", the
|
|
1022
|
+
# AdCP version that flips the requirement
|
|
1023
|
+
# (e.g., "4.0"). REQUIRED for future_required
|
|
1024
|
+
# severity, MAY be present on "deprecation"
|
|
1025
|
+
# to name the removal version, MUST NOT be
|
|
1026
|
+
# set on "info".
|
|
1027
|
+
- requirement # When the notice is tied to a structured
|
|
1028
|
+
# `requires:` name in storyboard-schema.yaml,
|
|
1029
|
+
# repeat the requirement value here so
|
|
1030
|
+
# dashboards can correlate notices with the
|
|
1031
|
+
# gate that motivated them.
|
|
1032
|
+
- capability_path # Dotted path into the agent's
|
|
1033
|
+
# `get_adcp_capabilities` response that
|
|
1034
|
+
# motivated the notice
|
|
1035
|
+
# (e.g., "request_signing.supported",
|
|
1036
|
+
# "webhook_signing.legacy_hmac_fallback").
|
|
1037
|
+
# Lets consumers link the notice to the
|
|
1038
|
+
# exact capability flag without parsing the
|
|
1039
|
+
# message string.
|
|
1040
|
+
- reference_url # optional spec or issue URL with more context
|
|
1041
|
+
# (e.g., the upstream issue tracking the
|
|
1042
|
+
# deprecation, or the relevant section in
|
|
1043
|
+
# /docs/building/by-layer/L3/error-handling.mdx).
|
|
1044
|
+
canonical_codes:
|
|
1045
|
+
description: |
|
|
1046
|
+
First-day published codes runners SHOULD emit when the underlying
|
|
1047
|
+
condition holds. Additional codes are registered by adding entries
|
|
1048
|
+
here in subsequent spec revisions; runners MAY emit codes outside
|
|
1049
|
+
this list (consumers must accept unknown codes per the forward-compat
|
|
1050
|
+
rule above), but SHOULD prefer canonical codes when one fits.
|
|
1051
|
+
signed_requests_specialism_deprecated:
|
|
1052
|
+
severity: deprecation
|
|
1053
|
+
spec_source: universal/signed-requests.yaml
|
|
1054
|
+
capability_path: specialisms
|
|
1055
|
+
message_template: |
|
|
1056
|
+
Agent advertises the deprecated `signed-requests` specialism
|
|
1057
|
+
enum value. Drop it and rely solely on
|
|
1058
|
+
`request_signing.supported: true`. The enum value is removed
|
|
1059
|
+
in AdCP 4.0 (see adcontextprotocol/adcp#3078).
|
|
1060
|
+
request_signing_required_in_4_0:
|
|
1061
|
+
severity: future_required
|
|
1062
|
+
effective_version: "4.0"
|
|
1063
|
+
spec_source: protocol/get-adcp-capabilities-response.json#request_signing
|
|
1064
|
+
capability_path: request_signing.supported
|
|
1065
|
+
message_template: |
|
|
1066
|
+
`request_signing.supported: true` is optional in 3.x but required
|
|
1067
|
+
for spend-committing operations in AdCP 4.0. Agents that do not
|
|
1068
|
+
advertise support will fail compliance on the 4.0 cut.
|
|
1069
|
+
legacy_hmac_fallback_removed_in_4_0:
|
|
1070
|
+
severity: deprecation
|
|
1071
|
+
effective_version: "4.0"
|
|
1072
|
+
spec_source: protocol/get-adcp-capabilities-response.json#webhook_signing.legacy_hmac_fallback
|
|
1073
|
+
capability_path: webhook_signing.legacy_hmac_fallback
|
|
1074
|
+
message_template: |
|
|
1075
|
+
Agent advertises `webhook_signing.legacy_hmac_fallback: true`.
|
|
1076
|
+
The HMAC fallback path is deprecated and removed in AdCP 4.0;
|
|
1077
|
+
receivers SHOULD migrate to RFC 9421 signatures only.
|
|
1078
|
+
|
|
1079
|
+
cascade_rules:
|
|
1080
|
+
description: |
|
|
1081
|
+
Rules governing when a runner MUST propagate `prerequisite_failed` to
|
|
1082
|
+
downstream stateful steps and when it MUST NOT. These complement the
|
|
1083
|
+
per-reason text in `skip_result.reasons`: the skip reason describes WHY
|
|
1084
|
+
a step was skipped; cascade rules describe what effect that skip has on
|
|
1085
|
+
later phases. Runners MUST evaluate these rules after per-step grading
|
|
1086
|
+
completes, before downstream skip propagation runs.
|
|
1087
|
+
default_cascade: |
|
|
1088
|
+
When a stateful step produces `passed: false` (a genuine failure), or
|
|
1089
|
+
skips with `prerequisite_failed`, `unsatisfied_contract`, or
|
|
1090
|
+
`peer_branch_taken`, the runner MUST cascade `prerequisite_failed` to
|
|
1091
|
+
downstream stateful phases so implementors know that dependent coverage
|
|
1092
|
+
collapsed. Steps that skip with `peer_substituted` do NOT trigger the
|
|
1093
|
+
cascade — the `provides_state_for` mechanism already waived it (see
|
|
1094
|
+
`skip_result.reasons.peer_substituted`). Steps that skip with
|
|
1095
|
+
`not_applicable`, `missing_tool`, or `missing_test_controller` do NOT
|
|
1096
|
+
trigger the cascade when the `sole_stateful_step_exemption` below applies.
|
|
1097
|
+
sole_stateful_step_exemption: |
|
|
1098
|
+
When ALL of the following hold, the runner MUST NOT cascade
|
|
1099
|
+
`prerequisite_failed` to downstream stateful phases:
|
|
1100
|
+
|
|
1101
|
+
1. The step grades `not_applicable`, `missing_tool`, or
|
|
1102
|
+
`missing_test_controller`.
|
|
1103
|
+
2. It is the sole stateful step in its phase (no other stateful step
|
|
1104
|
+
exists in the same phase that could have established substitute state).
|
|
1105
|
+
3. No same-phase peer step has declared `provides_state_for:
|
|
1106
|
+
<this_step_id>`.
|
|
1107
|
+
|
|
1108
|
+
When these conditions are met, downstream phases evaluate independently —
|
|
1109
|
+
their stateful steps do NOT receive `prerequisite_failed` from this step
|
|
1110
|
+
and are graded on their own merits. The skipping step still emits its own
|
|
1111
|
+
skip_result with the original reason (`not_applicable | missing_tool |
|
|
1112
|
+
missing_test_controller`); the exemption suppresses only the cascade, not
|
|
1113
|
+
the step's own skip reason.
|
|
1114
|
+
|
|
1115
|
+
Rationale: a sole stateful step has no peer that could have established
|
|
1116
|
+
substitute state. The platform legitimately does not implement this pathway
|
|
1117
|
+
(e.g., proposal-mode / implicit-account adopters that materialize account
|
|
1118
|
+
state via the first `get_products` call rather than `sync_accounts`).
|
|
1119
|
+
Cascading `prerequisite_failed` to all downstream stateful phases collapses
|
|
1120
|
+
useful coverage on the framework paths the adopter does implement.
|
|
1121
|
+
|
|
1122
|
+
When the skipping step has at least one stateful peer in the phase, the
|
|
1123
|
+
existing rules apply: `provides_state_for` declarations defer the cascade
|
|
1124
|
+
(see `skip_result.reasons.peer_substituted`), and unrescued hard-missing
|
|
1125
|
+
or real failures trip it.
|
|
1126
|
+
|
|
1127
|
+
Note on `not_applicable`: unlike `missing_tool` and
|
|
1128
|
+
`missing_test_controller` (where the agent declared the specialism but
|
|
1129
|
+
lacks the tool/controller), `not_applicable` means the agent did not
|
|
1130
|
+
declare the specialism at all. The cascade exemption still applies because
|
|
1131
|
+
the structural condition — no peer available to establish substitute state —
|
|
1132
|
+
is identical. A sole-stateful-step `not_applicable` that cascades to all
|
|
1133
|
+
downstream phases would collapse coverage for agents that legitimately omit
|
|
1134
|
+
a pathway; the exemption prevents this collapse regardless of the specific
|
|
1135
|
+
skip reason. Dashboard consumers that need to distinguish "agent does not
|
|
1136
|
+
support the specialism" from "agent supports it via an alternate tool"
|
|
1137
|
+
should read the step's `reason` field rather than inferring from whether
|
|
1138
|
+
downstream phases ran.
|
|
1139
|
+
|
|
1140
|
+
References: adcp-client#1146 (original `not_applicable` exemption);
|
|
1141
|
+
adcp-client#1545 (extension to `missing_tool` / `missing_test_controller`);
|
|
1142
|
+
adcp-client-python#550 (adopter pattern that surfaced the cross-runner gap).
|
|
1143
|
+
|
|
1144
|
+
run_summary:
|
|
1145
|
+
description: |
|
|
1146
|
+
Runners MUST expose a top-level summary for every run. UI surfaces
|
|
1147
|
+
(Addie, CLI, web) may present a condensed form, but the full summary
|
|
1148
|
+
MUST be available in the machine-readable (--json / structuredContent)
|
|
1149
|
+
output.
|
|
1150
|
+
notes:
|
|
1151
|
+
capture_failures_count_as_failed: |
|
|
1152
|
+
Steps that fail due to capture_path_not_resolvable or
|
|
1153
|
+
unresolved_substitution MUST contribute to steps_failed, not
|
|
1154
|
+
steps_skipped. The capturing step failing is a conformance failure
|
|
1155
|
+
on that step; the downstream consumer step that cannot run due to
|
|
1156
|
+
the missing context value uses the skip_result.reason:
|
|
1157
|
+
prerequisite_failed path and contributes to steps_skipped. This
|
|
1158
|
+
attribution is load-bearing — silently swallowing a capture failure
|
|
1159
|
+
and reporting only the downstream skip points the diagnostic at the
|
|
1160
|
+
wrong place.
|
|
1161
|
+
upstream_traffic_not_applicable: |
|
|
1162
|
+
Steps whose only failing validation is upstream_traffic against an
|
|
1163
|
+
adopter that did not advertise query_upstream_traffic via
|
|
1164
|
+
list_scenarios MUST NOT contribute to steps_failed. The runner
|
|
1165
|
+
grades the upstream_traffic validation as not_applicable (with
|
|
1166
|
+
skip_result.reason: missing_test_controller, detail:
|
|
1167
|
+
"query_upstream_traffic scenario not advertised") and the step
|
|
1168
|
+
grades on its remaining authored checks. An adopter that exposes
|
|
1169
|
+
the scenario but returns an empty recorded_calls array DOES grade
|
|
1170
|
+
as failed for upstream_traffic — the difference is "controller
|
|
1171
|
+
not present" (opt-out) vs "controller present and observed nothing"
|
|
1172
|
+
(façade signal).
|
|
1173
|
+
required_fields:
|
|
1174
|
+
- total_steps
|
|
1175
|
+
- steps_passed
|
|
1176
|
+
- steps_failed
|
|
1177
|
+
- steps_skipped
|
|
1178
|
+
- steps_not_selected # count of steps excluded before execution by
|
|
1179
|
+
# suite selection, run mode, AdCP version, or
|
|
1180
|
+
# verification profile. MUST NOT be included
|
|
1181
|
+
# in steps_skipped.
|
|
1182
|
+
- tracks # per-track status with the skip distinctions above
|
|
1183
|
+
- schemas_used # array of { schema_id, schema_url } so an
|
|
1184
|
+
# implementor can re-validate locally against
|
|
1185
|
+
# the exact artifacts the runner applied
|
|
1186
|
+
- runner_capability_version
|
|
1187
|
+
# semver self-declared by the runner so
|
|
1188
|
+
# consumers can correlate a run's grading
|
|
1189
|
+
# behavior with the spec capability the
|
|
1190
|
+
# runner offers. Authors target capability
|
|
1191
|
+
# versions when they write
|
|
1192
|
+
# expires_after_version on advisory
|
|
1193
|
+
# validations (see storyboard-schema.yaml >
|
|
1194
|
+
# expires_after_version) and the runner's
|
|
1195
|
+
# promotion logic compares its declared
|
|
1196
|
+
# value against the storyboard's expiry. The
|
|
1197
|
+
# runner chooses what its capability version
|
|
1198
|
+
# corresponds to — @adcp/sdk semver, the
|
|
1199
|
+
# AdCP spec version it implements, or a
|
|
1200
|
+
# runner-binary version — and is responsible
|
|
1201
|
+
# for advancing it as new check kinds and
|
|
1202
|
+
# grading semantics ship. Adopters who run
|
|
1203
|
+
# multiple runners against the same agent
|
|
1204
|
+
# SHOULD select the highest-capability runner
|
|
1205
|
+
# for conformance grading.
|
|
1206
|
+
optional_fields:
|
|
1207
|
+
- not_selected # array of selection_result objects, or
|
|
1208
|
+
# implementation-specific objects carrying at
|
|
1209
|
+
# least selection_result.reason/detail plus the
|
|
1210
|
+
# storyboard/phase/step identity. Required for
|
|
1211
|
+
# human-facing reports that mention a
|
|
1212
|
+
# not-selected count; otherwise the count is not
|
|
1213
|
+
# actionable.
|
|
1214
|
+
- not_selected_by_reason # object mapping selection_result.reason values
|
|
1215
|
+
# to counts. Recommended for dashboards and
|
|
1216
|
+
# buyer profile evaluators.
|
|
1217
|
+
- skipped_by_reason # object mapping skip_result.reason values to
|
|
1218
|
+
# counts. Recommended whenever steps_skipped > 0
|
|
1219
|
+
# so consumers can distinguish optional
|
|
1220
|
+
# capability skips from missing required
|
|
1221
|
+
# surfaces without parsing prose detail strings.
|
|
1222
|
+
- validations_not_applicable # count of validation_result entries graded
|
|
1223
|
+
# not_applicable due to forward-compat
|
|
1224
|
+
# (runner does not implement the storyboard's
|
|
1225
|
+
# declared check type). Surfaces "runner is
|
|
1226
|
+
# older than the storyboard" as a distinct
|
|
1227
|
+
# signal from clean passes.
|
|
1228
|
+
- notices # array of notice objects scoped to the run
|
|
1229
|
+
# rather than a specific step (e.g., a
|
|
1230
|
+
# `request_signing_required_in_4_0` notice
|
|
1231
|
+
# emitted once per run when the agent does
|
|
1232
|
+
# not advertise `request_signing.supported`,
|
|
1233
|
+
# regardless of which storyboard the
|
|
1234
|
+
# observation surfaced on). Runners MAY
|
|
1235
|
+
# emit the same code on step_result.notices
|
|
1236
|
+
# AND run_summary.notices when an advisory
|
|
1237
|
+
# is both step-specific and run-wide;
|
|
1238
|
+
# consumers dedupe by `code`. See the
|
|
1239
|
+
# notice block above for shape and
|
|
1240
|
+
# canonical_codes.
|
|
1241
|
+
- validations_advisory_failed # count of validation_result entries with
|
|
1242
|
+
# passed: false and severity: advisory.
|
|
1243
|
+
# These do NOT contribute to steps_failed
|
|
1244
|
+
# (the step grades on its required
|
|
1245
|
+
# validations); this counter surfaces them
|
|
1246
|
+
# for visibility without polluting the
|
|
1247
|
+
# conformance verdict.
|
|
1248
|
+
#
|
|
1249
|
+
# Rendered-summary rule: when the runner
|
|
1250
|
+
# renders a human-facing summary line
|
|
1251
|
+
# (CLI, dashboard, chat surface),
|
|
1252
|
+
# validations_advisory_failed MUST be
|
|
1253
|
+
# displayed adjacent to steps_failed in
|
|
1254
|
+
# the same line or section, NOT buried
|
|
1255
|
+
# at the bottom of the summary. Otherwise
|
|
1256
|
+
# a façade declaring its anti-façade
|
|
1257
|
+
# validations as advisory produces a
|
|
1258
|
+
# passing summary line that hides the
|
|
1259
|
+
# advisory failures from human
|
|
1260
|
+
# reviewers. The two counters together
|
|
1261
|
+
# are the conformance signal.
|
|
1262
|
+
#
|
|
1263
|
+
# Use case: author-managed rollout
|
|
1264
|
+
# gating during runner adoption windows
|
|
1265
|
+
# — see storyboard-schema.yaml >
|
|
1266
|
+
# "Validation" severity field.
|
|
1267
|
+
|
|
1268
|
+
# --- Non-goals ---
|
|
1269
|
+
#
|
|
1270
|
+
# This contract does NOT specify:
|
|
1271
|
+
# - Output formatting (markdown, JSON shape in the outer envelope, colors).
|
|
1272
|
+
# - Storage or retention of run artifacts.
|
|
1273
|
+
# - Scoring weights or pass/fail thresholds for a "compliant" verdict.
|
|
1274
|
+
# - How to render results in conversational interfaces.
|
|
1275
|
+
# Runners remain free to add fields, nest them under implementation-specific
|
|
1276
|
+
# keys, and render them however best fits the surface. The contract is about
|
|
1277
|
+
# minimum actionability.
|
|
1278
|
+
|
|
1279
|
+
references:
|
|
1280
|
+
storyboard_schema: static/compliance/source/universal/storyboard-schema.yaml
|
|
1281
|
+
mcp_extraction: docs/building/implementation/mcp-response-extraction.mdx
|
|
1282
|
+
a2a_extraction: docs/building/implementation/a2a-response-extraction.mdx
|
|
1283
|
+
transport_errors: docs/building/implementation/transport-errors.mdx
|
|
1284
|
+
signed_requests_runner: static/compliance/source/test-kits/signed-requests-runner.yaml
|
|
1285
|
+
conforming_implementation: https://github.com/adcontextprotocol/adcp-client/pull/611
|