@adcp/sdk 14.0.0-rc.37 → 14.0.0-rc.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adcp-storyboard-summary.js +286 -0
- package/bin/adcp.js +221 -10
- package/dist/lib/conformance/schemaLoader.d.mts +1 -1
- package/dist/lib/conformance/schemaLoader.d.ts +1 -1
- package/dist/lib/core/AgentClient.d.mts +6 -1
- package/dist/lib/core/AgentClient.d.ts +6 -1
- package/dist/lib/core/AgentClient.js +9 -0
- package/dist/lib/core/AgentClient.mjs +9 -0
- package/dist/lib/core/ConversationTypes.d.mts +29 -0
- package/dist/lib/core/ConversationTypes.d.ts +29 -0
- package/dist/lib/core/SingleAgentClient.d.mts +3 -1
- package/dist/lib/core/SingleAgentClient.d.ts +3 -1
- package/dist/lib/core/SingleAgentClient.js +9 -1
- package/dist/lib/core/SingleAgentClient.mjs +9 -1
- package/dist/lib/core/TaskExecutor.d.mts +13 -1
- package/dist/lib/core/TaskExecutor.d.ts +13 -1
- package/dist/lib/core/TaskExecutor.js +216 -18
- package/dist/lib/core/TaskExecutor.mjs +216 -19
- package/dist/lib/index.d.mts +5 -2
- package/dist/lib/index.d.ts +5 -2
- package/dist/lib/index.js +10 -1
- package/dist/lib/index.mjs +10 -1
- package/dist/lib/media-buy/action-assessment.d.mts +77 -0
- package/dist/lib/media-buy/action-assessment.d.ts +77 -0
- package/dist/lib/media-buy/action-assessment.js +300 -0
- package/dist/lib/media-buy/action-assessment.mjs +284 -0
- package/dist/lib/media-buy/action-constraints.d.mts +9 -0
- package/dist/lib/media-buy/action-constraints.d.ts +9 -0
- package/dist/lib/media-buy/action-constraints.js +170 -0
- package/dist/lib/media-buy/action-constraints.mjs +146 -0
- package/dist/lib/media-buy/action-contracts.d.mts +40 -0
- package/dist/lib/media-buy/action-contracts.d.ts +40 -0
- package/dist/lib/media-buy/action-contracts.js +304 -0
- package/dist/lib/media-buy/action-contracts.mjs +267 -0
- package/dist/lib/media-buy/action-metadata.generated.d.mts +37 -0
- package/dist/lib/media-buy/action-metadata.generated.d.ts +37 -0
- package/dist/lib/media-buy/action-metadata.generated.js +128 -0
- package/dist/lib/media-buy/action-metadata.generated.mjs +101 -0
- package/dist/lib/media-buy/action-types.d.mts +106 -0
- package/dist/lib/media-buy/action-types.d.ts +106 -0
- package/dist/lib/{types/v3-1-beta/tools.generated.js → media-buy/action-types.js} +2 -2
- package/dist/lib/media-buy/actions.d.mts +6 -0
- package/dist/lib/media-buy/actions.d.ts +6 -0
- package/dist/lib/media-buy/actions.js +38 -0
- package/dist/lib/media-buy/actions.mjs +9 -0
- package/dist/lib/media-buy/available-actions.d.mts +2 -1
- package/dist/lib/media-buy/available-actions.d.ts +2 -1
- package/dist/lib/media-buy/available-actions.js +4 -3
- package/dist/lib/media-buy/available-actions.mjs +4 -3
- package/dist/lib/media-buy/compatibility.js +3 -0
- package/dist/lib/media-buy/compatibility.mjs +3 -0
- package/dist/lib/media-buy/index.d.mts +4 -0
- package/dist/lib/media-buy/index.d.ts +4 -0
- package/dist/lib/media-buy/index.js +3 -1
- package/dist/lib/media-buy/index.mjs +1 -0
- package/dist/lib/media-buy/legacy-action-ids.d.mts +1 -0
- package/dist/lib/media-buy/legacy-action-ids.d.ts +1 -0
- package/dist/lib/media-buy/legacy-action-ids.js +50 -0
- package/dist/lib/media-buy/legacy-action-ids.mjs +26 -0
- package/dist/lib/media-buy/mutations.d.mts +70 -0
- package/dist/lib/media-buy/mutations.d.ts +70 -0
- package/dist/lib/media-buy/mutations.js +525 -0
- package/dist/lib/media-buy/mutations.mjs +498 -0
- package/dist/lib/media-buy/preflight.d.mts +20 -69
- package/dist/lib/media-buy/preflight.d.ts +20 -69
- package/dist/lib/media-buy/preflight.js +100 -336
- package/dist/lib/media-buy/preflight.mjs +111 -333
- package/dist/lib/media-buy/targeting-input.d.mts +7 -4
- package/dist/lib/media-buy/targeting-input.d.ts +7 -4
- package/dist/lib/media-buy/types.d.mts +55 -7
- package/dist/lib/media-buy/types.d.ts +55 -7
- package/dist/lib/protocols/rawResponseCapture.d.mts +12 -0
- package/dist/lib/protocols/rawResponseCapture.d.ts +12 -0
- package/dist/lib/protocols/rawResponseCapture.js +33 -3
- package/dist/lib/protocols/rawResponseCapture.mjs +32 -3
- package/dist/lib/registry/types.generated.d.mts +377 -9
- package/dist/lib/registry/types.generated.d.ts +377 -9
- package/dist/lib/reporting/content-mismatch.d.mts +126 -0
- package/dist/lib/reporting/content-mismatch.d.ts +126 -0
- package/dist/lib/reporting/content-mismatch.js +90 -0
- package/dist/lib/reporting/content-mismatch.mjs +66 -0
- package/dist/lib/reporting/evidence.d.mts +1 -0
- package/dist/lib/reporting/evidence.d.ts +1 -0
- package/dist/lib/reporting/evidence.js +32 -3
- package/dist/lib/reporting/evidence.mjs +31 -3
- package/dist/lib/reporting/index.d.mts +3 -1
- package/dist/lib/reporting/index.d.ts +3 -1
- package/dist/lib/reporting/index.js +3 -0
- package/dist/lib/reporting/index.mjs +2 -0
- package/dist/lib/reporting/ledger/handler.d.mts +51 -1
- package/dist/lib/reporting/ledger/handler.d.ts +51 -1
- package/dist/lib/reporting/ledger/handler.js +306 -38
- package/dist/lib/reporting/ledger/handler.mjs +304 -37
- package/dist/lib/reporting/ledger/health.d.mts +12 -0
- package/dist/lib/reporting/ledger/health.d.ts +12 -0
- package/dist/lib/reporting/ledger/health.js +15 -2
- package/dist/lib/reporting/ledger/health.mjs +13 -1
- package/dist/lib/reporting/ledger/index.d.mts +3 -0
- package/dist/lib/reporting/ledger/index.d.ts +3 -0
- package/dist/lib/reporting/ledger/index.js +7 -1
- package/dist/lib/reporting/ledger/index.mjs +3 -0
- package/dist/lib/reporting/ledger/lifecycle.d.mts +31 -4
- package/dist/lib/reporting/ledger/lifecycle.d.ts +31 -4
- package/dist/lib/reporting/ledger/lifecycle.js +244 -37
- package/dist/lib/reporting/ledger/lifecycle.mjs +244 -37
- package/dist/lib/reporting/ledger/managed-postgres.d.mts +231 -0
- package/dist/lib/reporting/ledger/managed-postgres.d.ts +231 -0
- package/dist/lib/reporting/ledger/managed-postgres.js +1797 -0
- package/dist/lib/reporting/ledger/managed-postgres.mjs +1776 -0
- package/dist/lib/reporting/ledger/managed.d.mts +355 -0
- package/dist/lib/reporting/ledger/managed.d.ts +355 -0
- package/dist/lib/reporting/ledger/managed.js +661 -0
- package/dist/lib/reporting/ledger/managed.mjs +633 -0
- package/dist/lib/reporting/ledger/notification-activity.d.mts +222 -0
- package/dist/lib/reporting/ledger/notification-activity.d.ts +222 -0
- package/dist/lib/reporting/ledger/notification-activity.js +1139 -0
- package/dist/lib/reporting/ledger/notification-activity.mjs +1110 -0
- package/dist/lib/reporting/ledger/postgres.d.mts +161 -1
- package/dist/lib/reporting/ledger/postgres.d.ts +161 -1
- package/dist/lib/reporting/ledger/postgres.js +1153 -21
- package/dist/lib/reporting/ledger/postgres.mjs +1152 -21
- package/dist/lib/reporting/ledger/producer.d.mts +8 -0
- package/dist/lib/reporting/ledger/producer.d.ts +8 -0
- package/dist/lib/reporting/ledger/producer.js +146 -52
- package/dist/lib/reporting/ledger/producer.mjs +146 -51
- package/dist/lib/reporting/ledger/types.d.mts +358 -1
- package/dist/lib/reporting/ledger/types.d.ts +358 -1
- package/dist/lib/reporting/ledger/types.js +3 -0
- package/dist/lib/reporting/ledger/types.mjs +2 -0
- package/dist/lib/reporting/reconciliation.d.mts +362 -2
- package/dist/lib/reporting/reconciliation.d.ts +362 -2
- package/dist/lib/reporting/reconciliation.js +1051 -7
- package/dist/lib/reporting/reconciliation.mjs +1053 -7
- package/dist/lib/reporting/service/conformance.d.mts +35 -0
- package/dist/lib/reporting/service/conformance.d.ts +35 -0
- package/dist/lib/reporting/service/conformance.js +89 -0
- package/dist/lib/reporting/service/conformance.mjs +68 -0
- package/dist/lib/reporting/service/index.d.mts +182 -0
- package/dist/lib/reporting/service/index.d.ts +182 -0
- package/dist/lib/reporting/service/index.js +793 -0
- package/dist/lib/reporting/service/index.mjs +787 -0
- package/dist/lib/reporting/source/index.d.mts +2 -1
- package/dist/lib/reporting/source/index.d.ts +2 -1
- package/dist/lib/reporting/source/index.js +16 -3
- package/dist/lib/reporting/source/index.mjs +12 -1
- package/dist/lib/reporting/source/inline.d.mts +88 -1
- package/dist/lib/reporting/source/inline.d.ts +88 -1
- package/dist/lib/reporting/source/inline.js +1161 -163
- package/dist/lib/reporting/source/inline.mjs +1166 -163
- package/dist/lib/reporting/source/manifest.js +12 -7
- package/dist/lib/reporting/source/manifest.mjs +12 -7
- package/dist/lib/reporting/source/source.d.mts +26 -0
- package/dist/lib/reporting/source/source.d.ts +26 -0
- package/dist/lib/reporting/source/source.js +71 -2
- package/dist/lib/reporting/source/source.mjs +65 -1
- package/dist/lib/schemas/index.d.mts +22 -1
- package/dist/lib/schemas/index.d.ts +22 -1
- package/dist/lib/schemas/index.js +7 -0
- package/dist/lib/schemas/index.mjs +7 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +18 -0
- package/dist/lib/server/create-adcp-server.d.ts +18 -0
- package/dist/lib/server/create-adcp-server.js +52 -2
- package/dist/lib/server/create-adcp-server.mjs +52 -2
- package/dist/lib/server/decisioning/account.d.mts +1 -1
- package/dist/lib/server/decisioning/account.d.ts +1 -1
- package/dist/lib/server/decisioning/index.d.mts +1 -0
- package/dist/lib/server/decisioning/index.d.ts +1 -0
- package/dist/lib/server/decisioning/platform.d.mts +3 -0
- package/dist/lib/server/decisioning/platform.d.ts +3 -0
- package/dist/lib/server/decisioning/runtime/from-platform.js +88 -10
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +88 -10
- package/dist/lib/server/decisioning/specialisms/reporting.d.mts +38 -0
- package/dist/lib/server/decisioning/specialisms/reporting.d.ts +38 -0
- package/dist/lib/{types/v3-1-beta/index.js → server/decisioning/specialisms/reporting.js} +2 -8
- package/dist/lib/server/decisioning/specialisms/reporting.mjs +0 -0
- package/dist/lib/server/index.d.mts +4 -2
- package/dist/lib/server/index.d.ts +4 -2
- package/dist/lib/server/index.js +5 -0
- package/dist/lib/server/index.mjs +4 -0
- package/dist/lib/server/media-buy-action-resolver.d.mts +63 -0
- package/dist/lib/server/media-buy-action-resolver.d.ts +63 -0
- package/dist/lib/server/media-buy-action-resolver.js +297 -0
- package/dist/lib/server/media-buy-action-resolver.mjs +285 -0
- package/dist/lib/server/media-buy-actions.d.mts +7 -8
- package/dist/lib/server/media-buy-actions.d.ts +7 -8
- package/dist/lib/server/media-buy-actions.js +57 -14
- package/dist/lib/server/media-buy-actions.mjs +63 -14
- package/dist/lib/server/notification-subscriptions/index.d.mts +2 -2
- package/dist/lib/server/notification-subscriptions/index.d.ts +2 -2
- package/dist/lib/server/notification-subscriptions/index.js +2 -0
- package/dist/lib/server/notification-subscriptions/index.mjs +2 -0
- package/dist/lib/server/notification-subscriptions/postgres-runtime.d.mts +3 -1
- package/dist/lib/server/notification-subscriptions/postgres-runtime.d.ts +3 -1
- package/dist/lib/server/notification-subscriptions/postgres-runtime.js +1 -0
- package/dist/lib/server/notification-subscriptions/postgres-runtime.mjs +1 -0
- package/dist/lib/server/notification-subscriptions/runtime.d.mts +12 -1
- package/dist/lib/server/notification-subscriptions/runtime.d.ts +12 -1
- package/dist/lib/server/notification-subscriptions/runtime.js +102 -16
- package/dist/lib/server/notification-subscriptions/runtime.mjs +101 -16
- package/dist/lib/server/notification-subscriptions/types.d.mts +104 -1
- package/dist/lib/server/notification-subscriptions/types.d.ts +104 -1
- package/dist/lib/server/webhook-emitter.d.mts +40 -5
- package/dist/lib/server/webhook-emitter.d.ts +40 -5
- package/dist/lib/server/webhook-emitter.js +23 -12
- package/dist/lib/server/webhook-emitter.mjs +23 -12
- package/dist/lib/storage/interfaces.d.mts +14 -2
- package/dist/lib/storage/interfaces.d.ts +14 -2
- package/dist/lib/testing/compliance/comply.d.mts +9 -3
- package/dist/lib/testing/compliance/comply.d.ts +9 -3
- package/dist/lib/testing/compliance/comply.js +158 -3
- package/dist/lib/testing/compliance/comply.mjs +159 -4
- package/dist/lib/testing/compliance/storyboard-tracks.js +7 -5
- package/dist/lib/testing/compliance/storyboard-tracks.mjs +7 -5
- package/dist/lib/testing/compliance/summary.js +10 -1
- package/dist/lib/testing/compliance/summary.mjs +10 -1
- package/dist/lib/testing/index.d.mts +1 -1
- package/dist/lib/testing/index.d.ts +1 -1
- package/dist/lib/testing/index.js +2 -0
- package/dist/lib/testing/index.mjs +3 -1
- package/dist/lib/testing/storyboard/agent-routing.d.mts +12 -43
- package/dist/lib/testing/storyboard/agent-routing.d.ts +12 -43
- package/dist/lib/testing/storyboard/agent-routing.js +75 -13
- package/dist/lib/testing/storyboard/agent-routing.mjs +70 -12
- package/dist/lib/testing/storyboard/index.d.mts +1 -0
- package/dist/lib/testing/storyboard/index.d.ts +1 -0
- package/dist/lib/testing/storyboard/index.js +3 -0
- package/dist/lib/testing/storyboard/index.mjs +2 -0
- package/dist/lib/testing/storyboard/junit.d.mts +1 -1
- package/dist/lib/testing/storyboard/junit.d.ts +1 -1
- package/dist/lib/testing/storyboard/junit.js +21 -2
- package/dist/lib/testing/storyboard/junit.mjs +21 -2
- package/dist/lib/testing/storyboard/probes.d.mts +130 -0
- package/dist/lib/testing/storyboard/probes.d.ts +130 -0
- package/dist/lib/testing/storyboard/probes.js +682 -10
- package/dist/lib/testing/storyboard/probes.mjs +683 -3
- package/dist/lib/testing/storyboard/request-signing/builder.d.mts +16 -5
- package/dist/lib/testing/storyboard/request-signing/builder.d.ts +16 -5
- package/dist/lib/testing/storyboard/request-signing/grader.d.mts +44 -1
- package/dist/lib/testing/storyboard/request-signing/grader.d.ts +44 -1
- package/dist/lib/testing/storyboard/request-signing/grader.js +46 -22
- package/dist/lib/testing/storyboard/request-signing/grader.mjs +43 -21
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.mts +86 -11
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.ts +86 -11
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.js +119 -25
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +117 -26
- package/dist/lib/testing/storyboard/request-signing/synthesize.js +22 -2
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +22 -2
- package/dist/lib/testing/storyboard/runner.d.mts +103 -0
- package/dist/lib/testing/storyboard/runner.d.ts +103 -0
- package/dist/lib/testing/storyboard/runner.js +1090 -268
- package/dist/lib/testing/storyboard/runner.mjs +1096 -261
- package/dist/lib/testing/storyboard/seeding.d.mts +4 -1
- package/dist/lib/testing/storyboard/seeding.d.ts +4 -1
- package/dist/lib/testing/storyboard/seeding.js +55 -24
- package/dist/lib/testing/storyboard/seeding.mjs +55 -24
- package/dist/lib/testing/storyboard/test-kit.d.mts +37 -3
- package/dist/lib/testing/storyboard/test-kit.d.ts +37 -3
- package/dist/lib/testing/storyboard/test-kit.js +8 -2
- package/dist/lib/testing/storyboard/test-kit.mjs +7 -2
- package/dist/lib/testing/storyboard/types.d.mts +132 -10
- package/dist/lib/testing/storyboard/types.d.ts +132 -10
- package/dist/lib/testing/storyboard/types.js +17 -0
- package/dist/lib/testing/storyboard/types.mjs +16 -0
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/testing/storyboard/validations.js +16 -0
- package/dist/lib/testing/storyboard/validations.mjs +16 -0
- package/dist/lib/testing/test-controller.d.mts +1 -1
- package/dist/lib/testing/test-controller.d.ts +1 -1
- package/dist/lib/types/buy-products.d.ts +71 -6
- package/dist/lib/types/control-media-buy.d.ts +25 -11
- package/dist/lib/types/core.generated.d.mts +69 -10
- package/dist/lib/types/core.generated.d.ts +69 -10
- package/dist/lib/types/create-media-buy.d.ts +71 -6
- package/dist/lib/types/forward-compat-error-codes.d.mts +7 -6
- package/dist/lib/types/forward-compat-error-codes.d.ts +7 -6
- package/dist/lib/types/index.d.mts +2 -2
- package/dist/lib/types/index.d.ts +2 -2
- package/dist/lib/types/schemas.generated.d.ts +8040 -8116
- package/dist/lib/types/schemas.generated.js +1074 -309
- package/dist/lib/types/schemas.generated.mjs +1068 -309
- package/dist/lib/types/tools.generated.d.mts +65 -6
- package/dist/lib/types/tools.generated.d.ts +65 -6
- package/dist/lib/types/update-media-buy.d.ts +71 -6
- package/dist/lib/utils/redact-secrets.d.mts +1 -1
- package/dist/lib/utils/redact-secrets.d.ts +1 -1
- package/dist/lib/utils/redact-secrets.js +1 -1
- package/dist/lib/utils/redact-secrets.mjs +1 -1
- package/dist/lib/v2/projection/cache-versions.d.mts +0 -1
- package/dist/lib/v2/projection/cache-versions.d.ts +0 -1
- package/dist/lib/v2/projection/cache-versions.js +1 -15
- package/dist/lib/v2/projection/cache-versions.mjs +1 -14
- package/dist/lib/v2/projection/canonical-properties.js +2 -2
- package/dist/lib/v2/projection/canonical-properties.mjs +3 -3
- package/dist/lib/v2/projection/registry.d.mts +1 -1
- package/dist/lib/v2/projection/registry.d.ts +1 -1
- package/dist/lib/v2/projection/registry.js +2 -2
- package/dist/lib/v2/projection/registry.mjs +3 -3
- package/dist/lib/validation/schema-loader.d.mts +9 -1
- package/dist/lib/validation/schema-loader.d.ts +9 -1
- package/dist/lib/validation/schema-loader.js +65 -8
- package/dist/lib/validation/schema-loader.mjs +64 -8
- package/dist/lib/version.d.mts +5 -5
- package/dist/lib/version.d.ts +5 -5
- package/dist/lib/version.js +3 -8
- package/dist/lib/version.mjs +3 -8
- package/dist/lib/wholesale-feed-sync/index.d.mts +1 -0
- package/dist/lib/wholesale-feed-sync/index.d.ts +1 -0
- package/dist/lib/wholesale-feed-sync/protocol-types.d.mts +42 -0
- package/dist/lib/wholesale-feed-sync/protocol-types.d.ts +42 -0
- package/dist/lib/wholesale-feed-sync/protocol-types.js +16 -0
- package/dist/lib/wholesale-feed-sync/protocol-types.mjs +0 -0
- package/dist/lib/wholesale-feed-sync/sync.d.mts +6 -6
- package/dist/lib/wholesale-feed-sync/sync.d.ts +6 -6
- package/dist/lib/wholesale-feed-sync/sync.js +3 -1
- package/dist/lib/wholesale-feed-sync/sync.mjs +3 -1
- package/dist/lib/wholesale-feed-sync/types.d.mts +15 -14
- package/dist/lib/wholesale-feed-sync/types.d.ts +15 -14
- package/dist/lib/wholesale-feed-sync/webhook-notification.d.mts +7 -5
- package/dist/lib/wholesale-feed-sync/webhook-notification.d.ts +7 -5
- package/dist/lib/wholesale-feed-sync/webhook-notification.js +45 -0
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +44 -0
- package/docs/CLI.md +1 -1
- package/docs/TYPE-SUMMARY.md +118 -4
- package/docs/guides/ASYNC-API-REFERENCE.md +62 -1
- package/docs/guides/ASYNC-DEVELOPER-GUIDE.md +25 -0
- package/docs/guides/ASYNC-DOCUMENTATION-INDEX.md +3 -0
- package/docs/guides/BUYER-QUICKSTART-3.2.md +5 -0
- package/docs/guides/DURABLE-BUYER-WRITES.md +337 -0
- package/docs/guides/EXISTING-PLATFORM.md +80 -1
- package/docs/guides/MEDIA-BUY-3.2-COMPATIBILITY.md +57 -0
- package/docs/guides/MEDIA-BUY-ACTION-ASSESSMENT.md +300 -0
- package/docs/guides/REPORTING-LEDGER.md +654 -3
- package/docs/guides/REPORTING-RECONCILIATION.md +50 -0
- package/docs/guides/REPORTING-SOURCE-EXECUTOR.md +63 -1
- package/docs/guides/SELLER-QUICKSTART-3.2.md +2 -0
- package/docs/guides/VALIDATE-YOUR-AGENT.md +35 -0
- package/docs/guides/idempotency-crash-recovery.md +4 -0
- package/docs/llms.txt +4 -2
- package/docs/migration-14.x-rc-worksheet.md +60 -5
- package/docs/migration-7.9-to-7.10.md +7 -5
- package/examples/README.md +17 -0
- package/examples/durable-buyer-writes/caller.ts +745 -0
- package/examples/durable-buyer-writes/worker.ts +240 -0
- package/examples/reliable-reporting-service/README.md +100 -0
- package/examples/seller-3.2-starter.ts +7 -8
- package/examples/targeting-input-existing-platform.ts +153 -0
- package/package.json +41 -29
- package/skills/build-seller-agent/SKILL.md +2 -0
- package/skills/build-seller-agent/specialisms/signed-requests.md +11 -1
- package/skills/cross-cutting.md +28 -11
- package/compliance/cache/3.1.0-beta.7/domains/brand/index.yaml +0 -160
- package/compliance/cache/3.1.0-beta.7/domains/brand/scenarios/distributed_brand_resolution.yaml +0 -415
- package/compliance/cache/3.1.0-beta.7/domains/brand/scenarios/single_side_trust_extension.yaml +0 -454
- package/compliance/cache/3.1.0-beta.7/domains/creative/index.yaml +0 -339
- package/compliance/cache/3.1.0-beta.7/domains/creative/scenarios/billing_out_of_band.yaml +0 -153
- package/compliance/cache/3.1.0-beta.7/domains/creative/scenarios/creative_lifecycle_webhooks.yaml +0 -389
- package/compliance/cache/3.1.0-beta.7/domains/creative/scenarios/native_in_feed.yaml +0 -543
- package/compliance/cache/3.1.0-beta.7/domains/governance/index.yaml +0 -682
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/index.yaml +0 -781
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/audience_buy_flow.yaml +0 -380
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/available_actions.yaml +0 -565
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/billing_finality_delivery.yaml +0 -354
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/canonical_formats.yaml +0 -711
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/clicks_buy_flow.yaml +0 -264
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/completed_views_buy_flow.yaml +0 -344
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/create_media_buy_async.yaml +0 -234
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/creative_fate_after_cancellation.yaml +0 -419
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/creative_reception.yaml +0 -247
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/delivery_reporting.yaml +0 -357
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/dependency_impairment.yaml +0 -633
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/dependency_impairment_cardinality.yaml +0 -800
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/event_dedup_flow.yaml +0 -399
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/frequency_cap_enforcement.yaml +0 -309
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_approved.yaml +0 -214
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_conditions.yaml +0 -199
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_denied.yaml +0 -204
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_denied_recovery.yaml +0 -252
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/invalid_transitions.yaml +0 -289
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/inventory_list_no_match.yaml +0 -148
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/inventory_list_targeting.yaml +0 -276
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/measurement_accountability.yaml +0 -244
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/measurement_terms_rejected.yaml +0 -203
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/pending_creatives_to_start.yaml +0 -274
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/per_creative_conversion_attribution.yaml +0 -500
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/performance_buy_flow.yaml +0 -428
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/performance_buy_flow_roas.yaml +0 -470
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/product_signal_targeting.yaml +0 -373
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/proposal_finalize.yaml +0 -399
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/proposal_finalize_asap_timing.yaml +0 -264
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/proposal_not_found_errors.yaml +0 -257
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/provenance_audit_observation.yaml +0 -333
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/provenance_enforcement.yaml +0 -517
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/provenance_truth_of_claim.yaml +0 -294
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/reach_buy_flow.yaml +0 -823
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/refine_finalize_exclusivity.yaml +0 -360
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/refine_products.yaml +0 -148
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/vendor_metric_accountability.yaml +0 -293
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +0 -307
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/vendor_metric_optimization_flow.yaml +0 -576
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/state-machine.yaml +0 -442
- package/compliance/cache/3.1.0-beta.7/domains/signals/index.yaml +0 -266
- package/compliance/cache/3.1.0-beta.7/domains/sponsored-intelligence/index.yaml +0 -256
- package/compliance/cache/3.1.0-beta.7/index.json +0 -356
- package/compliance/cache/3.1.0-beta.7/protocols/brand/index.yaml +0 -160
- package/compliance/cache/3.1.0-beta.7/protocols/brand/scenarios/distributed_brand_resolution.yaml +0 -415
- package/compliance/cache/3.1.0-beta.7/protocols/brand/scenarios/single_side_trust_extension.yaml +0 -454
- package/compliance/cache/3.1.0-beta.7/protocols/creative/index.yaml +0 -339
- package/compliance/cache/3.1.0-beta.7/protocols/creative/scenarios/billing_out_of_band.yaml +0 -153
- package/compliance/cache/3.1.0-beta.7/protocols/creative/scenarios/creative_lifecycle_webhooks.yaml +0 -389
- package/compliance/cache/3.1.0-beta.7/protocols/creative/scenarios/native_in_feed.yaml +0 -543
- package/compliance/cache/3.1.0-beta.7/protocols/governance/index.yaml +0 -682
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/index.yaml +0 -781
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/audience_buy_flow.yaml +0 -380
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/available_actions.yaml +0 -565
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/billing_finality_delivery.yaml +0 -354
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/canonical_formats.yaml +0 -711
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/clicks_buy_flow.yaml +0 -264
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/completed_views_buy_flow.yaml +0 -344
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/create_media_buy_async.yaml +0 -234
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/creative_fate_after_cancellation.yaml +0 -419
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/creative_reception.yaml +0 -247
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/delivery_reporting.yaml +0 -357
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/dependency_impairment.yaml +0 -633
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/dependency_impairment_cardinality.yaml +0 -800
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/event_dedup_flow.yaml +0 -399
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/frequency_cap_enforcement.yaml +0 -309
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_approved.yaml +0 -214
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_conditions.yaml +0 -199
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_denied.yaml +0 -204
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_denied_recovery.yaml +0 -252
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/invalid_transitions.yaml +0 -289
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/inventory_list_no_match.yaml +0 -148
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/inventory_list_targeting.yaml +0 -276
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/measurement_accountability.yaml +0 -244
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/measurement_terms_rejected.yaml +0 -203
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/pending_creatives_to_start.yaml +0 -274
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/per_creative_conversion_attribution.yaml +0 -500
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/performance_buy_flow.yaml +0 -428
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/performance_buy_flow_roas.yaml +0 -470
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/product_signal_targeting.yaml +0 -373
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/proposal_finalize.yaml +0 -399
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/proposal_finalize_asap_timing.yaml +0 -264
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/proposal_not_found_errors.yaml +0 -257
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/provenance_audit_observation.yaml +0 -333
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/provenance_enforcement.yaml +0 -517
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/provenance_truth_of_claim.yaml +0 -294
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/reach_buy_flow.yaml +0 -823
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/refine_finalize_exclusivity.yaml +0 -360
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/refine_products.yaml +0 -148
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/vendor_metric_accountability.yaml +0 -293
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +0 -307
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/vendor_metric_optimization_flow.yaml +0 -576
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/state-machine.yaml +0 -442
- package/compliance/cache/3.1.0-beta.7/protocols/signals/index.yaml +0 -266
- package/compliance/cache/3.1.0-beta.7/protocols/sponsored-intelligence/index.yaml +0 -256
- package/compliance/cache/3.1.0-beta.7/specialisms/audience-sync/index.yaml +0 -313
- package/compliance/cache/3.1.0-beta.7/specialisms/brand-rights/index.yaml +0 -350
- package/compliance/cache/3.1.0-beta.7/specialisms/brand-rights/scenarios/governance_denied.yaml +0 -226
- package/compliance/cache/3.1.0-beta.7/specialisms/collection-lists/index.yaml +0 -359
- package/compliance/cache/3.1.0-beta.7/specialisms/content-standards/index.yaml +0 -572
- package/compliance/cache/3.1.0-beta.7/specialisms/creative-ad-server/index.yaml +0 -409
- package/compliance/cache/3.1.0-beta.7/specialisms/creative-generative/generative-seller.yaml +0 -807
- package/compliance/cache/3.1.0-beta.7/specialisms/creative-generative/index.yaml +0 -758
- package/compliance/cache/3.1.0-beta.7/specialisms/creative-template/index.yaml +0 -510
- package/compliance/cache/3.1.0-beta.7/specialisms/governance-aware-seller/index.yaml +0 -143
- package/compliance/cache/3.1.0-beta.7/specialisms/governance-aware-seller/scenarios/governance_multi_agent_rejected.yaml +0 -117
- package/compliance/cache/3.1.0-beta.7/specialisms/governance-delivery-monitor/index.yaml +0 -441
- package/compliance/cache/3.1.0-beta.7/specialisms/governance-spend-authority/denied.yaml +0 -221
- package/compliance/cache/3.1.0-beta.7/specialisms/governance-spend-authority/index.yaml +0 -330
- package/compliance/cache/3.1.0-beta.7/specialisms/property-lists/index.yaml +0 -482
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-broadcast-tv/index.yaml +0 -738
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-catalog-driven/index.yaml +0 -840
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-guaranteed/index.yaml +0 -601
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-non-guaranteed/index.yaml +0 -546
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-proposal-mode/index.yaml +0 -586
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-social/index.yaml +0 -919
- package/compliance/cache/3.1.0-beta.7/specialisms/signal-marketplace/index.yaml +0 -424
- package/compliance/cache/3.1.0-beta.7/specialisms/signal-marketplace/scenarios/governance_denied.yaml +0 -211
- package/compliance/cache/3.1.0-beta.7/specialisms/signal-owned/index.yaml +0 -317
- package/compliance/cache/3.1.0-beta.7/specialisms/sponsored-intelligence/index.yaml +0 -59
- package/compliance/cache/3.1.0-beta.7/test-kits/acme-outdoor-live.yaml +0 -78
- package/compliance/cache/3.1.0-beta.7/test-kits/acme-outdoor.yaml +0 -223
- package/compliance/cache/3.1.0-beta.7/test-kits/billing-gate-runner.yaml +0 -115
- package/compliance/cache/3.1.0-beta.7/test-kits/bistro-oranje.yaml +0 -126
- package/compliance/cache/3.1.0-beta.7/test-kits/distributed-brand-runner.yaml +0 -281
- package/compliance/cache/3.1.0-beta.7/test-kits/nova-motors.yaml +0 -262
- package/compliance/cache/3.1.0-beta.7/test-kits/osei-natural.yaml +0 -126
- package/compliance/cache/3.1.0-beta.7/test-kits/parallel-dispatch-runner.yaml +0 -196
- package/compliance/cache/3.1.0-beta.7/test-kits/rate-limit-trip-runner.yaml +0 -172
- package/compliance/cache/3.1.0-beta.7/test-kits/signed-requests-runner.yaml +0 -155
- package/compliance/cache/3.1.0-beta.7/test-kits/single-side-trust-runner.yaml +0 -294
- package/compliance/cache/3.1.0-beta.7/test-kits/substitution-observer-runner.yaml +0 -688
- package/compliance/cache/3.1.0-beta.7/test-kits/summit-foods.yaml +0 -125
- package/compliance/cache/3.1.0-beta.7/test-kits/webhook-receiver-runner.yaml +0 -265
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/001-minimal-plan.json +0 -43
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/002-full-plan.json +0 -217
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/003-bookkeeping-stripped.json +0 -60
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/004a-human-review-omitted.json +0 -43
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/004b-human-review-explicit-null.json +0 -49
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/005a-policy-categories-order-1.json +0 -53
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/005b-policy-categories-order-2.json +0 -57
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/006a-ext-trace-v1.json +0 -49
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/006b-ext-trace-v2.json +0 -53
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/007-unicode-objectives.json +0 -43
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/008-numeric-canonicalization.json +0 -65
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/README.md +0 -220
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/canonicalization.json +0 -241
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/keys.json +0 -60
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/001-no-signature-header.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/002-wrong-tag.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/003-expired-signature.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/004-window-too-long.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/005-alg-not-allowed.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/006-missing-covered-component.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/007-missing-content-digest.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/008-unknown-keyid.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/009-key-ops-missing-verify.json +0 -27
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/010-content-digest-mismatch.json +0 -33
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/011-malformed-header.json +0 -27
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/012-missing-expires-param.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/013-expires-le-created.json +0 -27
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/014-missing-nonce-param.json +0 -27
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/015-signature-invalid.json +0 -28
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/016-replayed-nonce.json +0 -35
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/017-key-revoked.json +0 -38
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/018-digest-covered-when-forbidden.json +0 -28
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/019-signature-without-signature-input.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/020-rate-abuse.json +0 -34
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/021-duplicate-signature-input-label.json +0 -31
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/022-multi-valued-content-type.json +0 -31
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/023-multi-valued-content-digest.json +0 -32
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/024-unquoted-string-param.json +0 -31
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/025-jwk-alg-crv-mismatch.json +0 -43
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/026-non-ascii-host.json +0 -31
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/027-webhook-registration-authentication-unsigned.json +0 -25
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/028-unsigned-protocol-method-required.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/001-basic-post.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/002-post-with-content-digest.json +0 -31
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/003-es256-post.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/004-multiple-signature-labels.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/005-default-port-stripped.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/006-dot-segment-path.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/007-query-byte-preserved.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/008-percent-encoded-path.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/009-percent-encoded-unreserved-decoded.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/010-percent-encoded-slash-preserved.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/011-ipv6-authority.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/012-ipv6-authority-default-port-stripped.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/README.md +0 -211
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/keys.json +0 -61
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/001-wrong-tag.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/002-expired-signature.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/003-window-too-long.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/004-alg-not-allowed.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/005-missing-authority-component.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/006-missing-content-digest.json +0 -25
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/007-unknown-keyid.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/008-wrong-adcp-use.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/009-content-digest-mismatch.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/010-malformed-signature-input.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/011-signature-without-input.json +0 -25
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/012-missing-expires-param.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/013-expires-le-created.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/014-missing-nonce-param.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/015-signature-invalid.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/016-replayed-nonce.json +0 -37
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/017-key-revoked.json +0 -32
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/018-rate-abuse.json +0 -33
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/019-revocation-stale.json +0 -32
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/020-key-ops-missing-verify.json +0 -41
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/021-base64-alphabet-mixing.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/001-basic-post.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/002-es256-post.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/003-multiple-signature-labels.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/004-default-port-stripped.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/005-percent-encoded-path.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/006-query-byte-preserved.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/007-body-without-idempotency-key.json +0 -25
- package/compliance/cache/3.1.0-beta.7/universal/billing-gate-dispatch.yaml +0 -450
- package/compliance/cache/3.1.0-beta.7/universal/canonical-format-validate-input.yaml +0 -640
- package/compliance/cache/3.1.0-beta.7/universal/capability-discovery.yaml +0 -125
- package/compliance/cache/3.1.0-beta.7/universal/collection-lists-pagination-integrity.yaml +0 -306
- package/compliance/cache/3.1.0-beta.7/universal/comply-controller-mode-gate.yaml +0 -141
- package/compliance/cache/3.1.0-beta.7/universal/content-standards-pagination-integrity.yaml +0 -326
- package/compliance/cache/3.1.0-beta.7/universal/deterministic-testing.yaml +0 -1430
- package/compliance/cache/3.1.0-beta.7/universal/error-compliance-signals.yaml +0 -377
- package/compliance/cache/3.1.0-beta.7/universal/error-compliance.yaml +0 -528
- package/compliance/cache/3.1.0-beta.7/universal/fictional-entities.yaml +0 -307
- package/compliance/cache/3.1.0-beta.7/universal/get-media-buys-pagination-integrity.yaml +0 -160
- package/compliance/cache/3.1.0-beta.7/universal/get-signals-pagination-integrity.yaml +0 -211
- package/compliance/cache/3.1.0-beta.7/universal/idempotency.yaml +0 -861
- package/compliance/cache/3.1.0-beta.7/universal/notification-config-event-scope.yaml +0 -119
- package/compliance/cache/3.1.0-beta.7/universal/notification-config-lifecycle.yaml +0 -337
- package/compliance/cache/3.1.0-beta.7/universal/notification-config-rejections.yaml +0 -107
- package/compliance/cache/3.1.0-beta.7/universal/pagination-integrity-creative-formats.yaml +0 -265
- package/compliance/cache/3.1.0-beta.7/universal/pagination-integrity-list-accounts.yaml +0 -245
- package/compliance/cache/3.1.0-beta.7/universal/pagination-integrity.yaml +0 -263
- package/compliance/cache/3.1.0-beta.7/universal/property-lists-pagination-integrity.yaml +0 -307
- package/compliance/cache/3.1.0-beta.7/universal/read-tool-idempotency.yaml +0 -405
- package/compliance/cache/3.1.0-beta.7/universal/runner-output-contract.yaml +0 -1266
- package/compliance/cache/3.1.0-beta.7/universal/schema-validation-signals.yaml +0 -181
- package/compliance/cache/3.1.0-beta.7/universal/schema-validation.yaml +0 -548
- package/compliance/cache/3.1.0-beta.7/universal/security.yaml +0 -539
- package/compliance/cache/3.1.0-beta.7/universal/signed-requests.yaml +0 -217
- package/compliance/cache/3.1.0-beta.7/universal/stale-response-advisory.yaml +0 -295
- package/compliance/cache/3.1.0-beta.7/universal/storyboard-schema.yaml +0 -2136
- package/compliance/cache/3.1.0-beta.7/universal/v3-envelope-integrity.yaml +0 -117
- package/compliance/cache/3.1.0-beta.7/universal/version-negotiation.yaml +0 -130
- package/compliance/cache/3.1.0-beta.7/universal/webhook-emission.yaml +0 -411
- package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-bulk-webhooks.yaml +0 -82
- package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-product-webhooks.yaml +0 -83
- package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-products.yaml +0 -151
- package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-signal-webhooks.yaml +0 -83
- package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-signals.yaml +0 -149
- package/dist/lib/types/v3-1-beta/index.d.mts +0 -1
- package/dist/lib/types/v3-1-beta/index.d.ts +0 -1
- package/dist/lib/types/v3-1-beta/index.mjs +0 -1
- package/dist/lib/types/v3-1-beta/tools.generated.d.mts +0 -26788
- package/dist/lib/types/v3-1-beta/tools.generated.d.ts +0 -26788
- /package/dist/lib/{types/v3-1-beta/tools.generated.mjs → media-buy/action-types.mjs} +0 -0
|
@@ -251,6 +251,11 @@ interface TaskOptions {
|
|
|
251
251
|
contextId?: string;
|
|
252
252
|
/** Enable debug logging for this task */
|
|
253
253
|
debug?: boolean;
|
|
254
|
+
/** Operation-routed crash recovery for direct A2A mutations */
|
|
255
|
+
durableContinuationRecovery?: {
|
|
256
|
+
/** Stable host authorization scope for the authenticated principal + account */
|
|
257
|
+
ownerScope: string;
|
|
258
|
+
};
|
|
254
259
|
/** Additional metadata to include */
|
|
255
260
|
metadata?: Record<string, any>;
|
|
256
261
|
}
|
|
@@ -571,6 +576,11 @@ interface DeferredContinuation<T> {
|
|
|
571
576
|
question?: string;
|
|
572
577
|
/** Resume the task with user input */
|
|
573
578
|
resume: (input: any) => Promise<TaskResult<T>>;
|
|
579
|
+
/** Host-only route capability; present for opted-in direct mutations */
|
|
580
|
+
recovery?: {
|
|
581
|
+
operationId: string;
|
|
582
|
+
recoveryKey: string;
|
|
583
|
+
};
|
|
574
584
|
}
|
|
575
585
|
```
|
|
576
586
|
|
|
@@ -878,6 +888,9 @@ interface DeferredTaskState {
|
|
|
878
888
|
clientContext?: unknown; // Opaque SDK context; round-trip unchanged
|
|
879
889
|
settlementOperationId?: string; // Trusted committed-mutation recovery route
|
|
880
890
|
settlementOperationRouteRequired?: true; // New-format routed record; preserve on every successor
|
|
891
|
+
directContinuationRecovery?: true; // Routed direct pause, not committed settlement
|
|
892
|
+
directContinuationRecoveryKeyDigest?: string; // SHA-256; raw capability is never stored
|
|
893
|
+
directContinuationOwnerBindingDigest?: string; // Authenticated owner/account + trusted seller binding
|
|
881
894
|
settlementResumeAuthorizationRequired?: boolean; // Owning coordinator must authorize seller-input dispatch
|
|
882
895
|
settlementServerTaskId?: string; // Durably bound seller work handle
|
|
883
896
|
settlementPendingTaskId?: string; // Nonterminal seller work retained for restart polling
|
|
@@ -919,6 +932,12 @@ interface DeferredTaskStorage extends Storage<DeferredTaskState> {
|
|
|
919
932
|
```
|
|
920
933
|
|
|
921
934
|
`putIfAbsent()` must atomically reject an existing unexpired key.
|
|
935
|
+
Custom adapters MUST round-trip every `DeferredTaskState` field opaquely,
|
|
936
|
+
including fields introduced by newer SDK versions. When A→B moves an
|
|
937
|
+
operation route but retains A as a dispatch fence, later deletion or expiry of
|
|
938
|
+
A MUST clear the route only if it still points at A; it must never delete the
|
|
939
|
+
route that now points at B. Deploy readers that preserve new fields before
|
|
940
|
+
enabling new routed writers in a shared store.
|
|
922
941
|
For ordinary and marker-absent legacy records, `replaceIfVersion()` is the
|
|
923
942
|
exclusive seller-dispatch claim: it must replace only the exact generation and
|
|
924
943
|
keep the key present under the SDK-supplied internal safety TTL. New
|
|
@@ -939,7 +958,7 @@ dispatch, the SDK generation-conditionally restores the original state with
|
|
|
939
958
|
its remaining human-input TTL.
|
|
940
959
|
|
|
941
960
|
The three settlement-operation methods form a second atomic index over
|
|
942
|
-
committed continuations. Initial pause creation writes the opaque token and
|
|
961
|
+
committed continuations and opted-in direct mutation pauses. Initial pause creation writes the opaque token and
|
|
943
962
|
operation route together. A nested pause writes B and moves the route from the
|
|
944
963
|
exact dispatch-committed generation A in one transaction while retaining A as
|
|
945
964
|
a dispatch fence. `getBySettlementOperationId()` returns that exact current
|
|
@@ -959,6 +978,48 @@ trusted settlement operation identity. A terminal restart resume is returned
|
|
|
959
978
|
only after a reconstructed durable coordinator settles it; without a matching
|
|
960
979
|
recoverer, the resume fails closed.
|
|
961
980
|
|
|
981
|
+
Direct A2A mutations opt in per call with an authenticated owner/account scope:
|
|
982
|
+
|
|
983
|
+
```typescript
|
|
984
|
+
const paused = await agent.buyProducts(request, undefined, {
|
|
985
|
+
durableContinuationRecovery: {
|
|
986
|
+
ownerScope: `principal:${principalId}/account:${accountId}`,
|
|
987
|
+
},
|
|
988
|
+
});
|
|
989
|
+
|
|
990
|
+
// Persist this pair once in host-only storage. The recovery key is distinct
|
|
991
|
+
// from the human-facing resume token and must never be sent to the seller.
|
|
992
|
+
const route = paused.deferred?.recovery;
|
|
993
|
+
if (!route) throw new Error('Seller did not return a recoverable A2A pause');
|
|
994
|
+
|
|
995
|
+
const recovered = await restartedAgent.recoverDirectPauseContinuation({
|
|
996
|
+
operationId: route.operationId,
|
|
997
|
+
recoveryKey: route.recoveryKey,
|
|
998
|
+
ownerScope: `principal:${principalId}/account:${accountId}`,
|
|
999
|
+
});
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
The SDK stores only the recovery-key digest, binds it to the supplied stable
|
|
1003
|
+
principal/account owner scope and trusted seller ID/origin, and validates the route
|
|
1004
|
+
store before seller dispatch. Unknown routes, wrong capabilities, owner drift,
|
|
1005
|
+
and seller drift fail without revealing a token. The host must authenticate
|
|
1006
|
+
the caller before constructing `ownerScope`; request fields are not an
|
|
1007
|
+
authentication source. Keep the scope byte-stable for the operation lifetime;
|
|
1008
|
+
do not use a mutable display name, seller-supplied value, seller task ID, or
|
|
1009
|
+
request idempotency key. Custom stores must round-trip all three
|
|
1010
|
+
`directContinuation*` fields and implement the operation-route methods as one
|
|
1011
|
+
linearizable index. Direct routes do not enter committed-settlement recovery,
|
|
1012
|
+
so the existing callback and terminal settlement fences remain unchanged.
|
|
1013
|
+
The operation route covers resumable pause generations. If resume instead
|
|
1014
|
+
reaches `submitted` or a terminal result, persist the returned seller task ID
|
|
1015
|
+
and result through the normal host operation record; terminal uncertainty is
|
|
1016
|
+
reconciled by polling that seller task ID, never by redispatching the mutation.
|
|
1017
|
+
Persist the first returned recovery pair before considering the initial pause
|
|
1018
|
+
restart-safe. After any possible continuation dispatch, an absent pause route
|
|
1019
|
+
does not authorize redispatch.
|
|
1020
|
+
|
|
1021
|
+
### Committed coordinator checkpoints
|
|
1022
|
+
|
|
962
1023
|
If seller continuation reaches a terminal result, the SDK replaces the human
|
|
963
1024
|
input record with an opaque terminal checkpoint using the same independent
|
|
964
1025
|
safety horizon. Recovery and application completion handlers retry from that
|
|
@@ -412,6 +412,31 @@ async function manageTaskLifecycle() {
|
|
|
412
412
|
}
|
|
413
413
|
```
|
|
414
414
|
|
|
415
|
+
For a direct A2A mutation that may pause more than once, opt into an atomic
|
|
416
|
+
operation route and persist the returned host-only capability once:
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
const paused = await agent.buyProducts(request, undefined, {
|
|
420
|
+
durableContinuationRecovery: {
|
|
421
|
+
ownerScope: `principal:${principalId}/account:${accountId}`,
|
|
422
|
+
},
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
const savedRecovery = paused.deferred?.recovery;
|
|
426
|
+
if (!savedRecovery) throw new Error('Seller did not return a recoverable A2A pause');
|
|
427
|
+
await saveHostOnly(savedRecovery);
|
|
428
|
+
|
|
429
|
+
const current = await restartedAgent.recoverDirectPauseContinuation({
|
|
430
|
+
...savedRecovery,
|
|
431
|
+
ownerScope: `principal:${principalId}/account:${accountId}`,
|
|
432
|
+
});
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
`ownerScope` must come from authenticated host context. The recovery key is
|
|
436
|
+
separate from the resume token and must not be placed in approval links or
|
|
437
|
+
sent to the seller. Recovery returns the current nested pause without a seller
|
|
438
|
+
call; its `deferred.resume()` remains generation-fenced.
|
|
439
|
+
|
|
415
440
|
Durable snapshots redact entire secret-shaped containers and truncate
|
|
416
441
|
over-depth subtrees. `SingleAgentClient.getProducts()` rejects an authenticated
|
|
417
442
|
request `property_list` before seller dispatch when durable storage also needs
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
Complete documentation for the ADCP TypeScript client library's new async execution model introduced in PR #78. This documentation covers migration from old patterns, comprehensive developer guidance, and production-ready implementation strategies.
|
|
6
6
|
|
|
7
|
+
Deploying request-scoped callers across multiple processes? Start with
|
|
8
|
+
[Durable buyer writes across processes](./DURABLE-BUYER-WRITES.md).
|
|
9
|
+
|
|
7
10
|
## 📚 Documentation Structure
|
|
8
11
|
|
|
9
12
|
### 1. [Migration Guide](./ASYNC-MIGRATION-GUIDE.md)
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
# Call a seller with AdCP 3.2
|
|
2
2
|
|
|
3
|
+
For product possibility, accepted change rights, and current execution routes, use the [MediaBuy action assessment helpers](./MEDIA-BUY-ACTION-ASSESSMENT.md).
|
|
4
|
+
|
|
3
5
|
Requires Node.js `^20.19.0 || >=22.12.0`. Install the SDK 14 prerelease
|
|
4
6
|
and create one client:
|
|
5
7
|
|
|
8
|
+
For request-scoped callers whose callback or poll may run on another process,
|
|
9
|
+
use the [durable buyer writes recipe](./DURABLE-BUYER-WRITES.md).
|
|
10
|
+
|
|
6
11
|
```bash
|
|
7
12
|
npm install '@adcp/sdk@^14.0.0-0'
|
|
8
13
|
```
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# Durable buyer writes across processes
|
|
2
|
+
|
|
3
|
+
This recipe preserves one outbound AdCP 3.2 mutation when the HTTP caller,
|
|
4
|
+
callback receiver, poller, and publisher are different processes. It is
|
|
5
|
+
validated against `@adcp/sdk@14.0.0-rc.38` and the SDK's pinned
|
|
6
|
+
`3.2.0-rc.3` protocol bundle. Earlier SDK 14 prereleases are not the supported
|
|
7
|
+
baseline for this recipe.
|
|
8
|
+
|
|
9
|
+
The compiling two-process example is:
|
|
10
|
+
|
|
11
|
+
- [`caller.ts`](../../examples/durable-buyer-writes/caller.ts) — stages an
|
|
12
|
+
immutable `buy_products` request, binds the SDK callback operation to it in
|
|
13
|
+
the registration transaction, and dispatches with a request-scoped client.
|
|
14
|
+
- [`worker.ts`](../../examples/durable-buyer-writes/worker.ts) — reconstructs a
|
|
15
|
+
fresh authorized client for callback verification, polling, A2A continuation
|
|
16
|
+
resume, and host-outbox publication.
|
|
17
|
+
|
|
18
|
+
The example uses PostgreSQL, but the SDK also ships
|
|
19
|
+
`redisWebhookRegistrationStore` and Redis replay/idempotency backends. Do not
|
|
20
|
+
mix volatile and durable implementations in one receiver fleet.
|
|
21
|
+
|
|
22
|
+
## Four identities, four columns
|
|
23
|
+
|
|
24
|
+
Never substitute one of these values for another:
|
|
25
|
+
|
|
26
|
+
| Identity | Issuer and purpose | Example column |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| Logical operation ID | Host application; one business intent and its recovery record | `logical_operation_id` |
|
|
29
|
+
| Request `idempotency_key` | Buyer; immutable replay identity for one canonical mutating request | `request_idempotency_key` |
|
|
30
|
+
| Seller `task_id` | Seller; polling handle for accepted asynchronous work | `seller_task_id` |
|
|
31
|
+
| Webhook `idempotency_key` | Seller webhook infrastructure; delivery-key binding for retries of one payload | SDK webhook-dedup backend |
|
|
32
|
+
|
|
33
|
+
The webhook delivery key is an infrastructure-layer convention carried in the
|
|
34
|
+
AdCP webhook envelope, not the original request key. The SDK's client-minted
|
|
35
|
+
`operation_id` is a fifth correlation/routing value: the example stores it as
|
|
36
|
+
`sdk_operation_id` in an insert-only route table and binds every retry attempt
|
|
37
|
+
to the host operation before network dispatch. Late callbacks from an earlier
|
|
38
|
+
attempt therefore remain verifiable and routable.
|
|
39
|
+
An A2A `Task.id`, A2A `contextId`, and a deferred continuation token remain
|
|
40
|
+
separate again.
|
|
41
|
+
|
|
42
|
+
A retry after an uncertain response reloads the stored canonical payload and
|
|
43
|
+
request key. It does not regenerate either. A later A→B→A business sequence is
|
|
44
|
+
three operations with three keys even though the final business state resembles
|
|
45
|
+
the first. A timeout is not evidence that the seller rejected the request and
|
|
46
|
+
is never an automatic reason to rotate the key. Reconcile by the operation's
|
|
47
|
+
natural key before deciding that a new intent exists.
|
|
48
|
+
|
|
49
|
+
## Production wiring
|
|
50
|
+
|
|
51
|
+
The published example is source rather than a package export, so applications
|
|
52
|
+
normally copy it. Import its migration/readiness functions locally and run
|
|
53
|
+
them from deployment/startup tooling before accepting traffic:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { Pool } from 'pg';
|
|
57
|
+
import { migrateDurableBuyer, probeDurableBuyerStores } from './durable-buyer-writes/caller.js';
|
|
58
|
+
|
|
59
|
+
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
60
|
+
await migrateDurableBuyer(pool);
|
|
61
|
+
await probeDurableBuyerStores(pool); // startup/readiness, not once per request
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Its named tables are deployment-specific:
|
|
65
|
+
|
|
66
|
+
| State | Example namespace/table | Retention |
|
|
67
|
+
| --- | --- | --- |
|
|
68
|
+
| Host operation, natural key, and terminal winner | `buyer_prod_v1` in `buyer_adcp_operations` | Through business reconciliation and audit policy |
|
|
69
|
+
| SDK attempt-to-operation routes | `buyer_adcp_operation_routes` | At least as long as the matching callback registrations |
|
|
70
|
+
| Host publication outbox | `buyer_prod_v1` in `buyer_adcp_publications` | Until published, then through the host's duplicate-proof horizon |
|
|
71
|
+
| Trusted callback registration | `buyer_adcp_webhook_registrations` | At least the seller webhook retry horizon; seven days in the example |
|
|
72
|
+
| RFC 9421 nonce replay fence | `buyer_adcp_webhook_replays` | SDK signature window; sweep only expired rows |
|
|
73
|
+
| Webhook delivery and terminal dedup | `buyer_adcp_webhook_dedup` | At least `max(24h, advertised delivery retry horizon)`; seven days in the example |
|
|
74
|
+
| Deferred continuation | Host `DeferredTaskStorage` | At least the permitted human-input/recovery interval; seven days in the example |
|
|
75
|
+
|
|
76
|
+
Use deployment-unique PostgreSQL table names or Redis prefixes. Run the
|
|
77
|
+
root-exported `cleanupExpiredWebhookRegistrations()` and the
|
|
78
|
+
`@adcp/sdk/signing/server` export `sweepExpiredReplays()` as bounded
|
|
79
|
+
maintenance. Remove an attempt route only after its registration is gone;
|
|
80
|
+
idempotency-backend cleanup is likewise operational maintenance, not a
|
|
81
|
+
correctness prerequisite. The pinned 3.2 schema caps the advertised webhook
|
|
82
|
+
retry horizon at the example's seven-day value. Backend clocks, not process
|
|
83
|
+
clocks, decide expiry.
|
|
84
|
+
|
|
85
|
+
`DeferredTaskStorage` is deliberately an application adapter because paused
|
|
86
|
+
state can contain application-owned projection context. Supply the same atomic
|
|
87
|
+
implementation to every caller and worker. It must implement generation CAS,
|
|
88
|
+
atomic operation routing, encrypted-at-rest storage, expiry, and the full
|
|
89
|
+
contract in [Async API reference](./ASYNC-API-REFERENCE.md#deferredtaskstorage).
|
|
90
|
+
Do not replace it with `MemoryStorage` in a restart-sensitive deployment.
|
|
91
|
+
|
|
92
|
+
### Stage, then dispatch
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
const ledger = new PostgresOperationLedger(pool);
|
|
96
|
+
await ledger.stage(logicalOperationId, orderId, authorizedSession, {
|
|
97
|
+
account: { account_id: authorizedSession.sellerAccountId },
|
|
98
|
+
brand: { domain: advertiserDomain },
|
|
99
|
+
feed_version: selectedFeedVersion,
|
|
100
|
+
pricing_version: selectedPricingVersion, // when list_products supplied one
|
|
101
|
+
purchases: selectedRealProducts,
|
|
102
|
+
purchase_order_ref: orderId,
|
|
103
|
+
start_time: 'asap',
|
|
104
|
+
end_time: campaignEnd,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
await dispatchStagedBuy(dependencies, logicalOperationId);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`stage()` commits the logical ID, separately supplied natural key, request key,
|
|
111
|
+
complete canonical payload, seller/account binding, tenant, and principal before
|
|
112
|
+
the SDK call. Mirror the natural key into a seller-supported field such as
|
|
113
|
+
`purchase_order_ref` or namespaced `context` so seller readback can reconcile an
|
|
114
|
+
expired or ambiguous request. During SDK pre-dispatch registration,
|
|
115
|
+
the example's `OperationBoundRegistrationStore` atomically writes the supported
|
|
116
|
+
PostgreSQL registration and binds the new SDK `operation_id` to that row. A
|
|
117
|
+
crash before that transaction returns sends nothing; a crash after it remains
|
|
118
|
+
recoverable by a different process. A retry creates another operation route
|
|
119
|
+
but reuses the original canonical payload and request key. A seller response
|
|
120
|
+
without result data remains `dispatch-uncertain`; malformed result data becomes
|
|
121
|
+
`terminal-result-pending`. Neither can win terminal settlement merely because a
|
|
122
|
+
transport adapter reported `failed`. Treat `staged`, `dispatch-uncertain`, and
|
|
123
|
+
`terminal-result-pending` as reconciliation queues, not terminal outcomes.
|
|
124
|
+
Abort and deadline errors are thrown rather than returned by the SDK; the
|
|
125
|
+
example catches that path, marks the stored row `dispatch-uncertain`, and
|
|
126
|
+
rethrows the original error with its SDK-attached request key intact.
|
|
127
|
+
|
|
128
|
+
The host's `resolveSellerSession()` rechecks current tenant, principal, seller,
|
|
129
|
+
and account authorization and re-derives the request-local bearer. It returns
|
|
130
|
+
`undefined` for an authorization denial and throws for an infrastructure
|
|
131
|
+
failure, so callback workers can return static 404 versus retryable 5xx without
|
|
132
|
+
leaking details. No token is stored in the operation, deferred state, callback
|
|
133
|
+
URL, or `ctx_metadata`.
|
|
134
|
+
|
|
135
|
+
### Receive on a fresh process
|
|
136
|
+
|
|
137
|
+
Mount a raw-body route matching the configured server-owned template:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
app.post(
|
|
141
|
+
'/adcp/webhook/:task_type/:agent_id/:operation_id',
|
|
142
|
+
express.raw({ type: 'application/json' }),
|
|
143
|
+
async (req, res, next) => {
|
|
144
|
+
try {
|
|
145
|
+
await receiveTaskWebhook(dependencies, req, res);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
next(error); // static application 500/503 handler; never reflect error.message
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`receiveTaskWebhook()` resolves the operation from `(seller,
|
|
154
|
+
operation_id)`, reauthorizes it, constructs a new `AgentClient`, and invokes the
|
|
155
|
+
SDK HTTP helper. The helper reads the shared registration, verifies RFC 9421
|
|
156
|
+
and its replay fence, validates the route/envelope/task identities, and applies
|
|
157
|
+
the shared webhook-dedup claim before the host handler runs. Its public URL is
|
|
158
|
+
constructed from server-owned configuration, never `Host` or forwarding
|
|
159
|
+
headers. Preserve the helper's 2xx/409/429/503 mapping.
|
|
160
|
+
The example rejects seller IDs outside the RFC 3986 unreserved set because the
|
|
161
|
+
SDK substitutes callback macros without percent-encoding them. Missing or
|
|
162
|
+
unauthorized pre-verification routes receive a static 400/404; database or
|
|
163
|
+
readiness failures flow to the application's static error middleware.
|
|
164
|
+
|
|
165
|
+
### Poll or resume after restart
|
|
166
|
+
|
|
167
|
+
Persist `metadata.serverTaskId`, never `metadata.taskId`, as the seller polling
|
|
168
|
+
handle. When no callback arrives:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
await recoverByPolling(dependencies, logicalOperationId, AbortSignal.timeout(15_000));
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`recoverByPolling()` intentionally uses the public `TaskExecutor` because the
|
|
175
|
+
similarly named `AgentClient.getTaskStatus()` method is internal. Its third
|
|
176
|
+
positional argument is optional transport configuration; the example passes
|
|
177
|
+
`undefined` before the abort signal. A terminal poll without the canonical
|
|
178
|
+
`result` is evidence of status, but not enough to fingerprint or publish the
|
|
179
|
+
business result; keep reconciling until result readback or a callback supplies
|
|
180
|
+
it.
|
|
181
|
+
|
|
182
|
+
For an A2A pause with a verified native continuation, persist the SDK deferred
|
|
183
|
+
token and reconstruct the client with the same `DeferredTaskStorage` before:
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
await resumePendingInput(dependencies, logicalOperationId, approvedInput);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Reauthorization happens immediately before resume. MCP pauses and A2A pauses
|
|
190
|
+
without native `Task.id` plus `contextId` are intentionally nonresumable; the
|
|
191
|
+
status label or seller work ID cannot be promoted into a continuation
|
|
192
|
+
capability. For a committed legacy-purchase compatibility continuation,
|
|
193
|
+
negotiate `MediaBuyLifecycleCoordinator` on the fresh `AgentClient` with the
|
|
194
|
+
same durable continuation store, `principalScope`, and stable non-secret
|
|
195
|
+
`legacyPurchaseSellerSessionScope` before `resumeDeferredTask()`. That installs
|
|
196
|
+
the SDK settlement recoverer; a bare replacement client correctly fails closed.
|
|
197
|
+
For the direct `buy_products` path, the example also takes a leased host
|
|
198
|
+
continuation claim immediately before resume. Terminal callbacks return a
|
|
199
|
+
retryable in-progress response while that claim is live; a callback that wins
|
|
200
|
+
before the claim prevents resume. The example enforces a five-minute minimum
|
|
201
|
+
and renews the claim while the resume call is active. If renewal is lost, it
|
|
202
|
+
refuses to commit that worker's observation and lets callback or polling
|
|
203
|
+
reconciliation choose the terminal winner.
|
|
204
|
+
|
|
205
|
+
Direct A2A mutations can close the nested-pause handoff window with
|
|
206
|
+
`TaskOptions.durableContinuationRecovery`. Supply an `ownerScope` derived from
|
|
207
|
+
the authenticated principal and seller account, then persist the initial
|
|
208
|
+
`result.deferred.recovery` operation ID and host-only recovery key. If a worker
|
|
209
|
+
dies after atomically moving the SDK route from token A to token B but before
|
|
210
|
+
the host observes B, a fresh `AgentClient` calls
|
|
211
|
+
`recoverDirectPauseContinuation({ operationId, recoveryKey, ownerScope })` to
|
|
212
|
+
reconstruct B without seller I/O. The SDK stores only a key digest, also binds
|
|
213
|
+
the route to the supplied owner scope and trusted seller identity, and keeps this
|
|
214
|
+
direct route separate from the legacy compatibility coordinator's committed
|
|
215
|
+
settlement path. A claimed uncertain-dispatch fence fails with an explicit
|
|
216
|
+
"do not redispatch" error. Persist the initial recovery pair before treating
|
|
217
|
+
the first pause as restart-safe. The route ends when continuation leaves a
|
|
218
|
+
resumable pause; a missing route after possible dispatch is never evidence
|
|
219
|
+
that redispatch is safe. Reconcile terminal uncertainty by polling the saved
|
|
220
|
+
seller task ID.
|
|
221
|
+
|
|
222
|
+
## Terminal settlement and host publication
|
|
223
|
+
|
|
224
|
+
Direct responses, verified callbacks, polls, and continuation results compete
|
|
225
|
+
to update one locked operation row. The first authoritative terminal
|
|
226
|
+
fingerprint wins. An exact duplicate sees the same fingerprint and one existing
|
|
227
|
+
outbox row. A different canonical terminal payload rolls back with a conflict
|
|
228
|
+
and cannot replace the winner. Task-envelope labels that carry the same
|
|
229
|
+
canonical commitment payload intentionally converge; the first observed label
|
|
230
|
+
remains in the operational status column.
|
|
231
|
+
|
|
232
|
+
Only schema-valid terminal seller result payloads are fingerprinted. The
|
|
233
|
+
fingerprint projects immutable commitment identity (`media_buy_id`, `revision`,
|
|
234
|
+
`accepted_proposal`, and `purchase_bindings`) and excludes delivery-only or
|
|
235
|
+
time-varying fields such as `replayed`, `context`, `ext`, `available_actions`,
|
|
236
|
+
`media_buy_status`, `confirmed_at`, and `warnings`, so direct, poll, and
|
|
237
|
+
callback delivery of the same business result converge. The first full
|
|
238
|
+
validated payload remains the publication value. The ledger's `status` column records task-envelope
|
|
239
|
+
status independently from the commitment payload's own `completed`/`failed`
|
|
240
|
+
discriminant. SDK-local transport failures and terminal polls that
|
|
241
|
+
omit `result` remain nonterminal host observations. An incomplete terminal
|
|
242
|
+
callback is rejected with a retryable 503 before the SDK publishes its dedup
|
|
243
|
+
claim, so a corrected retry can still settle the operation.
|
|
244
|
+
|
|
245
|
+
The same database transaction records the terminal winner and inserts the
|
|
246
|
+
publication outbox row. `publishOne()` establishes a leased publication owner
|
|
247
|
+
before calling application code. Because PostgreSQL and an external event bus
|
|
248
|
+
do not share a transaction, the downstream publisher must atomically
|
|
249
|
+
deduplicate `logicalOperationId`. A crash after the external send but before
|
|
250
|
+
the database ACK then causes an idempotent retry, not a duplicate business
|
|
251
|
+
effect. Keep each send below the example's 60-second lease or renew the claim
|
|
252
|
+
effect. Keep each send below the example's 60-second lease; this compact helper
|
|
253
|
+
does not expose publication-lease renewal. If the destination cannot offer that
|
|
254
|
+
contract, publish into a database table consumed transactionally with the
|
|
255
|
+
destination's own state instead.
|
|
256
|
+
|
|
257
|
+
The SDK owns transport/protocol validation, callback authentication, replay
|
|
258
|
+
protection, registration persistence, delivery claims, status normalization,
|
|
259
|
+
and continuation fencing. The host still owns:
|
|
260
|
+
|
|
261
|
+
- authenticated tenant/principal/seller/account resolution and credential
|
|
262
|
+
re-derivation;
|
|
263
|
+
- durable logical-operation, canonical-request, natural-key, and task-handle
|
|
264
|
+
storage;
|
|
265
|
+
- an atomic `DeferredTaskStorage` implementation for restart-safe A2A pauses;
|
|
266
|
+
- terminal winner plus publication-outbox transaction;
|
|
267
|
+
- idempotent downstream publication, leases, monitoring, dead letters, and
|
|
268
|
+
retention/cleanup scheduling;
|
|
269
|
+
- campaign approvals, budgets, per-seller orchestration, and ongoing delivery
|
|
270
|
+
reconciliation.
|
|
271
|
+
|
|
272
|
+
## Evidence matrix
|
|
273
|
+
|
|
274
|
+
| Boundary | Expected convergence | Existing SDK evidence / host proof |
|
|
275
|
+
| --- | --- | --- |
|
|
276
|
+
| Seller accepts, response is lost | Retry the same canonical payload and request key; reconcile before any new intent | Exact pinned-key transport retry is covered by [`media-buy-lifecycle-coordinator.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/media-buy-lifecycle-coordinator.test.js#L12478); typed replay, conflict, and expiry surfaces are covered by [`idempotency-client.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/idempotency-client.test.js#L114), [line 288](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/idempotency-client.test.js#L288), and [line 307](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/idempotency-client.test.js#L307). The example stages the canonical request value and key first. |
|
|
277
|
+
| Callback before submitted response | Callback winner is retained; later nonterminal response is stale | [`task-executor-pre-dispatch-boundary.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/task-executor-pre-dispatch-boundary.test.js#L351). |
|
|
278
|
+
| Callback reaches another process after caller exit | Fresh receiver reads the shared trusted registration and operation binding | PostgreSQL and Redis reconstruction are covered by [`webhook-registration-durability.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/webhook-registration-durability.test.js#L239) and [line 359](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/webhook-registration-durability.test.js#L359); restarted durable callback settlement is covered by [`task-executor-pre-dispatch-boundary.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/task-executor-pre-dispatch-boundary.test.js#L2096). |
|
|
279
|
+
| Restart after observation, before host publication | Terminal winner and one outbox row commit together; a publisher lease is recoverable | The example's PostgreSQL rollback and expired-lease recovery are exercised in [`durable-buyer-writes.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/examples/durable-buyer-writes.test.js#L91) and [line 128](https://github.com/adcontextprotocol/adcp-client/blob/main/test/examples/durable-buyer-writes.test.js#L128). Downstream idempotency on `logicalOperationId` closes the post-send/pre-ACK window. |
|
|
280
|
+
| Repeated identical terminal observations | Acknowledge without another handler/publication | Host transaction race: [`durable-buyer-writes.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/examples/durable-buyer-writes.test.js#L59). SDK delivery-key and cross-key terminal dedup: [`async-handler-webhook-dedup.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/async-handler-webhook-dedup.test.js#L194) and [`task-executor-pre-dispatch-boundary.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/task-executor-pre-dispatch-boundary.test.js#L2505). |
|
|
281
|
+
| Conflicting terminal observations | Preserve first winner and return conflict | Host winner preservation: [`durable-buyer-writes.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/examples/durable-buyer-writes.test.js#L59). SDK dedup and deferred winner protection: [`async-handler-webhook-dedup.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/async-handler-webhook-dedup.test.js#L288) and [`single-agent-deferred-recovery.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/single-agent-deferred-recovery.test.js#L3006). |
|
|
282
|
+
| Pending input or authorization | A fresh authorized process resumes the persisted current A2A token once; callbacks and the host lease fence competing settlement | SDK generation fencing and restart settlement are covered by [`single-agent-deferred-recovery.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/single-agent-deferred-recovery.test.js#L155), [line 411](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/single-agent-deferred-recovery.test.js#L411), and [line 2136](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/single-agent-deferred-recovery.test.js#L2136). The host reauthorization/lease is in `resumePendingInput()`. Direct A→B route recovery at the store-B/host-observation crash boundary is covered by [`direct-pause-recovery.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/direct-pause-recovery.test.js). |
|
|
283
|
+
| No callback; polling recovery | Poll exact seller `task_id`; callback and poll race to the same terminal winner | Poll-first closure and competing callback fencing: [`task-executor-pre-dispatch-boundary.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/task-executor-pre-dispatch-boundary.test.js#L1104). Restarted pending polling without redispatch: [`single-agent-deferred-recovery.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/lib/single-agent-deferred-recovery.test.js#L2524). |
|
|
284
|
+
|
|
285
|
+
## Task completion is not delivery completion
|
|
286
|
+
|
|
287
|
+
A completed `buy_products`, `accept_proposal`, or `create_media_buy` task says
|
|
288
|
+
that mutation finished and yields a MediaBuy identity. It does not say the buy
|
|
289
|
+
finished delivering. Move that `media_buy_id` into a separate, durable delivery
|
|
290
|
+
reconciliation loop using `get_media_buys`, `get_media_buy_delivery`, reporting
|
|
291
|
+
materializations, and their own notification receipts. Deleting the task
|
|
292
|
+
operation must never delete the campaign/delivery watch.
|
|
293
|
+
|
|
294
|
+
Task-status push is eligible only after the seller returns `submitted` or
|
|
295
|
+
otherwise creates durable asynchronous work. AdCP 3.2 synchronous terminal
|
|
296
|
+
responses are authoritative inline and must not produce a task-completion
|
|
297
|
+
webhook. The server-side silence contract is tested in
|
|
298
|
+
[`server-decisioning-auto-emit-completion.test.js`](https://github.com/adcontextprotocol/adcp-client/blob/main/test/server-decisioning-auto-emit-completion.test.js#L94).
|
|
299
|
+
`reporting_webhook` is a distinct ongoing-delivery channel and remains in the
|
|
300
|
+
task parameters; it is not a substitute for `push_notification_config`.
|
|
301
|
+
|
|
302
|
+
## Helper boundaries
|
|
303
|
+
|
|
304
|
+
`attachTaskDeadlineIdempotencyKey` is an internal SDK helper, not a package-root
|
|
305
|
+
API. After the SDK already selected the request key, it copies that key onto a
|
|
306
|
+
pending `TaskTimeoutError` so callers can recover the exact request. It does not
|
|
307
|
+
derive a logical operation ID, canonicalize business intent, persist a request,
|
|
308
|
+
or authorize rotation. Application code should inspect the timeout's exposed
|
|
309
|
+
idempotency-key field and return to its own durable operation row.
|
|
310
|
+
|
|
311
|
+
Media-buy action helpers have a different boundary. `assessMediaBuyAction` and
|
|
312
|
+
the legacy `preflightUpdateMediaBuy` assess whether a proposed update/control
|
|
313
|
+
is legal against accepted terms, current state, and advertised actions. They do
|
|
314
|
+
not prove creative validity, account authorization, product availability,
|
|
315
|
+
budget approval, or final seller acceptance. Product/capability discovery,
|
|
316
|
+
`validate_input` or `sync_creatives({ dry_run: true })`, authenticated account
|
|
317
|
+
resolution, and the actual mutation retain those responsibilities.
|
|
318
|
+
`preflightUpdateMediaBuy` is root-exported; import `assessMediaBuyAction` from
|
|
319
|
+
`@adcp/sdk/media-buy/actions`.
|
|
320
|
+
|
|
321
|
+
## Adoption checklist
|
|
322
|
+
|
|
323
|
+
- [ ] Pin and test `@adcp/sdk@14.0.0-rc.38` with AdCP `3.2.0-rc.3`; reassess this guide when upgrading either pin.
|
|
324
|
+
- [ ] Apply every current migration helper and the host operation/outbox migration before traffic; configure unique tables/prefixes and readiness probes.
|
|
325
|
+
- [ ] Persist one logical operation, natural key, request key, and canonical request before dispatch; refuse same-operation payload drift.
|
|
326
|
+
- [ ] Keep every SDK attempt route through the matching callback-registration retention window; retries add routes but preserve the request key.
|
|
327
|
+
- [ ] Use one stable seller ID and the same registration, RFC 9421 replay, webhook-dedup, deferred, operation, and publication stores on every replica.
|
|
328
|
+
- [ ] Retain callback/dedup/proof state for at least `max(24h, seller advertised webhook horizon)` and request keys through the seller replay horizon.
|
|
329
|
+
- [ ] Re-resolve tenant, principal, seller credential, and seller account before dispatch, callback handling, polling, and continuation resume.
|
|
330
|
+
- [ ] Capture exact raw callback bytes and build the public URL from trusted configuration; keep the SDK's failure status mapping.
|
|
331
|
+
- [ ] Persist `metadata.serverTaskId` for polling. Never poll with SDK `operation_id`, request key, A2A `Task.id`, or continuation token.
|
|
332
|
+
- [ ] Make terminal settlement first-writer-wins, fingerprint canonical task value, insert the host outbox in the same transaction, and make the downstream consumer idempotent by logical operation ID.
|
|
333
|
+
- [ ] Configure and contract-test a durable `DeferredTaskStorage` before accepting restart-sensitive A2A pauses; never fabricate MCP continuation identity.
|
|
334
|
+
- [ ] For direct A2A mutations, enable `durableContinuationRecovery`, persist the first `deferred.recovery` pair before treating the pause as restart-safe, and recover the current pause route after a crash; a missing route after possible dispatch never authorizes redispatch.
|
|
335
|
+
- [ ] Alert on aged reconciliation rows, unpublished outbox rows, and repeated publisher failures; apply a host-owned retry/dead-letter policy.
|
|
336
|
+
- [ ] Keep MediaBuy/delivery reconciliation alive after create-task completion.
|
|
337
|
+
- [ ] Run `npm run ci:doc-links` and `npm run ci:quick`; the linked focused suites are the acceptance evidence for the SDK-owned boundaries.
|
|
@@ -14,6 +14,41 @@ This is the thin integration path for an application that already owns authentic
|
|
|
14
14
|
|
|
15
15
|
The example accepts an already authenticated request context, rechecks tenant/account authorization before starting a submitted-task poll, calls `list_products`, records the initial mixed-status result in the application's transaction, and records terminal settlement after polling. Its store also implements `WebhookRegistrationStore` and idempotent `recordWebhookSettlement`, so verified callbacks can resolve the persisted operation to its tenant, re-authorize, and save completion after a restart. It imports only from `@adcp/sdk`, uses no private `dist/` path, and does not enable the optional schema subpath.
|
|
16
16
|
|
|
17
|
+
## Migrate targeting adapters without casts
|
|
18
|
+
|
|
19
|
+
AdCP 3.2 mutation targeting is a command shape, while accepted provider state
|
|
20
|
+
and response readback are strict state shapes. The packed, compile-gated
|
|
21
|
+
[`targeting-input-existing-platform.ts`](../../examples/targeting-input-existing-platform.ts)
|
|
22
|
+
example derives its input types from the public `BuyProductsRequest` and
|
|
23
|
+
`ControlMediaBuyRequest` exports and uses only public projection helpers.
|
|
24
|
+
|
|
25
|
+
| Request state | Adapter action | Accepted/readback state |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| Dimension omitted | Create: preserve the product/provider default. Update: make no provider call and retain stored state. | Existing strict value remains; no command is stored. |
|
|
28
|
+
| Dimension `null` | Verify that the product and provider support clearing, then send the provider's explicit clear/replacement operation. | The dimension is absent. Never echo `null`. |
|
|
29
|
+
| Dimension has a value | Translate and replace the complete provider dimension. | Persist and return the validated value. |
|
|
30
|
+
|
|
31
|
+
Translate the original request into provider set/clear operations first; do not
|
|
32
|
+
drop `null` before the provider executes the clear. On create, start from the
|
|
33
|
+
selected product's strict configured/default targeting and call
|
|
34
|
+
`applyTargetingInput()` so omitted dimensions are materialized, cleared defaults
|
|
35
|
+
are removed, and supplied dimensions replace them. On update, load the prior
|
|
36
|
+
strict state and apply the same helper. Commit only that complete strict result.
|
|
37
|
+
`resolveTargetingInput()` removes request commands but cannot materialize create
|
|
38
|
+
defaults on its own. If the provider succeeds but the local commit fails,
|
|
39
|
+
reconcile through the application's existing transaction or outbox boundary.
|
|
40
|
+
The outer `control_media_buy` handler must also serialize or CAS the whole
|
|
41
|
+
read-provider-save block using the request revision so concurrent patches cannot
|
|
42
|
+
lose an accepted dimension. The example's provider seam assumes exact, atomic
|
|
43
|
+
application: an adapter whose provider normalizes values should return its
|
|
44
|
+
canonical post-mutation readback and persist that instead of the request value.
|
|
45
|
+
|
|
46
|
+
The example deliberately throws `UnsupportedTargetingClearError` before any
|
|
47
|
+
provider call or durable write. Do not cast the request to a strict overlay,
|
|
48
|
+
drop `null` keys before the provider has executed the clear, or persist the
|
|
49
|
+
request object unchanged. Provider adapters should also reject targeting
|
|
50
|
+
dimensions they do not translate instead of silently discarding them.
|
|
51
|
+
|
|
17
52
|
Configure the callback as an absolute template containing both trusted route macros, for example `https://buyer.example/adcp/webhook/{task_type}/{operation_id}`. Supply a framework adapter that derives the public URL only from server-owned configuration, and mount raw-body parsing on the matching route:
|
|
18
53
|
|
|
19
54
|
```ts
|
|
@@ -37,10 +72,22 @@ The submitted continuation's `waitForCompletion` function is deliberately proces
|
|
|
37
72
|
| Client task | `TaskOptions.timeout` is one absolute task deadline; `signal` is caller cancellation | Throws the abort/timeout error | Returns `TaskResult` with `success: false` and structured `adcpError` |
|
|
38
73
|
| `validateAdAgents` | `signal` spans the whole discovery; `timeoutMs` bounds each fetch | Throws the signal's abort reason and starts no later fallback | Returns `valid: false` with discovery errors |
|
|
39
74
|
| Submitted wait | `waitForCompletion(interval, signal)` | Stops polling; A2A cancellation is a best-effort protocol courtesy | Returns the latest/terminal `TaskResult` |
|
|
40
|
-
| Transport observer |
|
|
75
|
+
| Transport observer | Response delivery waits up to 1 s for a cloned body preview; task completion then waits up to 5 s for pending async observers | Never becomes an unbounded request dependency | Observer rejection is isolated from protocol behavior |
|
|
41
76
|
|
|
42
77
|
Do not catch every outcome into a string. Switch on `result.status`; use `result.adcpError` for failed results, and catch thrown cancellation/configuration errors separately. Internal transport retries reuse an idempotency key. A new application intent must receive a new key; after an ambiguous timeout, reconcile by the persisted natural key before deciding to retry.
|
|
43
78
|
|
|
79
|
+
Transport diagnostics are bounded, but they remain on the critical path when
|
|
80
|
+
`onTransportActivity` is enabled. The SDK may spend up to
|
|
81
|
+
`BODY_SNIPPET_TIMEOUT_MS` (currently 1 second) capturing a redacted preview from
|
|
82
|
+
a clone before returning the original `Response`, then up to
|
|
83
|
+
`OBSERVER_FLUSH_TIMEOUT_MS` (currently 5 seconds) waiting for observer promises
|
|
84
|
+
before the enclosing task settles. The original response stream remains owned
|
|
85
|
+
by the protocol client, previews stay size-bounded, and SSE bodies are not
|
|
86
|
+
captured. There is no detached-observer or explicit-flush mode. A
|
|
87
|
+
latency-sensitive application should synchronously enqueue each event into its
|
|
88
|
+
own bounded in-memory or durable queue and return promptly; flushing that queue
|
|
89
|
+
is then an application lifecycle concern rather than part of request latency.
|
|
90
|
+
|
|
44
91
|
## Reuse scoped capability evidence
|
|
45
92
|
|
|
46
93
|
An application that already performs a bounded seller preflight can prime the specific client instance instead of triggering another probe:
|
|
@@ -61,4 +108,36 @@ if (!reused) await agent.getCapabilities({ signal }); // rejected evidence clear
|
|
|
61
108
|
|
|
62
109
|
The compiling example's `reuseCapabilityEvidence` method contains this flow without an undefined helper. The scope binds evidence to the normalized endpoint, configured AdCP release, and this immutable client's authorization/transport instance; preserve the seller's normalized `capabilities.servedVersion` when the preflight supplies it. Use one client per authorization context. Expired, malformed, endpoint-mismatched, release-mismatched, or differently scoped evidence is refused, clears older cached state, and leaves discovery cold; `refreshCapabilities()` rotates the scope so older snapshots cannot be reinstalled. Include `toolSchemas` when the preflight observed MCP `tools/list`; compatibility projection augments and uses the same tool evidence. A constructor-level scoped fetch refuses priming, and a per-call `trustedFetchFn` bypasses primed state, because either fetch defines a narrower transport scope.
|
|
63
110
|
|
|
111
|
+
This is same-instance preflight reuse, not a durable cache identity. The opaque
|
|
112
|
+
`scopeKey` is created per client instance and is intentionally not reconstructable
|
|
113
|
+
from endpoint, credentials, or version. After a process restart, a snapshot
|
|
114
|
+
persisted by the old client is refused by the new client even when its timestamps
|
|
115
|
+
are still fresh. Do not attach the new scope to that old observation. Construct
|
|
116
|
+
the replacement client first, obtain its scope, and either perform a fresh
|
|
117
|
+
tenant-scoped preflight for that scope or let `getCapabilities()` discover cold:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
const replacement = new AgentClient(
|
|
121
|
+
{
|
|
122
|
+
id: 'seller',
|
|
123
|
+
name: 'Seller',
|
|
124
|
+
agent_uri: sellerUrl,
|
|
125
|
+
protocol: 'mcp',
|
|
126
|
+
auth_token: requestScopedAuthToken,
|
|
127
|
+
},
|
|
128
|
+
clientOptions
|
|
129
|
+
);
|
|
130
|
+
const replacementScope = replacement.getCapabilityEvidenceScope();
|
|
131
|
+
const fresh = await tenantScopedCapabilityPreflight(replacementScope, signal);
|
|
132
|
+
|
|
133
|
+
if (!replacement.primeCapabilities({ ...fresh, scope: replacementScope })) {
|
|
134
|
+
await replacement.getCapabilities({ signal });
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
An application-owned persisted discovery cache may still accelerate the
|
|
139
|
+
application's own preflight logic, but it cannot currently be installed across
|
|
140
|
+
SDK client instances. Retain a process-local client when same-instance reuse is
|
|
141
|
+
required; otherwise budget for fresh discovery after reconstruction.
|
|
142
|
+
|
|
64
143
|
For durable webhook and reporting flows, continue with [Push notification configuration](./PUSH-NOTIFICATION-CONFIG.md) and the [Reporting ledger](./REPORTING-LEDGER.md).
|