@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,500 @@
1
+ id: media_buy_seller/per_creative_conversion_attribution
2
+ version: "1.0.0"
3
+ title: "Seller surfaces per-creative conversion attribution in delivery reporting"
4
+ category: media_buy_seller
5
+ summary: "Verifies that a seller advertising conversion_tracking.per_creative_attribution can register two creatives on a single package, accept a media buy with a CPA event-kind goal, ingest conversion events, and surface a populated by_package[].by_creative[] breakdown carrying conversions per creative in get_media_buy_delivery. Sibling to media_buy_seller/performance_buy_flow gated on the per_creative_attribution sub-capability: sellers that report attribution only at the line / package / placement / campaign granularity (retail-media, MMP-mediated mobile, CTV performance) grade not_applicable, not failing."
6
+ track: media_buy
7
+
8
+ # Gate: scenario runs only when the seller declares
9
+ # conversion_tracking.per_creative_attribution equals true. Sellers that
10
+ # attribute at coarser granularity (retail-media per-line, MMP per-campaign,
11
+ # broadcast/CTV per-placement) grade `not_applicable`, not failing.
12
+ # per_creative_attribution is a sub-capability of conversion_tracking — gating
13
+ # on this bit rather than on conversion_tracking presence is what keeps
14
+ # honest coarser-granularity implementations from failing on the per-creative
15
+ # breakdown that performance_buy_flow deliberately defers.
16
+ requires_capability:
17
+ path: media_buy.conversion_tracking.per_creative_attribution
18
+ equals: true
19
+
20
+ required_tools:
21
+ - get_products
22
+ - sync_event_sources
23
+ - sync_creatives
24
+ - create_media_buy
25
+ - log_event
26
+ - get_media_buy_delivery
27
+ - comply_test_controller
28
+
29
+ invariants:
30
+ - status.monotonic
31
+
32
+ narrative: |
33
+ Per-creative conversion attribution is the discriminating capability of
34
+ sellers whose attribution pipelines can route a logged conversion back to
35
+ the specific creative that drove it — typically via internal click-id or
36
+ view-through correlation that ties the event to the served impression. When
37
+ the seller advertises per_creative_attribution: true, buyers can rely on
38
+ the by_package[].by_creative[] breakdown in delivery reporting carrying
39
+ conversions per creative, not just aggregate package totals.
40
+
41
+ Most performance sellers cannot do this. Retail-media networks (Criteo,
42
+ Amazon Ads) typically expose conversions at the line level with creative
43
+ rotation opaque. MMP-mediated mobile (post-iOS-14) attributes at the
44
+ campaign / ad-set level. Broadcast and CTV performance products attribute
45
+ at the placement. Gating this scenario on the explicit sub-capability bit
46
+ is what keeps honest coarser-granularity implementations from failing on a
47
+ breakdown they truthfully don't produce.
48
+
49
+ This is the deferred half of performance_buy_flow. The CPA scenario
50
+ deliberately omits per-creative assertions for exactly this reason —
51
+ honest adopters report at differing granularities. The bit gates the
52
+ scenario; the scenario asserts the breakdown is populated end-to-end.
53
+
54
+ Discriminating behaviors this scenario verifies:
55
+ 1. sync_creatives registers two distinct creatives on the buyer's account,
56
+ each with its own creative_id and shape-valid display assets.
57
+ 2. create_media_buy accepts a package whose creative_assignments references
58
+ BOTH creatives and whose optimization_goal is event-kind with a CPA
59
+ target — the seller commits to rotating across both creatives AND
60
+ attributing conversions per creative.
61
+ 3. log_event flows conversions back against the registered event source.
62
+ log_event does not carry creative_id on the event payload (core/event.json) —
63
+ the seller MUST attribute via its internal click / view-through
64
+ correlation. Two events with distinct event_ids are logged; the seller
65
+ spreads attributed conversions across the two creatives per its own
66
+ correlation, and simulate_delivery's conversions count drives the
67
+ totals.
68
+ 4. get_media_buy_delivery returns the by_package[].by_creative[] breakdown
69
+ populated for BOTH creatives, each carrying creative_id and conversions.
70
+ The discriminating signal is the second row — a single-row breakdown
71
+ covering only one of the two assigned creatives would be a façade
72
+ (matching the impression rotation but not the conversion attribution).
73
+
74
+ Per-creative conversion_value / roas breakdown is intentionally NOT
75
+ asserted here. Sellers that compute ROAS at the creative level can declare
76
+ the per_creative_attribution bit and surface conversion_value on each
77
+ by_creative row, but the assertion target of this scenario is conversion
78
+ attribution (the field the bit names); per-creative value is a strict
79
+ superset that doesn't need an additional gate.
80
+
81
+ agent:
82
+ interaction_model: media_buy_seller
83
+ capabilities:
84
+ - sells_media
85
+ - supports_non_guaranteed
86
+ - conversion_tracking
87
+ examples:
88
+ - "Social platforms with per-ad conversion attribution (Meta, TikTok, Snap)"
89
+ - "DSPs operating their own attribution graph with creative-level resolution"
90
+ - "Walled-garden platforms with deterministic per-creative attribution"
91
+
92
+ caller:
93
+ role: buyer_agent
94
+ example: "Pinnacle Agency (buyer)"
95
+
96
+ prerequisites:
97
+ description: |
98
+ The seller must implement comply_test_controller with simulate_delivery
99
+ accepting a `conversions` param so the per-creative breakdown is
100
+ observable via get_media_buy_delivery without a real attribution run.
101
+
102
+ The buyer fixture supplies a brand, an operator, a conversion event
103
+ source definition, and two distinct display creatives sufficient to
104
+ exercise the per-creative breakdown.
105
+ test_kit: "test-kits/acme-outdoor.yaml"
106
+ controller_seeding: true
107
+
108
+ fixtures:
109
+ products:
110
+ - product_id: "performance_per_creative_q2"
111
+ delivery_type: "non_guaranteed"
112
+ channels: ["display"]
113
+ format_ids:
114
+ - id: "display_300x250"
115
+ pricing_options:
116
+ - product_id: "performance_per_creative_q2"
117
+ pricing_option_id: "auction_cpm"
118
+ pricing_model: "cpm"
119
+ currency: "USD"
120
+ floor_price: 1.50
121
+
122
+ phases:
123
+
124
+ - id: setup
125
+ title: "Establish account and discover products"
126
+ steps:
127
+ - id: sync_accounts
128
+ title: "Establish account"
129
+ task: sync_accounts
130
+ schema_ref: "account/sync-accounts-request.json"
131
+ response_schema_ref: "account/sync-accounts-response.json"
132
+ doc_ref: "/accounts/tasks/sync_accounts"
133
+ stateful: true
134
+ expected: |
135
+ Return the account with account_id and status active.
136
+ sample_request:
137
+ accounts:
138
+ - brand:
139
+ domain: "acmeoutdoor.example"
140
+ operator: "pinnacle-agency.example"
141
+ billing: "operator"
142
+ idempotency_key: "$generate:uuid_v4#per_creative_conversion_attribution_setup_sync_accounts"
143
+ validations:
144
+ - check: response_schema
145
+ description: "Response matches sync-accounts-response.json schema"
146
+ - check: field_present
147
+ path: "accounts[0].account_id"
148
+ description: "Account has a platform-assigned ID"
149
+
150
+ - id: get_products_for_per_creative
151
+ title: "Discover products supporting per-creative conversion attribution"
152
+ task: get_products
153
+ schema_ref: "media-buy/get-products-request.json"
154
+ response_schema_ref: "media-buy/get-products-response.json"
155
+ doc_ref: "/media-buy/task-reference/get_products"
156
+ stateful: false
157
+ expected: |
158
+ Return at least one product whose conversion_tracking capabilities
159
+ include per-creative attribution.
160
+ sample_request:
161
+ buying_mode: "brief"
162
+ brief: "Performance display, US, adults 25-54. Target CPA $35 on purchase events from acmeoutdoor.example. Two creative variants — need per-creative conversion breakdown in delivery reporting."
163
+ required_capabilities:
164
+ - "conversion_tracking"
165
+ account:
166
+ brand:
167
+ domain: "acmeoutdoor.example"
168
+ operator: "pinnacle-agency.example"
169
+ validations:
170
+ - check: response_schema
171
+ description: "Response matches get-products-response.json schema"
172
+ - check: field_present
173
+ path: "products"
174
+ description: "Response contains products"
175
+
176
+ - id: event_source_binding
177
+ title: "Register the conversion event source"
178
+ narrative: |
179
+ The performance buy cannot be created without a registered event
180
+ source. This phase exercises the binding — sync_event_sources returns
181
+ an event_source_id that the next phase's create_media_buy references on
182
+ the package's optimization_goal.
183
+
184
+ steps:
185
+ - id: sync_event_sources
186
+ title: "Register a website conversion source"
187
+ task: sync_event_sources
188
+ schema_ref: "media-buy/sync-event-sources-request.json"
189
+ response_schema_ref: "media-buy/sync-event-sources-response.json"
190
+ doc_ref: "/media-buy/task-reference/sync_event_sources"
191
+ stateful: true
192
+ expected: |
193
+ Return event_sources with event_source_id, setup.snippet, and
194
+ action: created. The id is captured for the create_media_buy phase.
195
+ sample_request:
196
+ account:
197
+ brand:
198
+ domain: "acmeoutdoor.example"
199
+ operator: "pinnacle-agency.example"
200
+ event_sources:
201
+ - event_source_id: "acmeoutdoor_website"
202
+ name: "Acme Outdoor Website"
203
+ event_types: ["purchase"]
204
+ allowed_domains: ["acmeoutdoor.example"]
205
+ idempotency_key: "$generate:uuid_v4#per_creative_conversion_attribution_event_source_binding_sync_event_sources"
206
+ validations:
207
+ - check: response_schema
208
+ description: "Response matches sync-event-sources-response.json schema"
209
+ - check: field_present
210
+ path: "event_sources[0].event_source_id"
211
+ description: "Event source has a platform-assigned ID"
212
+ # Anti-façade: an adapter that returns a shape-valid
213
+ # sync_event_sources response without forwarding the source
214
+ # definition upstream fails this check.
215
+ - check: upstream_traffic
216
+ description: "sync_event_sources caused upstream traffic registering the event source"
217
+ min_count: 1
218
+ endpoint_pattern: "POST *"
219
+
220
+ - id: register_two_creatives_and_create_buy
221
+ title: "Register two creatives and create a buy assigning both to one package"
222
+ narrative: |
223
+ The buyer pushes two distinct display creatives to the seller's
224
+ creative library via sync_creatives, then creates a media buy whose
225
+ single package's creative_assignments references BOTH creatives. The
226
+ package carries an event-kind optimization_goal binding to the
227
+ registered event source with a CPA target — the seller commits to
228
+ rotating delivery across both creatives AND attributing conversions
229
+ per creative.
230
+
231
+ steps:
232
+ - id: sync_two_creatives
233
+ title: "Push two distinct display creatives"
234
+ task: sync_creatives
235
+ schema_ref: "creative/sync-creatives-request.json"
236
+ response_schema_ref: "creative/sync-creatives-response.json"
237
+ doc_ref: "/creative/task-reference/sync_creatives"
238
+ stateful: true
239
+ expected: |
240
+ Accept both creatives and return them in the creatives array with
241
+ per-creative action (created) and platform-assigned status. Both
242
+ creative_ids are referenced in the next step's create_media_buy.
243
+ sample_request:
244
+ account:
245
+ brand:
246
+ domain: "acmeoutdoor.example"
247
+ operator: "pinnacle-agency.example"
248
+ creatives:
249
+ - creative_id: "creative_acme_1"
250
+ name: "Acme Outdoor — Trail Pro display 300x250 (variant A)"
251
+ format_id:
252
+ agent_url: "https://your-platform.example.com"
253
+ id: "display_300x250"
254
+ assets:
255
+ image:
256
+ asset_type: "image"
257
+ url: "https://test-assets.adcontextprotocol.org/acme-outdoor/trail-pro-a-300x250.jpg"
258
+ width: 300
259
+ height: 250
260
+ click_url:
261
+ asset_type: "url"
262
+ url: "https://acmeoutdoor.example/trail-pro?v=a"
263
+ - creative_id: "creative_acme_2"
264
+ name: "Acme Outdoor — Trail Pro display 300x250 (variant B)"
265
+ format_id:
266
+ agent_url: "https://your-platform.example.com"
267
+ id: "display_300x250"
268
+ assets:
269
+ image:
270
+ asset_type: "image"
271
+ url: "https://test-assets.adcontextprotocol.org/acme-outdoor/trail-pro-b-300x250.jpg"
272
+ width: 300
273
+ height: 250
274
+ click_url:
275
+ asset_type: "url"
276
+ url: "https://acmeoutdoor.example/trail-pro?v=b"
277
+ idempotency_key: "$generate:uuid_v4#per_creative_conversion_attribution_register_two_creatives_and_create_buy_sync_creatives"
278
+ validations:
279
+ - check: response_schema
280
+ description: "Response matches sync-creatives-response.json schema"
281
+ - check: field_present
282
+ path: "creatives[0].action"
283
+ description: "First creative has an action (created/updated)"
284
+ - check: field_present
285
+ path: "creatives[1].action"
286
+ description: "Second creative has an action (created/updated) — both must be registered for the per-creative breakdown to be meaningful"
287
+
288
+ - id: create_media_buy_two_creatives
289
+ title: "Create media buy assigning both creatives to one package with a CPA goal"
290
+ task: create_media_buy
291
+ schema_ref: "media-buy/create-media-buy-request.json"
292
+ response_schema_ref: "media-buy/create-media-buy-response.json"
293
+ doc_ref: "/media-buy/task-reference/create_media_buy"
294
+ stateful: true
295
+ expected: |
296
+ Create the media buy. Response carries a media_buy_id used for
297
+ subsequent log_event and get_media_buy_delivery calls. Both
298
+ creative_ids appear in the package's creative_assignments.
299
+ sample_request:
300
+ brand:
301
+ domain: "acmeoutdoor.example"
302
+ account:
303
+ brand:
304
+ domain: "acmeoutdoor.example"
305
+ operator: "pinnacle-agency.example"
306
+ start_time: "2026-06-01T00:00:00Z"
307
+ end_time: "2026-06-30T23:59:59Z"
308
+ packages:
309
+ - product_id: "performance_per_creative_q2"
310
+ budget: 25000
311
+ pricing_option_id: "auction_cpm"
312
+ creative_assignments:
313
+ - creative_id: "creative_acme_1"
314
+ - creative_id: "creative_acme_2"
315
+ optimization_goals:
316
+ - kind: "event"
317
+ event_sources:
318
+ - event_source_id: "acmeoutdoor_website"
319
+ event_type: "purchase"
320
+ target:
321
+ kind: "cost_per"
322
+ value: 35.00
323
+ priority: 1
324
+ idempotency_key: "$generate:uuid_v4#per_creative_conversion_attribution_register_two_creatives_and_create_buy_create_media_buy"
325
+ context_outputs:
326
+ - name: media_buy_id
327
+ path: "media_buy_id"
328
+ validations:
329
+ - check: response_schema
330
+ description: "Response matches create-media-buy-response.json schema"
331
+ - check: field_present
332
+ path: "media_buy_id"
333
+ description: "Media buy has a platform-assigned ID"
334
+
335
+ - id: log_conversions_against_both_creatives
336
+ title: "Log two purchase events against the bound event source"
337
+ narrative: |
338
+ The buyer logs two purchase events against the registered event source.
339
+ log_event's payload (core/event.json) does NOT carry creative_id —
340
+ attributing the event back to a specific creative is the seller's
341
+ internal click / view-through correlation responsibility, not the
342
+ buyer's. The buyer simply emits two events with distinct event_ids;
343
+ the seller is expected to spread attributed conversions across the
344
+ two assigned creatives per its own correlation, and simulate_delivery's
345
+ conversions count drives the totals that surface in by_creative[] in
346
+ the next phase.
347
+
348
+ Two events (rather than one) make the buyer's intent observable: the
349
+ buyer expects more than one conversion to surface, and the per-creative
350
+ breakdown should distribute them across creatives rather than
351
+ collapsing to a single row.
352
+
353
+ steps:
354
+ - id: log_purchase_event_1
355
+ title: "Log first purchase event"
356
+ task: log_event
357
+ schema_ref: "media-buy/log-event-request.json"
358
+ response_schema_ref: "media-buy/log-event-response.json"
359
+ doc_ref: "/media-buy/task-reference/log_event"
360
+ stateful: true
361
+ expected: |
362
+ Acknowledge the event with accepted status.
363
+ sample_request:
364
+ account:
365
+ brand:
366
+ domain: "acmeoutdoor.example"
367
+ operator: "pinnacle-agency.example"
368
+ event_source_id: "acmeoutdoor_website"
369
+ events:
370
+ - event_type: "purchase"
371
+ event_id: "evt_per_creative_001"
372
+ event_time: "2026-06-05T14:30:00Z"
373
+ user_match:
374
+ hashed_email: "a000000000000000000000000000000000000000000000000000000000000030"
375
+ custom_data:
376
+ order_total: 99.99
377
+ currency: "USD"
378
+ idempotency_key: "$generate:uuid_v4#per_creative_conversion_attribution_log_conversions_against_both_creatives_log_event_1"
379
+ validations:
380
+ - check: response_schema
381
+ description: "Response matches log-event-response.json schema"
382
+
383
+ - id: log_purchase_event_2
384
+ title: "Log second purchase event"
385
+ task: log_event
386
+ schema_ref: "media-buy/log-event-request.json"
387
+ response_schema_ref: "media-buy/log-event-response.json"
388
+ doc_ref: "/media-buy/task-reference/log_event"
389
+ stateful: true
390
+ expected: |
391
+ Acknowledge the event with accepted status. The seller is expected
392
+ to spread attributed conversions across the two assigned creatives
393
+ via internal click / view-through correlation; the discriminating
394
+ assertion is the populated by_creative[] breakdown in delivery, not
395
+ the per-event acknowledgement here.
396
+ sample_request:
397
+ account:
398
+ brand:
399
+ domain: "acmeoutdoor.example"
400
+ operator: "pinnacle-agency.example"
401
+ event_source_id: "acmeoutdoor_website"
402
+ events:
403
+ - event_type: "purchase"
404
+ event_id: "evt_per_creative_002"
405
+ event_time: "2026-06-06T10:15:00Z"
406
+ user_match:
407
+ hashed_email: "a000000000000000000000000000000000000000000000000000000000000031"
408
+ custom_data:
409
+ order_total: 149.99
410
+ currency: "USD"
411
+ idempotency_key: "$generate:uuid_v4#per_creative_conversion_attribution_log_conversions_against_both_creatives_log_event_2"
412
+ validations:
413
+ - check: response_schema
414
+ description: "Response matches log-event-response.json schema"
415
+
416
+ - id: assert_per_creative_breakdown_in_delivery
417
+ title: "Delivery reporting carries a populated per-creative conversion breakdown"
418
+ narrative: |
419
+ The discriminating assertion of per-creative attribution: delivery
420
+ reporting MUST surface conversions on each by_creative[] row, not just
421
+ at the package or buy level. The runner injects simulated impressions
422
+ + conversions + spend via the test controller, then verifies
423
+ get_media_buy_delivery returns a by_package[].by_creative[] array with
424
+ at least two rows — one per assigned creative — each carrying
425
+ creative_id and conversions.
426
+
427
+ A single-row breakdown covering only one of the two assigned creatives
428
+ would be a façade (the seller is rotating impressions but collapsing
429
+ conversion attribution to whichever creative it tracked first). The
430
+ second-row assertion is what keeps honest per-creative implementations
431
+ separated from coarser-granularity ones — sellers that can't attribute
432
+ per creative don't advertise the bit and grade not_applicable.
433
+
434
+ steps:
435
+ - id: simulate_per_creative_delivery
436
+ title: "Inject impressions + conversions + spend"
437
+ task: comply_test_controller
438
+ requires_tool: comply_test_controller
439
+ stateful: true
440
+ expected: |
441
+ The test controller acknowledges the simulated delivery.
442
+ sample_request:
443
+ account:
444
+ sandbox: true
445
+ scenario: "simulate_delivery"
446
+ params:
447
+ media_buy_id: "$context.media_buy_id"
448
+ impressions: 200000
449
+ clicks: 4500
450
+ conversions: 90
451
+ reported_spend:
452
+ amount: 3000.00
453
+ currency: "USD"
454
+ validations:
455
+ - check: field_value
456
+ path: "success"
457
+ allowed_values: [true]
458
+ description: "Delivery simulation succeeds"
459
+
460
+ - id: get_per_creative_delivery
461
+ title: "Get delivery and verify the per-creative conversion breakdown"
462
+ task: get_media_buy_delivery
463
+ schema_ref: "media-buy/get-media-buy-delivery-request.json"
464
+ response_schema_ref: "media-buy/get-media-buy-delivery-response.json"
465
+ doc_ref: "/media-buy/task-reference/get_media_buy_delivery"
466
+ stateful: true
467
+ expected: |
468
+ Delivery response includes:
469
+ - totals.conversions at the buy level (still required, same as
470
+ performance_buy_flow)
471
+ - by_package[0].by_creative[] array with at least two rows, each
472
+ carrying creative_id and conversions — the discriminating
473
+ assertion that the per_creative_attribution bit commits to
474
+
475
+ Single-row by_creative[] coverage is a façade signal: the seller
476
+ is reporting at the package level and labelling it per-creative.
477
+ The second-row assertion is the asymmetry check.
478
+ sample_request:
479
+ account:
480
+ brand:
481
+ domain: "acmeoutdoor.example"
482
+ operator: "pinnacle-agency.example"
483
+ media_buy_ids:
484
+ - "$context.media_buy_id"
485
+ include_package_daily_breakdown: true
486
+ validations:
487
+ - check: response_schema
488
+ description: "Response matches get-media-buy-delivery-response.json schema"
489
+ - check: field_present
490
+ path: "media_buy_deliveries[0].totals.conversions"
491
+ description: "Conversion count surfaced at the buy level"
492
+ - check: field_present
493
+ path: "media_buy_deliveries[0].by_package[0].by_creative[0].creative_id"
494
+ description: "First by_creative row carries creative_id — the breakdown is keyed"
495
+ - check: field_present
496
+ path: "media_buy_deliveries[0].by_package[0].by_creative[0].conversions"
497
+ description: "First by_creative row carries conversions — the discriminating assertion of per_creative_attribution"
498
+ - check: field_present
499
+ path: "media_buy_deliveries[0].by_package[0].by_creative[1].conversions"
500
+ description: "Second by_creative row carries conversions — confirms the breakdown isn't a single-row façade collapsing attribution to one creative when two were assigned"