@adcp/sdk 5.25.0 → 6.0.0
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/README.md +45 -7
- package/dist/lib/compliance-fixtures/index.d.ts +1 -1
- package/dist/lib/compliance-fixtures/index.js +1 -1
- package/dist/lib/conformance/runners.d.ts.map +1 -1
- package/dist/lib/conformance/runners.js +13 -1
- package/dist/lib/conformance/runners.js.map +1 -1
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +15 -0
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/core/TaskExecutor.d.ts +7 -0
- package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
- package/dist/lib/core/TaskExecutor.js +9 -2
- package/dist/lib/core/TaskExecutor.js.map +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +7 -8
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/protocols/index.d.ts +3 -1
- package/dist/lib/protocols/index.d.ts.map +1 -1
- package/dist/lib/protocols/index.js +23 -14
- package/dist/lib/protocols/index.js.map +1 -1
- package/dist/lib/schemas/index.d.ts +1 -1
- package/dist/lib/schemas/index.js +1 -1
- package/dist/lib/server/create-adcp-server.d.ts +142 -11
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +211 -2
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/memory.d.ts +27 -0
- package/dist/lib/server/ctx-metadata/backends/memory.d.ts.map +1 -0
- package/dist/lib/server/ctx-metadata/backends/memory.js +72 -0
- package/dist/lib/server/ctx-metadata/backends/memory.js.map +1 -0
- package/dist/lib/server/ctx-metadata/backends/pg.d.ts +62 -0
- package/dist/lib/server/ctx-metadata/backends/pg.d.ts.map +1 -0
- package/dist/lib/server/ctx-metadata/backends/pg.js +145 -0
- package/dist/lib/server/ctx-metadata/backends/pg.js.map +1 -0
- package/dist/lib/server/ctx-metadata/index.d.ts +15 -0
- package/dist/lib/server/ctx-metadata/index.d.ts.map +1 -0
- package/dist/lib/server/ctx-metadata/index.js +28 -0
- package/dist/lib/server/ctx-metadata/index.js.map +1 -0
- package/dist/lib/server/ctx-metadata/store.d.ts +177 -0
- package/dist/lib/server/ctx-metadata/store.d.ts.map +1 -0
- package/dist/lib/server/ctx-metadata/store.js +327 -0
- package/dist/lib/server/ctx-metadata/store.js.map +1 -0
- package/dist/lib/server/ctx-metadata/wire-shape.d.ts +55 -0
- package/dist/lib/server/ctx-metadata/wire-shape.d.ts.map +1 -0
- package/dist/lib/server/ctx-metadata/wire-shape.js +121 -0
- package/dist/lib/server/ctx-metadata/wire-shape.js.map +1 -0
- package/dist/lib/server/decisioning/account.d.ts +309 -0
- package/dist/lib/server/decisioning/account.d.ts.map +1 -0
- package/dist/lib/server/decisioning/account.js +102 -0
- package/dist/lib/server/decisioning/account.js.map +1 -0
- package/dist/lib/server/decisioning/admin-router.d.ts +75 -0
- package/dist/lib/server/decisioning/admin-router.d.ts.map +1 -0
- package/dist/lib/server/decisioning/admin-router.js +120 -0
- package/dist/lib/server/decisioning/admin-router.js.map +1 -0
- package/dist/lib/server/decisioning/assembly-helpers.d.ts +204 -0
- package/dist/lib/server/decisioning/assembly-helpers.d.ts.map +1 -0
- package/dist/lib/server/decisioning/assembly-helpers.js +173 -0
- package/dist/lib/server/decisioning/assembly-helpers.js.map +1 -0
- package/dist/lib/server/decisioning/async-outcome.d.ts +154 -0
- package/dist/lib/server/decisioning/async-outcome.d.ts.map +1 -0
- package/dist/lib/server/decisioning/async-outcome.js +239 -0
- package/dist/lib/server/decisioning/async-outcome.js.map +1 -0
- package/dist/lib/server/decisioning/capabilities.d.ts +251 -0
- package/dist/lib/server/decisioning/capabilities.d.ts.map +1 -0
- package/dist/lib/server/decisioning/capabilities.js +16 -0
- package/dist/lib/server/decisioning/capabilities.js.map +1 -0
- package/dist/lib/server/decisioning/context.d.ts +212 -0
- package/dist/lib/server/decisioning/context.d.ts.map +1 -0
- package/dist/lib/server/decisioning/context.js +26 -0
- package/dist/lib/server/decisioning/context.js.map +1 -0
- package/dist/lib/server/decisioning/errors-typed.d.ts +104 -0
- package/dist/lib/server/decisioning/errors-typed.d.ts.map +1 -0
- package/dist/lib/server/decisioning/errors-typed.js +304 -0
- package/dist/lib/server/decisioning/errors-typed.js.map +1 -0
- package/dist/lib/server/decisioning/helpers.d.ts +131 -0
- package/dist/lib/server/decisioning/helpers.d.ts.map +1 -0
- package/dist/lib/server/decisioning/helpers.js +134 -0
- package/dist/lib/server/decisioning/helpers.js.map +1 -0
- package/dist/lib/server/decisioning/index.d.ts +46 -0
- package/dist/lib/server/decisioning/index.d.ts.map +1 -0
- package/dist/lib/server/decisioning/index.js +120 -0
- package/dist/lib/server/decisioning/index.js.map +1 -0
- package/dist/lib/server/decisioning/list-helpers.d.ts +53 -0
- package/dist/lib/server/decisioning/list-helpers.d.ts.map +1 -0
- package/dist/lib/server/decisioning/list-helpers.js +96 -0
- package/dist/lib/server/decisioning/list-helpers.js.map +1 -0
- package/dist/lib/server/decisioning/manifest-helpers.d.ts +56 -0
- package/dist/lib/server/decisioning/manifest-helpers.d.ts.map +1 -0
- package/dist/lib/server/decisioning/manifest-helpers.js +78 -0
- package/dist/lib/server/decisioning/manifest-helpers.js.map +1 -0
- package/dist/lib/server/decisioning/pagination.d.ts +21 -0
- package/dist/lib/server/decisioning/pagination.d.ts.map +1 -0
- package/dist/lib/server/decisioning/pagination.js +12 -0
- package/dist/lib/server/decisioning/pagination.js.map +1 -0
- package/dist/lib/server/decisioning/platform.d.ts +188 -0
- package/dist/lib/server/decisioning/platform.d.ts.map +1 -0
- package/dist/lib/server/decisioning/platform.js +19 -0
- package/dist/lib/server/decisioning/platform.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +510 -0
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/from-platform.js +2196 -0
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts +114 -0
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +247 -0
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.d.ts +32 -0
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.js +127 -0
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts +105 -0
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/task-registry.js +96 -0
- package/dist/lib/server/decisioning/runtime/task-registry.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/to-context.d.ts +54 -0
- package/dist/lib/server/decisioning/runtime/to-context.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/to-context.js +166 -0
- package/dist/lib/server/decisioning/runtime/to-context.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/validate-platform.d.ts +20 -0
- package/dist/lib/server/decisioning/runtime/validate-platform.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/validate-platform.js +93 -0
- package/dist/lib/server/decisioning/runtime/validate-platform.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/audiences.d.ts +72 -0
- package/dist/lib/server/decisioning/specialisms/audiences.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/audiences.js +15 -0
- package/dist/lib/server/decisioning/specialisms/audiences.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts +92 -0
- package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/brand-rights.js +28 -0
- package/dist/lib/server/decisioning/specialisms/brand-rights.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/campaign-governance.d.ts +67 -0
- package/dist/lib/server/decisioning/specialisms/campaign-governance.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/campaign-governance.js +31 -0
- package/dist/lib/server/decisioning/specialisms/campaign-governance.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/content-standards.d.ts +78 -0
- package/dist/lib/server/decisioning/specialisms/content-standards.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/content-standards.js +35 -0
- package/dist/lib/server/decisioning/specialisms/content-standards.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts +81 -0
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.js +28 -0
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/creative.d.ts +144 -0
- package/dist/lib/server/decisioning/specialisms/creative.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/creative.js +19 -0
- package/dist/lib/server/decisioning/specialisms/creative.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/lists.d.ts +61 -0
- package/dist/lib/server/decisioning/specialisms/lists.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/lists.js +30 -0
- package/dist/lib/server/decisioning/specialisms/lists.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/sales.d.ts +163 -0
- package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/sales.js +64 -0
- package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/signals.d.ts +64 -0
- package/dist/lib/server/decisioning/specialisms/signals.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/signals.js +28 -0
- package/dist/lib/server/decisioning/specialisms/signals.js.map +1 -0
- package/dist/lib/server/decisioning/start-time.d.ts +76 -0
- package/dist/lib/server/decisioning/start-time.d.ts.map +1 -0
- package/dist/lib/server/decisioning/start-time.js +81 -0
- package/dist/lib/server/decisioning/start-time.js.map +1 -0
- package/dist/lib/server/decisioning/status-changes.d.ts +165 -0
- package/dist/lib/server/decisioning/status-changes.d.ts.map +1 -0
- package/dist/lib/server/decisioning/status-changes.js +131 -0
- package/dist/lib/server/decisioning/status-changes.js.map +1 -0
- package/dist/lib/server/decisioning/status-mappers.d.ts +46 -0
- package/dist/lib/server/decisioning/status-mappers.d.ts.map +1 -0
- package/dist/lib/server/decisioning/status-mappers.js +46 -0
- package/dist/lib/server/decisioning/status-mappers.js.map +1 -0
- package/dist/lib/server/decisioning/tenant-registry.d.ts +289 -0
- package/dist/lib/server/decisioning/tenant-registry.d.ts.map +1 -0
- package/dist/lib/server/decisioning/tenant-registry.js +503 -0
- package/dist/lib/server/decisioning/tenant-registry.js.map +1 -0
- package/dist/lib/server/express-adapter.d.ts +1 -1
- package/dist/lib/server/express-adapter.js +1 -1
- package/dist/lib/server/governance.d.ts +1 -1
- package/dist/lib/server/governance.js +1 -1
- package/dist/lib/server/idempotency/store.d.ts +1 -1
- package/dist/lib/server/idempotency/store.js +1 -1
- package/dist/lib/server/index.d.ts +9 -2
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js +79 -4
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/legacy/v5/index.d.ts +38 -0
- package/dist/lib/server/legacy/v5/index.d.ts.map +1 -0
- package/dist/lib/server/legacy/v5/index.js +60 -0
- package/dist/lib/server/legacy/v5/index.js.map +1 -0
- package/dist/lib/server/normalize-errors.d.ts +88 -0
- package/dist/lib/server/normalize-errors.d.ts.map +1 -0
- package/dist/lib/server/normalize-errors.js +146 -0
- package/dist/lib/server/normalize-errors.js.map +1 -0
- package/dist/lib/server/pick-safe-details.d.ts +90 -0
- package/dist/lib/server/pick-safe-details.d.ts.map +1 -0
- package/dist/lib/server/pick-safe-details.js +148 -0
- package/dist/lib/server/pick-safe-details.js.map +1 -0
- package/dist/lib/server/postgres-state-store.d.ts +1 -1
- package/dist/lib/server/postgres-state-store.js +1 -1
- package/dist/lib/server/responses.d.ts +38 -0
- package/dist/lib/server/responses.d.ts.map +1 -1
- package/dist/lib/server/responses.js +38 -0
- package/dist/lib/server/responses.js.map +1 -1
- package/dist/lib/server/state-store.d.ts +1 -1
- package/dist/lib/server/state-store.js +1 -1
- package/dist/lib/server/test-controller.d.ts +10 -3
- package/dist/lib/server/test-controller.d.ts.map +1 -1
- package/dist/lib/server/test-controller.js +10 -3
- package/dist/lib/server/test-controller.js.map +1 -1
- package/dist/lib/testing/comply-controller.d.ts +47 -1
- package/dist/lib/testing/comply-controller.d.ts.map +1 -1
- package/dist/lib/testing/comply-controller.js +11 -4
- package/dist/lib/testing/comply-controller.js.map +1 -1
- package/dist/lib/testing/index.d.ts +1 -1
- package/dist/lib/testing/index.d.ts.map +1 -1
- package/dist/lib/testing/index.js.map +1 -1
- package/dist/lib/testing/personas/index.d.ts +143 -0
- package/dist/lib/testing/personas/index.d.ts.map +1 -0
- package/dist/lib/testing/personas/index.js +190 -0
- package/dist/lib/testing/personas/index.js.map +1 -0
- package/dist/lib/testing/storyboard/index.d.ts +1 -1
- package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/index.js +3 -2
- package/dist/lib/testing/storyboard/index.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts +13 -0
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +179 -7
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/types/adcp.d.ts.map +1 -1
- package/dist/lib/types/adcp.js +1 -0
- package/dist/lib/types/adcp.js.map +1 -1
- package/dist/lib/types/asset-instances.d.ts +1 -0
- package/dist/lib/types/asset-instances.d.ts.map +1 -1
- package/dist/lib/types/core.generated.d.ts +203 -98
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js +1 -1
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.d.ts.map +1 -1
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/types/schemas.generated.d.ts +599 -159
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +175 -94
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/tools.generated.d.ts +315 -46
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/utils/capabilities.d.ts +1 -1
- package/dist/lib/utils/capabilities.d.ts.map +1 -1
- package/dist/lib/utils/capabilities.js +6 -0
- package/dist/lib/utils/capabilities.js.map +1 -1
- package/dist/lib/validation/schema-validator.d.ts +13 -0
- package/dist/lib/validation/schema-validator.d.ts.map +1 -1
- package/dist/lib/validation/schema-validator.js +240 -3
- package/dist/lib/validation/schema-validator.js.map +1 -1
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.d.ts.map +1 -1
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/docs/guides/BUILD-AN-AGENT.md +30 -5
- package/docs/llms.txt +28 -17
- package/examples/README.md +3 -1
- package/examples/decisioning-platform-broadcast-tv.ts +300 -0
- package/examples/decisioning-platform-identity-graph.ts +214 -0
- package/examples/decisioning-platform-mock-seller.ts +332 -0
- package/examples/decisioning-platform-multi-tenant.ts +128 -0
- package/examples/decisioning-platform-programmatic.ts +254 -0
- package/examples/signals-agent.ts +1 -1
- package/package.json +13 -2
- package/skills/build-brand-rights-agent/SKILL.md +10 -3
- package/skills/build-creative-agent/SKILL.md +94 -64
- package/skills/build-decisioning-creative-template/SKILL.md +554 -0
- package/skills/build-decisioning-platform/SKILL.md +304 -0
- package/skills/build-decisioning-platform/advanced/BRAND-RIGHTS.md +25 -0
- package/skills/build-decisioning-platform/advanced/COMPLIANCE.md +23 -0
- package/skills/build-decisioning-platform/advanced/GOVERNANCE.md +24 -0
- package/skills/build-decisioning-platform/advanced/HITL.md +34 -0
- package/skills/build-decisioning-platform/advanced/IDEMPOTENCY.md +52 -0
- package/skills/build-decisioning-platform/advanced/MULTI-TENANT.md +47 -0
- package/skills/build-decisioning-platform/advanced/OAUTH.md +22 -0
- package/skills/build-decisioning-platform/advanced/REFERENCE.md +991 -0
- package/skills/build-decisioning-platform/advanced/SANDBOX.md +24 -0
- package/skills/build-decisioning-platform/advanced/STATE-MACHINE.md +52 -0
- package/skills/build-decisioning-signal-marketplace/SKILL.md +269 -0
- package/skills/build-generative-seller-agent/SKILL.md +89 -53
- package/skills/build-governance-agent/SKILL.md +76 -45
- package/skills/build-retail-media-agent/SKILL.md +87 -62
- package/skills/build-seller-agent/SKILL.md +384 -255
- package/skills/build-seller-agent/deployment.md +5 -3
- package/skills/build-seller-agent/specialisms/audience-sync.md +0 -2
- package/skills/build-seller-agent/specialisms/sales-broadcast-tv.md +0 -2
- package/skills/build-seller-agent/specialisms/sales-guaranteed.md +0 -2
- package/skills/build-seller-agent/specialisms/sales-non-guaranteed.md +0 -2
- package/skills/build-seller-agent/specialisms/sales-proposal-mode.md +0 -2
- package/skills/build-seller-agent/specialisms/sales-social.md +0 -2
- package/skills/build-seller-agent/specialisms/signed-requests.md +0 -2
- package/skills/build-si-agent/SKILL.md +40 -32
- package/skills/build-signals-agent/SKILL.md +139 -92
- package/skills/call-adcp-agent.previous/SKILL.md +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/server/ctx-metadata/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,iCAQiB;AAPf,+GAAA,sBAAsB,OAAA;AACtB,6GAAA,oBAAoB,OAAA;AACpB,4GAAA,mBAAmB,OAAA;AACnB,mHAAA,0BAA0B,OAAA;AAC1B,0GAAA,iBAAiB,OAAA;AACjB,gHAAA,uBAAuB,OAAA;AACvB,wGAAA,eAAe,OAAA;AAYjB,4CAA2D;AAAlD,gHAAA,sBAAsB,OAAA;AAG/B,oCAKuB;AAJrB,wGAAA,kBAAkB,OAAA;AAClB,6GAAA,uBAAuB,OAAA;AACvB,+GAAA,yBAAyB,OAAA;AACzB,4GAAA,sBAAsB,OAAA;AAIxB,2CAAgE;AAAvD,8GAAA,gBAAgB,OAAA;AAAE,4GAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ctx-metadata store for AdCP server handlers.
|
|
3
|
+
*
|
|
4
|
+
* Publishers attach platform-specific opaque blobs to any returned
|
|
5
|
+
* resource (product, media_buy, package, creative, audience, signal,
|
|
6
|
+
* rights_grant). The framework persists the blob keyed by
|
|
7
|
+
* `(account_id, kind, id)`, strips it from buyer-facing wire payloads,
|
|
8
|
+
* and threads it back into the publisher's request context on
|
|
9
|
+
* subsequent calls referencing the same resource ID.
|
|
10
|
+
*
|
|
11
|
+
* Use case: GAM ad_unit_ids per product, GAM order_id per media_buy,
|
|
12
|
+
* line_item_id per package — adapter-internal state the AdCP wire
|
|
13
|
+
* spec doesn't model. Avoids forcing publishers to re-derive on every
|
|
14
|
+
* call or maintain a side-cache the SDK could provide.
|
|
15
|
+
*
|
|
16
|
+
* Scope is `(account_id, kind, id)` — keys are tenant-isolated. No
|
|
17
|
+
* auto-eviction by design (a media buy lifetime can be months).
|
|
18
|
+
* Adopter-driven cleanup via `cleanupExpiredCtxMetadata(db)` for
|
|
19
|
+
* Postgres deployments that opt into row-level `expires_at`.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { createCtxMetadataStore, memoryCtxMetadataStore } from '@adcp/sdk/server';
|
|
24
|
+
*
|
|
25
|
+
* const store = createCtxMetadataStore({ backend: memoryCtxMetadataStore() });
|
|
26
|
+
*
|
|
27
|
+
* createAdcpServerFromPlatform({ platform, ctxMetadata: store });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* Resource kinds the ctx-metadata store recognizes. Closed enum:
|
|
34
|
+
* adding a new kind is a coordinated change across the framework
|
|
35
|
+
* dispatch (which kinds get hydrated on which request shapes).
|
|
36
|
+
*/
|
|
37
|
+
export type ResourceKind = 'account' | 'product' | 'media_buy' | 'package' | 'creative' | 'audience' | 'signal' | 'rights_grant' | 'property_list' | 'collection_list';
|
|
38
|
+
/**
|
|
39
|
+
* Default size cap on serialized blob, in bytes. Crossed → `CTX_METADATA_TOO_LARGE`.
|
|
40
|
+
*
|
|
41
|
+
* Memory backend without a cap is a single-node DoS vector; Postgres
|
|
42
|
+
* JSONB performance dies at scale before disk does. 16KB covers the
|
|
43
|
+
* common case (ad_unit_ids arrays, key-value targeting maps) with
|
|
44
|
+
* room to spare.
|
|
45
|
+
*/
|
|
46
|
+
export declare const DEFAULT_MAX_VALUE_BYTES: number;
|
|
47
|
+
/**
|
|
48
|
+
* Maximum allowed TTL in seconds. Crossed → throws at `set()`.
|
|
49
|
+
*
|
|
50
|
+
* Lifetime of a media buy can be months, but unbounded retention
|
|
51
|
+
* compounds drift between SDK cache and publisher truth. 30 days is
|
|
52
|
+
* the soft ceiling; cleanup is adopter-driven beyond that.
|
|
53
|
+
*/
|
|
54
|
+
export declare const MAX_TTL_SECONDS: number;
|
|
55
|
+
/**
|
|
56
|
+
* Symbol tag attached to retrieved blobs. Symbols don't survive
|
|
57
|
+
* `JSON.stringify`, so an accidental serialization in error envelopes
|
|
58
|
+
* / log lines / agent-card payloads silently elides the blob.
|
|
59
|
+
* Defense-in-depth against LLM-context leaks.
|
|
60
|
+
*/
|
|
61
|
+
export declare const ADCP_INTERNAL_TAG: unique symbol;
|
|
62
|
+
export interface CtxMetadataEntry {
|
|
63
|
+
/** Opaque publisher-attached value. Untouched by the framework. */
|
|
64
|
+
value: unknown;
|
|
65
|
+
/**
|
|
66
|
+
* SDK-attached AdCP wire resource shape (e.g., the full `Product` /
|
|
67
|
+
* `MediaBuy` / `Creative` object minus `ctx_metadata`). Populated by
|
|
68
|
+
* the framework's auto-hydration path, not by adopter code.
|
|
69
|
+
*
|
|
70
|
+
* Used to reconstruct a hydrated resource on subsequent calls that
|
|
71
|
+
* reference the same id by string. Buyer sends `product_id: 'p1'`;
|
|
72
|
+
* SDK looks up the entry, builds `{ ...resource, ctx_metadata: value }`,
|
|
73
|
+
* attaches as `req.packages[i].product`.
|
|
74
|
+
*
|
|
75
|
+
* Adopter code never reads or writes this field — the framework owns
|
|
76
|
+
* it end-to-end.
|
|
77
|
+
*/
|
|
78
|
+
resource?: unknown;
|
|
79
|
+
/** Optional unix epoch seconds expiry. Informational; no auto-eviction. */
|
|
80
|
+
expiresAt?: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Storage backend interface. Swap implementations for memory / Postgres / Redis.
|
|
84
|
+
*
|
|
85
|
+
* Keys are flattened to `${accountId}${kind}${id}` before
|
|
86
|
+
* reaching the backend. Validation runs before flattening — backends
|
|
87
|
+
* trust their inputs.
|
|
88
|
+
*/
|
|
89
|
+
export interface CtxMetadataBackend {
|
|
90
|
+
get(scopedKey: string): Promise<CtxMetadataEntry | null>;
|
|
91
|
+
bulkGet(scopedKeys: readonly string[]): Promise<Map<string, CtxMetadataEntry>>;
|
|
92
|
+
put(scopedKey: string, entry: CtxMetadataEntry): Promise<void>;
|
|
93
|
+
delete(scopedKey: string): Promise<void>;
|
|
94
|
+
/** Optional startup probe. Implementations wrapping an external store should implement. */
|
|
95
|
+
probe?(): Promise<void>;
|
|
96
|
+
/** Optional resource-release hook. Called by `store.close()`. */
|
|
97
|
+
close?(): Promise<void>;
|
|
98
|
+
/** Optional test-harness flush. Used by `compliance.reset()` between storyboards. */
|
|
99
|
+
clearAll?(): Promise<void>;
|
|
100
|
+
}
|
|
101
|
+
export interface CtxMetadataStoreConfig {
|
|
102
|
+
/** Storage backend. Use `memoryCtxMetadataStore()` for dev, `pgCtxMetadataStore(pool)` for cluster. */
|
|
103
|
+
backend: CtxMetadataBackend;
|
|
104
|
+
/**
|
|
105
|
+
* Max serialized blob size in bytes. Defaults to 16384 (16KB).
|
|
106
|
+
* Crossed → `CTX_METADATA_TOO_LARGE` thrown at `set()`.
|
|
107
|
+
*/
|
|
108
|
+
maxValueBytes?: number;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Reference to a stored entry. `bulkGet` accepts an array of these;
|
|
112
|
+
* the resulting Map is keyed by `${kind}:${id}` for caller convenience.
|
|
113
|
+
*/
|
|
114
|
+
export interface CtxMetadataRef {
|
|
115
|
+
kind: ResourceKind;
|
|
116
|
+
id: string;
|
|
117
|
+
}
|
|
118
|
+
export interface CtxMetadataStore {
|
|
119
|
+
/**
|
|
120
|
+
* Look up a single entry. Returns `undefined` (not `null`) for misses
|
|
121
|
+
* so publishers can branch with `??` against their own DB.
|
|
122
|
+
*
|
|
123
|
+
* Returned values carry a non-enumerable `[ADCP_INTERNAL_TAG]: true`
|
|
124
|
+
* marker — JSON serialization elides it automatically (defense
|
|
125
|
+
* against accidental leak via error envelopes and log lines).
|
|
126
|
+
*/
|
|
127
|
+
get(accountId: string, kind: ResourceKind, id: string): Promise<unknown | undefined>;
|
|
128
|
+
/**
|
|
129
|
+
* Bulk lookup. Returns a Map keyed by `${kind}:${id}` so callers
|
|
130
|
+
* with mixed-kind refs (e.g., `create_media_buy` carrying products
|
|
131
|
+
* + an audience ref) can index without remembering what they asked for.
|
|
132
|
+
* Misses are absent from the Map (no `undefined` entries).
|
|
133
|
+
*/
|
|
134
|
+
bulkGet(accountId: string, refs: readonly CtxMetadataRef[]): Promise<ReadonlyMap<string, unknown>>;
|
|
135
|
+
/**
|
|
136
|
+
* Store a blob. Throws `CTX_METADATA_TOO_LARGE` if `JSON.stringify(value).length`
|
|
137
|
+
* exceeds the configured cap. Throws `INVALID_ARGUMENT` for null/undefined/empty
|
|
138
|
+
* `accountId` or out-of-shape `id`.
|
|
139
|
+
*
|
|
140
|
+
* `ttlSeconds` is optional and capped at 30 days. No auto-eviction.
|
|
141
|
+
*/
|
|
142
|
+
set(accountId: string, kind: ResourceKind, id: string, value: unknown, ttlSeconds?: number): Promise<void>;
|
|
143
|
+
/** Delete a single entry. Tenant-scoped via `accountId`. */
|
|
144
|
+
delete(accountId: string, kind: ResourceKind, id: string): Promise<void>;
|
|
145
|
+
/** Probe the backend for boot-time readiness. */
|
|
146
|
+
probe(): Promise<void>;
|
|
147
|
+
/** Release backend resources (close pools, clear timers). */
|
|
148
|
+
close(): Promise<void>;
|
|
149
|
+
/** Test-harness reset. Throws if backend doesn't support it (no `force` opt — production safety). */
|
|
150
|
+
clearAll(): Promise<void>;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Validation error thrown for bad input shape. Distinct from
|
|
154
|
+
* `CTX_METADATA_TOO_LARGE` (size violation) so callers can branch.
|
|
155
|
+
*/
|
|
156
|
+
export declare class CtxMetadataValidationError extends Error {
|
|
157
|
+
readonly code: 'INVALID_ARGUMENT' | 'CTX_METADATA_TOO_LARGE';
|
|
158
|
+
constructor(code: 'INVALID_ARGUMENT' | 'CTX_METADATA_TOO_LARGE', message: string);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Compose the flattened storage key. Internal — backends trust this format.
|
|
162
|
+
*/
|
|
163
|
+
export declare function scopeCtxMetadataKey(accountId: string, kind: ResourceKind, id: string): string;
|
|
164
|
+
/**
|
|
165
|
+
* Compose the bulkGet result key. External — callers index Map entries by this.
|
|
166
|
+
*/
|
|
167
|
+
export declare function ctxMetadataResultKey(kind: ResourceKind, id: string): string;
|
|
168
|
+
/**
|
|
169
|
+
* Build a CtxMetadataStore wrapping a backend.
|
|
170
|
+
*
|
|
171
|
+
* Memory backend is fine for single-process dev. Cluster deployments
|
|
172
|
+
* MUST use `pgCtxMetadataStore` — silent ctx_metadata loss after a
|
|
173
|
+
* rolling restart produces "package not found" errors that look like
|
|
174
|
+
* publisher bugs and run for weeks.
|
|
175
|
+
*/
|
|
176
|
+
export declare function createCtxMetadataStore(config: CtxMetadataStoreConfig): CtxMetadataStore;
|
|
177
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/ctx-metadata/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Ctx-metadata store for AdCP server handlers.
|
|
4
|
+
*
|
|
5
|
+
* Publishers attach platform-specific opaque blobs to any returned
|
|
6
|
+
* resource (product, media_buy, package, creative, audience, signal,
|
|
7
|
+
* rights_grant). The framework persists the blob keyed by
|
|
8
|
+
* `(account_id, kind, id)`, strips it from buyer-facing wire payloads,
|
|
9
|
+
* and threads it back into the publisher's request context on
|
|
10
|
+
* subsequent calls referencing the same resource ID.
|
|
11
|
+
*
|
|
12
|
+
* Use case: GAM ad_unit_ids per product, GAM order_id per media_buy,
|
|
13
|
+
* line_item_id per package — adapter-internal state the AdCP wire
|
|
14
|
+
* spec doesn't model. Avoids forcing publishers to re-derive on every
|
|
15
|
+
* call or maintain a side-cache the SDK could provide.
|
|
16
|
+
*
|
|
17
|
+
* Scope is `(account_id, kind, id)` — keys are tenant-isolated. No
|
|
18
|
+
* auto-eviction by design (a media buy lifetime can be months).
|
|
19
|
+
* Adopter-driven cleanup via `cleanupExpiredCtxMetadata(db)` for
|
|
20
|
+
* Postgres deployments that opt into row-level `expires_at`.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { createCtxMetadataStore, memoryCtxMetadataStore } from '@adcp/sdk/server';
|
|
25
|
+
*
|
|
26
|
+
* const store = createCtxMetadataStore({ backend: memoryCtxMetadataStore() });
|
|
27
|
+
*
|
|
28
|
+
* createAdcpServerFromPlatform({ platform, ctxMetadata: store });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.CtxMetadataValidationError = exports.ADCP_INTERNAL_TAG = exports.MAX_TTL_SECONDS = exports.DEFAULT_MAX_VALUE_BYTES = void 0;
|
|
35
|
+
exports.scopeCtxMetadataKey = scopeCtxMetadataKey;
|
|
36
|
+
exports.ctxMetadataResultKey = ctxMetadataResultKey;
|
|
37
|
+
exports.createCtxMetadataStore = createCtxMetadataStore;
|
|
38
|
+
const ALL_RESOURCE_KINDS = [
|
|
39
|
+
'account',
|
|
40
|
+
'product',
|
|
41
|
+
'media_buy',
|
|
42
|
+
'package',
|
|
43
|
+
'creative',
|
|
44
|
+
'audience',
|
|
45
|
+
'signal',
|
|
46
|
+
'rights_grant',
|
|
47
|
+
'property_list',
|
|
48
|
+
'collection_list',
|
|
49
|
+
];
|
|
50
|
+
/**
|
|
51
|
+
* Default size cap on serialized blob, in bytes. Crossed → `CTX_METADATA_TOO_LARGE`.
|
|
52
|
+
*
|
|
53
|
+
* Memory backend without a cap is a single-node DoS vector; Postgres
|
|
54
|
+
* JSONB performance dies at scale before disk does. 16KB covers the
|
|
55
|
+
* common case (ad_unit_ids arrays, key-value targeting maps) with
|
|
56
|
+
* room to spare.
|
|
57
|
+
*/
|
|
58
|
+
exports.DEFAULT_MAX_VALUE_BYTES = 16 * 1024;
|
|
59
|
+
/**
|
|
60
|
+
* Maximum allowed TTL in seconds. Crossed → throws at `set()`.
|
|
61
|
+
*
|
|
62
|
+
* Lifetime of a media buy can be months, but unbounded retention
|
|
63
|
+
* compounds drift between SDK cache and publisher truth. 30 days is
|
|
64
|
+
* the soft ceiling; cleanup is adopter-driven beyond that.
|
|
65
|
+
*/
|
|
66
|
+
exports.MAX_TTL_SECONDS = 30 * 24 * 60 * 60;
|
|
67
|
+
/**
|
|
68
|
+
* Account ID and resource ID shape allowlist. Excludes the U+001F
|
|
69
|
+
* separator used in the flattened storage key, NUL bytes that
|
|
70
|
+
* Postgres TEXT rejects, and anything else that could confuse the
|
|
71
|
+
* key parser.
|
|
72
|
+
*/
|
|
73
|
+
const VALID_KEY_SEGMENT = /^[A-Za-z0-9_.:\-]{1,255}$/;
|
|
74
|
+
/**
|
|
75
|
+
* Symbol tag attached to retrieved blobs. Symbols don't survive
|
|
76
|
+
* `JSON.stringify`, so an accidental serialization in error envelopes
|
|
77
|
+
* / log lines / agent-card payloads silently elides the blob.
|
|
78
|
+
* Defense-in-depth against LLM-context leaks.
|
|
79
|
+
*/
|
|
80
|
+
exports.ADCP_INTERNAL_TAG = Symbol.for('adcp.ctx_metadata.internal');
|
|
81
|
+
/**
|
|
82
|
+
* Validation error thrown for bad input shape. Distinct from
|
|
83
|
+
* `CTX_METADATA_TOO_LARGE` (size violation) so callers can branch.
|
|
84
|
+
*/
|
|
85
|
+
class CtxMetadataValidationError extends Error {
|
|
86
|
+
code;
|
|
87
|
+
constructor(code, message) {
|
|
88
|
+
super(message);
|
|
89
|
+
this.code = code;
|
|
90
|
+
this.name = 'CtxMetadataValidationError';
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
exports.CtxMetadataValidationError = CtxMetadataValidationError;
|
|
94
|
+
/**
|
|
95
|
+
* Compose the flattened storage key. Internal — backends trust this format.
|
|
96
|
+
*/
|
|
97
|
+
function scopeCtxMetadataKey(accountId, kind, id) {
|
|
98
|
+
return `${accountId}${kind}${id}`;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Compose the bulkGet result key. External — callers index Map entries by this.
|
|
102
|
+
*/
|
|
103
|
+
function ctxMetadataResultKey(kind, id) {
|
|
104
|
+
return `${kind}:${id}`;
|
|
105
|
+
}
|
|
106
|
+
function validateAccountId(accountId) {
|
|
107
|
+
if (accountId == null || accountId === '') {
|
|
108
|
+
throw new CtxMetadataValidationError('INVALID_ARGUMENT', 'ctx_metadata requires an account scope. No-account tools (provide_performance_feedback, ' +
|
|
109
|
+
'list_creative_formats) cannot use ctx_metadata.');
|
|
110
|
+
}
|
|
111
|
+
if (!VALID_KEY_SEGMENT.test(accountId)) {
|
|
112
|
+
throw new CtxMetadataValidationError('INVALID_ARGUMENT', `Invalid accountId shape: must match ${VALID_KEY_SEGMENT}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function validateResourceId(id) {
|
|
116
|
+
if (id == null || id === '') {
|
|
117
|
+
throw new CtxMetadataValidationError('INVALID_ARGUMENT', 'ctx_metadata resource id must be non-empty');
|
|
118
|
+
}
|
|
119
|
+
if (!VALID_KEY_SEGMENT.test(id)) {
|
|
120
|
+
throw new CtxMetadataValidationError('INVALID_ARGUMENT', `Invalid resource id shape: must match ${VALID_KEY_SEGMENT}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function validateResourceKind(kind) {
|
|
124
|
+
if (!ALL_RESOURCE_KINDS.includes(kind)) {
|
|
125
|
+
throw new CtxMetadataValidationError('INVALID_ARGUMENT', `Unknown ctx_metadata resource kind: ${kind}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function tagInternal(value) {
|
|
129
|
+
if (value == null || typeof value !== 'object')
|
|
130
|
+
return value;
|
|
131
|
+
Object.defineProperty(value, exports.ADCP_INTERNAL_TAG, {
|
|
132
|
+
value: true,
|
|
133
|
+
enumerable: false,
|
|
134
|
+
writable: false,
|
|
135
|
+
configurable: false,
|
|
136
|
+
});
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Build a CtxMetadataStore wrapping a backend.
|
|
141
|
+
*
|
|
142
|
+
* Memory backend is fine for single-process dev. Cluster deployments
|
|
143
|
+
* MUST use `pgCtxMetadataStore` — silent ctx_metadata loss after a
|
|
144
|
+
* rolling restart produces "package not found" errors that look like
|
|
145
|
+
* publisher bugs and run for weeks.
|
|
146
|
+
*/
|
|
147
|
+
function createCtxMetadataStore(config) {
|
|
148
|
+
const backend = config.backend;
|
|
149
|
+
const maxValueBytes = config.maxValueBytes ?? exports.DEFAULT_MAX_VALUE_BYTES;
|
|
150
|
+
return {
|
|
151
|
+
async get(accountId, kind, id) {
|
|
152
|
+
validateAccountId(accountId);
|
|
153
|
+
validateResourceKind(kind);
|
|
154
|
+
validateResourceId(id);
|
|
155
|
+
const entry = await backend.get(scopeCtxMetadataKey(accountId, kind, id));
|
|
156
|
+
if (!entry)
|
|
157
|
+
return undefined;
|
|
158
|
+
if (entry.expiresAt != null && entry.expiresAt < Math.floor(Date.now() / 1000)) {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
return tagInternal(entry.value);
|
|
162
|
+
},
|
|
163
|
+
async bulkGet(accountId, refs) {
|
|
164
|
+
validateAccountId(accountId);
|
|
165
|
+
if (refs.length === 0)
|
|
166
|
+
return new Map();
|
|
167
|
+
const scopedKeys = [];
|
|
168
|
+
const scopedToResultKey = new Map();
|
|
169
|
+
for (const ref of refs) {
|
|
170
|
+
validateResourceKind(ref.kind);
|
|
171
|
+
validateResourceId(ref.id);
|
|
172
|
+
const scoped = scopeCtxMetadataKey(accountId, ref.kind, ref.id);
|
|
173
|
+
scopedKeys.push(scoped);
|
|
174
|
+
scopedToResultKey.set(scoped, ctxMetadataResultKey(ref.kind, ref.id));
|
|
175
|
+
}
|
|
176
|
+
const entries = await backend.bulkGet(scopedKeys);
|
|
177
|
+
const result = new Map();
|
|
178
|
+
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
179
|
+
for (const [scopedKey, entry] of entries) {
|
|
180
|
+
if (entry.expiresAt != null && entry.expiresAt < nowSeconds)
|
|
181
|
+
continue;
|
|
182
|
+
const resultKey = scopedToResultKey.get(scopedKey);
|
|
183
|
+
if (resultKey != null)
|
|
184
|
+
result.set(resultKey, tagInternal(entry.value));
|
|
185
|
+
}
|
|
186
|
+
return result;
|
|
187
|
+
},
|
|
188
|
+
async set(accountId, kind, id, value, ttlSeconds) {
|
|
189
|
+
validateAccountId(accountId);
|
|
190
|
+
validateResourceKind(kind);
|
|
191
|
+
validateResourceId(id);
|
|
192
|
+
if (ttlSeconds != null) {
|
|
193
|
+
if (!Number.isFinite(ttlSeconds) || ttlSeconds <= 0) {
|
|
194
|
+
throw new CtxMetadataValidationError('INVALID_ARGUMENT', 'ttlSeconds must be a positive finite number');
|
|
195
|
+
}
|
|
196
|
+
if (ttlSeconds > exports.MAX_TTL_SECONDS) {
|
|
197
|
+
throw new CtxMetadataValidationError('INVALID_ARGUMENT', `ttlSeconds exceeds the 30-day maximum (${exports.MAX_TTL_SECONDS}s)`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const serialized = JSON.stringify(value);
|
|
201
|
+
if (serialized == null) {
|
|
202
|
+
throw new CtxMetadataValidationError('INVALID_ARGUMENT', 'ctx_metadata value must be JSON-serializable (got undefined / function / symbol)');
|
|
203
|
+
}
|
|
204
|
+
const byteLen = Buffer.byteLength(serialized, 'utf8');
|
|
205
|
+
if (byteLen > maxValueBytes) {
|
|
206
|
+
throw new CtxMetadataValidationError('CTX_METADATA_TOO_LARGE', `ctx_metadata blob is ${byteLen} bytes, exceeds the configured cap of ${maxValueBytes} bytes ` +
|
|
207
|
+
`for ${kind}:${id}. Offload large payloads to your own storage and reference by ID.`);
|
|
208
|
+
}
|
|
209
|
+
const expiresAt = ttlSeconds != null ? Math.floor(Date.now() / 1000) + ttlSeconds : undefined;
|
|
210
|
+
// Preserve any prior `resource` from the framework-managed entry —
|
|
211
|
+
// adopter `set()` only mutates `value`. The dispatch seam writes
|
|
212
|
+
// resource via `setEntry`.
|
|
213
|
+
const prior = await backend.get(scopeCtxMetadataKey(accountId, kind, id));
|
|
214
|
+
const next = {
|
|
215
|
+
value,
|
|
216
|
+
...(prior?.resource !== undefined && { resource: prior.resource }),
|
|
217
|
+
...(expiresAt !== undefined
|
|
218
|
+
? { expiresAt }
|
|
219
|
+
: prior?.expiresAt !== undefined
|
|
220
|
+
? { expiresAt: prior.expiresAt }
|
|
221
|
+
: {}),
|
|
222
|
+
};
|
|
223
|
+
await backend.put(scopeCtxMetadataKey(accountId, kind, id), next);
|
|
224
|
+
},
|
|
225
|
+
async setEntry(accountId, kind, id, entry) {
|
|
226
|
+
validateAccountId(accountId);
|
|
227
|
+
validateResourceKind(kind);
|
|
228
|
+
validateResourceId(id);
|
|
229
|
+
// Cap applied to the COMBINED serialization (value + resource) since
|
|
230
|
+
// both round-trip together. Use the same upstream message so adopters
|
|
231
|
+
// see the same diagnostic surface.
|
|
232
|
+
const serialized = JSON.stringify({ value: entry.value, resource: entry.resource });
|
|
233
|
+
const byteLen = Buffer.byteLength(serialized, 'utf8');
|
|
234
|
+
if (byteLen > maxValueBytes) {
|
|
235
|
+
throw new CtxMetadataValidationError('CTX_METADATA_TOO_LARGE', `ctx_metadata combined blob is ${byteLen} bytes, exceeds the configured cap of ${maxValueBytes} bytes ` +
|
|
236
|
+
`for ${kind}:${id}. Offload large payloads to your own storage and reference by ID.`);
|
|
237
|
+
}
|
|
238
|
+
await backend.put(scopeCtxMetadataKey(accountId, kind, id), entry);
|
|
239
|
+
},
|
|
240
|
+
async setResource(accountId, kind, id, resource, publisherCtxMetadata) {
|
|
241
|
+
validateAccountId(accountId);
|
|
242
|
+
validateResourceKind(kind);
|
|
243
|
+
validateResourceId(id);
|
|
244
|
+
const scopedKey = scopeCtxMetadataKey(accountId, kind, id);
|
|
245
|
+
const prior = await backend.get(scopedKey);
|
|
246
|
+
// Resolve the value to persist:
|
|
247
|
+
// - publisher returned ctx_metadata on the wire shape → use it (overrides prior)
|
|
248
|
+
// - publisher omitted ctx_metadata → preserve prior value (don't clobber)
|
|
249
|
+
// - no prior, no publisher value → store null
|
|
250
|
+
const nextValue = publisherCtxMetadata !== undefined && publisherCtxMetadata !== null
|
|
251
|
+
? publisherCtxMetadata
|
|
252
|
+
: (prior?.value ?? null);
|
|
253
|
+
const nextEntry = {
|
|
254
|
+
value: nextValue,
|
|
255
|
+
resource,
|
|
256
|
+
...(prior?.expiresAt !== undefined && { expiresAt: prior.expiresAt }),
|
|
257
|
+
};
|
|
258
|
+
// Apply the same size cap used by setEntry.
|
|
259
|
+
const serialized = JSON.stringify({ value: nextEntry.value, resource: nextEntry.resource });
|
|
260
|
+
const byteLen = Buffer.byteLength(serialized, 'utf8');
|
|
261
|
+
if (byteLen > maxValueBytes) {
|
|
262
|
+
throw new CtxMetadataValidationError('CTX_METADATA_TOO_LARGE', `ctx_metadata combined blob is ${byteLen} bytes, exceeds the configured cap of ${maxValueBytes} bytes ` +
|
|
263
|
+
`for ${kind}:${id}. Offload large payloads to your own storage and reference by ID.`);
|
|
264
|
+
}
|
|
265
|
+
await backend.put(scopedKey, nextEntry);
|
|
266
|
+
},
|
|
267
|
+
async getEntry(accountId, kind, id) {
|
|
268
|
+
validateAccountId(accountId);
|
|
269
|
+
validateResourceKind(kind);
|
|
270
|
+
validateResourceId(id);
|
|
271
|
+
const entry = await backend.get(scopeCtxMetadataKey(accountId, kind, id));
|
|
272
|
+
if (!entry)
|
|
273
|
+
return undefined;
|
|
274
|
+
if (entry.expiresAt != null && entry.expiresAt < Math.floor(Date.now() / 1000)) {
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
277
|
+
return entry;
|
|
278
|
+
},
|
|
279
|
+
async bulkGetEntries(accountId, refs) {
|
|
280
|
+
validateAccountId(accountId);
|
|
281
|
+
if (refs.length === 0)
|
|
282
|
+
return new Map();
|
|
283
|
+
const scopedKeys = [];
|
|
284
|
+
const scopedToResultKey = new Map();
|
|
285
|
+
for (const ref of refs) {
|
|
286
|
+
validateResourceKind(ref.kind);
|
|
287
|
+
validateResourceId(ref.id);
|
|
288
|
+
const scoped = scopeCtxMetadataKey(accountId, ref.kind, ref.id);
|
|
289
|
+
scopedKeys.push(scoped);
|
|
290
|
+
scopedToResultKey.set(scoped, ctxMetadataResultKey(ref.kind, ref.id));
|
|
291
|
+
}
|
|
292
|
+
const entries = await backend.bulkGet(scopedKeys);
|
|
293
|
+
const result = new Map();
|
|
294
|
+
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
295
|
+
for (const [scopedKey, entry] of entries) {
|
|
296
|
+
if (entry.expiresAt != null && entry.expiresAt < nowSeconds)
|
|
297
|
+
continue;
|
|
298
|
+
const resultKey = scopedToResultKey.get(scopedKey);
|
|
299
|
+
if (resultKey != null)
|
|
300
|
+
result.set(resultKey, entry);
|
|
301
|
+
}
|
|
302
|
+
return result;
|
|
303
|
+
},
|
|
304
|
+
async delete(accountId, kind, id) {
|
|
305
|
+
validateAccountId(accountId);
|
|
306
|
+
validateResourceKind(kind);
|
|
307
|
+
validateResourceId(id);
|
|
308
|
+
await backend.delete(scopeCtxMetadataKey(accountId, kind, id));
|
|
309
|
+
},
|
|
310
|
+
async probe() {
|
|
311
|
+
if (backend.probe)
|
|
312
|
+
await backend.probe();
|
|
313
|
+
},
|
|
314
|
+
async close() {
|
|
315
|
+
if (backend.close)
|
|
316
|
+
await backend.close();
|
|
317
|
+
},
|
|
318
|
+
async clearAll() {
|
|
319
|
+
if (!backend.clearAll) {
|
|
320
|
+
throw new Error('ctx_metadata backend does not support clearAll(). ' +
|
|
321
|
+
'Production backends (e.g., shared Postgres) should refuse this; use memory backend for tests.');
|
|
322
|
+
}
|
|
323
|
+
await backend.clearAll();
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/lib/server/ctx-metadata/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile-time + runtime defense against `ctx_metadata` leaking into
|
|
3
|
+
* buyer-facing wire payloads.
|
|
4
|
+
*
|
|
5
|
+
* - **Compile-time:** `WireShape<T>` strips `ctx_metadata` from a type
|
|
6
|
+
* tree, so the framework's response builder return types refuse a
|
|
7
|
+
* payload that carries it.
|
|
8
|
+
* - **Runtime:** `stripCtxMetadata(value)` shape-aware shallow walk
|
|
9
|
+
* over known carrier locations (response root + `packages[]` +
|
|
10
|
+
* `creatives[]` + `audiences[]` + `signals[]` + `media_buys[]` +
|
|
11
|
+
* `products[]`). Catches custom-handler escape hatches and HITL
|
|
12
|
+
* task return values that re-introduce the field at runtime.
|
|
13
|
+
*
|
|
14
|
+
* Single chokepoint at the dispatcher seam. Strip runs *before* the
|
|
15
|
+
* idempotency cache write so cached replays don't leak.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Compile-time strip: recursively remove `ctx_metadata` from a type
|
|
21
|
+
* tree. Used as the framework's response-boundary type so a publisher
|
|
22
|
+
* payload that carries the field fails type-checking before it
|
|
23
|
+
* reaches the wire.
|
|
24
|
+
*
|
|
25
|
+
* Strips `ctx_metadata` at top level, inside arrays, and inside
|
|
26
|
+
* objects nested under `packages` / `creatives` / `audiences` /
|
|
27
|
+
* `signals` / `media_buys` / `products` — the carrier shapes the
|
|
28
|
+
* AdCP 3.0 wire spec defines. Other shapes pass through unchanged
|
|
29
|
+
* (the runtime walk is deliberately not recursive everywhere — see
|
|
30
|
+
* the docstring).
|
|
31
|
+
*/
|
|
32
|
+
export type WireShape<T> = T extends ReadonlyArray<infer U> ? ReadonlyArray<WireShape<U>> : T extends object ? {
|
|
33
|
+
[K in keyof T as K extends 'ctx_metadata' ? never : K]: WireShape<T[K]>;
|
|
34
|
+
} : T;
|
|
35
|
+
/**
|
|
36
|
+
* Runtime strip. Walks known carrier shapes in the response and
|
|
37
|
+
* deletes `ctx_metadata` keys. Returns the input value (mutates in
|
|
38
|
+
* place — the dispatcher constructs a fresh response per call, so
|
|
39
|
+
* mutation is safe).
|
|
40
|
+
*
|
|
41
|
+
* **Why shape-aware shallow walk, not full recursion.** Full
|
|
42
|
+
* recursion is O(response size) and risks stripping a field a
|
|
43
|
+
* future spec adds with the same name elsewhere (e.g., a diagnostic
|
|
44
|
+
* envelope's `ctx_metadata`). Shape-aware walks the carrier
|
|
45
|
+
* locations defined by AdCP 3.0 — adding a new carrier requires
|
|
46
|
+
* updating this list, which is the right kind of friction.
|
|
47
|
+
*/
|
|
48
|
+
export declare function stripCtxMetadata<T>(value: T): WireShape<T>;
|
|
49
|
+
/**
|
|
50
|
+
* Detect whether a payload contains `ctx_metadata` at any walked
|
|
51
|
+
* carrier location. Used by the test suite to assert wire payloads
|
|
52
|
+
* are clean — production code paths just call `stripCtxMetadata`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function hasCtxMetadata(value: unknown): boolean;
|
|
55
|
+
//# sourceMappingURL=wire-shape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire-shape.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/ctx-metadata/wire-shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,IACrB,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAC5B,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAC3B,CAAC,SAAS,MAAM,GACd;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,cAAc,GAAG,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GAC3E,CAAC,CAAC;AAEV;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAI1D;AA+CD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGtD"}
|