@adcp/sdk 7.10.2 → 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.
Files changed (305) hide show
  1. package/compliance/cache/3.1.0-rc.2/domains/brand/index.yaml +160 -0
  2. package/compliance/cache/3.1.0-rc.2/domains/brand/scenarios/distributed_brand_resolution.yaml +415 -0
  3. package/compliance/cache/3.1.0-rc.2/domains/brand/scenarios/single_side_trust_extension.yaml +454 -0
  4. package/compliance/cache/3.1.0-rc.2/domains/creative/index.yaml +339 -0
  5. package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/billing_out_of_band.yaml +153 -0
  6. package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/canonical_supported_formats.yaml +212 -0
  7. package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/creative_lifecycle_webhooks.yaml +389 -0
  8. package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/native_in_feed.yaml +543 -0
  9. package/compliance/cache/3.1.0-rc.2/domains/governance/index.yaml +682 -0
  10. package/compliance/cache/3.1.0-rc.2/domains/media-buy/index.yaml +789 -0
  11. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/audience_buy_flow.yaml +380 -0
  12. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/available_actions.yaml +565 -0
  13. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/billing_finality_delivery.yaml +354 -0
  14. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/canonical_formats.yaml +861 -0
  15. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/clicks_buy_flow.yaml +264 -0
  16. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/completed_views_buy_flow.yaml +344 -0
  17. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/create_media_buy_async.yaml +234 -0
  18. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/creative_fate_after_cancellation.yaml +419 -0
  19. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/creative_reception.yaml +247 -0
  20. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/delivery_reporting.yaml +357 -0
  21. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/dependency_impairment.yaml +633 -0
  22. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/dependency_impairment_cardinality.yaml +800 -0
  23. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/event_dedup_flow.yaml +399 -0
  24. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/frequency_cap_enforcement.yaml +309 -0
  25. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_approved.yaml +214 -0
  26. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_conditions.yaml +199 -0
  27. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_denied.yaml +204 -0
  28. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_denied_recovery.yaml +252 -0
  29. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/invalid_transitions.yaml +289 -0
  30. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/inventory_list_no_match.yaml +148 -0
  31. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/inventory_list_targeting.yaml +276 -0
  32. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/measurement_accountability.yaml +244 -0
  33. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/measurement_terms_rejected.yaml +203 -0
  34. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/package_correlation_legacy_fallback.yaml +113 -0
  35. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/pending_creatives_to_start.yaml +292 -0
  36. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/per_creative_conversion_attribution.yaml +500 -0
  37. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/performance_buy_flow.yaml +428 -0
  38. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/performance_buy_flow_roas.yaml +470 -0
  39. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/product_signal_targeting.yaml +373 -0
  40. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/proposal_finalize.yaml +399 -0
  41. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/proposal_finalize_asap_timing.yaml +264 -0
  42. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/proposal_not_found_errors.yaml +257 -0
  43. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/provenance_audit_observation.yaml +333 -0
  44. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/provenance_enforcement.yaml +517 -0
  45. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/provenance_truth_of_claim.yaml +294 -0
  46. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/reach_buy_flow.yaml +823 -0
  47. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/refine_finalize_exclusivity.yaml +360 -0
  48. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/refine_products.yaml +148 -0
  49. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/vendor_metric_accountability.yaml +293 -0
  50. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +307 -0
  51. package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/vendor_metric_optimization_flow.yaml +576 -0
  52. package/compliance/cache/3.1.0-rc.2/domains/media-buy/state-machine.yaml +442 -0
  53. package/compliance/cache/3.1.0-rc.2/domains/signals/index.yaml +266 -0
  54. package/compliance/cache/3.1.0-rc.2/domains/sponsored-intelligence/index.yaml +256 -0
  55. package/compliance/cache/3.1.0-rc.2/index.json +356 -0
  56. package/compliance/cache/3.1.0-rc.2/protocols/brand/index.yaml +160 -0
  57. package/compliance/cache/3.1.0-rc.2/protocols/brand/scenarios/distributed_brand_resolution.yaml +415 -0
  58. package/compliance/cache/3.1.0-rc.2/protocols/brand/scenarios/single_side_trust_extension.yaml +454 -0
  59. package/compliance/cache/3.1.0-rc.2/protocols/creative/index.yaml +339 -0
  60. package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/billing_out_of_band.yaml +153 -0
  61. package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/canonical_supported_formats.yaml +212 -0
  62. package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/creative_lifecycle_webhooks.yaml +389 -0
  63. package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/native_in_feed.yaml +543 -0
  64. package/compliance/cache/3.1.0-rc.2/protocols/governance/index.yaml +682 -0
  65. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/index.yaml +789 -0
  66. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/audience_buy_flow.yaml +380 -0
  67. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/available_actions.yaml +565 -0
  68. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/billing_finality_delivery.yaml +354 -0
  69. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/canonical_formats.yaml +861 -0
  70. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/clicks_buy_flow.yaml +264 -0
  71. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/completed_views_buy_flow.yaml +344 -0
  72. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/create_media_buy_async.yaml +234 -0
  73. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/creative_fate_after_cancellation.yaml +419 -0
  74. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/creative_reception.yaml +247 -0
  75. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/delivery_reporting.yaml +357 -0
  76. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/dependency_impairment.yaml +633 -0
  77. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/dependency_impairment_cardinality.yaml +800 -0
  78. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/event_dedup_flow.yaml +399 -0
  79. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/frequency_cap_enforcement.yaml +309 -0
  80. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_approved.yaml +214 -0
  81. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_conditions.yaml +199 -0
  82. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_denied.yaml +204 -0
  83. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_denied_recovery.yaml +252 -0
  84. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/invalid_transitions.yaml +289 -0
  85. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/inventory_list_no_match.yaml +148 -0
  86. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/inventory_list_targeting.yaml +276 -0
  87. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/measurement_accountability.yaml +244 -0
  88. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/measurement_terms_rejected.yaml +203 -0
  89. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/package_correlation_legacy_fallback.yaml +113 -0
  90. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/pending_creatives_to_start.yaml +292 -0
  91. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/per_creative_conversion_attribution.yaml +500 -0
  92. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/performance_buy_flow.yaml +428 -0
  93. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/performance_buy_flow_roas.yaml +470 -0
  94. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/product_signal_targeting.yaml +373 -0
  95. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/proposal_finalize.yaml +399 -0
  96. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/proposal_finalize_asap_timing.yaml +264 -0
  97. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/proposal_not_found_errors.yaml +257 -0
  98. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/provenance_audit_observation.yaml +333 -0
  99. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/provenance_enforcement.yaml +517 -0
  100. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/provenance_truth_of_claim.yaml +294 -0
  101. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/reach_buy_flow.yaml +823 -0
  102. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/refine_finalize_exclusivity.yaml +360 -0
  103. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/refine_products.yaml +148 -0
  104. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/vendor_metric_accountability.yaml +293 -0
  105. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +307 -0
  106. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/vendor_metric_optimization_flow.yaml +576 -0
  107. package/compliance/cache/3.1.0-rc.2/protocols/media-buy/state-machine.yaml +442 -0
  108. package/compliance/cache/3.1.0-rc.2/protocols/signals/index.yaml +266 -0
  109. package/compliance/cache/3.1.0-rc.2/protocols/sponsored-intelligence/index.yaml +256 -0
  110. package/compliance/cache/3.1.0-rc.2/specialisms/audience-sync/index.yaml +313 -0
  111. package/compliance/cache/3.1.0-rc.2/specialisms/brand-rights/index.yaml +350 -0
  112. package/compliance/cache/3.1.0-rc.2/specialisms/brand-rights/scenarios/governance_denied.yaml +226 -0
  113. package/compliance/cache/3.1.0-rc.2/specialisms/collection-lists/index.yaml +359 -0
  114. package/compliance/cache/3.1.0-rc.2/specialisms/content-standards/index.yaml +572 -0
  115. package/compliance/cache/3.1.0-rc.2/specialisms/creative-ad-server/index.yaml +409 -0
  116. package/compliance/cache/3.1.0-rc.2/specialisms/creative-generative/generative-seller.yaml +807 -0
  117. package/compliance/cache/3.1.0-rc.2/specialisms/creative-generative/index.yaml +758 -0
  118. package/compliance/cache/3.1.0-rc.2/specialisms/creative-template/index.yaml +510 -0
  119. package/compliance/cache/3.1.0-rc.2/specialisms/governance-aware-seller/index.yaml +143 -0
  120. package/compliance/cache/3.1.0-rc.2/specialisms/governance-aware-seller/scenarios/governance_multi_agent_rejected.yaml +117 -0
  121. package/compliance/cache/3.1.0-rc.2/specialisms/governance-delivery-monitor/index.yaml +441 -0
  122. package/compliance/cache/3.1.0-rc.2/specialisms/governance-spend-authority/denied.yaml +221 -0
  123. package/compliance/cache/3.1.0-rc.2/specialisms/governance-spend-authority/index.yaml +330 -0
  124. package/compliance/cache/3.1.0-rc.2/specialisms/property-lists/index.yaml +482 -0
  125. package/compliance/cache/3.1.0-rc.2/specialisms/sales-broadcast-tv/index.yaml +738 -0
  126. package/compliance/cache/3.1.0-rc.2/specialisms/sales-catalog-driven/index.yaml +840 -0
  127. package/compliance/cache/3.1.0-rc.2/specialisms/sales-guaranteed/index.yaml +601 -0
  128. package/compliance/cache/3.1.0-rc.2/specialisms/sales-non-guaranteed/index.yaml +546 -0
  129. package/compliance/cache/3.1.0-rc.2/specialisms/sales-proposal-mode/index.yaml +586 -0
  130. package/compliance/cache/3.1.0-rc.2/specialisms/sales-social/index.yaml +919 -0
  131. package/compliance/cache/3.1.0-rc.2/specialisms/signal-marketplace/index.yaml +424 -0
  132. package/compliance/cache/3.1.0-rc.2/specialisms/signal-marketplace/scenarios/governance_denied.yaml +210 -0
  133. package/compliance/cache/3.1.0-rc.2/specialisms/signal-owned/index.yaml +317 -0
  134. package/compliance/cache/3.1.0-rc.2/specialisms/sponsored-intelligence/index.yaml +59 -0
  135. package/compliance/cache/3.1.0-rc.2/test-kits/acme-outdoor-live.yaml +78 -0
  136. package/compliance/cache/3.1.0-rc.2/test-kits/acme-outdoor.yaml +223 -0
  137. package/compliance/cache/3.1.0-rc.2/test-kits/billing-gate-runner.yaml +115 -0
  138. package/compliance/cache/3.1.0-rc.2/test-kits/bistro-oranje.yaml +126 -0
  139. package/compliance/cache/3.1.0-rc.2/test-kits/distributed-brand-runner.yaml +281 -0
  140. package/compliance/cache/3.1.0-rc.2/test-kits/nova-motors.yaml +262 -0
  141. package/compliance/cache/3.1.0-rc.2/test-kits/osei-natural.yaml +126 -0
  142. package/compliance/cache/3.1.0-rc.2/test-kits/parallel-dispatch-runner.yaml +196 -0
  143. package/compliance/cache/3.1.0-rc.2/test-kits/rate-limit-trip-runner.yaml +172 -0
  144. package/compliance/cache/3.1.0-rc.2/test-kits/signed-requests-runner.yaml +155 -0
  145. package/compliance/cache/3.1.0-rc.2/test-kits/single-side-trust-runner.yaml +294 -0
  146. package/compliance/cache/3.1.0-rc.2/test-kits/substitution-observer-runner.yaml +688 -0
  147. package/compliance/cache/3.1.0-rc.2/test-kits/summit-foods.yaml +125 -0
  148. package/compliance/cache/3.1.0-rc.2/test-kits/webhook-receiver-runner.yaml +265 -0
  149. package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/001-minimal-plan.json +43 -0
  150. package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/002-full-plan.json +217 -0
  151. package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/003-bookkeeping-stripped.json +60 -0
  152. package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/004a-human-review-omitted.json +43 -0
  153. package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/004b-human-review-explicit-null.json +49 -0
  154. package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/005a-policy-categories-order-1.json +53 -0
  155. package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/005b-policy-categories-order-2.json +57 -0
  156. package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/006a-ext-trace-v1.json +49 -0
  157. package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/006b-ext-trace-v2.json +53 -0
  158. package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/007-unicode-objectives.json +43 -0
  159. package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/008-numeric-canonicalization.json +65 -0
  160. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/README.md +220 -0
  161. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/canonicalization.json +241 -0
  162. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/keys.json +60 -0
  163. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/001-no-signature-header.json +24 -0
  164. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/002-wrong-tag.json +26 -0
  165. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/003-expired-signature.json +26 -0
  166. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/004-window-too-long.json +26 -0
  167. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/005-alg-not-allowed.json +26 -0
  168. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/006-missing-covered-component.json +26 -0
  169. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/007-missing-content-digest.json +26 -0
  170. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/008-unknown-keyid.json +26 -0
  171. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/009-key-ops-missing-verify.json +27 -0
  172. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/010-content-digest-mismatch.json +33 -0
  173. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/011-malformed-header.json +27 -0
  174. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/012-missing-expires-param.json +26 -0
  175. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/013-expires-le-created.json +27 -0
  176. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/014-missing-nonce-param.json +27 -0
  177. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/015-signature-invalid.json +28 -0
  178. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/016-replayed-nonce.json +35 -0
  179. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/017-key-revoked.json +38 -0
  180. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/018-digest-covered-when-forbidden.json +28 -0
  181. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/019-signature-without-signature-input.json +26 -0
  182. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/020-rate-abuse.json +34 -0
  183. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/021-duplicate-signature-input-label.json +31 -0
  184. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/022-multi-valued-content-type.json +31 -0
  185. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/023-multi-valued-content-digest.json +32 -0
  186. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/024-unquoted-string-param.json +31 -0
  187. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/025-jwk-alg-crv-mismatch.json +43 -0
  188. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/026-non-ascii-host.json +31 -0
  189. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/027-webhook-registration-authentication-unsigned.json +25 -0
  190. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/028-unsigned-protocol-method-required.json +26 -0
  191. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/001-basic-post.json +30 -0
  192. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/002-post-with-content-digest.json +31 -0
  193. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/003-es256-post.json +30 -0
  194. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/004-multiple-signature-labels.json +26 -0
  195. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/005-default-port-stripped.json +30 -0
  196. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/006-dot-segment-path.json +30 -0
  197. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/007-query-byte-preserved.json +30 -0
  198. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/008-percent-encoded-path.json +30 -0
  199. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/009-percent-encoded-unreserved-decoded.json +30 -0
  200. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/010-percent-encoded-slash-preserved.json +30 -0
  201. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/011-ipv6-authority.json +30 -0
  202. package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/012-ipv6-authority-default-port-stripped.json +30 -0
  203. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/README.md +211 -0
  204. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/keys.json +61 -0
  205. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/001-wrong-tag.json +26 -0
  206. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/002-expired-signature.json +26 -0
  207. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/003-window-too-long.json +26 -0
  208. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/004-alg-not-allowed.json +26 -0
  209. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/005-missing-authority-component.json +26 -0
  210. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/006-missing-content-digest.json +25 -0
  211. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/007-unknown-keyid.json +26 -0
  212. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/008-wrong-adcp-use.json +26 -0
  213. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/009-content-digest-mismatch.json +26 -0
  214. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/010-malformed-signature-input.json +26 -0
  215. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/011-signature-without-input.json +25 -0
  216. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/012-missing-expires-param.json +26 -0
  217. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/013-expires-le-created.json +26 -0
  218. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/014-missing-nonce-param.json +26 -0
  219. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/015-signature-invalid.json +26 -0
  220. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/016-replayed-nonce.json +37 -0
  221. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/017-key-revoked.json +32 -0
  222. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/018-rate-abuse.json +33 -0
  223. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/019-revocation-stale.json +32 -0
  224. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/020-key-ops-missing-verify.json +41 -0
  225. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/021-base64-alphabet-mixing.json +26 -0
  226. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/001-basic-post.json +24 -0
  227. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/002-es256-post.json +24 -0
  228. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/003-multiple-signature-labels.json +24 -0
  229. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/004-default-port-stripped.json +24 -0
  230. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/005-percent-encoded-path.json +24 -0
  231. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/006-query-byte-preserved.json +24 -0
  232. package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/007-body-without-idempotency-key.json +25 -0
  233. package/compliance/cache/3.1.0-rc.2/universal/billing-gate-dispatch.yaml +450 -0
  234. package/compliance/cache/3.1.0-rc.2/universal/canonical-format-validate-input.yaml +640 -0
  235. package/compliance/cache/3.1.0-rc.2/universal/capability-discovery.yaml +125 -0
  236. package/compliance/cache/3.1.0-rc.2/universal/collection-lists-pagination-integrity.yaml +306 -0
  237. package/compliance/cache/3.1.0-rc.2/universal/comply-controller-mode-gate.yaml +141 -0
  238. package/compliance/cache/3.1.0-rc.2/universal/content-standards-pagination-integrity.yaml +326 -0
  239. package/compliance/cache/3.1.0-rc.2/universal/deterministic-testing.yaml +1430 -0
  240. package/compliance/cache/3.1.0-rc.2/universal/error-compliance-signals.yaml +377 -0
  241. package/compliance/cache/3.1.0-rc.2/universal/error-compliance.yaml +528 -0
  242. package/compliance/cache/3.1.0-rc.2/universal/fictional-entities.yaml +307 -0
  243. package/compliance/cache/3.1.0-rc.2/universal/get-media-buys-pagination-integrity.yaml +160 -0
  244. package/compliance/cache/3.1.0-rc.2/universal/get-signals-pagination-integrity.yaml +210 -0
  245. package/compliance/cache/3.1.0-rc.2/universal/idempotency.yaml +861 -0
  246. package/compliance/cache/3.1.0-rc.2/universal/notification-config-event-scope.yaml +119 -0
  247. package/compliance/cache/3.1.0-rc.2/universal/notification-config-lifecycle.yaml +337 -0
  248. package/compliance/cache/3.1.0-rc.2/universal/notification-config-rejections.yaml +107 -0
  249. package/compliance/cache/3.1.0-rc.2/universal/pagination-integrity-creative-formats.yaml +265 -0
  250. package/compliance/cache/3.1.0-rc.2/universal/pagination-integrity-list-accounts.yaml +245 -0
  251. package/compliance/cache/3.1.0-rc.2/universal/pagination-integrity.yaml +263 -0
  252. package/compliance/cache/3.1.0-rc.2/universal/property-lists-pagination-integrity.yaml +307 -0
  253. package/compliance/cache/3.1.0-rc.2/universal/read-tool-idempotency.yaml +405 -0
  254. package/compliance/cache/3.1.0-rc.2/universal/runner-output-contract.yaml +1285 -0
  255. package/compliance/cache/3.1.0-rc.2/universal/schema-validation-signals.yaml +181 -0
  256. package/compliance/cache/3.1.0-rc.2/universal/schema-validation.yaml +548 -0
  257. package/compliance/cache/3.1.0-rc.2/universal/security.yaml +539 -0
  258. package/compliance/cache/3.1.0-rc.2/universal/signed-requests.yaml +217 -0
  259. package/compliance/cache/3.1.0-rc.2/universal/stale-response-advisory.yaml +295 -0
  260. package/compliance/cache/3.1.0-rc.2/universal/storyboard-schema.yaml +2194 -0
  261. package/compliance/cache/3.1.0-rc.2/universal/v3-envelope-integrity.yaml +117 -0
  262. package/compliance/cache/3.1.0-rc.2/universal/version-negotiation.yaml +130 -0
  263. package/compliance/cache/3.1.0-rc.2/universal/webhook-emission.yaml +411 -0
  264. package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-bulk-webhooks.yaml +82 -0
  265. package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-product-webhooks.yaml +83 -0
  266. package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-products.yaml +151 -0
  267. package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-signal-webhooks.yaml +83 -0
  268. package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-signals.yaml +149 -0
  269. package/dist/lib/index.d.ts +1 -1
  270. package/dist/lib/index.d.ts.map +1 -1
  271. package/dist/lib/index.js +9 -5
  272. package/dist/lib/index.js.map +1 -1
  273. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  274. package/dist/lib/testing/storyboard/default-invariants.js +30 -1
  275. package/dist/lib/testing/storyboard/default-invariants.js.map +1 -1
  276. package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
  277. package/dist/lib/testing/storyboard/runner.js +84 -21
  278. package/dist/lib/testing/storyboard/runner.js.map +1 -1
  279. package/dist/lib/testing/storyboard/types.d.ts +21 -0
  280. package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
  281. package/dist/lib/testing/storyboard/types.js.map +1 -1
  282. package/dist/lib/testing/types.d.ts +9 -0
  283. package/dist/lib/testing/types.d.ts.map +1 -1
  284. package/dist/lib/types/schemas.generated.d.ts +6707 -12040
  285. package/dist/lib/types/schemas.generated.d.ts.map +1 -1
  286. package/dist/lib/types/schemas.generated.js +1 -1
  287. package/dist/lib/types/schemas.generated.js.map +1 -1
  288. package/dist/lib/utils/signal-id-builders.d.ts +19 -0
  289. package/dist/lib/utils/signal-id-builders.d.ts.map +1 -1
  290. package/dist/lib/utils/signal-id-builders.js +30 -0
  291. package/dist/lib/utils/signal-id-builders.js.map +1 -1
  292. package/dist/lib/utils/tool-request-schemas.d.ts.map +1 -1
  293. package/dist/lib/utils/tool-request-schemas.js +3 -0
  294. package/dist/lib/utils/tool-request-schemas.js.map +1 -1
  295. package/dist/lib/v2/projection/constants.d.ts +28 -0
  296. package/dist/lib/v2/projection/constants.d.ts.map +1 -0
  297. package/dist/lib/v2/projection/constants.js +31 -0
  298. package/dist/lib/v2/projection/constants.js.map +1 -0
  299. package/dist/lib/v2/projection/registry.d.ts.map +1 -1
  300. package/dist/lib/v2/projection/registry.js +9 -4
  301. package/dist/lib/v2/projection/registry.js.map +1 -1
  302. package/dist/lib/version.d.ts +3 -3
  303. package/dist/lib/version.js +3 -3
  304. package/package.json +1 -1
  305. package/skills/SHAPE-GOTCHAS.md +5 -0
@@ -0,0 +1,539 @@
1
+ id: security_baseline
2
+ version: "1.0.0"
3
+ title: "Authentication baseline"
4
+ category: security
5
+ summary: "Every AdCP agent MUST require authentication on protected operations. At least one of static credentials or OAuth MUST be implemented and correctly advertised."
6
+ track: security
7
+ required_tools: [] # protocol-level, not tool-level
8
+
9
+ narrative: |
10
+ Every AdCP agent handles data belonging to publishers or buyers that other parties
11
+ should not see or modify. Without authentication on protected operations, a seller
12
+ agent would leak media buys, creative libraries, or account-level reports to anyone
13
+ who knew the URL. Without correct authentication metadata, buyers cannot obtain
14
+ tokens with the right audience and every authenticated request fails with 401 — an
15
+ agent-side misconfiguration that looks identical to "my client is broken".
16
+
17
+ AdCP uses a tiered model: discovery operations (`get_adcp_capabilities`,
18
+ `list_creative_formats`, `get_products` without pricing) are public; operations
19
+ that return tenant-scoped data or modify state (`list_creatives`, `create_media_buy`,
20
+ `get_media_buy_delivery`, `sync_creatives`, etc.) require credentials. See
21
+ [/docs/building/by-layer/L2/authentication](/docs/building/by-layer/L2/authentication).
22
+
23
+ AdCP accepts three credential mechanisms: static API keys (Authorization:
24
+ Bearer <key>), HTTP Basic credentials sent in the Authorization header, or OAuth
25
+ 2.0 + RFC 8707 resource indicators. An agent MUST implement at least one. It
26
+ MAY implement more than one. This storyboard verifies that (a) a protected
27
+ operation is rejected when called without credentials, (b) deliberately invalid
28
+ credentials are also rejected (an agent that 200s on an unauth call and 200s on
29
+ a bad-credential call is ignoring credentials entirely), and (c) at least one
30
+ auth mechanism is present and correctly advertised.
31
+
32
+ Pass semantics are encoded in the step flow: the unauth probe and
33
+ invalid-credential probe (when a test-kit key or Basic credential is present)
34
+ are always required, and at least one of the API key phase, Basic phase, or
35
+ OAuth discovery phase must contribute `auth_mechanism_verified`. Agents that
36
+ fail any required phase, or advertise no working auth mechanism, are
37
+ non-conformant.
38
+
39
+ **Static-credential agents (no OAuth).** An agent with no OAuth issuer -
40
+ sandbox, staging, or any production deployment that chose Bearer or Basic auth
41
+ - does NOT need to advertise RFC 9728 protected-resource metadata. Declare
42
+ `auth.api_key` or `auth.basic` in the test-kit and do not serve
43
+ `/.well-known/oauth-protected-resource/...`. The matching static-credential
44
+ phase contributes `auth_mechanism_verified` and `oauth_discovery` is allowed
45
+ to fail silently as an optional phase - no fake issuer URL or stub RFC 8414
46
+ metadata document is required. Agents that DO advertise `authorization_servers`
47
+ in their PRM MUST stand up the RFC 8414 auth-server metadata document to match;
48
+ advertising an issuer without serving its metadata is the failure mode this
49
+ storyboard was written to catch.
50
+
51
+ For local debugging before re-running compliance, use `adcp diagnose-auth <alias>`
52
+ (see adcp-client#563) to trace the full OAuth handshake and surface ranked
53
+ hypotheses about what's wrong.
54
+
55
+ agent:
56
+ interaction_model: "*" # applies to every agent regardless of specialism
57
+ examples:
58
+ - "Any AdCP agent (seller, signals, creative, retail media, SI, governance)"
59
+
60
+ caller:
61
+ role: buyer_agent
62
+ example: "Compliance test harness"
63
+
64
+ prerequisites:
65
+ description: |
66
+ The test kit declares the agent's **protected probe task** at `auth.probe_task`
67
+ — an auth-required, read-only task the agent supports (`list_creatives`,
68
+ `get_media_buy_delivery`, `get_signals`, etc.). The runner defaults to
69
+ `list_creatives` if unspecified. This is the task used for both the unauth and
70
+ invalid-credential probes, since public tasks like `get_adcp_capabilities`
71
+ return 200 without credentials by design.
72
+
73
+ The test kit MAY also provide an API key at `auth.api_key` or HTTP Basic
74
+ credentials at `auth.basic`. If both are absent, the static-credential phases
75
+ are skipped and the OAuth discovery phase MUST succeed instead. OAuth discovery
76
+ probes the well-known endpoint directly and does not require any test-kit
77
+ input.
78
+
79
+ Agent URLs MUST use `https://` in production compliance runs. The runner rejects
80
+ `http://` agent URLs outright unless invoked with `--allow-http` for local dev.
81
+ test_kit: "test-kits/acme-outdoor.yaml"
82
+
83
+ phases:
84
+ - id: unauth_rejection
85
+ title: "Unauthenticated requests on protected operations are rejected"
86
+ narrative: |
87
+ The baseline conformance bar. A compliant agent MUST NOT serve protected
88
+ operations without credentials. 401 is the semantically correct response
89
+ (no/invalid credentials, retry with auth); 403 is accepted for pragmatic
90
+ reasons (many production gateways conflate them behind path-based ACLs)
91
+ but is suboptimal — 403 means "authenticated but forbidden" and should not
92
+ apply to an anonymous caller. Anything else (200, 500, network hang) is
93
+ non-conformant.
94
+
95
+ On 401, the response MUST include a `WWW-Authenticate` header so clients
96
+ know how to authenticate. Correct examples:
97
+
98
+ ```
99
+ WWW-Authenticate: Bearer realm="https://agent.example.com/mcp", as_uri="https://auth.example.com"
100
+ WWW-Authenticate: Basic realm="https://agent.example.com/mcp"
101
+ ```
102
+
103
+ steps:
104
+ - id: probe_unauth
105
+ title: "Call the protected probe task with no credentials"
106
+ narrative: |
107
+ Send the test kit's declared protected task (`auth.probe_task`, default
108
+ `list_creatives`) with no Authorization header and no API key. The runner
109
+ forces credentials to be stripped via `auth: none` even when the transport
110
+ has a valid token configured. Expect 401 or 403.
111
+
112
+ If this probe returns 200 the agent is ignoring credentials on protected
113
+ operations — the most serious conformance failure this storyboard catches.
114
+ task: "$test_kit.auth.probe_task"
115
+ task_default: list_creatives
116
+ doc_ref: "/protocol/authentication"
117
+ comply_scenario: security_unauth_rejection
118
+ stateful: false
119
+ auth: none
120
+ expect_error: true
121
+ negative_path: schema_invalid
122
+ expected: |
123
+ The agent rejects the request with:
124
+ - http_status: 401 (preferred) or 403
125
+ - On 401, a `WWW-Authenticate` header naming the supported scheme
126
+ - Example: `WWW-Authenticate: Bearer realm="<agent-url>", as_uri="<auth-server>"`
127
+ - Example: `WWW-Authenticate: Basic realm="<agent-url>"`
128
+
129
+ sample_request:
130
+ context:
131
+ correlation_id: "security_baseline--probe_unauth"
132
+
133
+ validations:
134
+ - check: http_status_in
135
+ allowed_values: [401, 403]
136
+ description: "Agent returned 200 or 5xx on an unauthenticated protected call — it MUST reject with 401 (and send WWW-Authenticate) or 403"
137
+ - check: on_401_require_header
138
+ value: "www-authenticate"
139
+ description: "401 responses MUST include a WWW-Authenticate header naming the supported scheme (e.g. `Bearer realm=\"<agent-url>\", as_uri=\"<auth-server>\"` or `Basic realm=\"<agent-url>\"`)"
140
+
141
+ - id: api_key_path
142
+ title: "API key mechanism"
143
+ narrative: |
144
+ **This phase OR `basic_path` OR `oauth_discovery` MUST pass — see `mechanism_required`.**
145
+
146
+ If the test kit provides an API key, the agent MUST accept it on the protected
147
+ probe task AND MUST reject a deliberately invalid key. Both checks together
148
+ prove the key is actually enforced — a 200 response with a valid key means
149
+ nothing if the agent returns 200 with an obviously bad key too. If no key is
150
+ provided the phase is skipped and OAuth discovery must succeed instead.
151
+
152
+ optional: true
153
+ skip_if: "!test_kit.auth.api_key"
154
+ branch_set:
155
+ id: auth_mechanism_verified
156
+ semantics: any_of
157
+
158
+ steps:
159
+ - id: probe_api_key
160
+ title: "Call the protected probe task with the provided API key"
161
+ narrative: |
162
+ Authenticate with the API key supplied by the test kit (as a Bearer token
163
+ in the Authorization header) and expect a normal 200 response on the
164
+ declared protected task. This confirms the static-credential path works
165
+ end to end.
166
+ task: "$test_kit.auth.probe_task"
167
+ task_default: list_creatives
168
+ doc_ref: "/protocol/authentication"
169
+ comply_scenario: security_api_key
170
+ stateful: false
171
+ auth:
172
+ type: api_key
173
+ from_test_kit: true
174
+ expected: |
175
+ The agent accepts the API key and returns a well-formed response with
176
+ http_status 200.
177
+
178
+ sample_request:
179
+ context:
180
+ correlation_id: "security_baseline--probe_api_key"
181
+
182
+ validations:
183
+ - check: http_status
184
+ value: 200
185
+ description: "Agent accepts the provided API key on the protected probe task"
186
+ - check: field_present
187
+ path: "context"
188
+ description: "Response echoes back the context object"
189
+ - check: field_value
190
+ path: "context.correlation_id"
191
+ value: "security_baseline--probe_api_key"
192
+ description: "Context correlation_id returned unchanged"
193
+
194
+ - id: probe_invalid_api_key
195
+ title: "Reject a deliberately invalid API key"
196
+ narrative: |
197
+ Send the same protected task with a Bearer token the runner generates
198
+ per-run from 32 random bytes (prefix `invalid-` for log readability,
199
+ e.g. `invalid-8e4a2c1f...`). A conformant agent rejects this with
200
+ 401/403. An agent that returns 200 here is ignoring credentials entirely
201
+ and falsely appeared to pass `probe_api_key` — only the pair of (200 with
202
+ valid key, 401/403 with random-invalid key) proves the key is actually
203
+ checked. The token is randomized per run so no allowlist can collide
204
+ with it by accident.
205
+
206
+ Contributes `auth_mechanism_verified` only when *both* this step and
207
+ `probe_api_key` succeed.
208
+ task: "$test_kit.auth.probe_task"
209
+ task_default: list_creatives
210
+ doc_ref: "/protocol/authentication"
211
+ comply_scenario: security_invalid_key_rejection
212
+ stateful: false
213
+ auth:
214
+ type: api_key
215
+ value_strategy: random_invalid
216
+ contributes: true
217
+ contributes_if: "prior_step.probe_api_key.passed"
218
+ expect_error: true
219
+ negative_path: schema_invalid
220
+ expected: |
221
+ The agent rejects the random-invalid key with:
222
+ - http_status: 400 (if the agent enforces a key format the random token
223
+ doesn't match), 401 (preferred), or 403
224
+ - On 401, a `WWW-Authenticate: Bearer ... error="invalid_token"` header
225
+
226
+ sample_request:
227
+ context:
228
+ correlation_id: "security_baseline--probe_invalid_api_key"
229
+
230
+ validations:
231
+ - check: http_status_in
232
+ allowed_values: [400, 401, 403]
233
+ description: "Agent returned 200 on a known-bad API key — credentials are not being validated. MUST reject with 400 (key-format validation failure per RFC 6750 §3.1), 401 (preferred), or 403"
234
+ - check: on_401_require_header
235
+ value: "www-authenticate"
236
+ description: "401 responses on invalid credentials MUST include WWW-Authenticate with `error=\"invalid_token\"` per RFC 6750 §3"
237
+
238
+ - id: basic_path
239
+ title: "HTTP Basic auth mechanism"
240
+ narrative: |
241
+ **This phase OR `api_key_path` OR `oauth_discovery` MUST pass — see
242
+ `mechanism_required`.**
243
+
244
+ If the test kit provides Basic credentials, the agent MUST accept them on
245
+ the protected probe task AND MUST reject deliberately invalid Basic
246
+ credentials. Both checks together prove the Basic credential is actually
247
+ enforced. Basic is a static shared-secret mechanism like a Bearer API key;
248
+ it is acceptable for conformance when sent in the Authorization header over
249
+ HTTPS and validated on every protected request. If no Basic credential is
250
+ provided the phase is skipped and another auth mechanism must succeed
251
+ instead.
252
+
253
+ optional: true
254
+ skip_if: "!test_kit.auth.basic"
255
+ branch_set:
256
+ id: auth_mechanism_verified
257
+ semantics: any_of
258
+
259
+ steps:
260
+ - id: probe_basic
261
+ title: "Call the protected probe task with the provided Basic credential"
262
+ narrative: |
263
+ Authenticate with the Basic credential supplied by the test kit (as an
264
+ `Authorization: Basic ...` header) and expect a normal 200 response on
265
+ the declared protected task. This confirms the Basic credential path
266
+ works end to end.
267
+ task: "$test_kit.auth.probe_task"
268
+ task_default: list_creatives
269
+ doc_ref: "/protocol/authentication"
270
+ comply_scenario: security_basic
271
+ stateful: false
272
+ auth:
273
+ type: basic
274
+ from_test_kit: "auth.basic"
275
+ expected: |
276
+ The agent accepts the Basic credential and returns a well-formed response
277
+ with http_status 200.
278
+
279
+ sample_request:
280
+ context:
281
+ correlation_id: "security_baseline--probe_basic"
282
+
283
+ validations:
284
+ - check: http_status
285
+ value: 200
286
+ description: "Agent accepts the provided Basic credential on the protected probe task"
287
+ - check: field_present
288
+ path: "context"
289
+ description: "Response echoes back the context object"
290
+ - check: field_value
291
+ path: "context.correlation_id"
292
+ value: "security_baseline--probe_basic"
293
+ description: "Context correlation_id returned unchanged"
294
+
295
+ - id: probe_invalid_basic
296
+ title: "Reject deliberately invalid Basic credentials"
297
+ narrative: |
298
+ Send the same protected task with Basic credentials the runner generates
299
+ per-run from random bytes. A conformant agent rejects this with 401/403.
300
+ An agent that returns 200 here is ignoring credentials entirely and
301
+ falsely appeared to pass `probe_basic` - only the pair of (200 with
302
+ valid Basic, 401/403 with random-invalid Basic) proves the credential is
303
+ actually checked. The credential is randomized per run so no allowlist
304
+ can collide with it by accident.
305
+
306
+ Contributes `auth_mechanism_verified` only when *both* this step and
307
+ `probe_basic` succeed.
308
+ task: "$test_kit.auth.probe_task"
309
+ task_default: list_creatives
310
+ doc_ref: "/protocol/authentication"
311
+ comply_scenario: security_invalid_basic_rejection
312
+ stateful: false
313
+ auth:
314
+ type: basic
315
+ value_strategy: random_invalid
316
+ contributes: true
317
+ contributes_if: "prior_step.probe_basic.passed"
318
+ expect_error: true
319
+ negative_path: schema_invalid
320
+ expected: |
321
+ The agent rejects the random-invalid Basic credential with:
322
+ - http_status: 400 (credential format validation failure), 401
323
+ (preferred), or 403
324
+ - On 401, a `WWW-Authenticate: Basic ...` header
325
+
326
+ sample_request:
327
+ context:
328
+ correlation_id: "security_baseline--probe_invalid_basic"
329
+
330
+ validations:
331
+ - check: http_status_in
332
+ allowed_values: [400, 401, 403]
333
+ description: "Agent returned 200 on known-bad Basic credentials — credentials are not being validated. MUST reject with 400 (credential-format validation failure), 401 (preferred), or 403"
334
+ - check: on_401_require_header
335
+ value: "www-authenticate"
336
+ description: "401 responses on invalid Basic credentials MUST include WWW-Authenticate (for example, `Basic realm=\"<agent-url>\"`)"
337
+
338
+ - id: oauth_discovery
339
+ title: "OAuth discovery and audience binding"
340
+ narrative: |
341
+ **This phase OR `api_key_path` OR `basic_path` MUST pass — see
342
+ `mechanism_required`.**
343
+
344
+ **Skip for static-credential-only agents.** If your agent has no OAuth
345
+ issuer, declare `auth.api_key` or `auth.basic` in the test-kit and do not
346
+ serve PRM. This phase will fail its probes (404 on the well-known path),
347
+ but failures inside an `optional: true` phase do not fail the storyboard —
348
+ the static credential path carries `auth_mechanism_verified` on its own.
349
+ Do NOT serve
350
+ PRM pointing at a fake issuer to "pass" this phase; that triggers the
351
+ advertised-but-unserved failure mode below.
352
+
353
+ OAuth-enabled agents advertise their auth server at the well-known path defined
354
+ by RFC 9728 §3. For an agent at `https://agent.example.com/mcp`, metadata lives
355
+ at `https://agent.example.com/.well-known/oauth-protected-resource/mcp` — the
356
+ agent's resource path is appended after the well-known segment. The metadata
357
+ MUST include a `resource` URL that matches the full URL being called (including
358
+ path) so clients issue RFC 8707 `resource` parameters that result in tokens
359
+ bound to the correct audience.
360
+
361
+ The canonical failure this phase catches: an agent advertising the auth
362
+ server's origin as its own `resource`, causing issued tokens to have the
363
+ wrong audience and every request to 401 for reasons the buyer cannot
364
+ diagnose from the error message alone (see adcp-client#563). Fix the metadata
365
+ document, not the OAuth config.
366
+
367
+ Contribution to `auth_mechanism_verified` is gated on the pair of
368
+ `probe_protected_resource` (advertises OAuth correctly) AND
369
+ `probe_invalid_oauth_token` (actually validates inbound tokens), symmetric
370
+ with the API key path. Metadata alone is not sufficient — an agent that
371
+ advertises OAuth but accepts any Bearer is broken in the same way an
372
+ agent that ignores API keys is broken.
373
+
374
+ optional: true
375
+ branch_set:
376
+ id: auth_mechanism_verified
377
+ semantics: any_of
378
+
379
+ steps:
380
+ - id: probe_protected_resource
381
+ title: "GET /.well-known/oauth-protected-resource/<path>"
382
+ narrative: |
383
+ Fetch the protected-resource metadata document for the agent's URL per
384
+ RFC 9728. Verify it returns 200, contains `resource` and
385
+ `authorization_servers`, and — the critical check — that the `resource`
386
+ value equals the agent URL under test. A mismatched `resource` silently
387
+ breaks every OAuth client.
388
+ task: protected_resource_metadata
389
+ doc_ref: "/protocol/authentication"
390
+ comply_scenario: security_oauth_discovery
391
+ stateful: false
392
+ expected: |
393
+ A 200 response with a JSON document. Example for an agent at
394
+ `https://agent.example.com/mcp`:
395
+
396
+ ```json
397
+ {
398
+ "resource": "https://agent.example.com/mcp",
399
+ "authorization_servers": ["https://auth.example.com"],
400
+ "bearer_methods_supported": ["header"]
401
+ }
402
+ ```
403
+
404
+ Required fields:
405
+ - `resource`: MUST equal the agent URL being called (including path)
406
+ - `authorization_servers`: MUST be a non-empty array of issuer URLs
407
+
408
+ sample_response:
409
+ resource: "https://agent.example.com/mcp"
410
+ authorization_servers:
411
+ - "https://auth.example.com"
412
+ bearer_methods_supported:
413
+ - "header"
414
+
415
+ validations:
416
+ - check: http_status
417
+ value: 200
418
+ description: "Protected-resource metadata is served at the well-known path per RFC 9728 §3"
419
+ - check: field_present
420
+ path: "resource"
421
+ description: "Metadata declares the protected resource URL"
422
+ - check: field_present
423
+ path: "authorization_servers"
424
+ description: "Metadata declares at least one authorization server issuer URL"
425
+ - check: resource_equals_agent_url
426
+ description: "The `resource` field in your metadata MUST equal the full URL clients call (including path). A common mistake: advertising the auth server's origin as `resource`. Fix the metadata document, not the OAuth config. Runner normalizes: scheme+host lowercased, default ports (443/80) elided; path is case-sensitive."
427
+
428
+ - id: probe_auth_server_metadata
429
+ title: "Verify authorization_servers[0] resolves (RFC 8414)"
430
+ narrative: |
431
+ Fetch the OAuth authorization-server metadata for the first issuer listed,
432
+ per RFC 8414 §3. The path is `<issuer>/.well-known/oauth-authorization-server`
433
+ — NOT `/.well-known/openid-configuration` (that's OIDC Discovery, a
434
+ different spec). Confirm the document is reachable and exposes the minimum
435
+ fields clients need to request a token (`issuer` and `token_endpoint`).
436
+
437
+ The runner applies SSRF guardrails on this outbound fetch: HTTPS only,
438
+ no RFC 1918 / loopback / link-local hosts, bounded response size and
439
+ time. If you are testing locally against a localhost auth server, run
440
+ the compliance runner with `--allow-http` to relax these guards for dev.
441
+ task: oauth_auth_server_metadata
442
+ doc_ref: "/protocol/authentication"
443
+ comply_scenario: security_oauth_discovery
444
+ stateful: false
445
+ expected: |
446
+ A 200 response from `<issuer>/.well-known/oauth-authorization-server` per
447
+ RFC 8414 §3 with at least `issuer`, `token_endpoint`, and one of
448
+ `grant_types_supported` or `response_types_supported` present.
449
+
450
+ validations:
451
+ - check: http_status
452
+ value: 200
453
+ description: "Authorization server metadata is reachable at <issuer>/.well-known/oauth-authorization-server (RFC 8414 §3) — not /.well-known/openid-configuration"
454
+ - check: field_present
455
+ path: "issuer"
456
+ description: "Authorization server declares its issuer"
457
+ - check: field_present
458
+ path: "token_endpoint"
459
+ description: "Authorization server exposes a token endpoint"
460
+
461
+ - id: probe_invalid_oauth_token
462
+ title: "Reject a bogus Bearer token on the protected task"
463
+ narrative: |
464
+ Metadata correctness proves the agent *advertises* OAuth correctly. It
465
+ does NOT prove the agent actually validates inbound tokens. An agent
466
+ that accepts any Bearer token on protected operations is broken in
467
+ exactly the same way an agent that ignores API keys is broken — this
468
+ step closes that loophole symmetrically.
469
+
470
+ The runner sends a JWT-shaped token generated per run: the header and
471
+ payload are well-formed base64url-encoded JSON objects
472
+ (`{"alg":"RS256","typ":"JWT"}` / `{"sub":"invalid","aud":"<agent-url>"}`)
473
+ so the agent's JWT parser succeeds, and the signature segment is
474
+ random base64url bytes so signature verification fails. Well-implemented
475
+ validators will return 401 `invalid_token` per RFC 6750 §3.1. Strict
476
+ validators that reject at parse time may return 400 `invalid_request`
477
+ per RFC 6750 §3.1 — both outcomes are conformant (the agent rejected
478
+ the bogus token). Minimal validators that don't parse at all should
479
+ still return 401 because the Bearer string doesn't match any issued
480
+ token. The token is randomized per run so no allowlist can collide
481
+ with it.
482
+ task: "$test_kit.auth.probe_task"
483
+ task_default: list_creatives
484
+ doc_ref: "/protocol/authentication"
485
+ comply_scenario: security_oauth_token_rejection
486
+ stateful: false
487
+ auth:
488
+ type: oauth_bearer
489
+ value_strategy: random_invalid_jwt
490
+ contributes: true
491
+ contributes_if: "prior_step.probe_protected_resource.passed"
492
+ expect_error: true
493
+ negative_path: schema_invalid
494
+ expected: |
495
+ The agent rejects the bogus Bearer with:
496
+ - http_status: 400 (syntactic parse-time rejection), 401 (preferred —
497
+ signature/audience/expiry failure), or 403
498
+ - On 401, a `WWW-Authenticate: Bearer ... error="invalid_token"` header
499
+
500
+ sample_request:
501
+ context:
502
+ correlation_id: "security_baseline--probe_invalid_oauth_token"
503
+
504
+ validations:
505
+ - check: http_status_in
506
+ allowed_values: [400, 401, 403]
507
+ description: "Agent returned 200 on a bogus Bearer token — OAuth validation is not running on protected operations. MUST reject with 400 (parse-time rejection per RFC 6750 §3.1), 401 (preferred — signature/audience failure), or 403"
508
+ - check: on_401_require_header
509
+ value: "www-authenticate"
510
+ description: "401 responses on invalid tokens MUST include WWW-Authenticate with `error=\"invalid_token\"` per RFC 6750 §3"
511
+
512
+ - id: mechanism_required
513
+ title: "At least one mechanism must be verified"
514
+ narrative: |
515
+ Logical check — not a network call. The storyboard runner fails this phase
516
+ if none of `api_key_path`, `basic_path`, or `oauth_discovery` contributed
517
+ `auth_mechanism_verified`. An agent that rejects unauthenticated requests
518
+ but advertises no working auth mechanism cannot actually be called by a
519
+ compliant buyer, so it does not pass the baseline.
520
+
521
+ steps:
522
+ - id: assert_mechanism
523
+ title: "Require auth_mechanism_verified from at least one path"
524
+ narrative: |
525
+ Synthetic assertion over accumulated flags from prior phases. Passes
526
+ if any prior optional phase contributed `auth_mechanism_verified`.
527
+ task: assert_contribution
528
+ comply_scenario: security_mechanism_required
529
+ stateful: false
530
+ expected: |
531
+ At least one of the API key path (both valid-key and invalid-key steps
532
+ must succeed), Basic path (both valid-credential and invalid-credential
533
+ steps must succeed), or OAuth path (correct metadata AND token
534
+ validation both must succeed) contributed `auth_mechanism_verified`.
535
+
536
+ validations:
537
+ - check: any_of
538
+ allowed_values: ["auth_mechanism_verified"]
539
+ description: "No auth mechanism was verified. Three things to check: (1) your test kit declares `auth.probe_task` pointing at a read-only authenticated task your agent supports (defaults to `list_creatives`); (2) you provide `auth.api_key` or `auth.basic` in your test kit AND the agent accepts it and rejects random-invalid credentials; OR (3) you serve protected-resource metadata at /.well-known/oauth-protected-resource/<path> with `resource` equal to your agent URL."