@adcp/sdk 7.11.0 → 7.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compliance/cache/3.1.0-rc.2/domains/brand/index.yaml +160 -0
- package/compliance/cache/3.1.0-rc.2/domains/brand/scenarios/distributed_brand_resolution.yaml +415 -0
- package/compliance/cache/3.1.0-rc.2/domains/brand/scenarios/single_side_trust_extension.yaml +454 -0
- package/compliance/cache/3.1.0-rc.2/domains/creative/index.yaml +339 -0
- package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/billing_out_of_band.yaml +153 -0
- package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/canonical_supported_formats.yaml +212 -0
- package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/creative_lifecycle_webhooks.yaml +389 -0
- package/compliance/cache/3.1.0-rc.2/domains/creative/scenarios/native_in_feed.yaml +543 -0
- package/compliance/cache/3.1.0-rc.2/domains/governance/index.yaml +682 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/index.yaml +789 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/audience_buy_flow.yaml +380 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/available_actions.yaml +565 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/billing_finality_delivery.yaml +354 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/canonical_formats.yaml +861 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/clicks_buy_flow.yaml +264 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/completed_views_buy_flow.yaml +344 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/create_media_buy_async.yaml +234 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/creative_fate_after_cancellation.yaml +419 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/creative_reception.yaml +247 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/delivery_reporting.yaml +357 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/dependency_impairment.yaml +633 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/dependency_impairment_cardinality.yaml +800 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/event_dedup_flow.yaml +399 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/frequency_cap_enforcement.yaml +309 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_approved.yaml +214 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_conditions.yaml +199 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_denied.yaml +204 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/governance_denied_recovery.yaml +252 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/invalid_transitions.yaml +289 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/inventory_list_no_match.yaml +148 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/inventory_list_targeting.yaml +276 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/measurement_accountability.yaml +244 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/measurement_terms_rejected.yaml +203 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/package_correlation_legacy_fallback.yaml +113 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/pending_creatives_to_start.yaml +292 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/per_creative_conversion_attribution.yaml +500 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/performance_buy_flow.yaml +428 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/performance_buy_flow_roas.yaml +470 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/product_signal_targeting.yaml +373 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/proposal_finalize.yaml +399 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/proposal_finalize_asap_timing.yaml +264 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/proposal_not_found_errors.yaml +257 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/provenance_audit_observation.yaml +333 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/provenance_enforcement.yaml +517 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/provenance_truth_of_claim.yaml +294 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/reach_buy_flow.yaml +823 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/refine_finalize_exclusivity.yaml +360 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/refine_products.yaml +148 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/vendor_metric_accountability.yaml +293 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +307 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/scenarios/vendor_metric_optimization_flow.yaml +576 -0
- package/compliance/cache/3.1.0-rc.2/domains/media-buy/state-machine.yaml +442 -0
- package/compliance/cache/3.1.0-rc.2/domains/signals/index.yaml +266 -0
- package/compliance/cache/3.1.0-rc.2/domains/sponsored-intelligence/index.yaml +256 -0
- package/compliance/cache/3.1.0-rc.2/index.json +356 -0
- package/compliance/cache/3.1.0-rc.2/protocols/brand/index.yaml +160 -0
- package/compliance/cache/3.1.0-rc.2/protocols/brand/scenarios/distributed_brand_resolution.yaml +415 -0
- package/compliance/cache/3.1.0-rc.2/protocols/brand/scenarios/single_side_trust_extension.yaml +454 -0
- package/compliance/cache/3.1.0-rc.2/protocols/creative/index.yaml +339 -0
- package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/billing_out_of_band.yaml +153 -0
- package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/canonical_supported_formats.yaml +212 -0
- package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/creative_lifecycle_webhooks.yaml +389 -0
- package/compliance/cache/3.1.0-rc.2/protocols/creative/scenarios/native_in_feed.yaml +543 -0
- package/compliance/cache/3.1.0-rc.2/protocols/governance/index.yaml +682 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/index.yaml +789 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/audience_buy_flow.yaml +380 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/available_actions.yaml +565 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/billing_finality_delivery.yaml +354 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/canonical_formats.yaml +861 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/clicks_buy_flow.yaml +264 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/completed_views_buy_flow.yaml +344 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/create_media_buy_async.yaml +234 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/creative_fate_after_cancellation.yaml +419 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/creative_reception.yaml +247 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/delivery_reporting.yaml +357 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/dependency_impairment.yaml +633 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/dependency_impairment_cardinality.yaml +800 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/event_dedup_flow.yaml +399 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/frequency_cap_enforcement.yaml +309 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_approved.yaml +214 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_conditions.yaml +199 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_denied.yaml +204 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/governance_denied_recovery.yaml +252 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/invalid_transitions.yaml +289 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/inventory_list_no_match.yaml +148 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/inventory_list_targeting.yaml +276 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/measurement_accountability.yaml +244 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/measurement_terms_rejected.yaml +203 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/package_correlation_legacy_fallback.yaml +113 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/pending_creatives_to_start.yaml +292 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/per_creative_conversion_attribution.yaml +500 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/performance_buy_flow.yaml +428 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/performance_buy_flow_roas.yaml +470 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/product_signal_targeting.yaml +373 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/proposal_finalize.yaml +399 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/proposal_finalize_asap_timing.yaml +264 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/proposal_not_found_errors.yaml +257 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/provenance_audit_observation.yaml +333 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/provenance_enforcement.yaml +517 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/provenance_truth_of_claim.yaml +294 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/reach_buy_flow.yaml +823 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/refine_finalize_exclusivity.yaml +360 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/refine_products.yaml +148 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/vendor_metric_accountability.yaml +293 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +307 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/scenarios/vendor_metric_optimization_flow.yaml +576 -0
- package/compliance/cache/3.1.0-rc.2/protocols/media-buy/state-machine.yaml +442 -0
- package/compliance/cache/3.1.0-rc.2/protocols/signals/index.yaml +266 -0
- package/compliance/cache/3.1.0-rc.2/protocols/sponsored-intelligence/index.yaml +256 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/audience-sync/index.yaml +313 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/brand-rights/index.yaml +350 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/brand-rights/scenarios/governance_denied.yaml +226 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/collection-lists/index.yaml +359 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/content-standards/index.yaml +572 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/creative-ad-server/index.yaml +409 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/creative-generative/generative-seller.yaml +807 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/creative-generative/index.yaml +758 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/creative-template/index.yaml +510 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/governance-aware-seller/index.yaml +143 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/governance-aware-seller/scenarios/governance_multi_agent_rejected.yaml +117 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/governance-delivery-monitor/index.yaml +441 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/governance-spend-authority/denied.yaml +221 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/governance-spend-authority/index.yaml +330 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/property-lists/index.yaml +482 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-broadcast-tv/index.yaml +738 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-catalog-driven/index.yaml +840 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-guaranteed/index.yaml +601 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-non-guaranteed/index.yaml +546 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-proposal-mode/index.yaml +586 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sales-social/index.yaml +919 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/signal-marketplace/index.yaml +424 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/signal-marketplace/scenarios/governance_denied.yaml +210 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/signal-owned/index.yaml +317 -0
- package/compliance/cache/3.1.0-rc.2/specialisms/sponsored-intelligence/index.yaml +59 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/acme-outdoor-live.yaml +78 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/acme-outdoor.yaml +223 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/billing-gate-runner.yaml +115 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/bistro-oranje.yaml +126 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/distributed-brand-runner.yaml +281 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/nova-motors.yaml +262 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/osei-natural.yaml +126 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/parallel-dispatch-runner.yaml +196 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/rate-limit-trip-runner.yaml +172 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/signed-requests-runner.yaml +155 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/single-side-trust-runner.yaml +294 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/substitution-observer-runner.yaml +688 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/summit-foods.yaml +125 -0
- package/compliance/cache/3.1.0-rc.2/test-kits/webhook-receiver-runner.yaml +265 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/001-minimal-plan.json +43 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/002-full-plan.json +217 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/003-bookkeeping-stripped.json +60 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/004a-human-review-omitted.json +43 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/004b-human-review-explicit-null.json +49 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/005a-policy-categories-order-1.json +53 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/005b-policy-categories-order-2.json +57 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/006a-ext-trace-v1.json +49 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/006b-ext-trace-v2.json +53 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/007-unicode-objectives.json +43 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/plan-hash/008-numeric-canonicalization.json +65 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/README.md +220 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/canonicalization.json +241 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/keys.json +60 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/001-no-signature-header.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/002-wrong-tag.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/003-expired-signature.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/004-window-too-long.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/005-alg-not-allowed.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/006-missing-covered-component.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/007-missing-content-digest.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/008-unknown-keyid.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/009-key-ops-missing-verify.json +27 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/010-content-digest-mismatch.json +33 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/011-malformed-header.json +27 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/012-missing-expires-param.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/013-expires-le-created.json +27 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/014-missing-nonce-param.json +27 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/015-signature-invalid.json +28 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/016-replayed-nonce.json +35 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/017-key-revoked.json +38 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/018-digest-covered-when-forbidden.json +28 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/019-signature-without-signature-input.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/020-rate-abuse.json +34 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/021-duplicate-signature-input-label.json +31 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/022-multi-valued-content-type.json +31 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/023-multi-valued-content-digest.json +32 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/024-unquoted-string-param.json +31 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/025-jwk-alg-crv-mismatch.json +43 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/026-non-ascii-host.json +31 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/027-webhook-registration-authentication-unsigned.json +25 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/negative/028-unsigned-protocol-method-required.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/001-basic-post.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/002-post-with-content-digest.json +31 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/003-es256-post.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/004-multiple-signature-labels.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/005-default-port-stripped.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/006-dot-segment-path.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/007-query-byte-preserved.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/008-percent-encoded-path.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/009-percent-encoded-unreserved-decoded.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/010-percent-encoded-slash-preserved.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/011-ipv6-authority.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/request-signing/positive/012-ipv6-authority-default-port-stripped.json +30 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/README.md +211 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/keys.json +61 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/001-wrong-tag.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/002-expired-signature.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/003-window-too-long.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/004-alg-not-allowed.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/005-missing-authority-component.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/006-missing-content-digest.json +25 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/007-unknown-keyid.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/008-wrong-adcp-use.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/009-content-digest-mismatch.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/010-malformed-signature-input.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/011-signature-without-input.json +25 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/012-missing-expires-param.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/013-expires-le-created.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/014-missing-nonce-param.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/015-signature-invalid.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/016-replayed-nonce.json +37 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/017-key-revoked.json +32 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/018-rate-abuse.json +33 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/019-revocation-stale.json +32 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/020-key-ops-missing-verify.json +41 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/negative/021-base64-alphabet-mixing.json +26 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/001-basic-post.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/002-es256-post.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/003-multiple-signature-labels.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/004-default-port-stripped.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/005-percent-encoded-path.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/006-query-byte-preserved.json +24 -0
- package/compliance/cache/3.1.0-rc.2/test-vectors/webhook-signing/positive/007-body-without-idempotency-key.json +25 -0
- package/compliance/cache/3.1.0-rc.2/universal/billing-gate-dispatch.yaml +450 -0
- package/compliance/cache/3.1.0-rc.2/universal/canonical-format-validate-input.yaml +640 -0
- package/compliance/cache/3.1.0-rc.2/universal/capability-discovery.yaml +125 -0
- package/compliance/cache/3.1.0-rc.2/universal/collection-lists-pagination-integrity.yaml +306 -0
- package/compliance/cache/3.1.0-rc.2/universal/comply-controller-mode-gate.yaml +141 -0
- package/compliance/cache/3.1.0-rc.2/universal/content-standards-pagination-integrity.yaml +326 -0
- package/compliance/cache/3.1.0-rc.2/universal/deterministic-testing.yaml +1430 -0
- package/compliance/cache/3.1.0-rc.2/universal/error-compliance-signals.yaml +377 -0
- package/compliance/cache/3.1.0-rc.2/universal/error-compliance.yaml +528 -0
- package/compliance/cache/3.1.0-rc.2/universal/fictional-entities.yaml +307 -0
- package/compliance/cache/3.1.0-rc.2/universal/get-media-buys-pagination-integrity.yaml +160 -0
- package/compliance/cache/3.1.0-rc.2/universal/get-signals-pagination-integrity.yaml +210 -0
- package/compliance/cache/3.1.0-rc.2/universal/idempotency.yaml +861 -0
- package/compliance/cache/3.1.0-rc.2/universal/notification-config-event-scope.yaml +119 -0
- package/compliance/cache/3.1.0-rc.2/universal/notification-config-lifecycle.yaml +337 -0
- package/compliance/cache/3.1.0-rc.2/universal/notification-config-rejections.yaml +107 -0
- package/compliance/cache/3.1.0-rc.2/universal/pagination-integrity-creative-formats.yaml +265 -0
- package/compliance/cache/3.1.0-rc.2/universal/pagination-integrity-list-accounts.yaml +245 -0
- package/compliance/cache/3.1.0-rc.2/universal/pagination-integrity.yaml +263 -0
- package/compliance/cache/3.1.0-rc.2/universal/property-lists-pagination-integrity.yaml +307 -0
- package/compliance/cache/3.1.0-rc.2/universal/read-tool-idempotency.yaml +405 -0
- package/compliance/cache/3.1.0-rc.2/universal/runner-output-contract.yaml +1285 -0
- package/compliance/cache/3.1.0-rc.2/universal/schema-validation-signals.yaml +181 -0
- package/compliance/cache/3.1.0-rc.2/universal/schema-validation.yaml +548 -0
- package/compliance/cache/3.1.0-rc.2/universal/security.yaml +539 -0
- package/compliance/cache/3.1.0-rc.2/universal/signed-requests.yaml +217 -0
- package/compliance/cache/3.1.0-rc.2/universal/stale-response-advisory.yaml +295 -0
- package/compliance/cache/3.1.0-rc.2/universal/storyboard-schema.yaml +2194 -0
- package/compliance/cache/3.1.0-rc.2/universal/v3-envelope-integrity.yaml +117 -0
- package/compliance/cache/3.1.0-rc.2/universal/version-negotiation.yaml +130 -0
- package/compliance/cache/3.1.0-rc.2/universal/webhook-emission.yaml +411 -0
- package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-bulk-webhooks.yaml +82 -0
- package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-product-webhooks.yaml +83 -0
- package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-products.yaml +151 -0
- package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-signal-webhooks.yaml +83 -0
- package/compliance/cache/3.1.0-rc.2/universal/wholesale-feed-signals.yaml +149 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/testing/storyboard/default-invariants.js +23 -0
- package/dist/lib/testing/storyboard/default-invariants.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +84 -21
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/testing/storyboard/types.d.ts +21 -0
- package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/types.js.map +1 -1
- package/dist/lib/testing/types.d.ts +9 -0
- package/dist/lib/testing/types.d.ts.map +1 -1
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/package.json +1 -1
|
@@ -0,0 +1,919 @@
|
|
|
1
|
+
id: sales_social
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
title: "Social platform"
|
|
4
|
+
protocol: media-buy
|
|
5
|
+
category: sales_social
|
|
6
|
+
summary: "Social media platform that accepts audience segments, native creatives, and conversion events from buyer agents."
|
|
7
|
+
track: audiences
|
|
8
|
+
required_tools:
|
|
9
|
+
- sync_governance
|
|
10
|
+
- sync_audiences
|
|
11
|
+
- sync_catalogs
|
|
12
|
+
- sync_creatives
|
|
13
|
+
- sync_event_sources
|
|
14
|
+
- preview_creative
|
|
15
|
+
requires_scenarios:
|
|
16
|
+
- governance_aware_seller/governance_multi_agent_rejected
|
|
17
|
+
|
|
18
|
+
# Cross-step assertion (adcp#2664). status.monotonic rejects resource
|
|
19
|
+
# status transitions observed across steps that aren't on the spec
|
|
20
|
+
# lifecycle graph — e.g. approved → processing on a creative asset or
|
|
21
|
+
# active → pending_creatives on a media_buy.
|
|
22
|
+
invariants:
|
|
23
|
+
- status.monotonic
|
|
24
|
+
|
|
25
|
+
narrative: |
|
|
26
|
+
You run a social media platform — Snap, Meta, TikTok, Pinterest, or any walled garden that
|
|
27
|
+
sells advertising through audience-based targeting and native creative formats. A buyer agent
|
|
28
|
+
connects to set up an account, push audience segments, sync native creatives, track conversion
|
|
29
|
+
events, and monitor spend.
|
|
30
|
+
|
|
31
|
+
Unlike open-web media buys, social platforms require the buyer to push assets into the
|
|
32
|
+
platform's environment. Audiences are activated via sync_audiences, creatives are pushed via
|
|
33
|
+
sync_creatives in platform-native formats, and conversion events flow back via log_event.
|
|
34
|
+
|
|
35
|
+
This storyboard covers the social platform integration from the buyer's perspective:
|
|
36
|
+
account setup, audience activation, native creative push, event tracking, and financial
|
|
37
|
+
monitoring.
|
|
38
|
+
|
|
39
|
+
context:
|
|
40
|
+
governance_agent_url: "https://test-agent.adcontextprotocol.org"
|
|
41
|
+
|
|
42
|
+
agent:
|
|
43
|
+
interaction_model: media_buy_seller
|
|
44
|
+
capabilities:
|
|
45
|
+
- sells_media
|
|
46
|
+
- accepts_briefs
|
|
47
|
+
- supports_non_guaranteed
|
|
48
|
+
examples:
|
|
49
|
+
- "Snap"
|
|
50
|
+
- "Meta"
|
|
51
|
+
- "TikTok"
|
|
52
|
+
- "Pinterest"
|
|
53
|
+
|
|
54
|
+
caller:
|
|
55
|
+
role: buyer_agent
|
|
56
|
+
example: "Scope3 (DSP)"
|
|
57
|
+
|
|
58
|
+
prerequisites:
|
|
59
|
+
description: |
|
|
60
|
+
The caller needs a brand identity, operator credentials, audience segment definitions,
|
|
61
|
+
and native creative assets. The test kit provides a sample brand with creative assets
|
|
62
|
+
suitable for social formats.
|
|
63
|
+
test_kit: "test-kits/acme-outdoor.yaml"
|
|
64
|
+
|
|
65
|
+
phases:
|
|
66
|
+
- id: capability_discovery
|
|
67
|
+
title: "Capability discovery"
|
|
68
|
+
narrative: |
|
|
69
|
+
The buyer calls get_adcp_capabilities to confirm the agent supports media buying before syncing audiences and native creatives.
|
|
70
|
+
|
|
71
|
+
steps:
|
|
72
|
+
- id: get_capabilities
|
|
73
|
+
title: "Check agent capabilities"
|
|
74
|
+
narrative: |
|
|
75
|
+
Verify that the agent declares the expected protocol support before
|
|
76
|
+
proceeding with domain-specific operations.
|
|
77
|
+
task: get_adcp_capabilities
|
|
78
|
+
schema_ref: "protocol/get-adcp-capabilities-request.json"
|
|
79
|
+
response_schema_ref: "protocol/get-adcp-capabilities-response.json"
|
|
80
|
+
doc_ref: "/protocol/get_adcp_capabilities"
|
|
81
|
+
comply_scenario: capability_discovery
|
|
82
|
+
stateful: false
|
|
83
|
+
expected: |
|
|
84
|
+
Return capabilities declaring media_buy in supported_protocols, confirming the agent sells media.
|
|
85
|
+
sample_request:
|
|
86
|
+
context:
|
|
87
|
+
correlation_id: "sales_social--get_capabilities"
|
|
88
|
+
validations:
|
|
89
|
+
- check: response_schema
|
|
90
|
+
description: "Response matches get-adcp-capabilities-response.json schema"
|
|
91
|
+
- check: field_present
|
|
92
|
+
path: "supported_protocols"
|
|
93
|
+
description: "Agent declares supported protocols"
|
|
94
|
+
|
|
95
|
+
- check: field_present
|
|
96
|
+
path: "context"
|
|
97
|
+
description: "Response echoes back the context object"
|
|
98
|
+
- check: field_value
|
|
99
|
+
path: "context.correlation_id"
|
|
100
|
+
value: "sales_social--get_capabilities"
|
|
101
|
+
description: "Context correlation_id returned unchanged"
|
|
102
|
+
- id: account_setup
|
|
103
|
+
title: "Account setup"
|
|
104
|
+
narrative: |
|
|
105
|
+
The buyer establishes an account with the social platform and verifies its status.
|
|
106
|
+
Social platforms often require advertiser verification before accepting ad spend.
|
|
107
|
+
|
|
108
|
+
steps:
|
|
109
|
+
- id: sync_accounts
|
|
110
|
+
title: "Register advertiser account"
|
|
111
|
+
narrative: |
|
|
112
|
+
The buyer registers their brand and operator with the social platform. The platform
|
|
113
|
+
provisions an advertiser account and returns its status. Social platforms may require
|
|
114
|
+
identity verification before the account goes active.
|
|
115
|
+
task: sync_accounts
|
|
116
|
+
schema_ref: "account/sync-accounts-request.json"
|
|
117
|
+
response_schema_ref: "account/sync-accounts-response.json"
|
|
118
|
+
doc_ref: "/accounts/tasks/sync_accounts"
|
|
119
|
+
stateful: true
|
|
120
|
+
expected: |
|
|
121
|
+
Return the advertiser account with:
|
|
122
|
+
- account_id: platform's identifier
|
|
123
|
+
- status: active or pending_approval (if verification required)
|
|
124
|
+
- account_scope: how the platform scopes this relationship
|
|
125
|
+
|
|
126
|
+
sample_request:
|
|
127
|
+
accounts:
|
|
128
|
+
- brand:
|
|
129
|
+
domain: "acmeoutdoor.example"
|
|
130
|
+
operator: "pinnacle-agency.example"
|
|
131
|
+
billing: "operator"
|
|
132
|
+
|
|
133
|
+
idempotency_key: "$generate:uuid_v4#sales_social_account_setup_sync_accounts"
|
|
134
|
+
context:
|
|
135
|
+
correlation_id: "sales_social--sync_accounts"
|
|
136
|
+
validations:
|
|
137
|
+
- check: response_schema
|
|
138
|
+
description: "Response matches sync-accounts-response.json schema"
|
|
139
|
+
- check: field_present
|
|
140
|
+
path: "accounts[0].account_id"
|
|
141
|
+
description: "Account has a platform-assigned ID"
|
|
142
|
+
|
|
143
|
+
- check: field_present
|
|
144
|
+
path: "context"
|
|
145
|
+
description: "Response echoes back the context object"
|
|
146
|
+
- check: field_value
|
|
147
|
+
path: "context.correlation_id"
|
|
148
|
+
value: "sales_social--sync_accounts"
|
|
149
|
+
description: "Context correlation_id returned unchanged"
|
|
150
|
+
- id: list_accounts
|
|
151
|
+
title: "Verify account status"
|
|
152
|
+
narrative: |
|
|
153
|
+
The buyer checks which accounts exist on the platform and their current status.
|
|
154
|
+
This confirms the account is active and shows any pending setup requirements.
|
|
155
|
+
task: list_accounts
|
|
156
|
+
schema_ref: "account/list-accounts-request.json"
|
|
157
|
+
response_schema_ref: "account/list-accounts-response.json"
|
|
158
|
+
doc_ref: "/accounts/tasks/list_accounts"
|
|
159
|
+
stateful: true
|
|
160
|
+
# Explicit-mode social platforms (Snap, Meta, TikTok) pre-provision
|
|
161
|
+
# advertiser accounts out-of-band — `sync_accounts` is intentionally
|
|
162
|
+
# missing_tool, with `list_accounts` as the canonical alternative.
|
|
163
|
+
# Declaring the substitution here lets the runner waive the
|
|
164
|
+
# downstream missing_tool cascade when list_accounts passes.
|
|
165
|
+
# See adcontextprotocol/adcp#3734.
|
|
166
|
+
provides_state_for: sync_accounts
|
|
167
|
+
expected: |
|
|
168
|
+
Return accounts matching the query:
|
|
169
|
+
- accounts array with status, account_id, brand, operator
|
|
170
|
+
- Active accounts ready for ad operations
|
|
171
|
+
- Pending accounts with accounts[].setup.url populated if verification is needed
|
|
172
|
+
|
|
173
|
+
sample_request:
|
|
174
|
+
context:
|
|
175
|
+
correlation_id: "sales_social--list_accounts"
|
|
176
|
+
validations:
|
|
177
|
+
- check: response_schema
|
|
178
|
+
description: "Response matches list-accounts-response.json schema"
|
|
179
|
+
- check: field_present
|
|
180
|
+
path: "accounts"
|
|
181
|
+
description: "Response contains accounts array"
|
|
182
|
+
|
|
183
|
+
- check: field_present
|
|
184
|
+
path: "context"
|
|
185
|
+
description: "Response echoes back the context object"
|
|
186
|
+
- check: field_value
|
|
187
|
+
path: "context.correlation_id"
|
|
188
|
+
value: "sales_social--list_accounts"
|
|
189
|
+
description: "Context correlation_id returned unchanged"
|
|
190
|
+
- id: sync_governance
|
|
191
|
+
title: "Register governance agent"
|
|
192
|
+
narrative: |
|
|
193
|
+
The buyer registers the configured governance agent on the advertiser
|
|
194
|
+
account before pushing audiences, creatives, catalogs, or conversion
|
|
195
|
+
events that can affect spend.
|
|
196
|
+
task: sync_governance
|
|
197
|
+
schema_ref: "account/sync-governance-request.json"
|
|
198
|
+
response_schema_ref: "account/sync-governance-response.json"
|
|
199
|
+
doc_ref: "/accounts/tasks/sync_governance"
|
|
200
|
+
stateful: true
|
|
201
|
+
expected: |
|
|
202
|
+
Acknowledge governance registration for the account:
|
|
203
|
+
- status: synced
|
|
204
|
+
- governance_agents[0].url echoes the configured governance agent
|
|
205
|
+
|
|
206
|
+
sample_request:
|
|
207
|
+
accounts:
|
|
208
|
+
- account:
|
|
209
|
+
brand:
|
|
210
|
+
domain: "acmeoutdoor.example"
|
|
211
|
+
operator: "pinnacle-agency.example"
|
|
212
|
+
governance_agents:
|
|
213
|
+
- url: "$context.governance_agent_url"
|
|
214
|
+
authentication:
|
|
215
|
+
schemes: ["Bearer"]
|
|
216
|
+
credentials: "gov-token-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
217
|
+
|
|
218
|
+
idempotency_key: "$generate:uuid_v4#sales_social_account_setup_sync_governance"
|
|
219
|
+
context:
|
|
220
|
+
correlation_id: "sales_social--sync_governance"
|
|
221
|
+
validations:
|
|
222
|
+
- check: response_schema
|
|
223
|
+
description: "Response matches sync-governance-response.json schema"
|
|
224
|
+
- check: field_value
|
|
225
|
+
path: "accounts[0].status"
|
|
226
|
+
value: "synced"
|
|
227
|
+
description: "Governance agent is registered on the advertiser account"
|
|
228
|
+
- check: field_present
|
|
229
|
+
path: "context"
|
|
230
|
+
description: "Response echoes back the context object"
|
|
231
|
+
- check: field_value
|
|
232
|
+
path: "context.correlation_id"
|
|
233
|
+
value: "sales_social--sync_governance"
|
|
234
|
+
description: "Context correlation_id returned unchanged"
|
|
235
|
+
- id: audience_sync
|
|
236
|
+
title: "Audience activation"
|
|
237
|
+
narrative: |
|
|
238
|
+
The buyer pushes audience segments to the platform. Social platforms use these segments
|
|
239
|
+
for targeting — the buyer defines who to reach, and the platform matches against its
|
|
240
|
+
user base.
|
|
241
|
+
|
|
242
|
+
steps:
|
|
243
|
+
- id: sync_audiences
|
|
244
|
+
title: "Push audience segments"
|
|
245
|
+
narrative: |
|
|
246
|
+
The buyer syncs audience segment definitions to the platform. Each segment includes
|
|
247
|
+
targeting criteria that the platform evaluates against its user graph. The platform
|
|
248
|
+
returns match rates and segment status.
|
|
249
|
+
task: sync_audiences
|
|
250
|
+
schema_ref: "media-buy/sync-audiences-request.json"
|
|
251
|
+
response_schema_ref: "media-buy/sync-audiences-response.json"
|
|
252
|
+
doc_ref: "/media-buy/task-reference/sync_audiences"
|
|
253
|
+
comply_scenario: sync_audiences
|
|
254
|
+
stateful: true
|
|
255
|
+
expected: |
|
|
256
|
+
Accept and process audience segments:
|
|
257
|
+
- Per-segment status: active, processing, or rejected
|
|
258
|
+
- Match rate estimates where available
|
|
259
|
+
- Platform-assigned segment IDs
|
|
260
|
+
|
|
261
|
+
sample_request:
|
|
262
|
+
account:
|
|
263
|
+
brand:
|
|
264
|
+
domain: "acmeoutdoor.example"
|
|
265
|
+
operator: "pinnacle-agency.example"
|
|
266
|
+
audiences:
|
|
267
|
+
- audience_id: "outdoor_enthusiasts_25_54"
|
|
268
|
+
name: "Outdoor enthusiasts 25-54"
|
|
269
|
+
description: "Adults 25-54 interested in hiking, camping, and outdoor gear"
|
|
270
|
+
# Realistic add[] payload forces adapters to call the upstream
|
|
271
|
+
# audience-upload endpoint rather than returning shape-valid
|
|
272
|
+
# responses from an empty-members branch. Hash values are
|
|
273
|
+
# fictional test vectors distinct from the audience_sync
|
|
274
|
+
# storyboard's fixtures to avoid cross-storyboard collision.
|
|
275
|
+
add:
|
|
276
|
+
- external_id: "acme-user-0001"
|
|
277
|
+
hashed_email: "a000000000000000000000000000000000000000000000000000000000000001"
|
|
278
|
+
- external_id: "acme-user-0002"
|
|
279
|
+
hashed_phone: "b000000000000000000000000000000000000000000000000000000000000002"
|
|
280
|
+
|
|
281
|
+
idempotency_key: "$generate:uuid_v4#sales_social_audience_sync_sync_audiences"
|
|
282
|
+
context:
|
|
283
|
+
correlation_id: "sales_social--sync_audiences"
|
|
284
|
+
validations:
|
|
285
|
+
- check: response_schema
|
|
286
|
+
description: "Response matches sync-audiences-response.json schema"
|
|
287
|
+
|
|
288
|
+
- check: field_present
|
|
289
|
+
path: "context"
|
|
290
|
+
description: "Response echoes back the context object"
|
|
291
|
+
- check: field_value
|
|
292
|
+
path: "context.correlation_id"
|
|
293
|
+
value: "sales_social--sync_audiences"
|
|
294
|
+
description: "Context correlation_id returned unchanged"
|
|
295
|
+
# Anti-façade: the adapter MUST forward the hashed identifiers to
|
|
296
|
+
# the upstream platform's audience-upload endpoint. Adopters who
|
|
297
|
+
# don't advertise query_upstream_traffic in list_scenarios grade
|
|
298
|
+
# this check not_applicable per the runner's forward-compat rule —
|
|
299
|
+
# opt-in by adopter capability.
|
|
300
|
+
- check: upstream_traffic
|
|
301
|
+
description: "sync_audiences caused upstream traffic carrying the supplied hashed identifiers"
|
|
302
|
+
min_count: 1
|
|
303
|
+
endpoint_pattern: "POST *"
|
|
304
|
+
identifier_paths:
|
|
305
|
+
- "audiences[*].add[*].hashed_email"
|
|
306
|
+
- "audiences[*].add[*].external_id"
|
|
307
|
+
- id: creative_push
|
|
308
|
+
title: "Native creative sync"
|
|
309
|
+
narrative: |
|
|
310
|
+
The buyer pushes native creative assets to the platform. Social platforms render ads
|
|
311
|
+
in their native format — the buyer provides assets (images, headlines, descriptions)
|
|
312
|
+
and the platform assembles them into the native ad unit.
|
|
313
|
+
|
|
314
|
+
steps:
|
|
315
|
+
- id: sync_creatives
|
|
316
|
+
title: "Push native creative assets"
|
|
317
|
+
narrative: |
|
|
318
|
+
The buyer syncs creative assets for native ad formats. The platform validates
|
|
319
|
+
each creative against its format requirements and returns per-creative status.
|
|
320
|
+
task: sync_creatives
|
|
321
|
+
schema_ref: "creative/sync-creatives-request.json"
|
|
322
|
+
response_schema_ref: "creative/sync-creatives-response.json"
|
|
323
|
+
doc_ref: "/creative/task-reference/sync_creatives"
|
|
324
|
+
comply_scenario: creative_sync
|
|
325
|
+
stateful: true
|
|
326
|
+
expected: |
|
|
327
|
+
Accept and validate native creatives:
|
|
328
|
+
- Per-creative action: created or updated
|
|
329
|
+
- Per-creative status: accepted, pending_review, or rejected
|
|
330
|
+
- Validation errors for rejected creatives
|
|
331
|
+
|
|
332
|
+
sample_request:
|
|
333
|
+
account:
|
|
334
|
+
brand:
|
|
335
|
+
domain: "acmeoutdoor.example"
|
|
336
|
+
operator: "pinnacle-agency.example"
|
|
337
|
+
creatives:
|
|
338
|
+
- creative_id: "native_trail_pro"
|
|
339
|
+
name: "Trail Pro 3000 - Native"
|
|
340
|
+
format_id:
|
|
341
|
+
agent_url: "https://social-platform.example.com"
|
|
342
|
+
id: "native_feed"
|
|
343
|
+
assets:
|
|
344
|
+
image:
|
|
345
|
+
asset_type: "image"
|
|
346
|
+
url: "https://cdn.pinnacle-agency.example/trail-pro-native.png"
|
|
347
|
+
width: 1200
|
|
348
|
+
height: 628
|
|
349
|
+
mime_type: "image/png"
|
|
350
|
+
headline:
|
|
351
|
+
asset_type: "text"
|
|
352
|
+
content: "Trail Pro 3000 — Built for the Summit"
|
|
353
|
+
|
|
354
|
+
idempotency_key: "$generate:uuid_v4#sales_social_creative_push_sync_creatives"
|
|
355
|
+
context:
|
|
356
|
+
correlation_id: "sales_social--sync_creatives"
|
|
357
|
+
validations:
|
|
358
|
+
- check: response_schema
|
|
359
|
+
description: "Response matches sync-creatives-response.json schema"
|
|
360
|
+
|
|
361
|
+
- check: field_present
|
|
362
|
+
path: "context"
|
|
363
|
+
description: "Response echoes back the context object"
|
|
364
|
+
- check: field_value
|
|
365
|
+
path: "context.correlation_id"
|
|
366
|
+
value: "sales_social--sync_creatives"
|
|
367
|
+
description: "Context correlation_id returned unchanged"
|
|
368
|
+
- id: catalog_driven_dynamic_ads
|
|
369
|
+
title: "Catalog-driven dynamic product ads"
|
|
370
|
+
narrative: |
|
|
371
|
+
Social platforms routinely ship dynamic product ads (Snap Dynamic Ads, Meta DPA,
|
|
372
|
+
TikTok Dynamic Showcase): the buyer pushes a product catalog and the platform
|
|
373
|
+
renders per-impression creative pulling product images, titles, and tracker URLs
|
|
374
|
+
from catalog items. The creative template references catalog-item macros
|
|
375
|
+
(`{SKU}`, `{GTIN}`) whose values resolve to the specific item shown at
|
|
376
|
+
impression time.
|
|
377
|
+
|
|
378
|
+
This phase exercises the catalog-acceptance leg of that flow: push a small inline
|
|
379
|
+
product catalog (with `content_id_type: "sku"` declared so macro resolution binds
|
|
380
|
+
to the right field), then push a DPA creative template using the AdCP-native
|
|
381
|
+
`product_carousel_3_to_10` format on `creative.adcontextprotocol.org`. Real
|
|
382
|
+
social-platform formats (Meta `native_carousel`, Snap dynamic ad set, TikTok
|
|
383
|
+
dynamic showcase) are platform-specific refinements tracked as follow-ups on
|
|
384
|
+
#2640; the AdCP-native format is the interop baseline.
|
|
385
|
+
|
|
386
|
+
Runtime substitution-safety — assertion that emitted tracker URLs percent-encode
|
|
387
|
+
catalog-item macro values per `docs/creative/universal-macros#substitution-safety-catalog-item-macros` —
|
|
388
|
+
runs in the separate `catalog_substitution_safety` phase below, gated on the
|
|
389
|
+
`substitution_observer_runner` test-kit contract.
|
|
390
|
+
|
|
391
|
+
steps:
|
|
392
|
+
- id: sync_product_catalog
|
|
393
|
+
title: "Push a product catalog"
|
|
394
|
+
narrative: |
|
|
395
|
+
The buyer pushes a small inline product catalog — the shape social platforms
|
|
396
|
+
accept for dynamic product ads. Your platform validates each item and
|
|
397
|
+
returns per-item approval status.
|
|
398
|
+
task: sync_catalogs
|
|
399
|
+
schema_ref: "media-buy/sync-catalogs-request.json"
|
|
400
|
+
response_schema_ref: "media-buy/sync-catalogs-response.json"
|
|
401
|
+
doc_ref: "/media-buy/task-reference/sync_catalogs"
|
|
402
|
+
stateful: true
|
|
403
|
+
expected: |
|
|
404
|
+
Return per-catalog results with catalog_id, action, item_count, and
|
|
405
|
+
items_approved counts.
|
|
406
|
+
|
|
407
|
+
sample_request:
|
|
408
|
+
account:
|
|
409
|
+
brand:
|
|
410
|
+
domain: "acmeoutdoor.example"
|
|
411
|
+
operator: "pinnacle-agency.example"
|
|
412
|
+
catalogs:
|
|
413
|
+
- catalog_id: "acme_gear_spring_2026"
|
|
414
|
+
type: "product"
|
|
415
|
+
content_id_type: "sku"
|
|
416
|
+
name: "Acme Outdoor — Spring 2026 Gear"
|
|
417
|
+
items:
|
|
418
|
+
- item_id: "trail_pro_3000"
|
|
419
|
+
title: "Trail Pro 3000 Backpack"
|
|
420
|
+
description: "65L expedition pack with torso-length adjustment."
|
|
421
|
+
url: "https://acmeoutdoor.example/gear/trail-pro-3000"
|
|
422
|
+
image_url: "https://cdn.acmeoutdoor.example/gear/trail-pro-3000.jpg"
|
|
423
|
+
price:
|
|
424
|
+
amount: 289.00
|
|
425
|
+
currency: "USD"
|
|
426
|
+
- item_id: "summit_tent_2p"
|
|
427
|
+
title: "Summit 2P Ultralight Tent"
|
|
428
|
+
description: "2-person four-season tent, 1.8kg packed."
|
|
429
|
+
url: "https://acmeoutdoor.example/gear/summit-tent-2p"
|
|
430
|
+
image_url: "https://cdn.acmeoutdoor.example/gear/summit-tent-2p.jpg"
|
|
431
|
+
price:
|
|
432
|
+
amount: 549.00
|
|
433
|
+
currency: "USD"
|
|
434
|
+
|
|
435
|
+
idempotency_key: "$generate:uuid_v4#sales_social_catalog_driven_dynamic_ads_sync_product_catalog"
|
|
436
|
+
context:
|
|
437
|
+
correlation_id: "sales_social--sync_product_catalog"
|
|
438
|
+
validations:
|
|
439
|
+
- check: response_schema
|
|
440
|
+
description: "Response matches sync-catalogs-response.json schema"
|
|
441
|
+
- check: field_present
|
|
442
|
+
path: "catalogs[0].catalog_id"
|
|
443
|
+
description: "Catalog has an ID"
|
|
444
|
+
- check: field_present
|
|
445
|
+
path: "catalogs[0].item_count"
|
|
446
|
+
description: "Catalog reports item count"
|
|
447
|
+
- check: field_present
|
|
448
|
+
path: "context"
|
|
449
|
+
description: "Response echoes back the context object"
|
|
450
|
+
- check: field_value
|
|
451
|
+
path: "context.correlation_id"
|
|
452
|
+
value: "sales_social--sync_product_catalog"
|
|
453
|
+
description: "Context correlation_id returned unchanged"
|
|
454
|
+
|
|
455
|
+
- id: sync_dpa_creative
|
|
456
|
+
title: "Push a dynamic product ad creative with catalog-item macros"
|
|
457
|
+
narrative: |
|
|
458
|
+
The buyer pushes a creative template whose tracker URLs reference
|
|
459
|
+
catalog-item macros (`{SKU}`, `{GTIN}`). At impression time, your platform
|
|
460
|
+
substitutes each catalog item's values into the template to render the
|
|
461
|
+
per-impression ad.
|
|
462
|
+
|
|
463
|
+
The template uses the AdCP-native `product_carousel_3_to_10` format
|
|
464
|
+
(see `docs/creative/channels/carousels.mdx`). Per #2620, values substituted
|
|
465
|
+
into URL contexts MUST be percent-encoded such that only RFC 3986 unreserved
|
|
466
|
+
characters remain unescaped; nested macro expansion is prohibited. This step
|
|
467
|
+
validates that the template is accepted into the library; runtime
|
|
468
|
+
substitution validation is tracked under #2638.
|
|
469
|
+
task: sync_creatives
|
|
470
|
+
schema_ref: "creative/sync-creatives-request.json"
|
|
471
|
+
response_schema_ref: "creative/sync-creatives-response.json"
|
|
472
|
+
doc_ref: "/creative/task-reference/sync_creatives"
|
|
473
|
+
comply_scenario: creative_sync
|
|
474
|
+
stateful: true
|
|
475
|
+
expected: |
|
|
476
|
+
Accept the DPA creative template. Per-creative action: created or updated.
|
|
477
|
+
|
|
478
|
+
sample_request:
|
|
479
|
+
account:
|
|
480
|
+
brand:
|
|
481
|
+
domain: "acmeoutdoor.example"
|
|
482
|
+
operator: "pinnacle-agency.example"
|
|
483
|
+
creatives:
|
|
484
|
+
- creative_id: "acme_dpa_spring_2026"
|
|
485
|
+
name: "Acme Outdoor — Spring DPA template"
|
|
486
|
+
format_id:
|
|
487
|
+
agent_url: "https://creative.adcontextprotocol.org"
|
|
488
|
+
id: "product_carousel_3_to_10"
|
|
489
|
+
assets:
|
|
490
|
+
impression_pixel:
|
|
491
|
+
asset_type: "url"
|
|
492
|
+
url: "https://track.acmeoutdoor.example/imp?sku={SKU}>in={GTIN}&mb={MEDIA_BUY_ID}"
|
|
493
|
+
click_url:
|
|
494
|
+
asset_type: "url"
|
|
495
|
+
url: "https://track.acmeoutdoor.example/click?sku={SKU}"
|
|
496
|
+
|
|
497
|
+
idempotency_key: "$generate:uuid_v4#sales_social_catalog_driven_dynamic_ads_sync_dpa_creative"
|
|
498
|
+
context:
|
|
499
|
+
correlation_id: "sales_social--sync_dpa_creative"
|
|
500
|
+
validations:
|
|
501
|
+
- check: response_schema
|
|
502
|
+
description: "Response matches sync-creatives-response.json schema"
|
|
503
|
+
- check: field_present
|
|
504
|
+
path: "context"
|
|
505
|
+
description: "Response echoes back the context object"
|
|
506
|
+
- check: field_value
|
|
507
|
+
path: "context.correlation_id"
|
|
508
|
+
value: "sales_social--sync_dpa_creative"
|
|
509
|
+
description: "Context correlation_id returned unchanged"
|
|
510
|
+
- id: catalog_substitution_safety
|
|
511
|
+
title: "Catalog-item macro substitution safety"
|
|
512
|
+
narrative: |
|
|
513
|
+
Per docs/creative/universal-macros#substitution-safety-catalog-item-macros,
|
|
514
|
+
sales agents MUST percent-encode catalog-item macro values such that only
|
|
515
|
+
RFC 3986 `unreserved` characters remain unescaped before substituting them
|
|
516
|
+
into a URL context. Nested macro expansion is prohibited.
|
|
517
|
+
|
|
518
|
+
This phase exercises the rule on the social-platform flow: push a probe
|
|
519
|
+
catalog whose items carry attacker-shaped `sku` values, push a DPA
|
|
520
|
+
creative template that binds to that catalog and references `{SKU}` in
|
|
521
|
+
its tracker URLs, then call `preview_creative` to render the bound
|
|
522
|
+
preview. The substitution-observer runner inspects `preview_html` from
|
|
523
|
+
the response and asserts each substituted `{SKU}` value is encoded per
|
|
524
|
+
the fixture at `static/test-vectors/catalog-macro-substitution.json`.
|
|
525
|
+
|
|
526
|
+
Scope note: this phase validates substitution on the PREVIEW surface
|
|
527
|
+
only. Social platforms with divergent preview vs impression-time
|
|
528
|
+
substitution paths MAY pass here while failing at serve time; serve-time
|
|
529
|
+
attestation is a known coverage limitation shared with creative-generative.
|
|
530
|
+
Real-impression observability for sales-social is deferred to a future
|
|
531
|
+
revision when platform attestation hooks become standardized.
|
|
532
|
+
|
|
533
|
+
The `expect_substitution_safe` step is gated on the
|
|
534
|
+
`substitution_observer_runner` test-kit contract (see
|
|
535
|
+
`test-kits/substitution-observer-runner.yaml`). Runners that do not
|
|
536
|
+
advertise the contract grade the step as `not_applicable` — the earlier
|
|
537
|
+
`sync_substitution_probe_catalog`, `sync_substitution_probe_creative`,
|
|
538
|
+
and `preview_substitution_probe_creative` steps still run (exercising
|
|
539
|
+
the catalog-acceptance, creative-push, and preview paths), but the
|
|
540
|
+
substituted-URL assertion is skipped.
|
|
541
|
+
|
|
542
|
+
steps:
|
|
543
|
+
- id: sync_substitution_probe_catalog
|
|
544
|
+
title: "Push a probe catalog with attacker-shaped values"
|
|
545
|
+
narrative: |
|
|
546
|
+
Push a small probe catalog whose `sku` fields contain five canonical
|
|
547
|
+
attacker-shaped values from the substitution-safety fixture. The
|
|
548
|
+
platform MUST accept the payload — the encoding rule applies at
|
|
549
|
+
substitution time, not at ingest — but the downstream `preview_creative`
|
|
550
|
+
output must percent-encode each value into tracker URLs.
|
|
551
|
+
task: sync_catalogs
|
|
552
|
+
schema_ref: "media-buy/sync-catalogs-request.json"
|
|
553
|
+
response_schema_ref: "media-buy/sync-catalogs-response.json"
|
|
554
|
+
doc_ref: "/media-buy/task-reference/sync_catalogs"
|
|
555
|
+
stateful: true
|
|
556
|
+
expected: |
|
|
557
|
+
Catalog accepted with per-item counts. Runner captures the
|
|
558
|
+
catalog_id + item_ids for the downstream assertion binding.
|
|
559
|
+
|
|
560
|
+
sample_request:
|
|
561
|
+
account:
|
|
562
|
+
brand:
|
|
563
|
+
domain: "acmeoutdoor.example"
|
|
564
|
+
operator: "pinnacle-agency.example"
|
|
565
|
+
catalogs:
|
|
566
|
+
- catalog_id: "sales_social_substitution_probe_v1"
|
|
567
|
+
type: "product"
|
|
568
|
+
content_id_type: "sku"
|
|
569
|
+
name: "Substitution safety probe"
|
|
570
|
+
items:
|
|
571
|
+
- item_id: "reserved_char_breakout"
|
|
572
|
+
sku: "00013&cmd=drop"
|
|
573
|
+
title: "Reserved-char breakout probe"
|
|
574
|
+
url: "https://acmeoutdoor.example/probe/reserved"
|
|
575
|
+
image_url: "https://cdn.acmeoutdoor.example/probe/reserved.jpg"
|
|
576
|
+
price: { amount: 1.00, currency: "USD" }
|
|
577
|
+
- item_id: "nested_expansion"
|
|
578
|
+
sku: "vacancy-{DEVICE_ID}-42"
|
|
579
|
+
title: "Nested-expansion probe"
|
|
580
|
+
url: "https://acmeoutdoor.example/probe/nested"
|
|
581
|
+
image_url: "https://cdn.acmeoutdoor.example/probe/nested.jpg"
|
|
582
|
+
price: { amount: 1.00, currency: "USD" }
|
|
583
|
+
- item_id: "non_ascii"
|
|
584
|
+
sku: "café-amsterdam"
|
|
585
|
+
title: "Non-ASCII UTF-8 probe"
|
|
586
|
+
url: "https://acmeoutdoor.example/probe/non-ascii"
|
|
587
|
+
image_url: "https://cdn.acmeoutdoor.example/probe/non-ascii.jpg"
|
|
588
|
+
price: { amount: 1.00, currency: "USD" }
|
|
589
|
+
- item_id: "crlf_injection"
|
|
590
|
+
sku: "abc\r\nHost: evil.example"
|
|
591
|
+
title: "CRLF injection probe"
|
|
592
|
+
url: "https://acmeoutdoor.example/probe/crlf"
|
|
593
|
+
image_url: "https://cdn.acmeoutdoor.example/probe/crlf.jpg"
|
|
594
|
+
price: { amount: 1.00, currency: "USD" }
|
|
595
|
+
- item_id: "bidi_override"
|
|
596
|
+
sku: "VIN-1234"
|
|
597
|
+
title: "Bidi-override probe"
|
|
598
|
+
url: "https://acmeoutdoor.example/probe/bidi"
|
|
599
|
+
image_url: "https://cdn.acmeoutdoor.example/probe/bidi.jpg"
|
|
600
|
+
price: { amount: 1.00, currency: "USD" }
|
|
601
|
+
|
|
602
|
+
idempotency_key: "$generate:uuid_v4#sales_social_catalog_substitution_safety_sync_substitution_probe_catalog"
|
|
603
|
+
context:
|
|
604
|
+
correlation_id: "sales_social--sync_substitution_probe_catalog"
|
|
605
|
+
validations:
|
|
606
|
+
- check: response_schema
|
|
607
|
+
description: "Response matches sync-catalogs-response.json schema"
|
|
608
|
+
- check: field_present
|
|
609
|
+
path: "catalogs[0].catalog_id"
|
|
610
|
+
description: "Probe catalog accepted"
|
|
611
|
+
|
|
612
|
+
- id: sync_substitution_probe_creative
|
|
613
|
+
title: "Push a DPA creative bound to the probe catalog"
|
|
614
|
+
narrative: |
|
|
615
|
+
Push a DPA creative template whose `product_catalog` asset binds to
|
|
616
|
+
the probe catalog from the previous step. Tracker URLs reference
|
|
617
|
+
`{SKU}` so the platform's substitution path resolves attacker-shaped
|
|
618
|
+
values into URL contexts at preview time.
|
|
619
|
+
task: sync_creatives
|
|
620
|
+
schema_ref: "creative/sync-creatives-request.json"
|
|
621
|
+
response_schema_ref: "creative/sync-creatives-response.json"
|
|
622
|
+
doc_ref: "/creative/task-reference/sync_creatives"
|
|
623
|
+
comply_scenario: creative_sync
|
|
624
|
+
stateful: true
|
|
625
|
+
expected: |
|
|
626
|
+
DPA creative template accepted. Per-creative action: created or updated.
|
|
627
|
+
|
|
628
|
+
sample_request:
|
|
629
|
+
account:
|
|
630
|
+
brand:
|
|
631
|
+
domain: "acmeoutdoor.example"
|
|
632
|
+
operator: "pinnacle-agency.example"
|
|
633
|
+
creatives:
|
|
634
|
+
- creative_id: "sales_social_substitution_probe_creative_v1"
|
|
635
|
+
name: "Substitution safety probe DPA"
|
|
636
|
+
format_id:
|
|
637
|
+
agent_url: "https://creative.adcontextprotocol.org"
|
|
638
|
+
id: "product_carousel_3_to_10"
|
|
639
|
+
assets:
|
|
640
|
+
product_catalog:
|
|
641
|
+
asset_type: "catalog"
|
|
642
|
+
type: "product"
|
|
643
|
+
catalog_id: "sales_social_substitution_probe_v1"
|
|
644
|
+
impression_pixel:
|
|
645
|
+
asset_type: "url"
|
|
646
|
+
url: "https://track.acmeoutdoor.example/imp?sku={SKU}"
|
|
647
|
+
click_url:
|
|
648
|
+
asset_type: "url"
|
|
649
|
+
url: "https://track.acmeoutdoor.example/click?sku={SKU}"
|
|
650
|
+
|
|
651
|
+
idempotency_key: "$generate:uuid_v4#sales_social_catalog_substitution_safety_sync_substitution_probe_creative"
|
|
652
|
+
context:
|
|
653
|
+
correlation_id: "sales_social--sync_substitution_probe_creative"
|
|
654
|
+
validations:
|
|
655
|
+
- check: response_schema
|
|
656
|
+
description: "Response matches sync-creatives-response.json schema"
|
|
657
|
+
- check: field_present
|
|
658
|
+
path: "context"
|
|
659
|
+
description: "Response echoes back the context object"
|
|
660
|
+
|
|
661
|
+
- id: preview_substitution_probe_creative
|
|
662
|
+
title: "Render a preview against the probe catalog"
|
|
663
|
+
narrative: |
|
|
664
|
+
Call `preview_creative` against the probe creative. The platform
|
|
665
|
+
renders the DPA template by binding `{SKU}` against the probe
|
|
666
|
+
catalog's items, returning `preview_html` whose tracker URLs carry
|
|
667
|
+
substituted SKU values. The substitution-observer runner uses this
|
|
668
|
+
response as its observation source in the next step.
|
|
669
|
+
|
|
670
|
+
`format: html` is requested so the response surfaces `preview_html`
|
|
671
|
+
directly; `item_limit: 5` ensures every probe catalog item is
|
|
672
|
+
rendered at least once so the observer can match every binding.
|
|
673
|
+
task: preview_creative
|
|
674
|
+
schema_ref: "creative/preview-creative-request.json"
|
|
675
|
+
response_schema_ref: "creative/preview-creative-response.json"
|
|
676
|
+
doc_ref: "/creative/task-reference/preview_creative"
|
|
677
|
+
stateful: true
|
|
678
|
+
expected: |
|
|
679
|
+
Preview returned with at least one render carrying preview_html
|
|
680
|
+
containing the substituted tracker URLs.
|
|
681
|
+
|
|
682
|
+
sample_request:
|
|
683
|
+
request_type: "single"
|
|
684
|
+
format: "html"
|
|
685
|
+
item_limit: 5
|
|
686
|
+
creative_manifest:
|
|
687
|
+
format_id:
|
|
688
|
+
agent_url: "https://creative.adcontextprotocol.org"
|
|
689
|
+
id: "product_carousel_3_to_10"
|
|
690
|
+
assets:
|
|
691
|
+
product_catalog:
|
|
692
|
+
asset_type: "catalog"
|
|
693
|
+
type: "product"
|
|
694
|
+
catalog_id: "sales_social_substitution_probe_v1"
|
|
695
|
+
impression_pixel:
|
|
696
|
+
asset_type: "url"
|
|
697
|
+
url: "https://track.acmeoutdoor.example/imp?sku={SKU}"
|
|
698
|
+
click_url:
|
|
699
|
+
asset_type: "url"
|
|
700
|
+
url: "https://track.acmeoutdoor.example/click?sku={SKU}"
|
|
701
|
+
account:
|
|
702
|
+
brand:
|
|
703
|
+
domain: "acmeoutdoor.example"
|
|
704
|
+
operator: "pinnacle-agency.example"
|
|
705
|
+
|
|
706
|
+
idempotency_key: "$generate:uuid_v4#sales_social_catalog_substitution_safety_preview_substitution_probe_creative"
|
|
707
|
+
context:
|
|
708
|
+
correlation_id: "sales_social--preview_substitution_probe_creative"
|
|
709
|
+
validations:
|
|
710
|
+
- check: response_schema
|
|
711
|
+
description: "Response matches preview-creative-response.json schema"
|
|
712
|
+
- check: field_present
|
|
713
|
+
path: "previews[0].renders[0].preview_html"
|
|
714
|
+
description: "Preview render carries preview_html"
|
|
715
|
+
|
|
716
|
+
- id: expect_substitution_safe
|
|
717
|
+
title: "Assert substituted tracker URLs percent-encode attacker shapes"
|
|
718
|
+
narrative: |
|
|
719
|
+
The runner inspects the `preview_html` from the previous step,
|
|
720
|
+
extracts tracker URLs that bind `{SKU}` to a probe catalog item,
|
|
721
|
+
and asserts each value is percent-encoded per RFC 3986
|
|
722
|
+
(unreserved-whitelist). Raw-byte leakage fails. Every declared
|
|
723
|
+
binding MUST be observed — a platform that silently strips `{SKU}`
|
|
724
|
+
rather than substituting it fails with `substitution_binding_missing`.
|
|
725
|
+
task: expect_substitution_safe
|
|
726
|
+
requires_contract: substitution_observer_runner
|
|
727
|
+
source: html_inline
|
|
728
|
+
source_path: "/previews/0/renders/0/preview_html"
|
|
729
|
+
macro_template: "https://track.acmeoutdoor.example/imp?sku={SKU}"
|
|
730
|
+
require_every_binding_observed: true
|
|
731
|
+
catalog_bindings:
|
|
732
|
+
- macro: "{SKU}"
|
|
733
|
+
catalog_item_id: "reserved_char_breakout"
|
|
734
|
+
vector_name: "reserved-character-breakout"
|
|
735
|
+
- macro: "{SKU}"
|
|
736
|
+
catalog_item_id: "nested_expansion"
|
|
737
|
+
vector_name: "nested-expansion-preserved-as-literal"
|
|
738
|
+
- macro: "{SKU}"
|
|
739
|
+
catalog_item_id: "non_ascii"
|
|
740
|
+
vector_name: "non-ascii-utf8-percent-encoding"
|
|
741
|
+
- macro: "{SKU}"
|
|
742
|
+
catalog_item_id: "crlf_injection"
|
|
743
|
+
vector_name: "crlf-injection-neutralized"
|
|
744
|
+
- macro: "{SKU}"
|
|
745
|
+
catalog_item_id: "bidi_override"
|
|
746
|
+
vector_name: "bidi-override-neutralized"
|
|
747
|
+
- id: event_setup
|
|
748
|
+
title: "Event source setup"
|
|
749
|
+
narrative: |
|
|
750
|
+
Before sending conversion events, the buyer registers the event sources the platform
|
|
751
|
+
should expect events from — a website pixel, a mobile SDK, or a server-to-server feed.
|
|
752
|
+
The platform returns setup instructions and binds the event_source_id that later
|
|
753
|
+
log_event calls will reference.
|
|
754
|
+
|
|
755
|
+
steps:
|
|
756
|
+
- id: sync_event_sources
|
|
757
|
+
title: "Register conversion event sources"
|
|
758
|
+
narrative: |
|
|
759
|
+
The buyer tells the platform where conversion events will come from. The
|
|
760
|
+
platform records each event_source_id, returns integration code, and will
|
|
761
|
+
accept log_event calls that reference it.
|
|
762
|
+
task: sync_event_sources
|
|
763
|
+
schema_ref: "media-buy/sync-event-sources-request.json"
|
|
764
|
+
response_schema_ref: "media-buy/sync-event-sources-response.json"
|
|
765
|
+
doc_ref: "/media-buy/task-reference/sync_event_sources"
|
|
766
|
+
stateful: true
|
|
767
|
+
expected: |
|
|
768
|
+
Return event sources with:
|
|
769
|
+
- event_source_id and seller_id
|
|
770
|
+
- setup.snippet: integration code (JavaScript pixel, HTML tag, or pixel URL)
|
|
771
|
+
- setup.instructions: human-readable integration guide
|
|
772
|
+
- action: created or updated
|
|
773
|
+
|
|
774
|
+
sample_request:
|
|
775
|
+
account:
|
|
776
|
+
brand:
|
|
777
|
+
domain: "acmeoutdoor.example"
|
|
778
|
+
operator: "pinnacle-agency.example"
|
|
779
|
+
event_sources:
|
|
780
|
+
- event_source_id: "acmeoutdoor_website"
|
|
781
|
+
name: "Acme Outdoor Website"
|
|
782
|
+
event_types: ["purchase", "add_to_cart", "page_view", "lead"]
|
|
783
|
+
allowed_domains: ["acmeoutdoor.example"]
|
|
784
|
+
|
|
785
|
+
idempotency_key: "$generate:uuid_v4#sales_social_event_setup_sync_event_sources"
|
|
786
|
+
context:
|
|
787
|
+
correlation_id: "sales_social--sync_event_sources"
|
|
788
|
+
validations:
|
|
789
|
+
- check: response_schema
|
|
790
|
+
description: "Response matches sync-event-sources-response.json schema"
|
|
791
|
+
- check: field_present
|
|
792
|
+
path: "event_sources[0].setup.snippet"
|
|
793
|
+
description: "Event source includes setup snippet"
|
|
794
|
+
|
|
795
|
+
- check: field_present
|
|
796
|
+
path: "context"
|
|
797
|
+
description: "Response echoes back the context object"
|
|
798
|
+
- check: field_value
|
|
799
|
+
path: "context.correlation_id"
|
|
800
|
+
value: "sales_social--sync_event_sources"
|
|
801
|
+
description: "Context correlation_id returned unchanged"
|
|
802
|
+
- id: event_logging
|
|
803
|
+
title: "Conversion event tracking"
|
|
804
|
+
narrative: |
|
|
805
|
+
The buyer sends conversion events back to the platform for measurement and optimization.
|
|
806
|
+
Events include purchases, signups, and other post-click actions that the platform uses
|
|
807
|
+
to optimize delivery and report on campaign performance.
|
|
808
|
+
|
|
809
|
+
steps:
|
|
810
|
+
- id: log_event
|
|
811
|
+
title: "Send conversion events"
|
|
812
|
+
narrative: |
|
|
813
|
+
The buyer logs conversion events that occurred after ad exposure. The platform
|
|
814
|
+
records these events for attribution, reporting, and delivery optimization.
|
|
815
|
+
task: log_event
|
|
816
|
+
schema_ref: "media-buy/log-event-request.json"
|
|
817
|
+
response_schema_ref: "media-buy/log-event-response.json"
|
|
818
|
+
doc_ref: "/media-buy/task-reference/log_event"
|
|
819
|
+
stateful: true
|
|
820
|
+
expected: |
|
|
821
|
+
Acknowledge the events:
|
|
822
|
+
- Per-event status: accepted or rejected
|
|
823
|
+
- Event IDs for deduplication
|
|
824
|
+
- Attribution window validation
|
|
825
|
+
|
|
826
|
+
sample_request:
|
|
827
|
+
account:
|
|
828
|
+
brand:
|
|
829
|
+
domain: "acmeoutdoor.example"
|
|
830
|
+
operator: "pinnacle-agency.example"
|
|
831
|
+
event_source_id: "acmeoutdoor_website"
|
|
832
|
+
events:
|
|
833
|
+
- event_type: "purchase"
|
|
834
|
+
event_id: "evt_trail_pro_001"
|
|
835
|
+
event_time: "2026-04-05T14:30:00Z"
|
|
836
|
+
# user_match prevents adapters from injecting synthetic placeholder
|
|
837
|
+
# identifiers to satisfy the upstream's required-field check.
|
|
838
|
+
# The hashed_email here matches the sync_audiences add[]
|
|
839
|
+
# member so an upstream_traffic identifier echo can confirm
|
|
840
|
+
# values were forwarded, not constants.
|
|
841
|
+
user_match:
|
|
842
|
+
hashed_email: "a000000000000000000000000000000000000000000000000000000000000001"
|
|
843
|
+
# value/currency belong inside custom_data per event-custom-data.json;
|
|
844
|
+
# additionalProperties: true on the parent silently swallowed them
|
|
845
|
+
# at the wrong nesting level, meaning real upstreams never saw
|
|
846
|
+
# the purchase value.
|
|
847
|
+
custom_data:
|
|
848
|
+
value: 149.99
|
|
849
|
+
currency: "USD"
|
|
850
|
+
|
|
851
|
+
idempotency_key: "$generate:uuid_v4#sales_social_event_logging_log_event"
|
|
852
|
+
context:
|
|
853
|
+
correlation_id: "sales_social--log_event"
|
|
854
|
+
validations:
|
|
855
|
+
- check: response_schema
|
|
856
|
+
description: "Response matches log-event-response.json schema"
|
|
857
|
+
|
|
858
|
+
- check: field_present
|
|
859
|
+
path: "context"
|
|
860
|
+
description: "Response echoes back the context object"
|
|
861
|
+
- check: field_value
|
|
862
|
+
path: "context.correlation_id"
|
|
863
|
+
value: "sales_social--log_event"
|
|
864
|
+
description: "Context correlation_id returned unchanged"
|
|
865
|
+
# Anti-façade: the adapter MUST forward the conversion event to the
|
|
866
|
+
# upstream platform's event-tracking endpoint, carrying the supplied
|
|
867
|
+
# user_match identifier. A façade that injects a constant placeholder
|
|
868
|
+
# hash to satisfy the upstream's required-field check fails the
|
|
869
|
+
# identifier_paths echo — the constant won't match the storyboard's
|
|
870
|
+
# supplied value.
|
|
871
|
+
- check: upstream_traffic
|
|
872
|
+
description: "log_event caused upstream traffic carrying the supplied user_match identifier"
|
|
873
|
+
min_count: 1
|
|
874
|
+
endpoint_pattern: "POST *"
|
|
875
|
+
identifier_paths:
|
|
876
|
+
- "events[*].user_match.hashed_email"
|
|
877
|
+
- id: financials
|
|
878
|
+
title: "Account financials"
|
|
879
|
+
narrative: |
|
|
880
|
+
The buyer checks account financials — spending, balance, and payment status. This is
|
|
881
|
+
essential for budget monitoring across multiple social platforms.
|
|
882
|
+
|
|
883
|
+
steps:
|
|
884
|
+
- id: get_account_financials
|
|
885
|
+
title: "Check account spending and balance"
|
|
886
|
+
narrative: |
|
|
887
|
+
The buyer retrieves financial information for the advertiser account. The platform
|
|
888
|
+
returns current spend, remaining balance, and payment status.
|
|
889
|
+
task: get_account_financials
|
|
890
|
+
schema_ref: "account/get-account-financials-request.json"
|
|
891
|
+
response_schema_ref: "account/get-account-financials-response.json"
|
|
892
|
+
doc_ref: "/accounts/tasks/get_account_financials"
|
|
893
|
+
stateful: true
|
|
894
|
+
expected: |
|
|
895
|
+
Return account financial data:
|
|
896
|
+
- Current spend to date
|
|
897
|
+
- Remaining balance or credit
|
|
898
|
+
- Payment status and terms
|
|
899
|
+
- Budget utilization metrics
|
|
900
|
+
|
|
901
|
+
sample_request:
|
|
902
|
+
account:
|
|
903
|
+
brand:
|
|
904
|
+
domain: "acmeoutdoor.example"
|
|
905
|
+
operator: "pinnacle-agency.example"
|
|
906
|
+
|
|
907
|
+
context:
|
|
908
|
+
correlation_id: "sales_social--get_account_financials"
|
|
909
|
+
validations:
|
|
910
|
+
- check: response_schema
|
|
911
|
+
description: "Response matches get-account-financials-response.json schema"
|
|
912
|
+
|
|
913
|
+
- check: field_present
|
|
914
|
+
path: "context"
|
|
915
|
+
description: "Response echoes back the context object"
|
|
916
|
+
- check: field_value
|
|
917
|
+
path: "context.correlation_id"
|
|
918
|
+
value: "sales_social--get_account_financials"
|
|
919
|
+
description: "Context correlation_id returned unchanged"
|