@adcp/sdk 12.0.0 → 12.0.2
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/dist/lib/adapters/content-standards-adapter.mjs +0 -6
- package/dist/lib/adapters/content-standards-adapter.mjs.map +1 -1
- package/dist/lib/adapters/derived-account-store.mjs +0 -6
- package/dist/lib/adapters/derived-account-store.mjs.map +1 -1
- package/dist/lib/adapters/governance-adapter.mjs +0 -6
- package/dist/lib/adapters/governance-adapter.mjs.map +1 -1
- package/dist/lib/adapters/implicit-account-store.mjs +0 -6
- package/dist/lib/adapters/implicit-account-store.mjs.map +1 -1
- package/dist/lib/adapters/index.mjs +0 -6
- package/dist/lib/adapters/index.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/get_products.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/get_products.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/index.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/index.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/types.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs.map +1 -1
- package/dist/lib/adapters/oauth-passthrough-resolver.mjs +0 -6
- package/dist/lib/adapters/oauth-passthrough-resolver.mjs.map +1 -1
- package/dist/lib/adapters/property-list-adapter.mjs +0 -6
- package/dist/lib/adapters/property-list-adapter.mjs.map +1 -1
- package/dist/lib/adapters/roster-account-store.mjs +0 -6
- package/dist/lib/adapters/roster-account-store.mjs.map +1 -1
- package/dist/lib/adapters/si-session-manager.mjs +0 -6
- package/dist/lib/adapters/si-session-manager.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/brand-fields.mjs +0 -6
- package/dist/lib/adapters/version/3.0/brand-fields.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/get-products.mjs +0 -6
- package/dist/lib/adapters/version/3.0/get-products.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/index.mjs +0 -6
- package/dist/lib/adapters/version/3.0/index.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/sync-accounts.mjs +0 -6
- package/dist/lib/adapters/version/3.0/sync-accounts.mjs.map +1 -1
- package/dist/lib/adapters/version/index.mjs +0 -6
- package/dist/lib/adapters/version/index.mjs.map +1 -1
- package/dist/lib/adapters/version/types.mjs +0 -6
- package/dist/lib/advanced.mjs +0 -6
- package/dist/lib/advanced.mjs.map +1 -1
- package/dist/lib/agents/index.generated.mjs +0 -6
- package/dist/lib/agents/index.generated.mjs.map +1 -1
- package/dist/lib/auth/index.mjs +0 -6
- package/dist/lib/auth/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs +0 -6
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs.map +1 -1
- package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs +0 -6
- package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs.map +1 -1
- package/dist/lib/auth/oauth/MCPOAuthProvider.mjs +0 -6
- package/dist/lib/auth/oauth/MCPOAuthProvider.mjs.map +1 -1
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs +0 -6
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs.map +1 -1
- package/dist/lib/auth/oauth/authorization-required.mjs +0 -6
- package/dist/lib/auth/oauth/authorization-required.mjs.map +1 -1
- package/dist/lib/auth/oauth/diagnose.mjs +0 -6
- package/dist/lib/auth/oauth/diagnose.mjs.map +1 -1
- package/dist/lib/auth/oauth/diagnostics.mjs +0 -6
- package/dist/lib/auth/oauth/diagnostics.mjs.map +1 -1
- package/dist/lib/auth/oauth/discovery.mjs +0 -6
- package/dist/lib/auth/oauth/discovery.mjs.map +1 -1
- package/dist/lib/auth/oauth/file-storage.mjs +0 -6
- package/dist/lib/auth/oauth/file-storage.mjs.map +1 -1
- package/dist/lib/auth/oauth/index.mjs +0 -6
- package/dist/lib/auth/oauth/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/secret-resolver.mjs +0 -6
- package/dist/lib/auth/oauth/secret-resolver.mjs.map +1 -1
- package/dist/lib/auth/oauth/storage-registry.mjs +0 -6
- package/dist/lib/auth/oauth/storage-registry.mjs.map +1 -1
- package/dist/lib/auth/oauth/types.mjs +0 -6
- package/dist/lib/auth/oauth/types.mjs.map +1 -1
- package/dist/lib/auth/oauth/web-flow.mjs +0 -6
- package/dist/lib/auth/oauth/web-flow.mjs.map +1 -1
- package/dist/lib/brand/index.mjs +0 -6
- package/dist/lib/brand/index.mjs.map +1 -1
- package/dist/lib/canonical-references/index.mjs +6 -7
- package/dist/lib/canonical-references/index.mjs.map +1 -1
- package/dist/lib/client/index.mjs +0 -6
- package/dist/lib/client/index.mjs.map +1 -1
- package/dist/lib/compliance/index.mjs +0 -6
- package/dist/lib/compliance/index.mjs.map +1 -1
- package/dist/lib/compliance-fixtures/index.mjs +0 -6
- package/dist/lib/compliance-fixtures/index.mjs.map +1 -1
- package/dist/lib/compliance-fixtures/test-authorization-server.mjs +0 -6
- package/dist/lib/compliance-fixtures/test-authorization-server.mjs.map +1 -1
- package/dist/lib/conformance/index.mjs +0 -6
- package/dist/lib/conformance/index.mjs.map +1 -1
- package/dist/lib/conformance/invariants/uniformError.mjs +0 -6
- package/dist/lib/conformance/invariants/uniformError.mjs.map +1 -1
- package/dist/lib/conformance/invariants/uniformErrorComparator.mjs +0 -6
- package/dist/lib/conformance/invariants/uniformErrorComparator.mjs.map +1 -1
- package/dist/lib/conformance/oracle.mjs +0 -6
- package/dist/lib/conformance/oracle.mjs.map +1 -1
- package/dist/lib/conformance/runConformance.mjs +0 -6
- package/dist/lib/conformance/runConformance.mjs.map +1 -1
- package/dist/lib/conformance/runners.mjs +0 -6
- package/dist/lib/conformance/runners.mjs.map +1 -1
- package/dist/lib/conformance/schemaArbitrary.mjs +0 -6
- package/dist/lib/conformance/schemaArbitrary.mjs.map +1 -1
- package/dist/lib/conformance/schemaLoader.mjs +5 -6
- package/dist/lib/conformance/schemaLoader.mjs.map +1 -1
- package/dist/lib/conformance/seeder.mjs +0 -6
- package/dist/lib/conformance/seeder.mjs.map +1 -1
- package/dist/lib/conformance/types.mjs +0 -6
- package/dist/lib/conformance/types.mjs.map +1 -1
- package/dist/lib/conformance/webhook.mjs +0 -6
- package/dist/lib/conformance/webhook.mjs.map +1 -1
- package/dist/lib/core/ADCPMultiAgentClient.mjs +0 -6
- package/dist/lib/core/ADCPMultiAgentClient.mjs.map +1 -1
- package/dist/lib/core/AgentClient.mjs +0 -6
- package/dist/lib/core/AgentClient.mjs.map +1 -1
- package/dist/lib/core/AsyncHandler.mjs +0 -6
- package/dist/lib/core/AsyncHandler.mjs.map +1 -1
- package/dist/lib/core/ConfigurationManager.mjs +0 -6
- package/dist/lib/core/ConfigurationManager.mjs.map +1 -1
- package/dist/lib/core/ConversationTypes.mjs +0 -6
- package/dist/lib/core/CreativeAgentClient.mjs +0 -6
- package/dist/lib/core/CreativeAgentClient.mjs.map +1 -1
- package/dist/lib/core/GovernanceMiddleware.mjs +0 -6
- package/dist/lib/core/GovernanceMiddleware.mjs.map +1 -1
- package/dist/lib/core/GovernanceTypes.mjs +0 -6
- package/dist/lib/core/GovernanceTypes.mjs.map +1 -1
- package/dist/lib/core/ProtocolResponseParser.mjs +0 -6
- package/dist/lib/core/ProtocolResponseParser.mjs.map +1 -1
- package/dist/lib/core/ResponseValidator.mjs +0 -6
- package/dist/lib/core/ResponseValidator.mjs.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +0 -6
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/core/TaskEventTypes.mjs +0 -6
- package/dist/lib/core/TaskEventTypes.mjs.map +1 -1
- package/dist/lib/core/TaskExecutor.mjs +0 -6
- package/dist/lib/core/TaskExecutor.mjs.map +1 -1
- package/dist/lib/core/match.mjs +0 -6
- package/dist/lib/core/match.mjs.map +1 -1
- package/dist/lib/core/task-status.mjs +0 -6
- package/dist/lib/core/task-status.mjs.map +1 -1
- package/dist/lib/core/webhook-url.mjs +0 -6
- package/dist/lib/core/webhook-url.mjs.map +1 -1
- package/dist/lib/discovery/adagents-redirects.mjs +0 -6
- package/dist/lib/discovery/adagents-redirects.mjs.map +1 -1
- package/dist/lib/discovery/agent-directory.mjs +0 -6
- package/dist/lib/discovery/agent-directory.mjs.map +1 -1
- package/dist/lib/discovery/inline-publisher-properties.mjs +0 -6
- package/dist/lib/discovery/inline-publisher-properties.mjs.map +1 -1
- package/dist/lib/discovery/network-consistency-checker.mjs +0 -6
- package/dist/lib/discovery/network-consistency-checker.mjs.map +1 -1
- package/dist/lib/discovery/property-crawler.mjs +0 -6
- package/dist/lib/discovery/property-crawler.mjs.map +1 -1
- package/dist/lib/discovery/property-index.mjs +0 -6
- package/dist/lib/discovery/property-index.mjs.map +1 -1
- package/dist/lib/discovery/publisher-property-selector.mjs +0 -6
- package/dist/lib/discovery/publisher-property-selector.mjs.map +1 -1
- package/dist/lib/discovery/resolve-agent-properties.mjs +0 -6
- package/dist/lib/discovery/resolve-agent-properties.mjs.map +1 -1
- package/dist/lib/discovery/types.mjs +0 -6
- package/dist/lib/discovery/validate-adagents.mjs +0 -6
- package/dist/lib/discovery/validate-adagents.mjs.map +1 -1
- package/dist/lib/enums.mjs +0 -6
- package/dist/lib/enums.mjs.map +1 -1
- package/dist/lib/errors/index.mjs +0 -6
- package/dist/lib/errors/index.mjs.map +1 -1
- package/dist/lib/express-mcp/index.mjs +0 -6
- package/dist/lib/express-mcp/index.mjs.map +1 -1
- package/dist/lib/governance/index.mjs +0 -6
- package/dist/lib/governance/index.mjs.map +1 -1
- package/dist/lib/handlers/types.mjs +0 -6
- package/dist/lib/handlers/types.mjs.map +1 -1
- package/dist/lib/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +0 -6
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/media-buy/available-actions.mjs +0 -6
- package/dist/lib/media-buy/available-actions.mjs.map +1 -1
- package/dist/lib/media-buy/index.mjs +0 -6
- package/dist/lib/media-buy/index.mjs.map +1 -1
- package/dist/lib/media-buy/preflight.mjs +0 -6
- package/dist/lib/media-buy/preflight.mjs.map +1 -1
- package/dist/lib/media-buy/property-policy.mjs +0 -6
- package/dist/lib/media-buy/property-policy.mjs.map +1 -1
- package/dist/lib/media-buy/types.mjs +0 -6
- package/dist/lib/media-buy/types.mjs.map +1 -1
- package/dist/lib/media-buy/update-fields.generated.mjs +0 -6
- package/dist/lib/media-buy/update-fields.generated.mjs.map +1 -1
- package/dist/lib/mock-server/creative-ad-server/seed-data.mjs +0 -6
- package/dist/lib/mock-server/creative-ad-server/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/creative-ad-server/server.mjs +0 -6
- package/dist/lib/mock-server/creative-ad-server/server.mjs.map +1 -1
- package/dist/lib/mock-server/creative-template/seed-data.mjs +0 -6
- package/dist/lib/mock-server/creative-template/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/creative-template/server.mjs +0 -6
- package/dist/lib/mock-server/creative-template/server.mjs.map +1 -1
- package/dist/lib/mock-server/index.mjs +0 -6
- package/dist/lib/mock-server/index.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/recipe.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/recipe.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/server.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/server.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/server.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/server.mjs.map +1 -1
- package/dist/lib/mock-server/sales-social/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-social/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-social/server.mjs +0 -6
- package/dist/lib/mock-server/sales-social/server.mjs.map +1 -1
- package/dist/lib/mock-server/scenario.mjs +0 -6
- package/dist/lib/mock-server/scenario.mjs.map +1 -1
- package/dist/lib/mock-server/signal-marketplace/seed-data.mjs +0 -6
- package/dist/lib/mock-server/signal-marketplace/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/signal-marketplace/server.mjs +0 -6
- package/dist/lib/mock-server/signal-marketplace/server.mjs.map +1 -1
- package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sponsored-intelligence/server.mjs +0 -6
- package/dist/lib/mock-server/sponsored-intelligence/server.mjs.map +1 -1
- package/dist/lib/net/address-guards.mjs +0 -6
- package/dist/lib/net/address-guards.mjs.map +1 -1
- package/dist/lib/net/index.mjs +0 -6
- package/dist/lib/net/index.mjs.map +1 -1
- package/dist/lib/net/ssrf-fetch.mjs +0 -6
- package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
- package/dist/lib/observability/index.mjs +0 -6
- package/dist/lib/observability/index.mjs.map +1 -1
- package/dist/lib/observability/tracing.mjs +6 -7
- package/dist/lib/observability/tracing.mjs.map +1 -1
- package/dist/lib/protocols/a2a.mjs +0 -6
- package/dist/lib/protocols/a2a.mjs.map +1 -1
- package/dist/lib/protocols/abort.mjs +0 -6
- package/dist/lib/protocols/abort.mjs.map +1 -1
- package/dist/lib/protocols/index.mjs +0 -6
- package/dist/lib/protocols/index.mjs.map +1 -1
- package/dist/lib/protocols/mcp-modern.mjs +0 -6
- package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
- package/dist/lib/protocols/mcp-tasks.mjs +0 -6
- package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
- package/dist/lib/protocols/mcp.mjs +0 -6
- package/dist/lib/protocols/mcp.mjs.map +1 -1
- package/dist/lib/protocols/rawResponseCapture.mjs +0 -6
- package/dist/lib/protocols/rawResponseCapture.mjs.map +1 -1
- package/dist/lib/protocols/responseSizeLimit.mjs +0 -6
- package/dist/lib/protocols/responseSizeLimit.mjs.map +1 -1
- package/dist/lib/protocols/transportDiagnostics.mjs +0 -6
- package/dist/lib/protocols/transportDiagnostics.mjs.map +1 -1
- package/dist/lib/registry/cursor-store.mjs +0 -6
- package/dist/lib/registry/cursor-store.mjs.map +1 -1
- package/dist/lib/registry/feed-stream.mjs +0 -6
- package/dist/lib/registry/feed-stream.mjs.map +1 -1
- package/dist/lib/registry/index.mjs +0 -6
- package/dist/lib/registry/index.mjs.map +1 -1
- package/dist/lib/registry/property-registry.mjs +0 -6
- package/dist/lib/registry/property-registry.mjs.map +1 -1
- package/dist/lib/registry/sync.mjs +0 -6
- package/dist/lib/registry/sync.mjs.map +1 -1
- package/dist/lib/registry/types.generated.mjs +0 -6
- package/dist/lib/registry/types.mjs +0 -6
- package/dist/lib/schemas/index.mjs +0 -6
- package/dist/lib/schemas/index.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/a2a-adapter.mjs +0 -6
- package/dist/lib/server/a2a-adapter.mjs.map +1 -1
- package/dist/lib/server/account-mode.mjs +0 -6
- package/dist/lib/server/account-mode.mjs.map +1 -1
- package/dist/lib/server/adcp-server.mjs +0 -6
- package/dist/lib/server/adcp-server.mjs.map +1 -1
- package/dist/lib/server/auth-introspection.mjs +0 -6
- package/dist/lib/server/auth-introspection.mjs.map +1 -1
- package/dist/lib/server/auth-signature.mjs +0 -6
- package/dist/lib/server/auth-signature.mjs.map +1 -1
- package/dist/lib/server/auth.mjs +0 -6
- package/dist/lib/server/auth.mjs.map +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +13 -0
- package/dist/lib/server/create-adcp-server.d.ts +13 -0
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +3 -2
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +3 -8
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/credential-policy.mjs +0 -6
- package/dist/lib/server/credential-policy.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/memory.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/memory.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/pg.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/pg.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/redis.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/redis.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/index.mjs +0 -6
- package/dist/lib/server/ctx-metadata/index.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/store.mjs +0 -6
- package/dist/lib/server/ctx-metadata/store.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/wire-shape.mjs +0 -6
- package/dist/lib/server/ctx-metadata/wire-shape.mjs.map +1 -1
- package/dist/lib/server/decisioning/account.mjs +0 -6
- package/dist/lib/server/decisioning/account.mjs.map +1 -1
- package/dist/lib/server/decisioning/admin-router.mjs +0 -6
- package/dist/lib/server/decisioning/admin-router.mjs.map +1 -1
- package/dist/lib/server/decisioning/assembly-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/assembly-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/async-outcome.mjs +0 -6
- package/dist/lib/server/decisioning/async-outcome.mjs.map +1 -1
- package/dist/lib/server/decisioning/buyer-agent.mjs +0 -6
- package/dist/lib/server/decisioning/buyer-agent.mjs.map +1 -1
- package/dist/lib/server/decisioning/capabilities.mjs +0 -6
- package/dist/lib/server/decisioning/capabilities.mjs.map +1 -1
- package/dist/lib/server/decisioning/compose.mjs +0 -6
- package/dist/lib/server/decisioning/compose.mjs.map +1 -1
- package/dist/lib/server/decisioning/context.mjs +0 -6
- package/dist/lib/server/decisioning/errors-typed.mjs +0 -6
- package/dist/lib/server/decisioning/errors-typed.mjs.map +1 -1
- package/dist/lib/server/decisioning/helpers.mjs +0 -6
- package/dist/lib/server/decisioning/helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.mjs +0 -6
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/list-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/list-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/manifest-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/pagination.mjs +0 -6
- package/dist/lib/server/decisioning/platform-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/platform-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/platform.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/dispatch.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/dispatch.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/index.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/lifecycle.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/lifecycle.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/mock-manager.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/mock-manager.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/store.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/store.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
- package/dist/lib/server/decisioning/resolve-presets.mjs +0 -6
- package/dist/lib/server/decisioning/resolve-presets.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/observed-modes.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/observed-modes.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/audiences.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/brand-rights.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/campaign-governance.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/content-standards.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/creative.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/lists.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/sales.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/signals.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.mjs +0 -6
- package/dist/lib/server/decisioning/start-time.mjs +0 -6
- package/dist/lib/server/decisioning/start-time.mjs.map +1 -1
- package/dist/lib/server/decisioning/status-changes.mjs +0 -6
- package/dist/lib/server/decisioning/status-changes.mjs.map +1 -1
- package/dist/lib/server/decisioning/status-mappers.mjs +0 -6
- package/dist/lib/server/decisioning/status-mappers.mjs.map +1 -1
- package/dist/lib/server/decisioning/tenant-registry.mjs +0 -6
- package/dist/lib/server/decisioning/tenant-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/tenant-store.mjs +0 -6
- package/dist/lib/server/decisioning/tenant-store.mjs.map +1 -1
- package/dist/lib/server/decisioning/validate-specialisms.mjs +0 -6
- package/dist/lib/server/decisioning/validate-specialisms.mjs.map +1 -1
- package/dist/lib/server/dynamic-registry.mjs +0 -6
- package/dist/lib/server/dynamic-registry.mjs.map +1 -1
- package/dist/lib/server/envelope-allowlist.mjs +0 -6
- package/dist/lib/server/envelope-allowlist.mjs.map +1 -1
- package/dist/lib/server/error-arm-tools.mjs +5 -6
- package/dist/lib/server/error-arm-tools.mjs.map +1 -1
- package/dist/lib/server/errors.mjs +0 -6
- package/dist/lib/server/errors.mjs.map +1 -1
- package/dist/lib/server/example-tld-guard.mjs +0 -6
- package/dist/lib/server/example-tld-guard.mjs.map +1 -1
- package/dist/lib/server/express-adapter.mjs +0 -6
- package/dist/lib/server/express-adapter.mjs.map +1 -1
- package/dist/lib/server/governance.mjs +0 -6
- package/dist/lib/server/governance.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/lazy.mjs +0 -6
- package/dist/lib/server/idempotency/backends/lazy.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/memory.mjs +0 -6
- package/dist/lib/server/idempotency/backends/memory.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/pg.mjs +0 -6
- package/dist/lib/server/idempotency/backends/pg.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/redis.mjs +0 -6
- package/dist/lib/server/idempotency/backends/redis.mjs.map +1 -1
- package/dist/lib/server/idempotency/index.mjs +0 -6
- package/dist/lib/server/idempotency/index.mjs.map +1 -1
- package/dist/lib/server/idempotency/store.mjs +0 -6
- package/dist/lib/server/idempotency/store.mjs.map +1 -1
- package/dist/lib/server/index.d.mts +1 -1
- package/dist/lib/server/index.d.ts +1 -1
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/index.mjs +0 -6
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/server/legacy/v5/index.d.mts +1 -1
- package/dist/lib/server/legacy/v5/index.d.ts +1 -1
- package/dist/lib/server/legacy/v5/index.d.ts.map +1 -1
- package/dist/lib/server/legacy/v5/index.js.map +1 -1
- package/dist/lib/server/legacy/v5/index.mjs +0 -6
- package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
- package/dist/lib/server/mcp-modern-server.mjs +0 -6
- package/dist/lib/server/mcp-modern-server.mjs.map +1 -1
- package/dist/lib/server/media-buy-actions.mjs +0 -6
- package/dist/lib/server/media-buy-actions.mjs.map +1 -1
- package/dist/lib/server/media-buy-helpers.mjs +0 -6
- package/dist/lib/server/media-buy-helpers.mjs.map +1 -1
- package/dist/lib/server/media-buy-store.mjs +0 -6
- package/dist/lib/server/media-buy-store.mjs.map +1 -1
- package/dist/lib/server/normalize-errors.mjs +0 -6
- package/dist/lib/server/normalize-errors.mjs.map +1 -1
- package/dist/lib/server/operational-platform.mjs +0 -6
- package/dist/lib/server/operational-platform.mjs.map +1 -1
- package/dist/lib/server/pick-safe-details.mjs +0 -6
- package/dist/lib/server/pick-safe-details.mjs.map +1 -1
- package/dist/lib/server/pin-and-bind-fetch.mjs +0 -6
- package/dist/lib/server/pin-and-bind-fetch.mjs.map +1 -1
- package/dist/lib/server/postgres-state-store.mjs +0 -6
- package/dist/lib/server/postgres-state-store.mjs.map +1 -1
- package/dist/lib/server/postgres-task-store.mjs +0 -6
- package/dist/lib/server/postgres-task-store.mjs.map +1 -1
- package/dist/lib/server/product-defaults.mjs +0 -6
- package/dist/lib/server/product-defaults.mjs.map +1 -1
- package/dist/lib/server/redact.mjs +0 -6
- package/dist/lib/server/redact.mjs.map +1 -1
- package/dist/lib/server/responses.mjs +0 -6
- package/dist/lib/server/responses.mjs.map +1 -1
- package/dist/lib/server/serve.mjs +0 -6
- package/dist/lib/server/serve.mjs.map +1 -1
- package/dist/lib/server/socket-mode/conformance-client.mjs +0 -6
- package/dist/lib/server/socket-mode/conformance-client.mjs.map +1 -1
- package/dist/lib/server/socket-mode/index.mjs +0 -6
- package/dist/lib/server/socket-mode/index.mjs.map +1 -1
- package/dist/lib/server/socket-mode/ws-transport.mjs +0 -6
- package/dist/lib/server/socket-mode/ws-transport.mjs.map +1 -1
- package/dist/lib/server/state-machine.mjs +0 -6
- package/dist/lib/server/state-machine.mjs.map +1 -1
- package/dist/lib/server/state-store.mjs +0 -6
- package/dist/lib/server/state-store.mjs.map +1 -1
- package/dist/lib/server/structured-serialize.mjs +0 -6
- package/dist/lib/server/structured-serialize.mjs.map +1 -1
- package/dist/lib/server/targeting-helpers.mjs +0 -6
- package/dist/lib/server/targeting-helpers.mjs.map +1 -1
- package/dist/lib/server/tasks.mjs +0 -6
- package/dist/lib/server/tasks.mjs.map +1 -1
- package/dist/lib/server/test-controller-bridge.mjs +0 -6
- package/dist/lib/server/test-controller-bridge.mjs.map +1 -1
- package/dist/lib/server/test-controller.mjs +0 -6
- package/dist/lib/server/test-controller.mjs.map +1 -1
- package/dist/lib/server/upstream-helpers.mjs +0 -6
- package/dist/lib/server/upstream-helpers.mjs.map +1 -1
- package/dist/lib/server/webhook-emitter.mjs +0 -6
- package/dist/lib/server/webhook-emitter.mjs.map +1 -1
- package/dist/lib/server/wire-safe.mjs +0 -6
- package/dist/lib/server/wire-safe.mjs.map +1 -1
- package/dist/lib/server/wire-spec-fields.generated.mjs +0 -6
- package/dist/lib/server/wire-spec-fields.generated.mjs.map +1 -1
- package/dist/lib/server/wrap-envelope.mjs +0 -6
- package/dist/lib/server/wrap-envelope.mjs.map +1 -1
- package/dist/lib/signing/agent-context.mjs +0 -6
- package/dist/lib/signing/agent-context.mjs.map +1 -1
- package/dist/lib/signing/agent-fetch.mjs +0 -6
- package/dist/lib/signing/agent-fetch.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/canonicalize.mjs +0 -6
- package/dist/lib/signing/agent-resolver/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs +0 -6
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/consistency.mjs +0 -6
- package/dist/lib/signing/agent-resolver/consistency.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/errors.mjs +0 -6
- package/dist/lib/signing/agent-resolver/errors.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/etld.mjs +0 -6
- package/dist/lib/signing/agent-resolver/etld.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +0 -6
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/index.mjs +0 -6
- package/dist/lib/signing/agent-resolver/index.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/jwks-set.mjs +0 -6
- package/dist/lib/signing/agent-resolver/jwks-set.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/select-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/select-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/strict-json.mjs +0 -6
- package/dist/lib/signing/agent-resolver/strict-json.mjs.map +1 -1
- package/dist/lib/signing/brand-jwks.mjs +0 -6
- package/dist/lib/signing/brand-jwks.mjs.map +1 -1
- package/dist/lib/signing/canonicalize.mjs +0 -6
- package/dist/lib/signing/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/capability-cache.mjs +0 -6
- package/dist/lib/signing/capability-cache.mjs.map +1 -1
- package/dist/lib/signing/capability-priming.mjs +0 -6
- package/dist/lib/signing/capability-priming.mjs.map +1 -1
- package/dist/lib/signing/client.mjs +0 -6
- package/dist/lib/signing/client.mjs.map +1 -1
- package/dist/lib/signing/content-digest.mjs +0 -6
- package/dist/lib/signing/content-digest.mjs.map +1 -1
- package/dist/lib/signing/crypto.mjs +0 -6
- package/dist/lib/signing/crypto.mjs.map +1 -1
- package/dist/lib/signing/ecdsa-encoding.mjs +0 -6
- package/dist/lib/signing/ecdsa-encoding.mjs.map +1 -1
- package/dist/lib/signing/errors.mjs +0 -6
- package/dist/lib/signing/errors.mjs.map +1 -1
- package/dist/lib/signing/fetch-async.mjs +0 -6
- package/dist/lib/signing/fetch-async.mjs.map +1 -1
- package/dist/lib/signing/fetch.mjs +0 -6
- package/dist/lib/signing/fetch.mjs.map +1 -1
- package/dist/lib/signing/index.mjs +0 -6
- package/dist/lib/signing/index.mjs.map +1 -1
- package/dist/lib/signing/jwks-helpers.mjs +0 -6
- package/dist/lib/signing/jwks-helpers.mjs.map +1 -1
- package/dist/lib/signing/jwks-https.mjs +0 -6
- package/dist/lib/signing/jwks-https.mjs.map +1 -1
- package/dist/lib/signing/jwks.mjs +0 -6
- package/dist/lib/signing/jwks.mjs.map +1 -1
- package/dist/lib/signing/middleware.mjs +0 -6
- package/dist/lib/signing/middleware.mjs.map +1 -1
- package/dist/lib/signing/parser.mjs +0 -6
- package/dist/lib/signing/parser.mjs.map +1 -1
- package/dist/lib/signing/postgres-replay-store.mjs +0 -6
- package/dist/lib/signing/postgres-replay-store.mjs.map +1 -1
- package/dist/lib/signing/protocol-response.mjs +0 -6
- package/dist/lib/signing/protocol-response.mjs.map +1 -1
- package/dist/lib/signing/provider.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs.map +1 -1
- package/dist/lib/signing/replay.mjs +0 -6
- package/dist/lib/signing/replay.mjs.map +1 -1
- package/dist/lib/signing/request-context.mjs +0 -6
- package/dist/lib/signing/request-context.mjs.map +1 -1
- package/dist/lib/signing/revocation-https.mjs +0 -6
- package/dist/lib/signing/revocation-https.mjs.map +1 -1
- package/dist/lib/signing/revocation.mjs +0 -6
- package/dist/lib/signing/revocation.mjs.map +1 -1
- package/dist/lib/signing/server.mjs +0 -6
- package/dist/lib/signing/server.mjs.map +1 -1
- package/dist/lib/signing/signer-async.mjs +0 -6
- package/dist/lib/signing/signer-async.mjs.map +1 -1
- package/dist/lib/signing/signer.mjs +0 -6
- package/dist/lib/signing/signer.mjs.map +1 -1
- package/dist/lib/signing/testing.mjs +0 -6
- package/dist/lib/signing/testing.mjs.map +1 -1
- package/dist/lib/signing/types.mjs +0 -6
- package/dist/lib/signing/types.mjs.map +1 -1
- package/dist/lib/signing/verifier.mjs +0 -6
- package/dist/lib/signing/verifier.mjs.map +1 -1
- package/dist/lib/signing/webhook-auth-detection.mjs +0 -6
- package/dist/lib/signing/webhook-auth-detection.mjs.map +1 -1
- package/dist/lib/signing/webhook-verifier.mjs +0 -6
- package/dist/lib/signing/webhook-verifier.mjs.map +1 -1
- package/dist/lib/storage/MemoryStorage.mjs +0 -6
- package/dist/lib/storage/MemoryStorage.mjs.map +1 -1
- package/dist/lib/storage/interfaces.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs.map +1 -1
- package/dist/lib/substitution/encoder/index.mjs +0 -6
- package/dist/lib/substitution/encoder/index.mjs.map +1 -1
- package/dist/lib/substitution/index.mjs +0 -6
- package/dist/lib/substitution/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs +0 -6
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs.map +1 -1
- package/dist/lib/substitution/observer/alignment.mjs +0 -6
- package/dist/lib/substitution/observer/alignment.mjs.map +1 -1
- package/dist/lib/substitution/observer/assertions.mjs +0 -6
- package/dist/lib/substitution/observer/assertions.mjs.map +1 -1
- package/dist/lib/substitution/observer/html-parser.mjs +0 -6
- package/dist/lib/substitution/observer/html-parser.mjs.map +1 -1
- package/dist/lib/substitution/observer/index.mjs +0 -6
- package/dist/lib/substitution/observer/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/ssrf.mjs +0 -6
- package/dist/lib/substitution/observer/ssrf.mjs.map +1 -1
- package/dist/lib/substitution/rfc3986.mjs +0 -6
- package/dist/lib/substitution/rfc3986.mjs.map +1 -1
- package/dist/lib/substitution/translate.mjs +0 -6
- package/dist/lib/substitution/translate.mjs.map +1 -1
- package/dist/lib/substitution/types.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs.map +1 -1
- package/dist/lib/testing/agent-tester.mjs +0 -6
- package/dist/lib/testing/agent-tester.mjs.map +1 -1
- package/dist/lib/testing/client.mjs +0 -6
- package/dist/lib/testing/client.mjs.map +1 -1
- package/dist/lib/testing/compliance/briefs.mjs +0 -6
- package/dist/lib/testing/compliance/briefs.mjs.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +0 -6
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/compliance/index.mjs +0 -6
- package/dist/lib/testing/compliance/index.mjs.map +1 -1
- package/dist/lib/testing/compliance/spec-conformance.mjs +0 -6
- package/dist/lib/testing/compliance/spec-conformance.mjs.map +1 -1
- package/dist/lib/testing/compliance/storyboard-tracks.mjs +0 -6
- package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
- package/dist/lib/testing/compliance/summary.mjs +0 -6
- package/dist/lib/testing/compliance/summary.mjs.map +1 -1
- package/dist/lib/testing/compliance/types.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs.map +1 -1
- package/dist/lib/testing/controller-assertions.mjs +0 -6
- package/dist/lib/testing/controller-assertions.mjs.map +1 -1
- package/dist/lib/testing/formatter.mjs +0 -6
- package/dist/lib/testing/formatter.mjs.map +1 -1
- package/dist/lib/testing/index.mjs +0 -6
- package/dist/lib/testing/index.mjs.map +1 -1
- package/dist/lib/testing/local-agent-runner.mjs +0 -6
- package/dist/lib/testing/local-agent-runner.mjs.map +1 -1
- package/dist/lib/testing/orchestrator.mjs +0 -6
- package/dist/lib/testing/orchestrator.mjs.map +1 -1
- package/dist/lib/testing/personas/index.mjs +0 -6
- package/dist/lib/testing/personas/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/brand-rights.mjs +0 -6
- package/dist/lib/testing/scenarios/brand-rights.mjs.map +1 -1
- package/dist/lib/testing/scenarios/capabilities.mjs +0 -6
- package/dist/lib/testing/scenarios/capabilities.mjs.map +1 -1
- package/dist/lib/testing/scenarios/creative.mjs +0 -6
- package/dist/lib/testing/scenarios/creative.mjs.map +1 -1
- package/dist/lib/testing/scenarios/deterministic.mjs +0 -6
- package/dist/lib/testing/scenarios/deterministic.mjs.map +1 -1
- package/dist/lib/testing/scenarios/discovery.mjs +0 -6
- package/dist/lib/testing/scenarios/discovery.mjs.map +1 -1
- package/dist/lib/testing/scenarios/edge-cases.mjs +0 -6
- package/dist/lib/testing/scenarios/edge-cases.mjs.map +1 -1
- package/dist/lib/testing/scenarios/error-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/error-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/governance.mjs +0 -6
- package/dist/lib/testing/scenarios/governance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/health.mjs +0 -6
- package/dist/lib/testing/scenarios/health.mjs.map +1 -1
- package/dist/lib/testing/scenarios/index.mjs +0 -6
- package/dist/lib/testing/scenarios/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.mjs +0 -6
- package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/schema-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/signals.mjs +0 -6
- package/dist/lib/testing/scenarios/signals.mjs.map +1 -1
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs +0 -6
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs.map +1 -1
- package/dist/lib/testing/scenarios/trusted-match.mjs +0 -6
- package/dist/lib/testing/scenarios/trusted-match.mjs.map +1 -1
- package/dist/lib/testing/seed-merge.mjs +0 -6
- package/dist/lib/testing/seed-merge.mjs.map +1 -1
- package/dist/lib/testing/storyboard/agent-routing.mjs +0 -6
- package/dist/lib/testing/storyboard/agent-routing.mjs.map +1 -1
- package/dist/lib/testing/storyboard/assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +0 -6
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs.map +1 -1
- package/dist/lib/testing/storyboard/compliance.mjs +5 -6
- package/dist/lib/testing/storyboard/compliance.mjs.map +1 -1
- package/dist/lib/testing/storyboard/context.mjs +0 -6
- package/dist/lib/testing/storyboard/context.mjs.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.mjs +0 -6
- package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
- package/dist/lib/testing/storyboard/index.mjs +0 -6
- package/dist/lib/testing/storyboard/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/junit.mjs +0 -6
- package/dist/lib/testing/storyboard/junit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/loader.mjs +0 -6
- package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/path.mjs +0 -6
- package/dist/lib/testing/storyboard/path.mjs.map +1 -1
- package/dist/lib/testing/storyboard/probes.mjs +0 -6
- package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs +0 -6
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rejection-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/rejection-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/index.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/types.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +0 -6
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/sandbox-entities.mjs +0 -6
- package/dist/lib/testing/storyboard/sandbox-entities.mjs.map +1 -1
- package/dist/lib/testing/storyboard/seeding.mjs +0 -6
- package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/index.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/types.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/task-map.mjs +0 -6
- package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
- package/dist/lib/testing/storyboard/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/types.mjs +0 -6
- package/dist/lib/testing/storyboard/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.mjs +0 -6
- package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
- package/dist/lib/testing/stubs/governance-agent-stub.mjs +0 -6
- package/dist/lib/testing/stubs/governance-agent-stub.mjs.map +1 -1
- package/dist/lib/testing/stubs/index.mjs +0 -6
- package/dist/lib/testing/stubs/index.mjs.map +1 -1
- package/dist/lib/testing/test-controller.mjs +0 -6
- package/dist/lib/testing/test-controller.mjs.map +1 -1
- package/dist/lib/testing/test-helpers.mjs +0 -6
- package/dist/lib/testing/test-helpers.mjs.map +1 -1
- package/dist/lib/testing/types.mjs +0 -6
- package/dist/lib/types/adcp.mjs +0 -6
- package/dist/lib/types/adcp.mjs.map +1 -1
- package/dist/lib/types/asset-instances.mjs +0 -6
- package/dist/lib/types/compat.mjs +0 -6
- package/dist/lib/types/compat.mjs.map +1 -1
- package/dist/lib/types/core.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs.map +1 -1
- package/dist/lib/types/error-codes.mjs +0 -6
- package/dist/lib/types/error-codes.mjs.map +1 -1
- package/dist/lib/types/error-details.aliases.mjs +0 -6
- package/dist/lib/types/error-details.aliases.mjs.map +1 -1
- package/dist/lib/types/format-asset-slots.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs.map +1 -1
- package/dist/lib/types/index.mjs +0 -6
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/types/inline-enums.aliases.mjs +0 -6
- package/dist/lib/types/inline-enums.aliases.mjs.map +1 -1
- package/dist/lib/types/inline-enums.generated.mjs +0 -6
- package/dist/lib/types/inline-enums.generated.mjs.map +1 -1
- package/dist/lib/types/manifest.generated.mjs +0 -6
- package/dist/lib/types/manifest.generated.mjs.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +0 -6
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/server-payload-aliases.mjs +0 -6
- package/dist/lib/types/server-payload.mjs +0 -6
- package/dist/lib/types/sync-rows.mjs +0 -6
- package/dist/lib/types/tools.generated.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs.map +1 -1
- package/dist/lib/types/v2-5/tools.generated.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs.map +1 -1
- package/dist/lib/types/v3-1-beta/tools.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs.map +1 -1
- package/dist/lib/upstream-recorder/constants.mjs +0 -6
- package/dist/lib/upstream-recorder/constants.mjs.map +1 -1
- package/dist/lib/upstream-recorder/index.mjs +0 -6
- package/dist/lib/upstream-recorder/index.mjs.map +1 -1
- package/dist/lib/upstream-recorder/recorder.mjs +0 -6
- package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
- package/dist/lib/upstream-recorder/types.mjs +0 -6
- package/dist/lib/upstream-recorder/types.mjs.map +1 -1
- package/dist/lib/utils/a2a-artifacts.mjs +0 -6
- package/dist/lib/utils/a2a-artifacts.mjs.map +1 -1
- package/dist/lib/utils/a2a-discovery.mjs +0 -6
- package/dist/lib/utils/a2a-discovery.mjs.map +1 -1
- package/dist/lib/utils/activation-key-builders.mjs +0 -6
- package/dist/lib/utils/activation-key-builders.mjs.map +1 -1
- package/dist/lib/utils/adcp-version-config.mjs +0 -6
- package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
- package/dist/lib/utils/asset-builders.mjs +0 -6
- package/dist/lib/utils/asset-builders.mjs.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.mjs +0 -6
- package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
- package/dist/lib/utils/buyer-retry-policy.mjs +0 -6
- package/dist/lib/utils/buyer-retry-policy.mjs.map +1 -1
- package/dist/lib/utils/capabilities.mjs +0 -6
- package/dist/lib/utils/capabilities.mjs.map +1 -1
- package/dist/lib/utils/capability-rollups.mjs +0 -6
- package/dist/lib/utils/capability-rollups.mjs.map +1 -1
- package/dist/lib/utils/creative-adapter.mjs +0 -6
- package/dist/lib/utils/creative-adapter.mjs.map +1 -1
- package/dist/lib/utils/creative-delivery.mjs +0 -6
- package/dist/lib/utils/creative-delivery.mjs.map +1 -1
- package/dist/lib/utils/deprecation.mjs +0 -6
- package/dist/lib/utils/deprecation.mjs.map +1 -1
- package/dist/lib/utils/envelope-status-compat.mjs +0 -6
- package/dist/lib/utils/envelope-status-compat.mjs.map +1 -1
- package/dist/lib/utils/error-extraction.mjs +0 -6
- package/dist/lib/utils/error-extraction.mjs.map +1 -1
- package/dist/lib/utils/extract-result.mjs +0 -6
- package/dist/lib/utils/extract-result.mjs.map +1 -1
- package/dist/lib/utils/format-asset-slot-builders.mjs +0 -6
- package/dist/lib/utils/format-asset-slot-builders.mjs.map +1 -1
- package/dist/lib/utils/format-assets.mjs +0 -6
- package/dist/lib/utils/format-assets.mjs.map +1 -1
- package/dist/lib/utils/format-render-builders.mjs +0 -6
- package/dist/lib/utils/format-render-builders.mjs.map +1 -1
- package/dist/lib/utils/format-renders.mjs +0 -6
- package/dist/lib/utils/format-renders.mjs.map +1 -1
- package/dist/lib/utils/get-products-cache-scope.mjs +0 -6
- package/dist/lib/utils/get-products-cache-scope.mjs.map +1 -1
- package/dist/lib/utils/glob.mjs +0 -6
- package/dist/lib/utils/glob.mjs.map +1 -1
- package/dist/lib/utils/global-async-local-storage.mjs +0 -6
- package/dist/lib/utils/global-async-local-storage.mjs.map +1 -1
- package/dist/lib/utils/idempotency.mjs +0 -6
- package/dist/lib/utils/idempotency.mjs.map +1 -1
- package/dist/lib/utils/index.mjs +0 -6
- package/dist/lib/utils/index.mjs.map +1 -1
- package/dist/lib/utils/jcs.mjs +0 -6
- package/dist/lib/utils/jcs.mjs.map +1 -1
- package/dist/lib/utils/json-depth.mjs +0 -6
- package/dist/lib/utils/json-depth.mjs.map +1 -1
- package/dist/lib/utils/logger.mjs +0 -6
- package/dist/lib/utils/logger.mjs.map +1 -1
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs +0 -6
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs.map +1 -1
- package/dist/lib/utils/media-buy-status.mjs +0 -6
- package/dist/lib/utils/media-buy-status.mjs.map +1 -1
- package/dist/lib/utils/pagination.mjs +0 -6
- package/dist/lib/utils/pagination.mjs.map +1 -1
- package/dist/lib/utils/preview-creative-builders.mjs +0 -6
- package/dist/lib/utils/preview-creative-builders.mjs.map +1 -1
- package/dist/lib/utils/preview-normalizer.mjs +0 -6
- package/dist/lib/utils/preview-normalizer.mjs.map +1 -1
- package/dist/lib/utils/preview-utils.mjs +0 -6
- package/dist/lib/utils/preview-utils.mjs.map +1 -1
- package/dist/lib/utils/pricing-adapter.mjs +0 -6
- package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
- package/dist/lib/utils/probe-policy.mjs +0 -6
- package/dist/lib/utils/probe-policy.mjs.map +1 -1
- package/dist/lib/utils/protocol-detection.mjs +0 -6
- package/dist/lib/utils/protocol-detection.mjs.map +1 -1
- package/dist/lib/utils/redact-secrets.mjs +0 -6
- package/dist/lib/utils/redact-secrets.mjs.map +1 -1
- package/dist/lib/utils/redis-default-prefix-warn.mjs +0 -6
- package/dist/lib/utils/redis-default-prefix-warn.mjs.map +1 -1
- package/dist/lib/utils/render-builders.mjs +0 -6
- package/dist/lib/utils/render-builders.mjs.map +1 -1
- package/dist/lib/utils/request-normalizer.mjs +0 -6
- package/dist/lib/utils/request-normalizer.mjs.map +1 -1
- package/dist/lib/utils/response-schemas.mjs +0 -6
- package/dist/lib/utils/response-schemas.mjs.map +1 -1
- package/dist/lib/utils/response-unwrapper.mjs +0 -6
- package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
- package/dist/lib/utils/retry.mjs +0 -6
- package/dist/lib/utils/retry.mjs.map +1 -1
- package/dist/lib/utils/signal-discovery-helpers.mjs +0 -6
- package/dist/lib/utils/signal-discovery-helpers.mjs.map +1 -1
- package/dist/lib/utils/signal-id-builders.mjs +0 -6
- package/dist/lib/utils/signal-id-builders.mjs.map +1 -1
- package/dist/lib/utils/sync-creatives-adapter.mjs +0 -6
- package/dist/lib/utils/sync-creatives-adapter.mjs.map +1 -1
- package/dist/lib/utils/task-state.mjs +0 -6
- package/dist/lib/utils/task-state.mjs.map +1 -1
- package/dist/lib/utils/tool-request-schemas.mjs +0 -6
- package/dist/lib/utils/tool-request-schemas.mjs.map +1 -1
- package/dist/lib/utils/typeGuards.mjs +0 -6
- package/dist/lib/utils/typeGuards.mjs.map +1 -1
- package/dist/lib/utils/union-errors.mjs +0 -6
- package/dist/lib/utils/union-errors.mjs.map +1 -1
- package/dist/lib/utils/validate-user-agent.mjs +0 -6
- package/dist/lib/utils/validate-user-agent.mjs.map +1 -1
- package/dist/lib/v2/format-schema/fetch.mjs +0 -6
- package/dist/lib/v2/format-schema/fetch.mjs.map +1 -1
- package/dist/lib/v2/format-schema/index.mjs +0 -6
- package/dist/lib/v2/format-schema/index.mjs.map +1 -1
- package/dist/lib/v2/format-schema/regex-safety.mjs +0 -6
- package/dist/lib/v2/format-schema/regex-safety.mjs.map +1 -1
- package/dist/lib/v2/format-schema/resolver.mjs +7 -8
- package/dist/lib/v2/format-schema/resolver.mjs.map +1 -1
- package/dist/lib/v2/format-schema/sandbox-refs.mjs +0 -6
- package/dist/lib/v2/format-schema/sandbox-refs.mjs.map +1 -1
- package/dist/lib/v2/projection/augment-response.mjs +0 -6
- package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
- package/dist/lib/v2/projection/builders.mjs +0 -6
- package/dist/lib/v2/projection/builders.mjs.map +1 -1
- package/dist/lib/v2/projection/cache-versions.mjs +0 -6
- package/dist/lib/v2/projection/cache-versions.mjs.map +1 -1
- package/dist/lib/v2/projection/canonical-properties.mjs +5 -6
- package/dist/lib/v2/projection/canonical-properties.mjs.map +1 -1
- package/dist/lib/v2/projection/catalog.mjs +5 -6
- package/dist/lib/v2/projection/catalog.mjs.map +1 -1
- package/dist/lib/v2/projection/constants.mjs +0 -6
- package/dist/lib/v2/projection/constants.mjs.map +1 -1
- package/dist/lib/v2/projection/index.mjs +0 -6
- package/dist/lib/v2/projection/index.mjs.map +1 -1
- package/dist/lib/v2/projection/registry.mjs +5 -6
- package/dist/lib/v2/projection/registry.mjs.map +1 -1
- package/dist/lib/v2/projection/types.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
- package/dist/lib/v2/projection/v2-to-v1.mjs +0 -6
- package/dist/lib/v2/projection/v2-to-v1.mjs.map +1 -1
- package/dist/lib/v2/projection/write-side.mjs +0 -6
- package/dist/lib/v2/projection/write-side.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/formats.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/formats.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/index.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/index.mjs.map +1 -1
- package/dist/lib/validation/client-hooks.mjs +0 -6
- package/dist/lib/validation/client-hooks.mjs.map +1 -1
- package/dist/lib/validation/hints.mjs +0 -6
- package/dist/lib/validation/hints.mjs.map +1 -1
- package/dist/lib/validation/index.mjs +0 -6
- package/dist/lib/validation/index.mjs.map +1 -1
- package/dist/lib/validation/schema-errors.mjs +0 -6
- package/dist/lib/validation/schema-errors.mjs.map +1 -1
- package/dist/lib/validation/schema-loader.mjs +5 -6
- package/dist/lib/validation/schema-loader.mjs.map +1 -1
- package/dist/lib/validation/schema-validator.mjs +0 -6
- package/dist/lib/validation/schema-validator.mjs.map +1 -1
- package/dist/lib/validation/sync-creatives.mjs +0 -6
- package/dist/lib/validation/sync-creatives.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -9
- package/dist/lib/version.mjs.map +1 -1
- package/dist/lib/webhooks/index.mjs +0 -6
- package/dist/lib/webhooks/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/index.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/sync.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/sync.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/types.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/media-buy/property-policy.ts"],"sourcesContent":["export type ProductPropertyPolicyMode = 'audit' | 'filter' | 'reject_response';\n\nexport type ProductPropertyPolicySelectorBehavior = 'allow' | 'flag' | 'reject';\n\nexport interface BuyerPropertyPolicy {\n /** Domains the buyer will accept in returned products. */\n allowedDomains?: readonly string[];\n /**\n * Resolved property-list identifiers the buyer will accept in returned\n * products. Domain identifiers are matched with AdCP property-list domain\n * semantics (`example.com` matches `www.example.com` and `m.example.com`;\n * `*.example.com` matches subdomains only).\n */\n allowedPropertyIdentifiers?: readonly ProductPropertyPolicyIdentifier[];\n /**\n * Require products to match the allowed domain/identifier set even when that\n * set is empty. Used when a request property_list resolves successfully to\n * zero identifiers; the safe interpretation is that no properties are\n * eligible.\n */\n requireAllowedPropertyMatch?: boolean;\n /** Domains the buyer will not accept in returned products. */\n excludedDomains?: readonly string[];\n /** Publisher-scoped property IDs the buyer will not accept in returned products. */\n excludedPropertyIds?: readonly string[];\n /**\n * Shorthand for strict brand-safety evaluation. Defaults unresolved tag\n * selectors and missing `publisher_properties` to rejection unless the more\n * specific behavior fields override it.\n */\n strict?: boolean;\n /**\n * How to handle selectors the SDK cannot confidently evaluate, such as\n * `selection_type: \"by_tag\"` without resolved property metadata.\n *\n * Default: `reject` when `strict` is true, otherwise `flag`.\n */\n unknownSelectorBehavior?: ProductPropertyPolicySelectorBehavior;\n /**\n * How to handle products that omit `publisher_properties`.\n *\n * Default: `reject` when `strict` is true, otherwise `allow`.\n */\n missingPublisherPropertiesBehavior?: ProductPropertyPolicySelectorBehavior;\n}\n\nexport interface ValidateProductsAgainstPropertyPolicyOptions<TProduct extends ProductPolicyProductLike> {\n products: readonly TProduct[];\n policy: BuyerPropertyPolicy;\n mode?: ProductPropertyPolicyMode;\n}\n\nexport interface ProductPolicyProductLike {\n product_id?: unknown;\n id?: unknown;\n publisher_properties?: unknown;\n property_targeting_allowed?: unknown;\n [key: string]: unknown;\n}\n\nexport interface ProductPropertyPolicyIdentifier {\n type: string;\n value: string;\n}\n\nexport type ProductPropertyPolicyDiagnosticCode =\n | 'outside_property_list'\n | 'excluded_domain'\n | 'excluded_property_id'\n | 'missing_publisher_properties'\n | 'unresolved_tag_selector'\n | 'unknown_selector'\n | 'malformed_publisher_domain';\n\nexport type ProductPropertyPolicyDiagnosticSeverity = 'rejected' | 'flagged';\n\nexport interface ProductPropertyPolicyDiagnostic {\n code: ProductPropertyPolicyDiagnosticCode;\n severity: ProductPropertyPolicyDiagnosticSeverity;\n message: string;\n product_index: number;\n product_id?: string;\n path: string;\n publisher_property_index?: number;\n selection_type?: string;\n publisher_domain?: string;\n publisher_domains?: string[];\n normalized_domain?: string;\n normalized_domains?: string[];\n matched_allowed_domain?: string;\n matched_excluded_domain?: string;\n property_ids?: string[];\n matched_property_ids?: string[];\n}\n\nexport interface ProductPropertyPolicyValidationResult<TProduct extends ProductPolicyProductLike> {\n mode: ProductPropertyPolicyMode;\n ok: boolean;\n /**\n * Mode-adjusted output. `audit` returns the original product list, `filter`\n * returns only policy-eligible products, and `reject_response` returns the\n * original list when no rejection occurs.\n */\n products: TProduct[];\n acceptedProducts: TProduct[];\n rejectedProducts: TProduct[];\n flaggedProducts: TProduct[];\n diagnostics: ProductPropertyPolicyDiagnostic[];\n}\n\nexport interface NormalizedPolicyDomain {\n input: string;\n host: string;\n comparable: string;\n}\n\nexport class ProductPropertyPolicyError<TProduct extends ProductPolicyProductLike> extends Error {\n readonly name = 'ProductPropertyPolicyError';\n\n constructor(public readonly result: ProductPropertyPolicyValidationResult<TProduct>) {\n super(\n `Product property policy rejected ${result.rejectedProducts.length} product${\n result.rejectedProducts.length === 1 ? '' : 's'\n }`\n );\n }\n}\n\ninterface CompiledPropertyPolicy {\n allowedDomains: NormalizedPolicyDomain[];\n allowedPropertyIdentifiers: ProductPropertyPolicyIdentifier[];\n requireAllowedPropertyMatch: boolean;\n excludedDomainsByComparable: Map<string, NormalizedPolicyDomain>;\n excludedPropertyIds: Set<string>;\n unknownSelectorBehavior: ProductPropertyPolicySelectorBehavior;\n missingPublisherPropertiesBehavior: ProductPropertyPolicySelectorBehavior;\n}\n\ninterface ProductPublisherPropertySelectorLike {\n selection_type?: unknown;\n publisher_domain?: unknown;\n publisher_domains?: unknown;\n property_ids?: unknown;\n}\n\ninterface PublisherDomainCandidate {\n raw: string;\n path: string;\n}\n\nexport function validateProductsAgainstPropertyPolicy<TProduct extends ProductPolicyProductLike>(\n options: ValidateProductsAgainstPropertyPolicyOptions<TProduct>\n): ProductPropertyPolicyValidationResult<TProduct> {\n const mode = options.mode ?? 'audit';\n const compiled = compilePolicy(options.policy);\n const diagnostics: ProductPropertyPolicyDiagnostic[] = [];\n\n options.products.forEach((product, productIndex) => {\n diagnostics.push(...diagnosticsForProduct(product, productIndex, compiled));\n });\n\n const rejectedIndexes = new Set(diagnostics.filter(d => d.severity === 'rejected').map(d => d.product_index));\n const flaggedIndexes = new Set(diagnostics.filter(d => d.severity === 'flagged').map(d => d.product_index));\n\n const acceptedProducts = options.products.filter((_, index) => !rejectedIndexes.has(index));\n const rejectedProducts = options.products.filter((_, index) => rejectedIndexes.has(index));\n const flaggedProducts = options.products.filter(\n (_, index) => flaggedIndexes.has(index) && !rejectedIndexes.has(index)\n );\n\n const result: ProductPropertyPolicyValidationResult<TProduct> = {\n mode,\n ok: rejectedProducts.length === 0,\n products: mode === 'filter' ? acceptedProducts : [...options.products],\n acceptedProducts,\n rejectedProducts,\n flaggedProducts,\n diagnostics,\n };\n\n if (mode === 'reject_response' && !result.ok) {\n throw new ProductPropertyPolicyError(result);\n }\n\n return result;\n}\n\nexport function normalizeDomainForPropertyPolicy(value: string): NormalizedPolicyDomain | undefined {\n const input = value;\n let host = extractHostname(value);\n if (!host) return undefined;\n host = host.toLowerCase().replace(/\\.$/, '');\n if (!isUsableHostname(host)) return undefined;\n return { input, host, comparable: comparableDomain(host) };\n}\n\nfunction compilePolicy(policy: BuyerPropertyPolicy): CompiledPropertyPolicy {\n const allowedDomains: NormalizedPolicyDomain[] = [];\n for (const domain of policy.allowedDomains ?? []) {\n const normalized = normalizeDomainForPropertyPolicy(domain);\n if (normalized) allowedDomains.push(normalized);\n }\n\n const excludedDomainsByComparable = new Map<string, NormalizedPolicyDomain>();\n for (const domain of policy.excludedDomains ?? []) {\n const normalized = normalizeDomainForPropertyPolicy(domain);\n if (normalized) excludedDomainsByComparable.set(normalized.comparable, normalized);\n }\n\n return {\n allowedDomains,\n allowedPropertyIdentifiers: [...(policy.allowedPropertyIdentifiers ?? [])],\n requireAllowedPropertyMatch:\n policy.requireAllowedPropertyMatch ??\n Boolean(policy.allowedDomains?.length || policy.allowedPropertyIdentifiers?.length),\n excludedDomainsByComparable,\n excludedPropertyIds: new Set(policy.excludedPropertyIds ?? []),\n unknownSelectorBehavior: policy.unknownSelectorBehavior ?? (policy.strict ? 'reject' : 'flag'),\n missingPublisherPropertiesBehavior:\n policy.missingPublisherPropertiesBehavior ?? (policy.strict ? 'reject' : 'allow'),\n };\n}\n\nfunction diagnosticsForProduct(\n product: ProductPolicyProductLike,\n productIndex: number,\n policy: CompiledPropertyPolicy\n): ProductPropertyPolicyDiagnostic[] {\n const publisherProperties = product.publisher_properties;\n const productId = productIdForDiagnostics(product);\n\n if (!Array.isArray(publisherProperties) || publisherProperties.length === 0) {\n return diagnosticForBehavior(policy.missingPublisherPropertiesBehavior, {\n code: 'missing_publisher_properties',\n message: 'Product is missing publisher_properties, so buyer property exclusions cannot be evaluated.',\n product_index: productIndex,\n product_id: productId,\n path: `products[${productIndex}].publisher_properties`,\n });\n }\n\n const diagnostics: ProductPropertyPolicyDiagnostic[] = [];\n let hasEligibleSubsetSelector = false;\n const requiresSubsetMatch = hasAllowedPropertyScope(policy) && product.property_targeting_allowed === true;\n publisherProperties.forEach((rawSelector, selectorIndex) => {\n diagnostics.push(\n ...diagnosticsForSelector(rawSelector, productIndex, selectorIndex, productId, policy, {\n enforceEveryDomainInAllowedScope: !requiresSubsetMatch,\n enforceExclusions: !requiresSubsetMatch,\n })\n );\n if (requiresSubsetMatch && selectorIsEligibleForSubsetTargeting(rawSelector, productIndex, selectorIndex, policy)) {\n hasEligibleSubsetSelector = true;\n }\n });\n if (requiresSubsetMatch && !hasEligibleSubsetSelector) {\n diagnostics.push({\n code: 'outside_property_list',\n severity: 'rejected',\n message: 'Product has no buyer-eligible publisher properties inside the requested property list.',\n product_index: productIndex,\n product_id: productId,\n path: `products[${productIndex}].publisher_properties`,\n });\n }\n return diagnostics;\n}\n\nfunction diagnosticsForSelector(\n rawSelector: unknown,\n productIndex: number,\n selectorIndex: number,\n productId: string | undefined,\n policy: CompiledPropertyPolicy,\n options: { enforceEveryDomainInAllowedScope: boolean; enforceExclusions: boolean }\n): ProductPropertyPolicyDiagnostic[] {\n const path = `products[${productIndex}].publisher_properties[${selectorIndex}]`;\n if (!rawSelector || typeof rawSelector !== 'object' || Array.isArray(rawSelector)) {\n return diagnosticForBehavior(policy.unknownSelectorBehavior, {\n code: 'unknown_selector',\n message: 'Publisher property selector is not an object and cannot be evaluated.',\n product_index: productIndex,\n product_id: productId,\n path,\n publisher_property_index: selectorIndex,\n });\n }\n\n const selector = rawSelector as ProductPublisherPropertySelectorLike;\n const selectionType = typeof selector.selection_type === 'string' ? selector.selection_type : undefined;\n const domainCandidates = publisherDomainCandidates(selector, path);\n const normalizedDomains = domainCandidates\n .map(candidate => ({ candidate, normalized: normalizeDomainForPropertyPolicy(candidate.raw) }))\n .filter((entry): entry is { candidate: PublisherDomainCandidate; normalized: NormalizedPolicyDomain } =>\n Boolean(entry.normalized)\n );\n const diagnostics: ProductPropertyPolicyDiagnostic[] = [];\n\n if (selector.publisher_domains !== undefined) {\n diagnostics.push({\n code: 'unknown_selector',\n severity: 'rejected',\n message:\n 'Product publisher property selector uses publisher_domains, which is not valid on product publisher_properties.',\n product_index: productIndex,\n product_id: productId,\n path,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n ...(typeof selector.publisher_domain === 'string' ? { publisher_domain: selector.publisher_domain } : {}),\n publisher_domains: stringArray(selector.publisher_domains),\n });\n }\n\n if (domainCandidates.length === 0) {\n diagnostics.push(\n ...diagnosticForBehavior(policy.unknownSelectorBehavior, {\n code: 'unknown_selector',\n message:\n 'Product publisher property selector is missing publisher_domain/publisher_domains and cannot be evaluated confidently.',\n product_index: productIndex,\n product_id: productId,\n path: `${path}.publisher_domain`,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n })\n );\n }\n\n for (const candidate of domainCandidates) {\n const normalizedDomain = normalizeDomainForPropertyPolicy(candidate.raw);\n if (normalizedDomain) continue;\n diagnostics.push(\n ...diagnosticForBehavior(policy.unknownSelectorBehavior, {\n code: 'malformed_publisher_domain',\n message: 'Publisher property selector has a malformed publisher domain and cannot be evaluated.',\n product_index: productIndex,\n product_id: productId,\n path: candidate.path,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: candidate.raw,\n })\n );\n }\n\n for (const { candidate, normalized: normalizedDomain } of normalizedDomains) {\n const matchedAllowedDomain = matchedAllowedDomainForCandidate(normalizedDomain, policy);\n if (options.enforceEveryDomainInAllowedScope && hasAllowedPropertyScope(policy) && !matchedAllowedDomain) {\n diagnostics.push({\n code: 'outside_property_list',\n severity: 'rejected',\n message: `Product includes publisher domain ${normalizedDomain.host} outside the requested property list.`,\n product_index: productIndex,\n product_id: productId,\n path: candidate.path,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: candidate.raw,\n publisher_domains: domainCandidates.map(candidate => candidate.raw),\n normalized_domain: normalizedDomain.host,\n normalized_domains: normalizedDomains.map(entry => entry.normalized.host),\n });\n }\n\n const excludedDomain = policy.excludedDomainsByComparable.get(normalizedDomain.comparable);\n if (options.enforceExclusions && excludedDomain) {\n diagnostics.push({\n code: 'excluded_domain',\n severity: 'rejected',\n message: `Product includes excluded publisher domain ${normalizedDomain.host}.`,\n product_index: productIndex,\n product_id: productId,\n path: candidate.path,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: candidate.raw,\n publisher_domains: domainCandidates.map(candidate => candidate.raw),\n normalized_domain: normalizedDomain.host,\n normalized_domains: normalizedDomains.map(entry => entry.normalized.host),\n matched_excluded_domain: excludedDomain.host,\n });\n }\n }\n\n if (selectionType === 'by_id') {\n const propertyIds = stringArray(selector.property_ids);\n const matchedPropertyIds = propertyIds.filter(id => policy.excludedPropertyIds.has(id));\n if (options.enforceExclusions && matchedPropertyIds.length > 0) {\n diagnostics.push({\n code: 'excluded_property_id',\n severity: 'rejected',\n message: `Product includes excluded publisher property ID${matchedPropertyIds.length === 1 ? '' : 's'}.`,\n product_index: productIndex,\n product_id: productId,\n path: `${path}.property_ids`,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: domainCandidates[0]?.raw,\n publisher_domains: domainCandidates.map(candidate => candidate.raw),\n normalized_domain: normalizedDomains[0]?.normalized.host,\n normalized_domains: normalizedDomains.map(entry => entry.normalized.host),\n property_ids: propertyIds,\n matched_property_ids: matchedPropertyIds,\n });\n }\n } else if (selectionType === 'by_tag') {\n diagnostics.push(\n ...diagnosticForBehavior(policy.unknownSelectorBehavior, {\n code: 'unresolved_tag_selector',\n message:\n 'Product uses selection_type by_tag; without resolved property metadata it cannot be evaluated confidently.',\n product_index: productIndex,\n product_id: productId,\n path,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: domainCandidates[0]?.raw,\n publisher_domains: domainCandidates.map(candidate => candidate.raw),\n normalized_domain: normalizedDomains[0]?.normalized.host,\n normalized_domains: normalizedDomains.map(entry => entry.normalized.host),\n })\n );\n } else if (selectionType !== 'all') {\n diagnostics.push(\n ...diagnosticForBehavior(policy.unknownSelectorBehavior, {\n code: 'unknown_selector',\n message: 'Product uses an unknown publisher_properties selection_type and cannot be evaluated.',\n product_index: productIndex,\n product_id: productId,\n path: `${path}.selection_type`,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: domainCandidates[0]?.raw,\n publisher_domains: domainCandidates.map(candidate => candidate.raw),\n normalized_domain: normalizedDomains[0]?.normalized.host,\n normalized_domains: normalizedDomains.map(entry => entry.normalized.host),\n })\n );\n }\n\n return diagnostics;\n}\n\nfunction hasAllowedPropertyScope(policy: CompiledPropertyPolicy): boolean {\n return policy.requireAllowedPropertyMatch;\n}\n\nfunction selectorIsEligibleForSubsetTargeting(\n rawSelector: unknown,\n productIndex: number,\n selectorIndex: number,\n policy: CompiledPropertyPolicy\n): boolean {\n const path = `products[${productIndex}].publisher_properties[${selectorIndex}]`;\n if (!rawSelector || typeof rawSelector !== 'object' || Array.isArray(rawSelector)) return false;\n const selector = rawSelector as ProductPublisherPropertySelectorLike;\n if (selector.publisher_domains !== undefined) return false;\n if (selector.selection_type === 'by_tag') return false;\n if (selector.selection_type !== 'all' && selector.selection_type !== 'by_id') return false;\n\n const hasEligibleDomain = publisherDomainCandidates(selector, path).some(candidate => {\n const normalized = normalizeDomainForPropertyPolicy(candidate.raw);\n if (!normalized) return false;\n if (hasAllowedPropertyScope(policy) && !matchedAllowedDomainForCandidate(normalized, policy)) return false;\n return !policy.excludedDomainsByComparable.has(normalized.comparable);\n });\n if (!hasEligibleDomain) return false;\n\n if (selector.selection_type !== 'by_id') return true;\n const propertyIds = stringArray(selector.property_ids);\n return propertyIds.length === 0 || propertyIds.some(id => !policy.excludedPropertyIds.has(id));\n}\n\nfunction matchedAllowedDomainForCandidate(\n candidate: NormalizedPolicyDomain,\n policy: CompiledPropertyPolicy\n): string | undefined {\n const explicitDomain = policy.allowedDomains.find(allowed =>\n propertyListDomainMatches(candidate.host, allowed.input)\n );\n if (explicitDomain) return explicitDomain.host;\n\n for (const identifier of policy.allowedPropertyIdentifiers) {\n if (identifier.type !== 'domain' && identifier.type !== 'subdomain') continue;\n if (propertyListDomainMatches(candidate.host, identifier.value, identifier.type)) {\n return identifier.value;\n }\n }\n return undefined;\n}\n\nfunction publisherDomainCandidates(\n selector: ProductPublisherPropertySelectorLike,\n path: string\n): PublisherDomainCandidate[] {\n const candidates: PublisherDomainCandidate[] = [];\n if (typeof selector.publisher_domain === 'string') {\n candidates.push({ raw: selector.publisher_domain, path: `${path}.publisher_domain` });\n }\n return candidates;\n}\n\nfunction diagnosticForBehavior(\n behavior: ProductPropertyPolicySelectorBehavior,\n diagnostic: Omit<ProductPropertyPolicyDiagnostic, 'severity'>\n): ProductPropertyPolicyDiagnostic[] {\n if (behavior === 'allow') return [];\n return [{ ...diagnostic, severity: behavior === 'reject' ? 'rejected' : 'flagged' }];\n}\n\nfunction productIdForDiagnostics(product: ProductPolicyProductLike): string | undefined {\n if (typeof product.product_id === 'string') return product.product_id;\n if (typeof product.id === 'string') return product.id;\n return undefined;\n}\n\nfunction stringArray(value: unknown): string[] {\n return Array.isArray(value) ? value.filter((v): v is string => typeof v === 'string') : [];\n}\n\nfunction extractHostname(value: string): string | undefined {\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n\n try {\n const url = new URL(hasScheme(trimmed) || trimmed.startsWith('//') ? trimmed : `https://${trimmed}`);\n return url.hostname;\n } catch {\n let host = trimmed.replace(/^[a-z][a-z0-9+.-]*:\\/\\//i, '').replace(/^\\/\\//, '');\n const firstPathChar = host.search(/[/?#]/);\n if (firstPathChar >= 0) host = host.slice(0, firstPathChar);\n const at = host.lastIndexOf('@');\n if (at >= 0) host = host.slice(at + 1);\n if (host.startsWith('[')) {\n const close = host.indexOf(']');\n if (close >= 0) host = host.slice(1, close);\n } else {\n host = host.replace(/:\\d+$/, '');\n }\n return host;\n }\n}\n\nfunction hasScheme(value: string): boolean {\n return /^[a-z][a-z0-9+.-]*:\\/\\//i.test(value);\n}\n\nfunction comparableDomain(host: string): string {\n return host.startsWith('www.') ? host.slice(4) : host;\n}\n\nfunction propertyListDomainMatches(candidateValue: string, patternValue: string, type: string = 'domain'): boolean {\n const candidate = normalizeDomainForPropertyPolicy(candidateValue)?.host;\n const pattern = normalizeDomainForPropertyPolicy(patternValue)?.host;\n if (!candidate || !pattern) return false;\n if (candidate === pattern) return true;\n if (type === 'subdomain') return false;\n if (pattern.startsWith('*.')) {\n const base = pattern.slice(2);\n return candidate.endsWith(`.${base}`) && candidate !== base;\n }\n return candidate === `www.${pattern}` || candidate === `m.${pattern}`;\n}\n\nfunction isUsableHostname(host: string): boolean {\n if (host.length === 0 || host.length > 253) return false;\n // eslint-disable-next-line no-control-regex\n return !/[\\x00-\\x1f\\x7f\\s/\\\\]/.test(host);\n}\n"],"mappings":"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","names":["candidate"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/media-buy/property-policy.ts"],"sourcesContent":["export type ProductPropertyPolicyMode = 'audit' | 'filter' | 'reject_response';\n\nexport type ProductPropertyPolicySelectorBehavior = 'allow' | 'flag' | 'reject';\n\nexport interface BuyerPropertyPolicy {\n /** Domains the buyer will accept in returned products. */\n allowedDomains?: readonly string[];\n /**\n * Resolved property-list identifiers the buyer will accept in returned\n * products. Domain identifiers are matched with AdCP property-list domain\n * semantics (`example.com` matches `www.example.com` and `m.example.com`;\n * `*.example.com` matches subdomains only).\n */\n allowedPropertyIdentifiers?: readonly ProductPropertyPolicyIdentifier[];\n /**\n * Require products to match the allowed domain/identifier set even when that\n * set is empty. Used when a request property_list resolves successfully to\n * zero identifiers; the safe interpretation is that no properties are\n * eligible.\n */\n requireAllowedPropertyMatch?: boolean;\n /** Domains the buyer will not accept in returned products. */\n excludedDomains?: readonly string[];\n /** Publisher-scoped property IDs the buyer will not accept in returned products. */\n excludedPropertyIds?: readonly string[];\n /**\n * Shorthand for strict brand-safety evaluation. Defaults unresolved tag\n * selectors and missing `publisher_properties` to rejection unless the more\n * specific behavior fields override it.\n */\n strict?: boolean;\n /**\n * How to handle selectors the SDK cannot confidently evaluate, such as\n * `selection_type: \"by_tag\"` without resolved property metadata.\n *\n * Default: `reject` when `strict` is true, otherwise `flag`.\n */\n unknownSelectorBehavior?: ProductPropertyPolicySelectorBehavior;\n /**\n * How to handle products that omit `publisher_properties`.\n *\n * Default: `reject` when `strict` is true, otherwise `allow`.\n */\n missingPublisherPropertiesBehavior?: ProductPropertyPolicySelectorBehavior;\n}\n\nexport interface ValidateProductsAgainstPropertyPolicyOptions<TProduct extends ProductPolicyProductLike> {\n products: readonly TProduct[];\n policy: BuyerPropertyPolicy;\n mode?: ProductPropertyPolicyMode;\n}\n\nexport interface ProductPolicyProductLike {\n product_id?: unknown;\n id?: unknown;\n publisher_properties?: unknown;\n property_targeting_allowed?: unknown;\n [key: string]: unknown;\n}\n\nexport interface ProductPropertyPolicyIdentifier {\n type: string;\n value: string;\n}\n\nexport type ProductPropertyPolicyDiagnosticCode =\n | 'outside_property_list'\n | 'excluded_domain'\n | 'excluded_property_id'\n | 'missing_publisher_properties'\n | 'unresolved_tag_selector'\n | 'unknown_selector'\n | 'malformed_publisher_domain';\n\nexport type ProductPropertyPolicyDiagnosticSeverity = 'rejected' | 'flagged';\n\nexport interface ProductPropertyPolicyDiagnostic {\n code: ProductPropertyPolicyDiagnosticCode;\n severity: ProductPropertyPolicyDiagnosticSeverity;\n message: string;\n product_index: number;\n product_id?: string;\n path: string;\n publisher_property_index?: number;\n selection_type?: string;\n publisher_domain?: string;\n publisher_domains?: string[];\n normalized_domain?: string;\n normalized_domains?: string[];\n matched_allowed_domain?: string;\n matched_excluded_domain?: string;\n property_ids?: string[];\n matched_property_ids?: string[];\n}\n\nexport interface ProductPropertyPolicyValidationResult<TProduct extends ProductPolicyProductLike> {\n mode: ProductPropertyPolicyMode;\n ok: boolean;\n /**\n * Mode-adjusted output. `audit` returns the original product list, `filter`\n * returns only policy-eligible products, and `reject_response` returns the\n * original list when no rejection occurs.\n */\n products: TProduct[];\n acceptedProducts: TProduct[];\n rejectedProducts: TProduct[];\n flaggedProducts: TProduct[];\n diagnostics: ProductPropertyPolicyDiagnostic[];\n}\n\nexport interface NormalizedPolicyDomain {\n input: string;\n host: string;\n comparable: string;\n}\n\nexport class ProductPropertyPolicyError<TProduct extends ProductPolicyProductLike> extends Error {\n readonly name = 'ProductPropertyPolicyError';\n\n constructor(public readonly result: ProductPropertyPolicyValidationResult<TProduct>) {\n super(\n `Product property policy rejected ${result.rejectedProducts.length} product${\n result.rejectedProducts.length === 1 ? '' : 's'\n }`\n );\n }\n}\n\ninterface CompiledPropertyPolicy {\n allowedDomains: NormalizedPolicyDomain[];\n allowedPropertyIdentifiers: ProductPropertyPolicyIdentifier[];\n requireAllowedPropertyMatch: boolean;\n excludedDomainsByComparable: Map<string, NormalizedPolicyDomain>;\n excludedPropertyIds: Set<string>;\n unknownSelectorBehavior: ProductPropertyPolicySelectorBehavior;\n missingPublisherPropertiesBehavior: ProductPropertyPolicySelectorBehavior;\n}\n\ninterface ProductPublisherPropertySelectorLike {\n selection_type?: unknown;\n publisher_domain?: unknown;\n publisher_domains?: unknown;\n property_ids?: unknown;\n}\n\ninterface PublisherDomainCandidate {\n raw: string;\n path: string;\n}\n\nexport function validateProductsAgainstPropertyPolicy<TProduct extends ProductPolicyProductLike>(\n options: ValidateProductsAgainstPropertyPolicyOptions<TProduct>\n): ProductPropertyPolicyValidationResult<TProduct> {\n const mode = options.mode ?? 'audit';\n const compiled = compilePolicy(options.policy);\n const diagnostics: ProductPropertyPolicyDiagnostic[] = [];\n\n options.products.forEach((product, productIndex) => {\n diagnostics.push(...diagnosticsForProduct(product, productIndex, compiled));\n });\n\n const rejectedIndexes = new Set(diagnostics.filter(d => d.severity === 'rejected').map(d => d.product_index));\n const flaggedIndexes = new Set(diagnostics.filter(d => d.severity === 'flagged').map(d => d.product_index));\n\n const acceptedProducts = options.products.filter((_, index) => !rejectedIndexes.has(index));\n const rejectedProducts = options.products.filter((_, index) => rejectedIndexes.has(index));\n const flaggedProducts = options.products.filter(\n (_, index) => flaggedIndexes.has(index) && !rejectedIndexes.has(index)\n );\n\n const result: ProductPropertyPolicyValidationResult<TProduct> = {\n mode,\n ok: rejectedProducts.length === 0,\n products: mode === 'filter' ? acceptedProducts : [...options.products],\n acceptedProducts,\n rejectedProducts,\n flaggedProducts,\n diagnostics,\n };\n\n if (mode === 'reject_response' && !result.ok) {\n throw new ProductPropertyPolicyError(result);\n }\n\n return result;\n}\n\nexport function normalizeDomainForPropertyPolicy(value: string): NormalizedPolicyDomain | undefined {\n const input = value;\n let host = extractHostname(value);\n if (!host) return undefined;\n host = host.toLowerCase().replace(/\\.$/, '');\n if (!isUsableHostname(host)) return undefined;\n return { input, host, comparable: comparableDomain(host) };\n}\n\nfunction compilePolicy(policy: BuyerPropertyPolicy): CompiledPropertyPolicy {\n const allowedDomains: NormalizedPolicyDomain[] = [];\n for (const domain of policy.allowedDomains ?? []) {\n const normalized = normalizeDomainForPropertyPolicy(domain);\n if (normalized) allowedDomains.push(normalized);\n }\n\n const excludedDomainsByComparable = new Map<string, NormalizedPolicyDomain>();\n for (const domain of policy.excludedDomains ?? []) {\n const normalized = normalizeDomainForPropertyPolicy(domain);\n if (normalized) excludedDomainsByComparable.set(normalized.comparable, normalized);\n }\n\n return {\n allowedDomains,\n allowedPropertyIdentifiers: [...(policy.allowedPropertyIdentifiers ?? [])],\n requireAllowedPropertyMatch:\n policy.requireAllowedPropertyMatch ??\n Boolean(policy.allowedDomains?.length || policy.allowedPropertyIdentifiers?.length),\n excludedDomainsByComparable,\n excludedPropertyIds: new Set(policy.excludedPropertyIds ?? []),\n unknownSelectorBehavior: policy.unknownSelectorBehavior ?? (policy.strict ? 'reject' : 'flag'),\n missingPublisherPropertiesBehavior:\n policy.missingPublisherPropertiesBehavior ?? (policy.strict ? 'reject' : 'allow'),\n };\n}\n\nfunction diagnosticsForProduct(\n product: ProductPolicyProductLike,\n productIndex: number,\n policy: CompiledPropertyPolicy\n): ProductPropertyPolicyDiagnostic[] {\n const publisherProperties = product.publisher_properties;\n const productId = productIdForDiagnostics(product);\n\n if (!Array.isArray(publisherProperties) || publisherProperties.length === 0) {\n return diagnosticForBehavior(policy.missingPublisherPropertiesBehavior, {\n code: 'missing_publisher_properties',\n message: 'Product is missing publisher_properties, so buyer property exclusions cannot be evaluated.',\n product_index: productIndex,\n product_id: productId,\n path: `products[${productIndex}].publisher_properties`,\n });\n }\n\n const diagnostics: ProductPropertyPolicyDiagnostic[] = [];\n let hasEligibleSubsetSelector = false;\n const requiresSubsetMatch = hasAllowedPropertyScope(policy) && product.property_targeting_allowed === true;\n publisherProperties.forEach((rawSelector, selectorIndex) => {\n diagnostics.push(\n ...diagnosticsForSelector(rawSelector, productIndex, selectorIndex, productId, policy, {\n enforceEveryDomainInAllowedScope: !requiresSubsetMatch,\n enforceExclusions: !requiresSubsetMatch,\n })\n );\n if (requiresSubsetMatch && selectorIsEligibleForSubsetTargeting(rawSelector, productIndex, selectorIndex, policy)) {\n hasEligibleSubsetSelector = true;\n }\n });\n if (requiresSubsetMatch && !hasEligibleSubsetSelector) {\n diagnostics.push({\n code: 'outside_property_list',\n severity: 'rejected',\n message: 'Product has no buyer-eligible publisher properties inside the requested property list.',\n product_index: productIndex,\n product_id: productId,\n path: `products[${productIndex}].publisher_properties`,\n });\n }\n return diagnostics;\n}\n\nfunction diagnosticsForSelector(\n rawSelector: unknown,\n productIndex: number,\n selectorIndex: number,\n productId: string | undefined,\n policy: CompiledPropertyPolicy,\n options: { enforceEveryDomainInAllowedScope: boolean; enforceExclusions: boolean }\n): ProductPropertyPolicyDiagnostic[] {\n const path = `products[${productIndex}].publisher_properties[${selectorIndex}]`;\n if (!rawSelector || typeof rawSelector !== 'object' || Array.isArray(rawSelector)) {\n return diagnosticForBehavior(policy.unknownSelectorBehavior, {\n code: 'unknown_selector',\n message: 'Publisher property selector is not an object and cannot be evaluated.',\n product_index: productIndex,\n product_id: productId,\n path,\n publisher_property_index: selectorIndex,\n });\n }\n\n const selector = rawSelector as ProductPublisherPropertySelectorLike;\n const selectionType = typeof selector.selection_type === 'string' ? selector.selection_type : undefined;\n const domainCandidates = publisherDomainCandidates(selector, path);\n const normalizedDomains = domainCandidates\n .map(candidate => ({ candidate, normalized: normalizeDomainForPropertyPolicy(candidate.raw) }))\n .filter((entry): entry is { candidate: PublisherDomainCandidate; normalized: NormalizedPolicyDomain } =>\n Boolean(entry.normalized)\n );\n const diagnostics: ProductPropertyPolicyDiagnostic[] = [];\n\n if (selector.publisher_domains !== undefined) {\n diagnostics.push({\n code: 'unknown_selector',\n severity: 'rejected',\n message:\n 'Product publisher property selector uses publisher_domains, which is not valid on product publisher_properties.',\n product_index: productIndex,\n product_id: productId,\n path,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n ...(typeof selector.publisher_domain === 'string' ? { publisher_domain: selector.publisher_domain } : {}),\n publisher_domains: stringArray(selector.publisher_domains),\n });\n }\n\n if (domainCandidates.length === 0) {\n diagnostics.push(\n ...diagnosticForBehavior(policy.unknownSelectorBehavior, {\n code: 'unknown_selector',\n message:\n 'Product publisher property selector is missing publisher_domain/publisher_domains and cannot be evaluated confidently.',\n product_index: productIndex,\n product_id: productId,\n path: `${path}.publisher_domain`,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n })\n );\n }\n\n for (const candidate of domainCandidates) {\n const normalizedDomain = normalizeDomainForPropertyPolicy(candidate.raw);\n if (normalizedDomain) continue;\n diagnostics.push(\n ...diagnosticForBehavior(policy.unknownSelectorBehavior, {\n code: 'malformed_publisher_domain',\n message: 'Publisher property selector has a malformed publisher domain and cannot be evaluated.',\n product_index: productIndex,\n product_id: productId,\n path: candidate.path,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: candidate.raw,\n })\n );\n }\n\n for (const { candidate, normalized: normalizedDomain } of normalizedDomains) {\n const matchedAllowedDomain = matchedAllowedDomainForCandidate(normalizedDomain, policy);\n if (options.enforceEveryDomainInAllowedScope && hasAllowedPropertyScope(policy) && !matchedAllowedDomain) {\n diagnostics.push({\n code: 'outside_property_list',\n severity: 'rejected',\n message: `Product includes publisher domain ${normalizedDomain.host} outside the requested property list.`,\n product_index: productIndex,\n product_id: productId,\n path: candidate.path,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: candidate.raw,\n publisher_domains: domainCandidates.map(candidate => candidate.raw),\n normalized_domain: normalizedDomain.host,\n normalized_domains: normalizedDomains.map(entry => entry.normalized.host),\n });\n }\n\n const excludedDomain = policy.excludedDomainsByComparable.get(normalizedDomain.comparable);\n if (options.enforceExclusions && excludedDomain) {\n diagnostics.push({\n code: 'excluded_domain',\n severity: 'rejected',\n message: `Product includes excluded publisher domain ${normalizedDomain.host}.`,\n product_index: productIndex,\n product_id: productId,\n path: candidate.path,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: candidate.raw,\n publisher_domains: domainCandidates.map(candidate => candidate.raw),\n normalized_domain: normalizedDomain.host,\n normalized_domains: normalizedDomains.map(entry => entry.normalized.host),\n matched_excluded_domain: excludedDomain.host,\n });\n }\n }\n\n if (selectionType === 'by_id') {\n const propertyIds = stringArray(selector.property_ids);\n const matchedPropertyIds = propertyIds.filter(id => policy.excludedPropertyIds.has(id));\n if (options.enforceExclusions && matchedPropertyIds.length > 0) {\n diagnostics.push({\n code: 'excluded_property_id',\n severity: 'rejected',\n message: `Product includes excluded publisher property ID${matchedPropertyIds.length === 1 ? '' : 's'}.`,\n product_index: productIndex,\n product_id: productId,\n path: `${path}.property_ids`,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: domainCandidates[0]?.raw,\n publisher_domains: domainCandidates.map(candidate => candidate.raw),\n normalized_domain: normalizedDomains[0]?.normalized.host,\n normalized_domains: normalizedDomains.map(entry => entry.normalized.host),\n property_ids: propertyIds,\n matched_property_ids: matchedPropertyIds,\n });\n }\n } else if (selectionType === 'by_tag') {\n diagnostics.push(\n ...diagnosticForBehavior(policy.unknownSelectorBehavior, {\n code: 'unresolved_tag_selector',\n message:\n 'Product uses selection_type by_tag; without resolved property metadata it cannot be evaluated confidently.',\n product_index: productIndex,\n product_id: productId,\n path,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: domainCandidates[0]?.raw,\n publisher_domains: domainCandidates.map(candidate => candidate.raw),\n normalized_domain: normalizedDomains[0]?.normalized.host,\n normalized_domains: normalizedDomains.map(entry => entry.normalized.host),\n })\n );\n } else if (selectionType !== 'all') {\n diagnostics.push(\n ...diagnosticForBehavior(policy.unknownSelectorBehavior, {\n code: 'unknown_selector',\n message: 'Product uses an unknown publisher_properties selection_type and cannot be evaluated.',\n product_index: productIndex,\n product_id: productId,\n path: `${path}.selection_type`,\n publisher_property_index: selectorIndex,\n selection_type: selectionType,\n publisher_domain: domainCandidates[0]?.raw,\n publisher_domains: domainCandidates.map(candidate => candidate.raw),\n normalized_domain: normalizedDomains[0]?.normalized.host,\n normalized_domains: normalizedDomains.map(entry => entry.normalized.host),\n })\n );\n }\n\n return diagnostics;\n}\n\nfunction hasAllowedPropertyScope(policy: CompiledPropertyPolicy): boolean {\n return policy.requireAllowedPropertyMatch;\n}\n\nfunction selectorIsEligibleForSubsetTargeting(\n rawSelector: unknown,\n productIndex: number,\n selectorIndex: number,\n policy: CompiledPropertyPolicy\n): boolean {\n const path = `products[${productIndex}].publisher_properties[${selectorIndex}]`;\n if (!rawSelector || typeof rawSelector !== 'object' || Array.isArray(rawSelector)) return false;\n const selector = rawSelector as ProductPublisherPropertySelectorLike;\n if (selector.publisher_domains !== undefined) return false;\n if (selector.selection_type === 'by_tag') return false;\n if (selector.selection_type !== 'all' && selector.selection_type !== 'by_id') return false;\n\n const hasEligibleDomain = publisherDomainCandidates(selector, path).some(candidate => {\n const normalized = normalizeDomainForPropertyPolicy(candidate.raw);\n if (!normalized) return false;\n if (hasAllowedPropertyScope(policy) && !matchedAllowedDomainForCandidate(normalized, policy)) return false;\n return !policy.excludedDomainsByComparable.has(normalized.comparable);\n });\n if (!hasEligibleDomain) return false;\n\n if (selector.selection_type !== 'by_id') return true;\n const propertyIds = stringArray(selector.property_ids);\n return propertyIds.length === 0 || propertyIds.some(id => !policy.excludedPropertyIds.has(id));\n}\n\nfunction matchedAllowedDomainForCandidate(\n candidate: NormalizedPolicyDomain,\n policy: CompiledPropertyPolicy\n): string | undefined {\n const explicitDomain = policy.allowedDomains.find(allowed =>\n propertyListDomainMatches(candidate.host, allowed.input)\n );\n if (explicitDomain) return explicitDomain.host;\n\n for (const identifier of policy.allowedPropertyIdentifiers) {\n if (identifier.type !== 'domain' && identifier.type !== 'subdomain') continue;\n if (propertyListDomainMatches(candidate.host, identifier.value, identifier.type)) {\n return identifier.value;\n }\n }\n return undefined;\n}\n\nfunction publisherDomainCandidates(\n selector: ProductPublisherPropertySelectorLike,\n path: string\n): PublisherDomainCandidate[] {\n const candidates: PublisherDomainCandidate[] = [];\n if (typeof selector.publisher_domain === 'string') {\n candidates.push({ raw: selector.publisher_domain, path: `${path}.publisher_domain` });\n }\n return candidates;\n}\n\nfunction diagnosticForBehavior(\n behavior: ProductPropertyPolicySelectorBehavior,\n diagnostic: Omit<ProductPropertyPolicyDiagnostic, 'severity'>\n): ProductPropertyPolicyDiagnostic[] {\n if (behavior === 'allow') return [];\n return [{ ...diagnostic, severity: behavior === 'reject' ? 'rejected' : 'flagged' }];\n}\n\nfunction productIdForDiagnostics(product: ProductPolicyProductLike): string | undefined {\n if (typeof product.product_id === 'string') return product.product_id;\n if (typeof product.id === 'string') return product.id;\n return undefined;\n}\n\nfunction stringArray(value: unknown): string[] {\n return Array.isArray(value) ? value.filter((v): v is string => typeof v === 'string') : [];\n}\n\nfunction extractHostname(value: string): string | undefined {\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n\n try {\n const url = new URL(hasScheme(trimmed) || trimmed.startsWith('//') ? trimmed : `https://${trimmed}`);\n return url.hostname;\n } catch {\n let host = trimmed.replace(/^[a-z][a-z0-9+.-]*:\\/\\//i, '').replace(/^\\/\\//, '');\n const firstPathChar = host.search(/[/?#]/);\n if (firstPathChar >= 0) host = host.slice(0, firstPathChar);\n const at = host.lastIndexOf('@');\n if (at >= 0) host = host.slice(at + 1);\n if (host.startsWith('[')) {\n const close = host.indexOf(']');\n if (close >= 0) host = host.slice(1, close);\n } else {\n host = host.replace(/:\\d+$/, '');\n }\n return host;\n }\n}\n\nfunction hasScheme(value: string): boolean {\n return /^[a-z][a-z0-9+.-]*:\\/\\//i.test(value);\n}\n\nfunction comparableDomain(host: string): string {\n return host.startsWith('www.') ? host.slice(4) : host;\n}\n\nfunction propertyListDomainMatches(candidateValue: string, patternValue: string, type: string = 'domain'): boolean {\n const candidate = normalizeDomainForPropertyPolicy(candidateValue)?.host;\n const pattern = normalizeDomainForPropertyPolicy(patternValue)?.host;\n if (!candidate || !pattern) return false;\n if (candidate === pattern) return true;\n if (type === 'subdomain') return false;\n if (pattern.startsWith('*.')) {\n const base = pattern.slice(2);\n return candidate.endsWith(`.${base}`) && candidate !== base;\n }\n return candidate === `www.${pattern}` || candidate === `m.${pattern}`;\n}\n\nfunction isUsableHostname(host: string): boolean {\n if (host.length === 0 || host.length > 253) return false;\n // eslint-disable-next-line no-control-regex\n return !/[\\x00-\\x1f\\x7f\\s/\\\\]/.test(host);\n}\n"],"mappings":"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","names":["candidate"]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
const LEGACY_COARSE_ACTIONS = [
|
|
8
2
|
"update_budget",
|
|
9
3
|
"update_dates",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/media-buy/types.ts"],"sourcesContent":["// Buyer-side type surface for the available_actions / ACTION_NOT_ALLOWED flow.\n// Wire-shape types come from the generated AdCP schema; the helper-local\n// types in this file are convenience subsets that the preflight resolver\n// reads against (kept narrow so a schema bump that adds optional fields\n// to MediaBuy / UpdateMediaBuyRequest doesn't churn the resolver\n// signature).\n\nexport type {\n ActionNotAllowedDetails,\n ActionNotAllowedReason,\n MediaBuyActionMode,\n MediaBuyAvailableAction,\n MediaBuyValidAction,\n SLAWindow,\n} from '../types/core.generated';\n\nimport type { MediaBuyAvailableAction, MediaBuyValidAction } from '../types/core.generated';\nimport type { SLAWindow } from '../types/core.generated';\n\n/**\n * @deprecated Use `SLAWindow`. Kept as an import-compatibility alias for the\n * pre-codegen draft export name; the shape is the generated wire contract.\n */\nexport type SlaWindow = SLAWindow;\n\n/**\n * Coarse-vocabulary actions retained for backwards compatibility with 3.x\n * sellers that haven't migrated to the fine-grained set. Each rolls up to\n * one or more fine-grained values per `enumMetadata[<value>].rollup`.\n * Removed from the spec in 4.0.\n */\nexport const LEGACY_COARSE_ACTIONS = [\n 'update_budget',\n 'update_dates',\n 'update_packages',\n 'sync_creatives',\n] as const satisfies readonly MediaBuyValidAction[];\n\nexport type LegacyCoarseAction = (typeof LEGACY_COARSE_ACTIONS)[number];\n\n/**\n * Minimum surface a media buy needs to expose for the preflight helpers to\n * operate. Picks the fields the helpers actually read so callers can pass\n * either a `MediaBuy`, a `CreateMediaBuySuccess`, an `UpdateMediaBuySuccess`,\n * or a `get_media_buys` entry. Optional fields match the schema; required\n * fields are required by the helpers themselves.\n */\nexport interface MediaBuyActionContext {\n media_buy_id?: string;\n status?: string;\n start_time?: string;\n end_time?: string;\n packages?: ReadonlyArray<{\n package_id?: string;\n budget?: number;\n start_time?: string;\n end_time?: string;\n }>;\n available_actions?: MediaBuyAvailableAction[];\n valid_actions?: MediaBuyValidAction[];\n}\n\n/**\n * Subset of `UpdateMediaBuyRequest` the resolver introspects. Reusing a\n * minimal interface keeps the preflight independent of the generated\n * request type so a schema bump that adds optional fields doesn't churn the\n * resolver signature.\n */\nexport interface UpdateMediaBuyRequestLike {\n paused?: boolean;\n canceled?: true;\n cancellation_reason?: string;\n start_time?: { datetime?: string } | string;\n end_time?: string;\n new_packages?: ReadonlyArray<unknown>;\n packages?: ReadonlyArray<{\n package_id: string;\n budget?: number;\n pacing?: unknown;\n start_time?: string;\n end_time?: string;\n paused?: boolean;\n canceled?: true;\n targeting_overlay?: { frequency_cap?: unknown; [k: string]: unknown };\n keyword_targets_add?: unknown;\n keyword_targets_remove?: unknown;\n negative_keywords_add?: unknown;\n negative_keywords_remove?: unknown;\n creative_assignments?: unknown;\n creatives?: unknown;\n }>;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/media-buy/types.ts"],"sourcesContent":["// Buyer-side type surface for the available_actions / ACTION_NOT_ALLOWED flow.\n// Wire-shape types come from the generated AdCP schema; the helper-local\n// types in this file are convenience subsets that the preflight resolver\n// reads against (kept narrow so a schema bump that adds optional fields\n// to MediaBuy / UpdateMediaBuyRequest doesn't churn the resolver\n// signature).\n\nexport type {\n ActionNotAllowedDetails,\n ActionNotAllowedReason,\n MediaBuyActionMode,\n MediaBuyAvailableAction,\n MediaBuyValidAction,\n SLAWindow,\n} from '../types/core.generated';\n\nimport type { MediaBuyAvailableAction, MediaBuyValidAction } from '../types/core.generated';\nimport type { SLAWindow } from '../types/core.generated';\n\n/**\n * @deprecated Use `SLAWindow`. Kept as an import-compatibility alias for the\n * pre-codegen draft export name; the shape is the generated wire contract.\n */\nexport type SlaWindow = SLAWindow;\n\n/**\n * Coarse-vocabulary actions retained for backwards compatibility with 3.x\n * sellers that haven't migrated to the fine-grained set. Each rolls up to\n * one or more fine-grained values per `enumMetadata[<value>].rollup`.\n * Removed from the spec in 4.0.\n */\nexport const LEGACY_COARSE_ACTIONS = [\n 'update_budget',\n 'update_dates',\n 'update_packages',\n 'sync_creatives',\n] as const satisfies readonly MediaBuyValidAction[];\n\nexport type LegacyCoarseAction = (typeof LEGACY_COARSE_ACTIONS)[number];\n\n/**\n * Minimum surface a media buy needs to expose for the preflight helpers to\n * operate. Picks the fields the helpers actually read so callers can pass\n * either a `MediaBuy`, a `CreateMediaBuySuccess`, an `UpdateMediaBuySuccess`,\n * or a `get_media_buys` entry. Optional fields match the schema; required\n * fields are required by the helpers themselves.\n */\nexport interface MediaBuyActionContext {\n media_buy_id?: string;\n status?: string;\n start_time?: string;\n end_time?: string;\n packages?: ReadonlyArray<{\n package_id?: string;\n budget?: number;\n start_time?: string;\n end_time?: string;\n }>;\n available_actions?: MediaBuyAvailableAction[];\n valid_actions?: MediaBuyValidAction[];\n}\n\n/**\n * Subset of `UpdateMediaBuyRequest` the resolver introspects. Reusing a\n * minimal interface keeps the preflight independent of the generated\n * request type so a schema bump that adds optional fields doesn't churn the\n * resolver signature.\n */\nexport interface UpdateMediaBuyRequestLike {\n paused?: boolean;\n canceled?: true;\n cancellation_reason?: string;\n start_time?: { datetime?: string } | string;\n end_time?: string;\n new_packages?: ReadonlyArray<unknown>;\n packages?: ReadonlyArray<{\n package_id: string;\n budget?: number;\n pacing?: unknown;\n start_time?: string;\n end_time?: string;\n paused?: boolean;\n canceled?: true;\n targeting_overlay?: { frequency_cap?: unknown; [k: string]: unknown };\n keyword_targets_add?: unknown;\n keyword_targets_remove?: unknown;\n negative_keywords_add?: unknown;\n negative_keywords_remove?: unknown;\n creative_assignments?: unknown;\n creatives?: unknown;\n }>;\n}\n"],"mappings":"AA+BO,MAAM,wBAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
const UPDATE_FIELDS_BY_ACTION = {
|
|
8
2
|
"pause": {
|
|
9
3
|
update_fields: ["paused"],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/media-buy/update-fields.generated.ts"],"sourcesContent":["// Generated by scripts/generate-media-buy-update-fields.ts.\n// Source: schemas/cache/<adcp_version>/enums/media-buy-valid-action.json (enumMetadata).\n// Do not hand-edit - regenerate after a schema bump.\n\nimport type { MediaBuyValidAction } from './types';\n\nexport interface UpdateFieldEntry {\n /** Dotted paths into the update_media_buy request body this action covers. */\n readonly update_fields: readonly string[];\n /** Fine-grained values this action rolls up to (legacy coarse actions only). */\n readonly rollup: readonly MediaBuyValidAction[] | null;\n /** True for `x-deprecated-enum-values` (legacy coarse vocabulary). */\n readonly deprecated: boolean;\n}\n\nexport const UPDATE_FIELDS_BY_ACTION: Readonly<\n Record<MediaBuyValidAction, UpdateFieldEntry>\n> = {\n \"pause\": {\n update_fields: [\"paused\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"resume\": {\n update_fields: [\"paused\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"cancel\": {\n update_fields: [\"canceled\", \"cancellation_reason\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"extend_flight\": {\n update_fields: [\"end_time\", \"packages[].end_time\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"shorten_flight\": {\n update_fields: [\"end_time\", \"packages[].end_time\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_flight_dates\": {\n update_fields: [\"start_time\", \"end_time\", \"packages[].start_time\", \"packages[].end_time\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"increase_budget\": {\n update_fields: [\"packages[].budget\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"decrease_budget\": {\n update_fields: [\"packages[].budget\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"reallocate_budget\": {\n update_fields: [\"packages[].budget\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_targeting\": {\n update_fields: [\"packages[].targeting_overlay\", \"packages[].keyword_targets_add\", \"packages[].keyword_targets_remove\", \"packages[].negative_keywords_add\", \"packages[].negative_keywords_remove\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_pacing\": {\n update_fields: [\"packages[].pacing\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_frequency_caps\": {\n update_fields: [\"packages[].targeting_overlay.frequency_cap\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"replace_creative\": {\n update_fields: [\"packages[].creatives\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_creative_assignments\": {\n update_fields: [\"packages[].creative_assignments\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"remove_creative\": {\n update_fields: [\"packages[].creatives\", \"packages[].creative_assignments\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"add_packages\": {\n update_fields: [\"new_packages\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"remove_packages\": {\n update_fields: [\"packages[].canceled\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_budget\": {\n update_fields: [\"packages[].budget\"] as const,\n rollup: [\"increase_budget\", \"decrease_budget\", \"reallocate_budget\"] as const,\n deprecated: true,\n },\n \"update_dates\": {\n update_fields: [\"start_time\", \"end_time\", \"packages[].start_time\", \"packages[].end_time\"] as const,\n rollup: [\"extend_flight\", \"shorten_flight\", \"update_flight_dates\"] as const,\n deprecated: true,\n },\n \"update_packages\": {\n update_fields: [\"packages[]\"] as const,\n rollup: [\"update_targeting\", \"update_pacing\", \"update_frequency_caps\", \"reallocate_budget\", \"remove_packages\"] as const,\n deprecated: true,\n },\n \"sync_creatives\": {\n update_fields: [\"packages[].creatives\", \"packages[].creative_assignments\"] as const,\n rollup: [\"replace_creative\", \"update_creative_assignments\", \"remove_creative\"] as const,\n deprecated: true,\n },\n} as const;\n\nexport const ACTIONS_BY_FIELD: Readonly<\n Record<string, readonly MediaBuyValidAction[]>\n> = {\n \"canceled\": [\"cancel\"] as const,\n \"cancellation_reason\": [\"cancel\"] as const,\n \"end_time\": [\"extend_flight\", \"shorten_flight\", \"update_flight_dates\"] as const,\n \"new_packages\": [\"add_packages\"] as const,\n \"packages[].budget\": [\"increase_budget\", \"decrease_budget\", \"reallocate_budget\"] as const,\n \"packages[].canceled\": [\"remove_packages\"] as const,\n \"packages[].creative_assignments\": [\"update_creative_assignments\", \"remove_creative\"] as const,\n \"packages[].creatives\": [\"replace_creative\", \"remove_creative\"] as const,\n \"packages[].end_time\": [\"extend_flight\", \"shorten_flight\", \"update_flight_dates\"] as const,\n \"packages[].keyword_targets_add\": [\"update_targeting\"] as const,\n \"packages[].keyword_targets_remove\": [\"update_targeting\"] as const,\n \"packages[].negative_keywords_add\": [\"update_targeting\"] as const,\n \"packages[].negative_keywords_remove\": [\"update_targeting\"] as const,\n \"packages[].pacing\": [\"update_pacing\"] as const,\n \"packages[].start_time\": [\"update_flight_dates\"] as const,\n \"packages[].targeting_overlay\": [\"update_targeting\"] as const,\n \"packages[].targeting_overlay.frequency_cap\": [\"update_frequency_caps\"] as const,\n \"paused\": [\"pause\", \"resume\"] as const,\n \"start_time\": [\"update_flight_dates\"] as const,\n} as const;\n\nexport { LEGACY_COARSE_ACTIONS } from './types';\nexport type { LegacyCoarseAction } from './types';\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/media-buy/update-fields.generated.ts"],"sourcesContent":["// Generated by scripts/generate-media-buy-update-fields.ts.\n// Source: schemas/cache/<adcp_version>/enums/media-buy-valid-action.json (enumMetadata).\n// Do not hand-edit - regenerate after a schema bump.\n\nimport type { MediaBuyValidAction } from './types';\n\nexport interface UpdateFieldEntry {\n /** Dotted paths into the update_media_buy request body this action covers. */\n readonly update_fields: readonly string[];\n /** Fine-grained values this action rolls up to (legacy coarse actions only). */\n readonly rollup: readonly MediaBuyValidAction[] | null;\n /** True for `x-deprecated-enum-values` (legacy coarse vocabulary). */\n readonly deprecated: boolean;\n}\n\nexport const UPDATE_FIELDS_BY_ACTION: Readonly<\n Record<MediaBuyValidAction, UpdateFieldEntry>\n> = {\n \"pause\": {\n update_fields: [\"paused\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"resume\": {\n update_fields: [\"paused\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"cancel\": {\n update_fields: [\"canceled\", \"cancellation_reason\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"extend_flight\": {\n update_fields: [\"end_time\", \"packages[].end_time\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"shorten_flight\": {\n update_fields: [\"end_time\", \"packages[].end_time\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_flight_dates\": {\n update_fields: [\"start_time\", \"end_time\", \"packages[].start_time\", \"packages[].end_time\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"increase_budget\": {\n update_fields: [\"packages[].budget\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"decrease_budget\": {\n update_fields: [\"packages[].budget\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"reallocate_budget\": {\n update_fields: [\"packages[].budget\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_targeting\": {\n update_fields: [\"packages[].targeting_overlay\", \"packages[].keyword_targets_add\", \"packages[].keyword_targets_remove\", \"packages[].negative_keywords_add\", \"packages[].negative_keywords_remove\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_pacing\": {\n update_fields: [\"packages[].pacing\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_frequency_caps\": {\n update_fields: [\"packages[].targeting_overlay.frequency_cap\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"replace_creative\": {\n update_fields: [\"packages[].creatives\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_creative_assignments\": {\n update_fields: [\"packages[].creative_assignments\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"remove_creative\": {\n update_fields: [\"packages[].creatives\", \"packages[].creative_assignments\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"add_packages\": {\n update_fields: [\"new_packages\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"remove_packages\": {\n update_fields: [\"packages[].canceled\"] as const,\n rollup: null,\n deprecated: false,\n },\n \"update_budget\": {\n update_fields: [\"packages[].budget\"] as const,\n rollup: [\"increase_budget\", \"decrease_budget\", \"reallocate_budget\"] as const,\n deprecated: true,\n },\n \"update_dates\": {\n update_fields: [\"start_time\", \"end_time\", \"packages[].start_time\", \"packages[].end_time\"] as const,\n rollup: [\"extend_flight\", \"shorten_flight\", \"update_flight_dates\"] as const,\n deprecated: true,\n },\n \"update_packages\": {\n update_fields: [\"packages[]\"] as const,\n rollup: [\"update_targeting\", \"update_pacing\", \"update_frequency_caps\", \"reallocate_budget\", \"remove_packages\"] as const,\n deprecated: true,\n },\n \"sync_creatives\": {\n update_fields: [\"packages[].creatives\", \"packages[].creative_assignments\"] as const,\n rollup: [\"replace_creative\", \"update_creative_assignments\", \"remove_creative\"] as const,\n deprecated: true,\n },\n} as const;\n\nexport const ACTIONS_BY_FIELD: Readonly<\n Record<string, readonly MediaBuyValidAction[]>\n> = {\n \"canceled\": [\"cancel\"] as const,\n \"cancellation_reason\": [\"cancel\"] as const,\n \"end_time\": [\"extend_flight\", \"shorten_flight\", \"update_flight_dates\"] as const,\n \"new_packages\": [\"add_packages\"] as const,\n \"packages[].budget\": [\"increase_budget\", \"decrease_budget\", \"reallocate_budget\"] as const,\n \"packages[].canceled\": [\"remove_packages\"] as const,\n \"packages[].creative_assignments\": [\"update_creative_assignments\", \"remove_creative\"] as const,\n \"packages[].creatives\": [\"replace_creative\", \"remove_creative\"] as const,\n \"packages[].end_time\": [\"extend_flight\", \"shorten_flight\", \"update_flight_dates\"] as const,\n \"packages[].keyword_targets_add\": [\"update_targeting\"] as const,\n \"packages[].keyword_targets_remove\": [\"update_targeting\"] as const,\n \"packages[].negative_keywords_add\": [\"update_targeting\"] as const,\n \"packages[].negative_keywords_remove\": [\"update_targeting\"] as const,\n \"packages[].pacing\": [\"update_pacing\"] as const,\n \"packages[].start_time\": [\"update_flight_dates\"] as const,\n \"packages[].targeting_overlay\": [\"update_targeting\"] as const,\n \"packages[].targeting_overlay.frequency_cap\": [\"update_frequency_caps\"] as const,\n \"paused\": [\"pause\", \"resume\"] as const,\n \"start_time\": [\"update_flight_dates\"] as const,\n} as const;\n\nexport { LEGACY_COARSE_ACTIONS } from './types';\nexport type { LegacyCoarseAction } from './types';\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
const DEFAULT_API_KEY = "mock_creative_ad_server_key_do_not_use_in_prod";
|
|
8
2
|
const NETWORKS = [
|
|
9
3
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/mock-server/creative-ad-server/seed-data.ts"],"sourcesContent":["/**\n * `creative-ad-server` upstream-shape seed data. Mirrors the GAM-creative /\n * Innovid / Flashtalking / CM360 model: per-network format catalog, stateful\n * creative library (writeable via POST /v1/creatives), tag generation against\n * stored snippet templates with macro substitution.\n *\n * The library is *stateful* (vs `creative-template`'s stateless transform):\n * `POST /v1/creatives` writes; `GET /v1/creatives` reads; `PATCH` mutates;\n * `POST /v1/creatives/{id}/render` substitutes macros and returns a tag URL.\n *\n * Format renders[] use the closed-shape `displayRender` / `parameterizedRender`\n * pattern (codegen tightening from #1325) so adapter projection composes\n * with `Format.renders[]` typed builders without `as` casts.\n */\n\nimport type { Format } from '../../types';\n\nexport const DEFAULT_API_KEY = 'mock_creative_ad_server_key_do_not_use_in_prod';\n\nexport interface MockNetwork {\n network_code: string;\n display_name: string;\n /** AdCP-side identifier the adapter uses to map principal → network. */\n adcp_publisher: string;\n}\n\nexport interface MockFormat {\n format_id: string;\n network_code: string;\n /** Human-readable name. */\n name: string;\n /** display | video | ctv | audio. The `Format` type doesn't carry a\n * top-level kind field; we project to closed-shape `renders[]` per\n * format. This stays on the upstream side for catalog filtering. */\n channel: 'display' | 'video' | 'ctv' | 'audio';\n /** Render kind drives the adapter's projection — we surface the\n * closed-shape `Format.renders[]` from this. */\n render_kind: 'fixed' | 'parameterized';\n width?: number;\n height?: number;\n duration_seconds?: number;\n /** MIME types the format accepts on upload. Mock uses these to\n * auto-detect format from upload mime in handleCreateCreative. */\n accepted_mimes: string[];\n /** Snippet template stored with the format. Substitutes\n * `{click_url}`, `{impression_pixel}`, `{cb}`, `{advertiser_id}`,\n * `{creative_id}`, `{width}`, `{height}` at render time. */\n snippet_template: string;\n}\n\nexport interface MockCreative {\n creative_id: string;\n network_code: string;\n advertiser_id: string;\n format_id: string;\n name: string;\n /** Snippet body — overrides the format's template if set. Otherwise\n * the format's `snippet_template` is used at render time. */\n snippet?: string;\n status: 'active' | 'paused' | 'archived' | 'rejected';\n click_url?: string;\n /** ISO 8601 created_at — used by `?created_after=` filter and to\n * scale synth delivery (older creatives have more delivery). */\n created_at: string;\n updated_at: string;\n}\n\nexport const NETWORKS: MockNetwork[] = [\n {\n network_code: 'net_creative_us',\n display_name: 'Creative Ad Server — US Network',\n adcp_publisher: 'creative-network.example',\n },\n {\n network_code: 'net_acmeoutdoor',\n display_name: 'Acme Outdoor Creative Network',\n adcp_publisher: 'acmeoutdoor.example',\n },\n {\n network_code: 'net_pinnacle',\n display_name: 'Pinnacle Agency Creative Tenant',\n adcp_publisher: 'pinnacle-agency.example',\n },\n];\n\n/**\n * Format catalog — 6 base formats spanning display / video / CTV. Each\n * is replicated across all networks (real ad servers do carry per-network\n * format catalogs but most formats are inherited from the platform's\n * default; modeling each network's full catalog as identical keeps the\n * mock simple and matches the Innovid/GAM-creative pattern). The\n * `snippet_template` is what the mock substitutes macros into when\n * `POST /v1/creatives/{id}/render` is called.\n */\nconst BASE_FORMATS: Omit<MockFormat, 'network_code'>[] = [\n {\n format_id: 'display_300x250',\n name: 'Display 300x250 (medrec)',\n channel: 'display',\n render_kind: 'fixed',\n width: 300,\n height: 250,\n accepted_mimes: ['image/jpeg', 'image/png', 'image/webp', 'text/html'],\n snippet_template:\n '<a href=\"{click_url}\" target=\"_blank\"><img src=\"{asset_url}\" width=\"{width}\" height=\"{height}\"/></a><img src=\"{impression_pixel}\" width=\"0\" height=\"0\"/>',\n },\n {\n format_id: 'display_728x90',\n name: 'Display 728x90 (leaderboard)',\n channel: 'display',\n render_kind: 'fixed',\n width: 728,\n height: 90,\n accepted_mimes: ['image/jpeg', 'image/png', 'image/webp', 'text/html'],\n snippet_template:\n '<a href=\"{click_url}\" target=\"_blank\"><img src=\"{asset_url}\" width=\"{width}\" height=\"{height}\"/></a><img src=\"{impression_pixel}\" width=\"0\" height=\"0\"/>',\n },\n {\n format_id: 'video_30s',\n name: 'Video 30s VAST',\n channel: 'video',\n render_kind: 'fixed',\n duration_seconds: 30,\n accepted_mimes: ['video/mp4', 'application/xml'],\n snippet_template:\n '<VAST version=\"4.2\"><Ad id=\"{creative_id}\"><InLine><Creatives><Creative><Linear><Duration>00:00:{duration_seconds}</Duration><MediaFiles><MediaFile delivery=\"progressive\" type=\"video/mp4\">{asset_url}</MediaFile></MediaFiles><VideoClicks><ClickThrough>{click_url}</ClickThrough></VideoClicks></Linear></Creative></Creatives><Impression>{impression_pixel}</Impression></InLine></Ad></VAST>',\n },\n {\n format_id: 'video_15s',\n name: 'Video 15s VAST',\n channel: 'video',\n render_kind: 'fixed',\n duration_seconds: 15,\n accepted_mimes: ['video/mp4', 'application/xml'],\n snippet_template:\n '<VAST version=\"4.2\"><Ad id=\"{creative_id}\"><InLine><Creatives><Creative><Linear><Duration>00:00:{duration_seconds}</Duration><MediaFiles><MediaFile delivery=\"progressive\" type=\"video/mp4\">{asset_url}</MediaFile></MediaFiles><VideoClicks><ClickThrough>{click_url}</ClickThrough></VideoClicks></Linear></Creative></Creatives><Impression>{impression_pixel}</Impression></InLine></Ad></VAST>',\n },\n {\n format_id: 'ctv_30s',\n name: 'CTV 30s VAST (1080p)',\n channel: 'ctv',\n render_kind: 'fixed',\n duration_seconds: 30,\n accepted_mimes: ['video/mp4'],\n snippet_template:\n '<VAST version=\"4.2\"><Ad id=\"{creative_id}\"><InLine><Creatives><Creative><Linear><Duration>00:00:{duration_seconds}</Duration><MediaFiles><MediaFile delivery=\"progressive\" type=\"video/mp4\" width=\"1920\" height=\"1080\">{asset_url}</MediaFile></MediaFiles></Linear></Creative></Creatives><Impression>{impression_pixel}</Impression></InLine></Ad></VAST>',\n },\n {\n format_id: 'vast_30s',\n name: 'VAST 30s (storyboard alias)',\n channel: 'video',\n render_kind: 'fixed',\n duration_seconds: 30,\n accepted_mimes: ['video/mp4', 'application/xml'],\n snippet_template:\n '<VAST version=\"4.2\"><Ad id=\"{creative_id}\"><InLine><Creatives><Creative><Linear><Duration>00:00:{duration_seconds}</Duration><MediaFiles><MediaFile delivery=\"progressive\" type=\"video/mp4\">{asset_url}</MediaFile></MediaFiles><VideoClicks><ClickThrough>{click_url}</ClickThrough></VideoClicks></Linear></Creative></Creatives><Impression>{impression_pixel}</Impression></InLine></Ad></VAST>',\n },\n {\n format_id: 'display_responsive',\n name: 'Display responsive (parameterized)',\n channel: 'display',\n render_kind: 'parameterized',\n accepted_mimes: ['image/jpeg', 'image/png', 'image/webp'],\n snippet_template:\n '<a href=\"{click_url}\" target=\"_blank\"><img src=\"{asset_url}\" style=\"max-width:100%\"/></a><img src=\"{impression_pixel}\" width=\"0\" height=\"0\"/>',\n },\n];\n\n/** Replicate base formats across every network for catalog lookups. */\nexport const FORMATS: MockFormat[] = NETWORKS.flatMap(net =>\n BASE_FORMATS.map(f => ({ ...f, network_code: net.network_code }))\n);\n\n/**\n * Seed creatives — 3 pre-loaded library entries the storyboard runner can\n * read on `GET /v1/creatives` without first POSTing. Production would\n * have an empty seed; these exist so the storyboard's `read-only` checks\n * (list + filter) have something to return on a clean boot.\n */\nexport const CREATIVES: MockCreative[] = [\n {\n creative_id: 'cr_seed_acme_medrec',\n network_code: 'net_acmeoutdoor',\n advertiser_id: 'adv_acmeoutdoor',\n format_id: 'display_300x250',\n name: 'Acme Outdoor — Summer Hero (300x250)',\n snippet:\n '<a href=\"https://acmeoutdoor.example/summer\" target=\"_blank\"><img src=\"https://test-assets.adcontextprotocol.org/acme-outdoor/hero-300x250.jpg\" width=\"300\" height=\"250\"/></a>',\n status: 'active',\n click_url: 'https://acmeoutdoor.example/summer',\n created_at: '2026-04-01T00:00:00Z',\n updated_at: '2026-04-01T00:00:00Z',\n },\n {\n creative_id: 'cr_seed_acme_leaderboard',\n network_code: 'net_acmeoutdoor',\n advertiser_id: 'adv_acmeoutdoor',\n format_id: 'display_728x90',\n name: 'Acme Outdoor — Summer Hero (728x90)',\n snippet:\n '<a href=\"https://acmeoutdoor.example/summer\" target=\"_blank\"><img src=\"https://test-assets.adcontextprotocol.org/acme-outdoor/hero-728x90.jpg\" width=\"728\" height=\"90\"/></a>',\n status: 'active',\n click_url: 'https://acmeoutdoor.example/summer',\n created_at: '2026-04-01T00:00:00Z',\n updated_at: '2026-04-01T00:00:00Z',\n },\n {\n creative_id: 'cr_seed_pinnacle_video',\n network_code: 'net_pinnacle',\n advertiser_id: 'adv_pinnacle',\n format_id: 'video_30s',\n name: 'Pinnacle Premium Q2 Preroll',\n status: 'active',\n created_at: '2026-04-01T00:00:00Z',\n updated_at: '2026-04-01T00:00:00Z',\n },\n];\n\n/**\n * Project an upstream `MockFormat` to the closed-shape `Format` shape the\n * mock surfaces on `GET /v1/formats`. Adapters consume this directly.\n *\n * Format.renders[] uses the closed-shape `displayRender` / `parameterizedRender`\n * convention from #1325 — `dimensions: { width, height, unit }` for fixed,\n * `accepts_parameters[]` for parameterized.\n */\nexport function projectFormat(format: MockFormat, agentUrl: string): Format {\n const baseFormat: Format = {\n format_id: { agent_url: agentUrl, id: format.format_id },\n name: format.name,\n };\n\n if (format.render_kind === 'fixed') {\n if (format.channel === 'display' && format.width !== undefined && format.height !== undefined) {\n return {\n ...baseFormat,\n renders: [\n {\n role: 'main',\n dimensions: { width: format.width, height: format.height, unit: 'px' as const },\n },\n ],\n };\n }\n if ((format.channel === 'video' || format.channel === 'ctv') && format.duration_seconds !== undefined) {\n return {\n ...baseFormat,\n renders: [\n {\n role: 'main',\n dimensions: { width: 1920, height: 1080, unit: 'px' as const },\n },\n ],\n };\n }\n }\n // Parameterized — adapter consumes accepts_parameters from format catalog\n // separately; renders[] declares the role only.\n return {\n ...baseFormat,\n renders: [{ role: 'main', dimensions: { width: 0, height: 0, unit: 'px' as const } }],\n };\n}\n"],"mappings":";;;;;;AAiBO,MAAM,kBAAkB;AAkDxB,MAAM,WAA0B;AAAA,EACrC;AAAA,IACE,cAAc;AAAA,IACd,cAAc;AAAA,IACd,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,cAAc;AAAA,IACd,cAAc;AAAA,IACd,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,cAAc;AAAA,IACd,cAAc;AAAA,IACd,gBAAgB;AAAA,EAClB;AACF;AAWA,MAAM,eAAmD;AAAA,EACvD;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,gBAAgB,CAAC,cAAc,aAAa,cAAc,WAAW;AAAA,IACrE,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,gBAAgB,CAAC,cAAc,aAAa,cAAc,WAAW;AAAA,IACrE,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,gBAAgB,CAAC,aAAa,iBAAiB;AAAA,IAC/C,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,gBAAgB,CAAC,aAAa,iBAAiB;AAAA,IAC/C,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,gBAAgB,CAAC,WAAW;AAAA,IAC5B,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,gBAAgB,CAAC,aAAa,iBAAiB;AAAA,IAC/C,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,gBAAgB,CAAC,cAAc,aAAa,YAAY;AAAA,IACxD,kBACE;AAAA,EACJ;AACF;AAGO,MAAM,UAAwB,SAAS;AAAA,EAAQ,SACpD,aAAa,IAAI,QAAM,EAAE,GAAG,GAAG,cAAc,IAAI,aAAa,EAAE;AAClE;AAQO,MAAM,YAA4B;AAAA,EACvC;AAAA,IACE,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,IACf,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,IACf,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,IACf,WAAW;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AACF;AAUO,SAAS,cAAc,QAAoB,UAA0B;AAC1E,QAAM,aAAqB;AAAA,IACzB,WAAW,EAAE,WAAW,UAAU,IAAI,OAAO,UAAU;AAAA,IACvD,MAAM,OAAO;AAAA,EACf;AAEA,MAAI,OAAO,gBAAgB,SAAS;AAClC,QAAI,OAAO,YAAY,aAAa,OAAO,UAAU,UAAa,OAAO,WAAW,QAAW;AAC7F,aAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,YAAY,EAAE,OAAO,OAAO,OAAO,QAAQ,OAAO,QAAQ,MAAM,KAAc;AAAA,UAChF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,SAAK,OAAO,YAAY,WAAW,OAAO,YAAY,UAAU,OAAO,qBAAqB,QAAW;AACrG,aAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,YAAY,EAAE,OAAO,MAAM,QAAQ,MAAM,MAAM,KAAc;AAAA,UAC/D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,CAAC,EAAE,MAAM,QAAQ,YAAY,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,KAAc,EAAE,CAAC;AAAA,EACtF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/mock-server/creative-ad-server/seed-data.ts"],"sourcesContent":["/**\n * `creative-ad-server` upstream-shape seed data. Mirrors the GAM-creative /\n * Innovid / Flashtalking / CM360 model: per-network format catalog, stateful\n * creative library (writeable via POST /v1/creatives), tag generation against\n * stored snippet templates with macro substitution.\n *\n * The library is *stateful* (vs `creative-template`'s stateless transform):\n * `POST /v1/creatives` writes; `GET /v1/creatives` reads; `PATCH` mutates;\n * `POST /v1/creatives/{id}/render` substitutes macros and returns a tag URL.\n *\n * Format renders[] use the closed-shape `displayRender` / `parameterizedRender`\n * pattern (codegen tightening from #1325) so adapter projection composes\n * with `Format.renders[]` typed builders without `as` casts.\n */\n\nimport type { Format } from '../../types';\n\nexport const DEFAULT_API_KEY = 'mock_creative_ad_server_key_do_not_use_in_prod';\n\nexport interface MockNetwork {\n network_code: string;\n display_name: string;\n /** AdCP-side identifier the adapter uses to map principal → network. */\n adcp_publisher: string;\n}\n\nexport interface MockFormat {\n format_id: string;\n network_code: string;\n /** Human-readable name. */\n name: string;\n /** display | video | ctv | audio. The `Format` type doesn't carry a\n * top-level kind field; we project to closed-shape `renders[]` per\n * format. This stays on the upstream side for catalog filtering. */\n channel: 'display' | 'video' | 'ctv' | 'audio';\n /** Render kind drives the adapter's projection — we surface the\n * closed-shape `Format.renders[]` from this. */\n render_kind: 'fixed' | 'parameterized';\n width?: number;\n height?: number;\n duration_seconds?: number;\n /** MIME types the format accepts on upload. Mock uses these to\n * auto-detect format from upload mime in handleCreateCreative. */\n accepted_mimes: string[];\n /** Snippet template stored with the format. Substitutes\n * `{click_url}`, `{impression_pixel}`, `{cb}`, `{advertiser_id}`,\n * `{creative_id}`, `{width}`, `{height}` at render time. */\n snippet_template: string;\n}\n\nexport interface MockCreative {\n creative_id: string;\n network_code: string;\n advertiser_id: string;\n format_id: string;\n name: string;\n /** Snippet body — overrides the format's template if set. Otherwise\n * the format's `snippet_template` is used at render time. */\n snippet?: string;\n status: 'active' | 'paused' | 'archived' | 'rejected';\n click_url?: string;\n /** ISO 8601 created_at — used by `?created_after=` filter and to\n * scale synth delivery (older creatives have more delivery). */\n created_at: string;\n updated_at: string;\n}\n\nexport const NETWORKS: MockNetwork[] = [\n {\n network_code: 'net_creative_us',\n display_name: 'Creative Ad Server — US Network',\n adcp_publisher: 'creative-network.example',\n },\n {\n network_code: 'net_acmeoutdoor',\n display_name: 'Acme Outdoor Creative Network',\n adcp_publisher: 'acmeoutdoor.example',\n },\n {\n network_code: 'net_pinnacle',\n display_name: 'Pinnacle Agency Creative Tenant',\n adcp_publisher: 'pinnacle-agency.example',\n },\n];\n\n/**\n * Format catalog — 6 base formats spanning display / video / CTV. Each\n * is replicated across all networks (real ad servers do carry per-network\n * format catalogs but most formats are inherited from the platform's\n * default; modeling each network's full catalog as identical keeps the\n * mock simple and matches the Innovid/GAM-creative pattern). The\n * `snippet_template` is what the mock substitutes macros into when\n * `POST /v1/creatives/{id}/render` is called.\n */\nconst BASE_FORMATS: Omit<MockFormat, 'network_code'>[] = [\n {\n format_id: 'display_300x250',\n name: 'Display 300x250 (medrec)',\n channel: 'display',\n render_kind: 'fixed',\n width: 300,\n height: 250,\n accepted_mimes: ['image/jpeg', 'image/png', 'image/webp', 'text/html'],\n snippet_template:\n '<a href=\"{click_url}\" target=\"_blank\"><img src=\"{asset_url}\" width=\"{width}\" height=\"{height}\"/></a><img src=\"{impression_pixel}\" width=\"0\" height=\"0\"/>',\n },\n {\n format_id: 'display_728x90',\n name: 'Display 728x90 (leaderboard)',\n channel: 'display',\n render_kind: 'fixed',\n width: 728,\n height: 90,\n accepted_mimes: ['image/jpeg', 'image/png', 'image/webp', 'text/html'],\n snippet_template:\n '<a href=\"{click_url}\" target=\"_blank\"><img src=\"{asset_url}\" width=\"{width}\" height=\"{height}\"/></a><img src=\"{impression_pixel}\" width=\"0\" height=\"0\"/>',\n },\n {\n format_id: 'video_30s',\n name: 'Video 30s VAST',\n channel: 'video',\n render_kind: 'fixed',\n duration_seconds: 30,\n accepted_mimes: ['video/mp4', 'application/xml'],\n snippet_template:\n '<VAST version=\"4.2\"><Ad id=\"{creative_id}\"><InLine><Creatives><Creative><Linear><Duration>00:00:{duration_seconds}</Duration><MediaFiles><MediaFile delivery=\"progressive\" type=\"video/mp4\">{asset_url}</MediaFile></MediaFiles><VideoClicks><ClickThrough>{click_url}</ClickThrough></VideoClicks></Linear></Creative></Creatives><Impression>{impression_pixel}</Impression></InLine></Ad></VAST>',\n },\n {\n format_id: 'video_15s',\n name: 'Video 15s VAST',\n channel: 'video',\n render_kind: 'fixed',\n duration_seconds: 15,\n accepted_mimes: ['video/mp4', 'application/xml'],\n snippet_template:\n '<VAST version=\"4.2\"><Ad id=\"{creative_id}\"><InLine><Creatives><Creative><Linear><Duration>00:00:{duration_seconds}</Duration><MediaFiles><MediaFile delivery=\"progressive\" type=\"video/mp4\">{asset_url}</MediaFile></MediaFiles><VideoClicks><ClickThrough>{click_url}</ClickThrough></VideoClicks></Linear></Creative></Creatives><Impression>{impression_pixel}</Impression></InLine></Ad></VAST>',\n },\n {\n format_id: 'ctv_30s',\n name: 'CTV 30s VAST (1080p)',\n channel: 'ctv',\n render_kind: 'fixed',\n duration_seconds: 30,\n accepted_mimes: ['video/mp4'],\n snippet_template:\n '<VAST version=\"4.2\"><Ad id=\"{creative_id}\"><InLine><Creatives><Creative><Linear><Duration>00:00:{duration_seconds}</Duration><MediaFiles><MediaFile delivery=\"progressive\" type=\"video/mp4\" width=\"1920\" height=\"1080\">{asset_url}</MediaFile></MediaFiles></Linear></Creative></Creatives><Impression>{impression_pixel}</Impression></InLine></Ad></VAST>',\n },\n {\n format_id: 'vast_30s',\n name: 'VAST 30s (storyboard alias)',\n channel: 'video',\n render_kind: 'fixed',\n duration_seconds: 30,\n accepted_mimes: ['video/mp4', 'application/xml'],\n snippet_template:\n '<VAST version=\"4.2\"><Ad id=\"{creative_id}\"><InLine><Creatives><Creative><Linear><Duration>00:00:{duration_seconds}</Duration><MediaFiles><MediaFile delivery=\"progressive\" type=\"video/mp4\">{asset_url}</MediaFile></MediaFiles><VideoClicks><ClickThrough>{click_url}</ClickThrough></VideoClicks></Linear></Creative></Creatives><Impression>{impression_pixel}</Impression></InLine></Ad></VAST>',\n },\n {\n format_id: 'display_responsive',\n name: 'Display responsive (parameterized)',\n channel: 'display',\n render_kind: 'parameterized',\n accepted_mimes: ['image/jpeg', 'image/png', 'image/webp'],\n snippet_template:\n '<a href=\"{click_url}\" target=\"_blank\"><img src=\"{asset_url}\" style=\"max-width:100%\"/></a><img src=\"{impression_pixel}\" width=\"0\" height=\"0\"/>',\n },\n];\n\n/** Replicate base formats across every network for catalog lookups. */\nexport const FORMATS: MockFormat[] = NETWORKS.flatMap(net =>\n BASE_FORMATS.map(f => ({ ...f, network_code: net.network_code }))\n);\n\n/**\n * Seed creatives — 3 pre-loaded library entries the storyboard runner can\n * read on `GET /v1/creatives` without first POSTing. Production would\n * have an empty seed; these exist so the storyboard's `read-only` checks\n * (list + filter) have something to return on a clean boot.\n */\nexport const CREATIVES: MockCreative[] = [\n {\n creative_id: 'cr_seed_acme_medrec',\n network_code: 'net_acmeoutdoor',\n advertiser_id: 'adv_acmeoutdoor',\n format_id: 'display_300x250',\n name: 'Acme Outdoor — Summer Hero (300x250)',\n snippet:\n '<a href=\"https://acmeoutdoor.example/summer\" target=\"_blank\"><img src=\"https://test-assets.adcontextprotocol.org/acme-outdoor/hero-300x250.jpg\" width=\"300\" height=\"250\"/></a>',\n status: 'active',\n click_url: 'https://acmeoutdoor.example/summer',\n created_at: '2026-04-01T00:00:00Z',\n updated_at: '2026-04-01T00:00:00Z',\n },\n {\n creative_id: 'cr_seed_acme_leaderboard',\n network_code: 'net_acmeoutdoor',\n advertiser_id: 'adv_acmeoutdoor',\n format_id: 'display_728x90',\n name: 'Acme Outdoor — Summer Hero (728x90)',\n snippet:\n '<a href=\"https://acmeoutdoor.example/summer\" target=\"_blank\"><img src=\"https://test-assets.adcontextprotocol.org/acme-outdoor/hero-728x90.jpg\" width=\"728\" height=\"90\"/></a>',\n status: 'active',\n click_url: 'https://acmeoutdoor.example/summer',\n created_at: '2026-04-01T00:00:00Z',\n updated_at: '2026-04-01T00:00:00Z',\n },\n {\n creative_id: 'cr_seed_pinnacle_video',\n network_code: 'net_pinnacle',\n advertiser_id: 'adv_pinnacle',\n format_id: 'video_30s',\n name: 'Pinnacle Premium Q2 Preroll',\n status: 'active',\n created_at: '2026-04-01T00:00:00Z',\n updated_at: '2026-04-01T00:00:00Z',\n },\n];\n\n/**\n * Project an upstream `MockFormat` to the closed-shape `Format` shape the\n * mock surfaces on `GET /v1/formats`. Adapters consume this directly.\n *\n * Format.renders[] uses the closed-shape `displayRender` / `parameterizedRender`\n * convention from #1325 — `dimensions: { width, height, unit }` for fixed,\n * `accepts_parameters[]` for parameterized.\n */\nexport function projectFormat(format: MockFormat, agentUrl: string): Format {\n const baseFormat: Format = {\n format_id: { agent_url: agentUrl, id: format.format_id },\n name: format.name,\n };\n\n if (format.render_kind === 'fixed') {\n if (format.channel === 'display' && format.width !== undefined && format.height !== undefined) {\n return {\n ...baseFormat,\n renders: [\n {\n role: 'main',\n dimensions: { width: format.width, height: format.height, unit: 'px' as const },\n },\n ],\n };\n }\n if ((format.channel === 'video' || format.channel === 'ctv') && format.duration_seconds !== undefined) {\n return {\n ...baseFormat,\n renders: [\n {\n role: 'main',\n dimensions: { width: 1920, height: 1080, unit: 'px' as const },\n },\n ],\n };\n }\n }\n // Parameterized — adapter consumes accepts_parameters from format catalog\n // separately; renders[] declares the role only.\n return {\n ...baseFormat,\n renders: [{ role: 'main', dimensions: { width: 0, height: 0, unit: 'px' as const } }],\n };\n}\n"],"mappings":"AAiBO,MAAM,kBAAkB;AAkDxB,MAAM,WAA0B;AAAA,EACrC;AAAA,IACE,cAAc;AAAA,IACd,cAAc;AAAA,IACd,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,cAAc;AAAA,IACd,cAAc;AAAA,IACd,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,cAAc;AAAA,IACd,cAAc;AAAA,IACd,gBAAgB;AAAA,EAClB;AACF;AAWA,MAAM,eAAmD;AAAA,EACvD;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,gBAAgB,CAAC,cAAc,aAAa,cAAc,WAAW;AAAA,IACrE,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,gBAAgB,CAAC,cAAc,aAAa,cAAc,WAAW;AAAA,IACrE,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,gBAAgB,CAAC,aAAa,iBAAiB;AAAA,IAC/C,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,gBAAgB,CAAC,aAAa,iBAAiB;AAAA,IAC/C,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,gBAAgB,CAAC,WAAW;AAAA,IAC5B,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,gBAAgB,CAAC,aAAa,iBAAiB;AAAA,IAC/C,kBACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,gBAAgB,CAAC,cAAc,aAAa,YAAY;AAAA,IACxD,kBACE;AAAA,EACJ;AACF;AAGO,MAAM,UAAwB,SAAS;AAAA,EAAQ,SACpD,aAAa,IAAI,QAAM,EAAE,GAAG,GAAG,cAAc,IAAI,aAAa,EAAE;AAClE;AAQO,MAAM,YAA4B;AAAA,EACvC;AAAA,IACE,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,IACf,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,IACf,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,IACf,WAAW;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AACF;AAUO,SAAS,cAAc,QAAoB,UAA0B;AAC1E,QAAM,aAAqB;AAAA,IACzB,WAAW,EAAE,WAAW,UAAU,IAAI,OAAO,UAAU;AAAA,IACvD,MAAM,OAAO;AAAA,EACf;AAEA,MAAI,OAAO,gBAAgB,SAAS;AAClC,QAAI,OAAO,YAAY,aAAa,OAAO,UAAU,UAAa,OAAO,WAAW,QAAW;AAC7F,aAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,YAAY,EAAE,OAAO,OAAO,OAAO,QAAQ,OAAO,QAAQ,MAAM,KAAc;AAAA,UAChF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,SAAK,OAAO,YAAY,WAAW,OAAO,YAAY,UAAU,OAAO,qBAAqB,QAAW;AACrG,aAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,YAAY,EAAE,OAAO,MAAM,QAAQ,MAAM,MAAM,KAAc;AAAA,UAC/D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,CAAC,EAAE,MAAM,QAAQ,YAAY,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,KAAc,EAAE,CAAC;AAAA,EACtF;AACF;","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
import { createServer } from "node:http";
|
|
8
2
|
import { createHash, randomUUID } from "node:crypto";
|
|
9
3
|
import {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/mock-server/creative-ad-server/server.ts"],"sourcesContent":["/**\n * `creative-ad-server` upstream-shape mock-server. Stateful creative\n * library (POST writes, GET reads), tag generation with macro substitution,\n * synth delivery reporting. Closes #1459 (sub-issue of #1381).\n *\n * Pattern source:\n * - Library state shape: `sales-guaranteed/server.ts` handleCreateCreative /\n * handleListCreatives — network-scoped, idempotency on client_request_id.\n * - Format catalog projection: `creative-template/server.ts` (templates\n * in seed-data, projected at request-time).\n *\n * Specialism deltas vs `creative-template`:\n * - Stateful library (writes persist across calls).\n * - Format auto-detection from upload mime (handleCreateCreative).\n * - Tag generation (POST /v1/creatives/{id}/render) substitutes macros\n * into a stored snippet template — `{click_url}`, `{impression_pixel}`,\n * `{cb}`, `{advertiser_id}`, etc.\n * - Real `/serve/{creative_id}` HTML response — adopters get a true\n * iframe-embeddable URL on previewCreative, not a synthetic string.\n * - Delivery reporting (GET /v1/creatives/{id}/delivery) — synth\n * impressions/clicks/CTR scaled by days-active, deterministic-seeded\n * on (creative_id, day).\n * - Multi-tenancy via X-Network-Code header (mirrors sales-guaranteed).\n */\n\nimport { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { createHash, randomUUID } from 'node:crypto';\nimport {\n CREATIVES,\n DEFAULT_API_KEY,\n FORMATS,\n NETWORKS,\n projectFormat,\n type MockCreative,\n type MockFormat,\n type MockNetwork,\n} from './seed-data';\nimport {\n createMockScenarioController,\n idempotencyKeyFromBody,\n stableFingerprint,\n writeCachedResponse,\n type MockScenarioHandle,\n} from '../scenario';\n\nexport interface BootOptions {\n port: number;\n apiKey?: string;\n networks?: MockNetwork[];\n formats?: MockFormat[];\n creatives?: MockCreative[];\n}\n\nexport interface BootResult {\n url: string;\n close: () => Promise<void>;\n scenario: MockScenarioHandle;\n}\n\ninterface CreativeState extends MockCreative {\n body_fingerprint: string;\n}\n\nconst PAGE_SIZE_DEFAULT = 50;\n\nexport async function bootCreativeAdServer(options: BootOptions): Promise<BootResult> {\n const apiKey = options.apiKey ?? DEFAULT_API_KEY;\n const networks = options.networks ?? NETWORKS;\n const formats = options.formats ?? FORMATS;\n const seededCreatives = options.creatives ?? CREATIVES;\n\n const creatives = new Map<string, CreativeState>();\n for (const seed of seededCreatives) {\n creatives.set(seed.creative_id, {\n ...seed,\n body_fingerprint: sha256(JSON.stringify(seed)),\n });\n }\n\n // Idempotency table — keyed `<network_code>::creative::<client_request_id>`.\n const idempotency = new Map<string, string>();\n\n // Traffic counters keyed by `<METHOD> <route-template>`. Harness queries\n // `GET /_debug/traffic` after the storyboard run and asserts headline\n // routes were hit ≥1. Façade adapters that skip the upstream produce\n // zero counters and fail the assertion.\n const traffic = new Map<string, number>();\n const bump = (routeTemplate: string): void => {\n traffic.set(routeTemplate, (traffic.get(routeTemplate) ?? 0) + 1);\n };\n const resetCreatives = (): void => {\n creatives.clear();\n for (const seed of seededCreatives) {\n creatives.set(seed.creative_id, {\n ...seed,\n body_fingerprint: sha256(JSON.stringify(seed)),\n });\n }\n };\n const scenario = createMockScenarioController({\n specialism: 'creative-ad-server',\n snapshot: () => ({\n creatives: creatives.size,\n idempotency: idempotency.size,\n traffic: Object.fromEntries(traffic),\n }),\n reset: () => {\n resetCreatives();\n idempotency.clear();\n traffic.clear();\n },\n });\n\n const server = createServer((req, res) => {\n handleRequest(req, res).catch(err => {\n writeJson(res, 500, { code: 'internal_error', message: err?.message ?? 'unexpected error' });\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(options.port, '127.0.0.1', () => {\n server.removeListener('error', reject);\n resolve();\n });\n });\n\n const addr = server.address();\n const boundPort = typeof addr === 'object' && addr ? addr.port : options.port;\n const url = `http://127.0.0.1:${boundPort}`;\n return {\n url,\n scenario: scenario.handle,\n close: () =>\n new Promise<void>((resolve, reject) => {\n server.close(err => (err ? reject(err) : resolve()));\n }),\n };\n\n async function handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const reqUrl = new URL(req.url ?? '/', url);\n const path = reqUrl.pathname;\n const method = req.method ?? 'GET';\n\n if (await scenario.handleControlRequest(req, res, method, path)) return;\n\n // Façade-detection traffic dump — harness-only, no auth required.\n if (method === 'GET' && path === '/_debug/traffic') {\n writeJson(res, 200, { traffic: Object.fromEntries(traffic) });\n return;\n }\n\n // Network discovery — no auth (happens before tenant context is known).\n if (method === 'GET' && path === '/_lookup/network') {\n bump('GET /_lookup/network');\n const adcpPublisher = reqUrl.searchParams.get('adcp_publisher');\n if (!adcpPublisher) {\n writeJson(res, 400, { code: 'invalid_request', message: 'adcp_publisher query parameter is required.' });\n return;\n }\n const match = networks.find(n => n.adcp_publisher === adcpPublisher);\n if (!match) {\n writeJson(res, 404, {\n code: 'network_not_found',\n message: `No upstream network registered for adcp_publisher=${adcpPublisher}.`,\n });\n return;\n }\n writeJson(res, 200, {\n adcp_publisher: match.adcp_publisher,\n network_code: match.network_code,\n display_name: match.display_name,\n });\n return;\n }\n\n // /serve/{creative_id} — real HTML response. No bearer auth: this is\n // the URL real ad servers expose to publisher iframes; gating it on\n // bearer tokens would defeat the test-mode CDN-style pattern. The\n // creative_id itself is the capability — leak prevention is whoever\n // gets the URL gets the render. Production servers of course gate\n // this through signed URLs / referrer checks.\n const serveMatch = path.match(/^\\/serve\\/([^/]+)$/);\n if (method === 'GET' && serveMatch && serveMatch[1]) {\n bump('GET /serve/{id}');\n const creativeId = decodeURIComponent(serveMatch[1]);\n const cr = creatives.get(creativeId);\n if (!cr) {\n res.writeHead(404, { 'Content-Type': 'text/html' });\n res.end('<!doctype html><title>Not found</title>');\n return;\n }\n const ctxParam = reqUrl.searchParams.get('ctx') ?? '';\n const html = renderServeHtml(cr, formats, url, ctxParam);\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(html);\n return;\n }\n\n // Auth gate for /v1/* surface.\n const auth = req.headers['authorization'];\n if (!auth || !auth.startsWith('Bearer ') || auth.slice(7) !== apiKey) {\n writeJson(res, 401, { code: 'unauthorized', message: 'Missing or invalid bearer credential.' });\n return;\n }\n const networkHeader = req.headers['x-network-code'];\n const networkCode = Array.isArray(networkHeader) ? networkHeader[0] : networkHeader;\n if (!networkCode) {\n writeJson(res, 403, { code: 'network_required', message: 'X-Network-Code header is required on every request.' });\n return;\n }\n const network = networks.find(n => n.network_code === networkCode);\n if (!network) {\n writeJson(res, 403, { code: 'unknown_network', message: `Unknown network: ${networkCode}` });\n return;\n }\n\n if (await scenario.handleScriptedResponse(res, method, path, (m, p) => bump(`${m} ${p}`))) return;\n\n if (method === 'GET' && path === '/v1/formats') {\n bump('GET /v1/formats');\n const filtered = formats.filter(f => f.network_code === network.network_code);\n writeJson(res, 200, {\n formats: filtered.map(f => ({\n format_id: f.format_id,\n name: f.name,\n channel: f.channel,\n render_kind: f.render_kind,\n ...(f.width !== undefined && { width: f.width }),\n ...(f.height !== undefined && { height: f.height }),\n ...(f.duration_seconds !== undefined && { duration_seconds: f.duration_seconds }),\n accepted_mimes: f.accepted_mimes,\n })),\n });\n return;\n }\n\n if (method === 'GET' && path === '/v1/creatives') {\n bump('GET /v1/creatives');\n return handleListCreatives(reqUrl, network, res);\n }\n\n if (method === 'POST' && path === '/v1/creatives') {\n bump('POST /v1/creatives');\n return handleCreateCreative(req, network, res);\n }\n\n const creativeMatch = path.match(/^\\/v1\\/creatives\\/([^/]+)(\\/.*)?$/);\n if (creativeMatch && creativeMatch[1]) {\n const creativeId = decodeURIComponent(creativeMatch[1]);\n const subPath = creativeMatch[2] ?? '/';\n const creative = creatives.get(creativeId);\n if (!creative || creative.network_code !== network.network_code) {\n writeJson(res, 404, { code: 'creative_not_found', message: `Creative ${creativeId} not found.` });\n return;\n }\n if (method === 'GET' && subPath === '/') {\n bump('GET /v1/creatives/{id}');\n writeJson(res, 200, stripFingerprint(creative));\n return;\n }\n if (method === 'PATCH' && subPath === '/') {\n bump('PATCH /v1/creatives/{id}');\n return handleUpdateCreative(req, creative, res);\n }\n if (method === 'POST' && subPath === '/render') {\n bump('POST /v1/creatives/{id}/render');\n return handleRenderCreative(req, creative, res);\n }\n if (method === 'GET' && subPath === '/delivery') {\n bump('GET /v1/creatives/{id}/delivery');\n return handleGetDelivery(reqUrl, creative, res);\n }\n }\n\n writeJson(res, 404, { code: 'not_found', message: `No route for ${method} ${path}` });\n }\n\n // ────────────────────────────────────────────────────────────\n // Creatives library\n // ────────────────────────────────────────────────────────────\n\n function handleListCreatives(reqUrl: URL, network: MockNetwork, res: ServerResponse): void {\n let visible = Array.from(creatives.values()).filter(c => c.network_code === network.network_code);\n const advertiserId = reqUrl.searchParams.get('advertiser_id');\n if (advertiserId) visible = visible.filter(c => c.advertiser_id === advertiserId);\n const formatId = reqUrl.searchParams.get('format_id');\n if (formatId) visible = visible.filter(c => c.format_id === formatId);\n const status = reqUrl.searchParams.get('status');\n if (status) visible = visible.filter(c => c.status === status);\n const createdAfter = reqUrl.searchParams.get('created_after');\n if (createdAfter) visible = visible.filter(c => c.created_at >= createdAfter);\n const creativeIdsParam = reqUrl.searchParams.get('creative_ids');\n if (creativeIdsParam) {\n const ids = new Set(creativeIdsParam.split(','));\n visible = visible.filter(c => ids.has(c.creative_id));\n }\n visible.sort((a, b) => a.created_at.localeCompare(b.created_at));\n\n // Pagination cursor — opaque base64 of the next-row created_at.\n const limit = Math.min(\n Math.max(parsePositiveNumber(reqUrl.searchParams.get('limit')) ?? PAGE_SIZE_DEFAULT, 1),\n 200\n );\n const cursor = reqUrl.searchParams.get('cursor');\n let startIdx = 0;\n if (cursor) {\n try {\n const decoded = Buffer.from(cursor, 'base64url').toString('utf8');\n startIdx = visible.findIndex(c => c.created_at > decoded);\n if (startIdx < 0) startIdx = visible.length;\n } catch {\n writeJson(res, 400, { code: 'invalid_cursor', message: 'cursor is not a valid pagination token.' });\n return;\n }\n }\n const page = visible.slice(startIdx, startIdx + limit);\n const next = visible[startIdx + limit];\n const nextCursor = next ? Buffer.from(page[page.length - 1]?.created_at ?? '', 'utf8').toString('base64url') : null;\n\n writeJson(res, 200, {\n creatives: page.map(stripFingerprint),\n ...(nextCursor && { next_cursor: nextCursor }),\n });\n }\n\n async function handleCreateCreative(req: IncomingMessage, network: MockNetwork, res: ServerResponse): Promise<void> {\n const body = await readJsonObject(req, res);\n if (!body) return;\n const exactReplay = scenario.idempotency.check(\n `${network.network_code}::creative`,\n idempotencyKeyFromBody(body),\n stableFingerprint(body)\n );\n if (exactReplay.kind === 'replay' || exactReplay.kind === 'conflict') {\n writeCachedResponse(res, exactReplay.response);\n return;\n }\n const name = typeof body.name === 'string' ? body.name : null;\n const advertiserId = typeof body.advertiser_id === 'string' ? body.advertiser_id : null;\n const explicitFormatId = typeof body.format_id === 'string' ? body.format_id : null;\n const snippet = typeof body.snippet === 'string' ? body.snippet : undefined;\n const clickUrl = typeof body.click_url === 'string' ? body.click_url : undefined;\n const uploadMime = typeof body.upload_mime === 'string' ? body.upload_mime : undefined;\n const widthHint = typeof body.width === 'number' ? body.width : undefined;\n const heightHint = typeof body.height === 'number' ? body.height : undefined;\n const clientRequestId = typeof body.client_request_id === 'string' ? body.client_request_id : undefined;\n\n if (!name || !advertiserId) {\n writeJson(res, 400, { code: 'invalid_request', message: 'name and advertiser_id are required.' });\n return;\n }\n\n // Format auto-detection when format_id isn't supplied. Sniff by mime\n // type + dimensions hint. Real ad servers use richer detection\n // (binary header inspection, codec sniff for video); this is the\n // minimum to demonstrate the auto-detect surface.\n let format: MockFormat | undefined;\n if (explicitFormatId) {\n format = formats.find(f => f.format_id === explicitFormatId && f.network_code === network.network_code);\n if (!format) {\n writeJson(res, 404, {\n code: 'format_not_found',\n message: `Format ${explicitFormatId} not found on network ${network.network_code}.`,\n });\n return;\n }\n } else if (uploadMime) {\n const candidates = formats.filter(\n f => f.network_code === network.network_code && f.accepted_mimes.includes(uploadMime)\n );\n // Prefer dimension-matched fixed format when hint provided.\n if (widthHint !== undefined && heightHint !== undefined) {\n format = candidates.find(c => c.width === widthHint && c.height === heightHint);\n }\n if (!format) format = candidates[0];\n if (!format) {\n writeJson(res, 422, {\n code: 'format_auto_detect_failed',\n message: `Could not auto-detect format for upload_mime=${uploadMime}; pass an explicit format_id.`,\n field: 'format_id',\n });\n return;\n }\n } else {\n writeJson(res, 400, {\n code: 'invalid_request',\n message: 'either format_id or upload_mime is required.',\n field: 'format_id',\n });\n return;\n }\n\n const fingerprint = sha256(JSON.stringify({ name, advertiserId, formatId: format.format_id, snippet, clickUrl }));\n if (clientRequestId) {\n const key = `${network.network_code}::creative::${clientRequestId}`;\n const existing = idempotency.get(key);\n if (existing) {\n const existingCr = creatives.get(existing);\n if (existingCr) {\n if (existingCr.body_fingerprint !== fingerprint) {\n writeJson(res, 409, {\n code: 'idempotency_conflict',\n message: `client_request_id ${clientRequestId} previously used for a different body.`,\n });\n return;\n }\n writeJson(res, 200, { ...stripFingerprint(existingCr), replayed: true });\n return;\n }\n }\n }\n\n // Allow caller-supplied `creative_id` override — real ad servers\n // reject this (the platform owns the namespace), but cascade-test\n // seeders need to write under a known id so storyboard fixtures\n // can reference them by alias. Production sellers ship without this\n // override path.\n //\n // SECURITY GATES:\n // 1. Env allowlist — `MOCK_ALLOW_CREATIVE_ID_OVERRIDE=1` is required.\n // Default-off prevents an adopter who forks this mock and points it\n // at a public host from accepting buyer-supplied ids. The compliance\n // runner sets it via the seeder env; production never does.\n // 2. Cross-tenant collision check — if the id already exists on a\n // DIFFERENT network, refuse with 409. Without this, tenant B can\n // POST `creative_id: <tenant-A-id>` and overwrite tenant A's record;\n // reads stay network-gated but `/serve/{id}` is auth-free, so the\n // overwrite would be served as canonical.\n const overrideAllowed =\n typeof body.creative_id === 'string' && process.env['MOCK_ALLOW_CREATIVE_ID_OVERRIDE'] === '1';\n const explicitCreativeId = overrideAllowed ? (body.creative_id as string) : null;\n if (explicitCreativeId) {\n const existing = creatives.get(explicitCreativeId);\n if (existing && existing.network_code !== network.network_code) {\n writeJson(res, 409, {\n code: 'creative_id_conflict',\n message: `creative_id ${explicitCreativeId} already exists on a different network; cannot overwrite cross-tenant.`,\n field: 'creative_id',\n });\n return;\n }\n }\n const creativeId = explicitCreativeId ?? `cr_${randomUUID().replace(/-/g, '').slice(0, 16)}`;\n const now = new Date().toISOString();\n const cr: CreativeState = {\n creative_id: creativeId,\n network_code: network.network_code,\n advertiser_id: advertiserId,\n format_id: format.format_id,\n name,\n ...(snippet !== undefined && { snippet }),\n ...(clickUrl !== undefined && { click_url: clickUrl }),\n status: 'active',\n created_at: now,\n updated_at: now,\n body_fingerprint: fingerprint,\n };\n creatives.set(creativeId, cr);\n if (clientRequestId) {\n idempotency.set(`${network.network_code}::creative::${clientRequestId}`, creativeId);\n }\n const responseBody = stripFingerprint(cr);\n if (exactReplay.kind === 'fresh') exactReplay.record({ status: 201, body: responseBody });\n writeJson(res, 201, responseBody);\n }\n\n async function handleUpdateCreative(req: IncomingMessage, cr: CreativeState, res: ServerResponse): Promise<void> {\n const body = await readJsonObject(req, res);\n if (!body) return;\n if (typeof body.snippet === 'string') cr.snippet = body.snippet;\n if (typeof body.click_url === 'string') cr.click_url = body.click_url;\n if (typeof body.name === 'string') cr.name = body.name;\n if (typeof body.status === 'string') {\n const allowed = ['active', 'paused', 'archived', 'rejected'];\n if (!allowed.includes(body.status)) {\n writeJson(res, 400, { code: 'invalid_status', message: `status must be one of ${allowed.join(', ')}.` });\n return;\n }\n cr.status = body.status as CreativeState['status'];\n }\n cr.updated_at = new Date().toISOString();\n cr.body_fingerprint = sha256(\n JSON.stringify({\n name: cr.name,\n advertiserId: cr.advertiser_id,\n formatId: cr.format_id,\n snippet: cr.snippet,\n clickUrl: cr.click_url,\n })\n );\n writeJson(res, 200, stripFingerprint(cr));\n }\n\n // ────────────────────────────────────────────────────────────\n // Tag generation — macro substitution\n // ────────────────────────────────────────────────────────────\n\n async function handleRenderCreative(req: IncomingMessage, cr: CreativeState, res: ServerResponse): Promise<void> {\n const body = await readJsonObject(req, res);\n if (!body) return;\n const ctx = isObject(body.context) ? body.context : {};\n const format = formats.find(f => f.format_id === cr.format_id && f.network_code === cr.network_code);\n if (!format) {\n writeJson(res, 500, {\n code: 'format_not_found',\n message: `Creative ${cr.creative_id} references unknown format ${cr.format_id}.`,\n });\n return;\n }\n const template = cr.snippet ?? format.snippet_template;\n // POST /render returns substituted HTML in the response body; the buyer\n // is expected to apply their own context (signed clickthroughs, viewability\n // shims) before serving. Escape values defensively because the same\n // bytes can land in a publisher's iframe via `tag_url` if the buyer\n // skips the secondary binding step.\n const substituted = substituteMacros(template, cr, format, ctx, true);\n const tagUrl = `${url}/serve/${encodeURIComponent(cr.creative_id)}?ctx=${encodeURIComponent(serializeCtx(ctx))}`;\n writeJson(res, 200, {\n creative_id: cr.creative_id,\n format_id: cr.format_id,\n tag_html: substituted,\n tag_url: tagUrl,\n preview_url: tagUrl,\n });\n }\n\n // ────────────────────────────────────────────────────────────\n // Delivery — synth impressions/clicks scaled by days-active\n // ────────────────────────────────────────────────────────────\n\n function handleGetDelivery(reqUrl: URL, cr: CreativeState, res: ServerResponse): void {\n const startStr = reqUrl.searchParams.get('start');\n const endStr = reqUrl.searchParams.get('end');\n const now = Date.now();\n const start = startStr ? Date.parse(startStr) : Date.parse(cr.created_at);\n const end = endStr ? Date.parse(endStr) : now;\n if (!Number.isFinite(start) || !Number.isFinite(end) || end < start) {\n writeJson(res, 400, { code: 'invalid_request', message: 'start/end must be ISO 8601 with end ≥ start.' });\n return;\n }\n\n const format = formats.find(f => f.format_id === cr.format_id && f.network_code === cr.network_code);\n const channel = format?.channel ?? 'display';\n // Per-format CTR baselines (industry-typical):\n // display ~0.10%, video ~1.5%, ctv ~3%, audio ~0.5%\n const ctrBaseline = channel === 'video' ? 0.015 : channel === 'ctv' ? 0.03 : channel === 'audio' ? 0.005 : 0.001;\n\n const days = Math.max(1, Math.ceil((end - start) / (24 * 60 * 60 * 1000)));\n const breakdown: Array<{ date: string; impressions: number; clicks: number }> = [];\n let totalImpressions = 0;\n let totalClicks = 0;\n for (let d = 0; d < days; d++) {\n const dayStart = new Date(start + d * 24 * 60 * 60 * 1000);\n const dateIso = dayStart.toISOString().slice(0, 10);\n const seedHex = sha256(`${cr.creative_id}::${dateIso}`).slice(0, 8);\n const seed = parseInt(seedHex, 16);\n // Deterministic pseudo-random impressions in [10_000, 100_000].\n const impressions = 10_000 + (seed % 90_001);\n const clicks = Math.round(impressions * ctrBaseline);\n breakdown.push({ date: dateIso, impressions, clicks });\n totalImpressions += impressions;\n totalClicks += clicks;\n }\n writeJson(res, 200, {\n creative_id: cr.creative_id,\n reporting_period: {\n start: new Date(start).toISOString(),\n end: new Date(end).toISOString(),\n },\n totals: {\n impressions: totalImpressions,\n clicks: totalClicks,\n ctr: totalImpressions > 0 ? totalClicks / totalImpressions : 0,\n },\n breakdown,\n });\n }\n}\n\n// ────────────────────────────────────────────────────────────\n// Helpers\n// ────────────────────────────────────────────────────────────\n\nfunction writeJson(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(body));\n}\n\nasync function readJsonObject(req: IncomingMessage, res: ServerResponse): Promise<Record<string, unknown> | null> {\n const text = await new Promise<string>((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on('data', c => chunks.push(c));\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));\n req.on('error', reject);\n });\n if (!text) return {};\n try {\n const parsed = JSON.parse(text);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n writeJson(res, 400, { code: 'invalid_request', message: 'request body must be a JSON object.' });\n return null;\n }\n return parsed as Record<string, unknown>;\n } catch {\n writeJson(res, 400, { code: 'invalid_request', message: 'request body is not valid JSON.' });\n return null;\n }\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v);\n}\n\nfunction parsePositiveNumber(s: string | null): number | undefined {\n if (s === null) return undefined;\n const n = Number(s);\n return Number.isFinite(n) && n > 0 ? n : undefined;\n}\n\nfunction sha256(s: string): string {\n return createHash('sha256').update(s).digest('hex');\n}\n\nfunction stripFingerprint(cr: CreativeState): MockCreative {\n const { body_fingerprint: _bf, ...rest } = cr;\n void _bf;\n return rest;\n}\n\n/** Substitute `{macro}` placeholders into the template.\n *\n * When `htmlEscapeValues` is true, every macro value is HTML-escaped before\n * substitution. The raw-substitution path (htmlEscapeValues=false) returns\n * values verbatim — used by `POST /v1/creatives/{id}/render` callers who\n * apply their own context binding (signed clickthroughs, viewability shims).\n * The escape path is used by `GET /serve/{id}` because that endpoint emits\n * the substituted HTML directly to the browser with no caller intervention,\n * so caller-controlled `ctx` values (e.g. `click_url`) must NOT be able to\n * break out of attribute context and inject `<script>`.\n */\nfunction substituteMacros(\n template: string,\n cr: CreativeState,\n format: MockFormat,\n ctx: Record<string, unknown>,\n htmlEscapeValues: boolean\n): string {\n const click = typeof ctx['click_url'] === 'string' ? ctx['click_url'] : (cr.click_url ?? 'https://example.com/click');\n const assetUrl =\n typeof ctx['asset_url'] === 'string'\n ? ctx['asset_url']\n : 'https://test-assets.adcontextprotocol.org/placeholder.jpg';\n const impressionPixel =\n typeof ctx['impression_pixel'] === 'string'\n ? ctx['impression_pixel']\n : `https://imp.example/i?cr=${encodeURIComponent(cr.creative_id)}`;\n const cb = typeof ctx['cb'] === 'string' ? ctx['cb'] : String(Date.now());\n const macros: Record<string, string> = {\n click_url: String(click),\n asset_url: String(assetUrl),\n impression_pixel: String(impressionPixel),\n cb: String(cb),\n advertiser_id: cr.advertiser_id,\n creative_id: cr.creative_id,\n width: String(format.width ?? 0),\n height: String(format.height ?? 0),\n duration_seconds: String(format.duration_seconds ?? 0),\n };\n return template.replace(/\\{(\\w+)\\}/g, (m, key: string) => {\n const value = macros[key];\n if (value === undefined) return m;\n return htmlEscapeValues ? escapeHtml(value) : value;\n });\n}\n\nfunction serializeCtx(ctx: Record<string, unknown>): string {\n // Compact deterministic serialization for the /serve URL — sorted\n // keys + JSON. Real ad servers use a binary keyed lookup; this is\n // human-debuggable for storyboard output.\n const sorted: Record<string, unknown> = {};\n for (const k of Object.keys(ctx).sort()) sorted[k] = ctx[k];\n return JSON.stringify(sorted);\n}\n\nfunction renderServeHtml(cr: CreativeState, formats: MockFormat[], baseUrl: string, ctxRaw: string): string {\n const format = formats.find(f => f.format_id === cr.format_id && f.network_code === cr.network_code);\n let ctx: Record<string, unknown> = {};\n try {\n if (ctxRaw) ctx = JSON.parse(ctxRaw) as Record<string, unknown>;\n } catch {\n // best-effort — treat as empty ctx\n }\n const template = cr.snippet ?? format?.snippet_template ?? '';\n // Escape macro values when rendering for the auth-free /serve endpoint.\n // Caller-controlled `ctx` (click_url, impression_pixel, etc.) flows\n // straight into attribute context; without escaping, a value like\n // `\"><script>...</script>` breaks out and executes under this origin.\n const body = format ? substituteMacros(template, cr, format, ctx, true) : template;\n return `<!doctype html>\n<html><head><meta charset=\"utf-8\"><title>${escapeHtml(cr.name)} — preview</title></head>\n<body style=\"margin:0;padding:0\">\n<!-- creative_id=${escapeHtml(cr.creative_id)} format_id=${escapeHtml(cr.format_id)} served from ${escapeHtml(baseUrl)} -->\n${body}\n</body></html>`;\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/[&<>\"']/g, c => {\n switch (c) {\n case '&':\n return '&';\n case '<':\n return '<';\n case '>':\n return '>';\n case '\"':\n return '"';\n case \"'\":\n return ''';\n default:\n return c;\n }\n });\n}\n\n// Re-export for adapters that want to drive Format projection from the\n// upstream catalog directly (rare — most adapters consume `GET /v1/formats`).\nexport { projectFormat };\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/mock-server/creative-ad-server/server.ts"],"sourcesContent":["/**\n * `creative-ad-server` upstream-shape mock-server. Stateful creative\n * library (POST writes, GET reads), tag generation with macro substitution,\n * synth delivery reporting. Closes #1459 (sub-issue of #1381).\n *\n * Pattern source:\n * - Library state shape: `sales-guaranteed/server.ts` handleCreateCreative /\n * handleListCreatives — network-scoped, idempotency on client_request_id.\n * - Format catalog projection: `creative-template/server.ts` (templates\n * in seed-data, projected at request-time).\n *\n * Specialism deltas vs `creative-template`:\n * - Stateful library (writes persist across calls).\n * - Format auto-detection from upload mime (handleCreateCreative).\n * - Tag generation (POST /v1/creatives/{id}/render) substitutes macros\n * into a stored snippet template — `{click_url}`, `{impression_pixel}`,\n * `{cb}`, `{advertiser_id}`, etc.\n * - Real `/serve/{creative_id}` HTML response — adopters get a true\n * iframe-embeddable URL on previewCreative, not a synthetic string.\n * - Delivery reporting (GET /v1/creatives/{id}/delivery) — synth\n * impressions/clicks/CTR scaled by days-active, deterministic-seeded\n * on (creative_id, day).\n * - Multi-tenancy via X-Network-Code header (mirrors sales-guaranteed).\n */\n\nimport { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { createHash, randomUUID } from 'node:crypto';\nimport {\n CREATIVES,\n DEFAULT_API_KEY,\n FORMATS,\n NETWORKS,\n projectFormat,\n type MockCreative,\n type MockFormat,\n type MockNetwork,\n} from './seed-data';\nimport {\n createMockScenarioController,\n idempotencyKeyFromBody,\n stableFingerprint,\n writeCachedResponse,\n type MockScenarioHandle,\n} from '../scenario';\n\nexport interface BootOptions {\n port: number;\n apiKey?: string;\n networks?: MockNetwork[];\n formats?: MockFormat[];\n creatives?: MockCreative[];\n}\n\nexport interface BootResult {\n url: string;\n close: () => Promise<void>;\n scenario: MockScenarioHandle;\n}\n\ninterface CreativeState extends MockCreative {\n body_fingerprint: string;\n}\n\nconst PAGE_SIZE_DEFAULT = 50;\n\nexport async function bootCreativeAdServer(options: BootOptions): Promise<BootResult> {\n const apiKey = options.apiKey ?? DEFAULT_API_KEY;\n const networks = options.networks ?? NETWORKS;\n const formats = options.formats ?? FORMATS;\n const seededCreatives = options.creatives ?? CREATIVES;\n\n const creatives = new Map<string, CreativeState>();\n for (const seed of seededCreatives) {\n creatives.set(seed.creative_id, {\n ...seed,\n body_fingerprint: sha256(JSON.stringify(seed)),\n });\n }\n\n // Idempotency table — keyed `<network_code>::creative::<client_request_id>`.\n const idempotency = new Map<string, string>();\n\n // Traffic counters keyed by `<METHOD> <route-template>`. Harness queries\n // `GET /_debug/traffic` after the storyboard run and asserts headline\n // routes were hit ≥1. Façade adapters that skip the upstream produce\n // zero counters and fail the assertion.\n const traffic = new Map<string, number>();\n const bump = (routeTemplate: string): void => {\n traffic.set(routeTemplate, (traffic.get(routeTemplate) ?? 0) + 1);\n };\n const resetCreatives = (): void => {\n creatives.clear();\n for (const seed of seededCreatives) {\n creatives.set(seed.creative_id, {\n ...seed,\n body_fingerprint: sha256(JSON.stringify(seed)),\n });\n }\n };\n const scenario = createMockScenarioController({\n specialism: 'creative-ad-server',\n snapshot: () => ({\n creatives: creatives.size,\n idempotency: idempotency.size,\n traffic: Object.fromEntries(traffic),\n }),\n reset: () => {\n resetCreatives();\n idempotency.clear();\n traffic.clear();\n },\n });\n\n const server = createServer((req, res) => {\n handleRequest(req, res).catch(err => {\n writeJson(res, 500, { code: 'internal_error', message: err?.message ?? 'unexpected error' });\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(options.port, '127.0.0.1', () => {\n server.removeListener('error', reject);\n resolve();\n });\n });\n\n const addr = server.address();\n const boundPort = typeof addr === 'object' && addr ? addr.port : options.port;\n const url = `http://127.0.0.1:${boundPort}`;\n return {\n url,\n scenario: scenario.handle,\n close: () =>\n new Promise<void>((resolve, reject) => {\n server.close(err => (err ? reject(err) : resolve()));\n }),\n };\n\n async function handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const reqUrl = new URL(req.url ?? '/', url);\n const path = reqUrl.pathname;\n const method = req.method ?? 'GET';\n\n if (await scenario.handleControlRequest(req, res, method, path)) return;\n\n // Façade-detection traffic dump — harness-only, no auth required.\n if (method === 'GET' && path === '/_debug/traffic') {\n writeJson(res, 200, { traffic: Object.fromEntries(traffic) });\n return;\n }\n\n // Network discovery — no auth (happens before tenant context is known).\n if (method === 'GET' && path === '/_lookup/network') {\n bump('GET /_lookup/network');\n const adcpPublisher = reqUrl.searchParams.get('adcp_publisher');\n if (!adcpPublisher) {\n writeJson(res, 400, { code: 'invalid_request', message: 'adcp_publisher query parameter is required.' });\n return;\n }\n const match = networks.find(n => n.adcp_publisher === adcpPublisher);\n if (!match) {\n writeJson(res, 404, {\n code: 'network_not_found',\n message: `No upstream network registered for adcp_publisher=${adcpPublisher}.`,\n });\n return;\n }\n writeJson(res, 200, {\n adcp_publisher: match.adcp_publisher,\n network_code: match.network_code,\n display_name: match.display_name,\n });\n return;\n }\n\n // /serve/{creative_id} — real HTML response. No bearer auth: this is\n // the URL real ad servers expose to publisher iframes; gating it on\n // bearer tokens would defeat the test-mode CDN-style pattern. The\n // creative_id itself is the capability — leak prevention is whoever\n // gets the URL gets the render. Production servers of course gate\n // this through signed URLs / referrer checks.\n const serveMatch = path.match(/^\\/serve\\/([^/]+)$/);\n if (method === 'GET' && serveMatch && serveMatch[1]) {\n bump('GET /serve/{id}');\n const creativeId = decodeURIComponent(serveMatch[1]);\n const cr = creatives.get(creativeId);\n if (!cr) {\n res.writeHead(404, { 'Content-Type': 'text/html' });\n res.end('<!doctype html><title>Not found</title>');\n return;\n }\n const ctxParam = reqUrl.searchParams.get('ctx') ?? '';\n const html = renderServeHtml(cr, formats, url, ctxParam);\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(html);\n return;\n }\n\n // Auth gate for /v1/* surface.\n const auth = req.headers['authorization'];\n if (!auth || !auth.startsWith('Bearer ') || auth.slice(7) !== apiKey) {\n writeJson(res, 401, { code: 'unauthorized', message: 'Missing or invalid bearer credential.' });\n return;\n }\n const networkHeader = req.headers['x-network-code'];\n const networkCode = Array.isArray(networkHeader) ? networkHeader[0] : networkHeader;\n if (!networkCode) {\n writeJson(res, 403, { code: 'network_required', message: 'X-Network-Code header is required on every request.' });\n return;\n }\n const network = networks.find(n => n.network_code === networkCode);\n if (!network) {\n writeJson(res, 403, { code: 'unknown_network', message: `Unknown network: ${networkCode}` });\n return;\n }\n\n if (await scenario.handleScriptedResponse(res, method, path, (m, p) => bump(`${m} ${p}`))) return;\n\n if (method === 'GET' && path === '/v1/formats') {\n bump('GET /v1/formats');\n const filtered = formats.filter(f => f.network_code === network.network_code);\n writeJson(res, 200, {\n formats: filtered.map(f => ({\n format_id: f.format_id,\n name: f.name,\n channel: f.channel,\n render_kind: f.render_kind,\n ...(f.width !== undefined && { width: f.width }),\n ...(f.height !== undefined && { height: f.height }),\n ...(f.duration_seconds !== undefined && { duration_seconds: f.duration_seconds }),\n accepted_mimes: f.accepted_mimes,\n })),\n });\n return;\n }\n\n if (method === 'GET' && path === '/v1/creatives') {\n bump('GET /v1/creatives');\n return handleListCreatives(reqUrl, network, res);\n }\n\n if (method === 'POST' && path === '/v1/creatives') {\n bump('POST /v1/creatives');\n return handleCreateCreative(req, network, res);\n }\n\n const creativeMatch = path.match(/^\\/v1\\/creatives\\/([^/]+)(\\/.*)?$/);\n if (creativeMatch && creativeMatch[1]) {\n const creativeId = decodeURIComponent(creativeMatch[1]);\n const subPath = creativeMatch[2] ?? '/';\n const creative = creatives.get(creativeId);\n if (!creative || creative.network_code !== network.network_code) {\n writeJson(res, 404, { code: 'creative_not_found', message: `Creative ${creativeId} not found.` });\n return;\n }\n if (method === 'GET' && subPath === '/') {\n bump('GET /v1/creatives/{id}');\n writeJson(res, 200, stripFingerprint(creative));\n return;\n }\n if (method === 'PATCH' && subPath === '/') {\n bump('PATCH /v1/creatives/{id}');\n return handleUpdateCreative(req, creative, res);\n }\n if (method === 'POST' && subPath === '/render') {\n bump('POST /v1/creatives/{id}/render');\n return handleRenderCreative(req, creative, res);\n }\n if (method === 'GET' && subPath === '/delivery') {\n bump('GET /v1/creatives/{id}/delivery');\n return handleGetDelivery(reqUrl, creative, res);\n }\n }\n\n writeJson(res, 404, { code: 'not_found', message: `No route for ${method} ${path}` });\n }\n\n // ────────────────────────────────────────────────────────────\n // Creatives library\n // ────────────────────────────────────────────────────────────\n\n function handleListCreatives(reqUrl: URL, network: MockNetwork, res: ServerResponse): void {\n let visible = Array.from(creatives.values()).filter(c => c.network_code === network.network_code);\n const advertiserId = reqUrl.searchParams.get('advertiser_id');\n if (advertiserId) visible = visible.filter(c => c.advertiser_id === advertiserId);\n const formatId = reqUrl.searchParams.get('format_id');\n if (formatId) visible = visible.filter(c => c.format_id === formatId);\n const status = reqUrl.searchParams.get('status');\n if (status) visible = visible.filter(c => c.status === status);\n const createdAfter = reqUrl.searchParams.get('created_after');\n if (createdAfter) visible = visible.filter(c => c.created_at >= createdAfter);\n const creativeIdsParam = reqUrl.searchParams.get('creative_ids');\n if (creativeIdsParam) {\n const ids = new Set(creativeIdsParam.split(','));\n visible = visible.filter(c => ids.has(c.creative_id));\n }\n visible.sort((a, b) => a.created_at.localeCompare(b.created_at));\n\n // Pagination cursor — opaque base64 of the next-row created_at.\n const limit = Math.min(\n Math.max(parsePositiveNumber(reqUrl.searchParams.get('limit')) ?? PAGE_SIZE_DEFAULT, 1),\n 200\n );\n const cursor = reqUrl.searchParams.get('cursor');\n let startIdx = 0;\n if (cursor) {\n try {\n const decoded = Buffer.from(cursor, 'base64url').toString('utf8');\n startIdx = visible.findIndex(c => c.created_at > decoded);\n if (startIdx < 0) startIdx = visible.length;\n } catch {\n writeJson(res, 400, { code: 'invalid_cursor', message: 'cursor is not a valid pagination token.' });\n return;\n }\n }\n const page = visible.slice(startIdx, startIdx + limit);\n const next = visible[startIdx + limit];\n const nextCursor = next ? Buffer.from(page[page.length - 1]?.created_at ?? '', 'utf8').toString('base64url') : null;\n\n writeJson(res, 200, {\n creatives: page.map(stripFingerprint),\n ...(nextCursor && { next_cursor: nextCursor }),\n });\n }\n\n async function handleCreateCreative(req: IncomingMessage, network: MockNetwork, res: ServerResponse): Promise<void> {\n const body = await readJsonObject(req, res);\n if (!body) return;\n const exactReplay = scenario.idempotency.check(\n `${network.network_code}::creative`,\n idempotencyKeyFromBody(body),\n stableFingerprint(body)\n );\n if (exactReplay.kind === 'replay' || exactReplay.kind === 'conflict') {\n writeCachedResponse(res, exactReplay.response);\n return;\n }\n const name = typeof body.name === 'string' ? body.name : null;\n const advertiserId = typeof body.advertiser_id === 'string' ? body.advertiser_id : null;\n const explicitFormatId = typeof body.format_id === 'string' ? body.format_id : null;\n const snippet = typeof body.snippet === 'string' ? body.snippet : undefined;\n const clickUrl = typeof body.click_url === 'string' ? body.click_url : undefined;\n const uploadMime = typeof body.upload_mime === 'string' ? body.upload_mime : undefined;\n const widthHint = typeof body.width === 'number' ? body.width : undefined;\n const heightHint = typeof body.height === 'number' ? body.height : undefined;\n const clientRequestId = typeof body.client_request_id === 'string' ? body.client_request_id : undefined;\n\n if (!name || !advertiserId) {\n writeJson(res, 400, { code: 'invalid_request', message: 'name and advertiser_id are required.' });\n return;\n }\n\n // Format auto-detection when format_id isn't supplied. Sniff by mime\n // type + dimensions hint. Real ad servers use richer detection\n // (binary header inspection, codec sniff for video); this is the\n // minimum to demonstrate the auto-detect surface.\n let format: MockFormat | undefined;\n if (explicitFormatId) {\n format = formats.find(f => f.format_id === explicitFormatId && f.network_code === network.network_code);\n if (!format) {\n writeJson(res, 404, {\n code: 'format_not_found',\n message: `Format ${explicitFormatId} not found on network ${network.network_code}.`,\n });\n return;\n }\n } else if (uploadMime) {\n const candidates = formats.filter(\n f => f.network_code === network.network_code && f.accepted_mimes.includes(uploadMime)\n );\n // Prefer dimension-matched fixed format when hint provided.\n if (widthHint !== undefined && heightHint !== undefined) {\n format = candidates.find(c => c.width === widthHint && c.height === heightHint);\n }\n if (!format) format = candidates[0];\n if (!format) {\n writeJson(res, 422, {\n code: 'format_auto_detect_failed',\n message: `Could not auto-detect format for upload_mime=${uploadMime}; pass an explicit format_id.`,\n field: 'format_id',\n });\n return;\n }\n } else {\n writeJson(res, 400, {\n code: 'invalid_request',\n message: 'either format_id or upload_mime is required.',\n field: 'format_id',\n });\n return;\n }\n\n const fingerprint = sha256(JSON.stringify({ name, advertiserId, formatId: format.format_id, snippet, clickUrl }));\n if (clientRequestId) {\n const key = `${network.network_code}::creative::${clientRequestId}`;\n const existing = idempotency.get(key);\n if (existing) {\n const existingCr = creatives.get(existing);\n if (existingCr) {\n if (existingCr.body_fingerprint !== fingerprint) {\n writeJson(res, 409, {\n code: 'idempotency_conflict',\n message: `client_request_id ${clientRequestId} previously used for a different body.`,\n });\n return;\n }\n writeJson(res, 200, { ...stripFingerprint(existingCr), replayed: true });\n return;\n }\n }\n }\n\n // Allow caller-supplied `creative_id` override — real ad servers\n // reject this (the platform owns the namespace), but cascade-test\n // seeders need to write under a known id so storyboard fixtures\n // can reference them by alias. Production sellers ship without this\n // override path.\n //\n // SECURITY GATES:\n // 1. Env allowlist — `MOCK_ALLOW_CREATIVE_ID_OVERRIDE=1` is required.\n // Default-off prevents an adopter who forks this mock and points it\n // at a public host from accepting buyer-supplied ids. The compliance\n // runner sets it via the seeder env; production never does.\n // 2. Cross-tenant collision check — if the id already exists on a\n // DIFFERENT network, refuse with 409. Without this, tenant B can\n // POST `creative_id: <tenant-A-id>` and overwrite tenant A's record;\n // reads stay network-gated but `/serve/{id}` is auth-free, so the\n // overwrite would be served as canonical.\n const overrideAllowed =\n typeof body.creative_id === 'string' && process.env['MOCK_ALLOW_CREATIVE_ID_OVERRIDE'] === '1';\n const explicitCreativeId = overrideAllowed ? (body.creative_id as string) : null;\n if (explicitCreativeId) {\n const existing = creatives.get(explicitCreativeId);\n if (existing && existing.network_code !== network.network_code) {\n writeJson(res, 409, {\n code: 'creative_id_conflict',\n message: `creative_id ${explicitCreativeId} already exists on a different network; cannot overwrite cross-tenant.`,\n field: 'creative_id',\n });\n return;\n }\n }\n const creativeId = explicitCreativeId ?? `cr_${randomUUID().replace(/-/g, '').slice(0, 16)}`;\n const now = new Date().toISOString();\n const cr: CreativeState = {\n creative_id: creativeId,\n network_code: network.network_code,\n advertiser_id: advertiserId,\n format_id: format.format_id,\n name,\n ...(snippet !== undefined && { snippet }),\n ...(clickUrl !== undefined && { click_url: clickUrl }),\n status: 'active',\n created_at: now,\n updated_at: now,\n body_fingerprint: fingerprint,\n };\n creatives.set(creativeId, cr);\n if (clientRequestId) {\n idempotency.set(`${network.network_code}::creative::${clientRequestId}`, creativeId);\n }\n const responseBody = stripFingerprint(cr);\n if (exactReplay.kind === 'fresh') exactReplay.record({ status: 201, body: responseBody });\n writeJson(res, 201, responseBody);\n }\n\n async function handleUpdateCreative(req: IncomingMessage, cr: CreativeState, res: ServerResponse): Promise<void> {\n const body = await readJsonObject(req, res);\n if (!body) return;\n if (typeof body.snippet === 'string') cr.snippet = body.snippet;\n if (typeof body.click_url === 'string') cr.click_url = body.click_url;\n if (typeof body.name === 'string') cr.name = body.name;\n if (typeof body.status === 'string') {\n const allowed = ['active', 'paused', 'archived', 'rejected'];\n if (!allowed.includes(body.status)) {\n writeJson(res, 400, { code: 'invalid_status', message: `status must be one of ${allowed.join(', ')}.` });\n return;\n }\n cr.status = body.status as CreativeState['status'];\n }\n cr.updated_at = new Date().toISOString();\n cr.body_fingerprint = sha256(\n JSON.stringify({\n name: cr.name,\n advertiserId: cr.advertiser_id,\n formatId: cr.format_id,\n snippet: cr.snippet,\n clickUrl: cr.click_url,\n })\n );\n writeJson(res, 200, stripFingerprint(cr));\n }\n\n // ────────────────────────────────────────────────────────────\n // Tag generation — macro substitution\n // ────────────────────────────────────────────────────────────\n\n async function handleRenderCreative(req: IncomingMessage, cr: CreativeState, res: ServerResponse): Promise<void> {\n const body = await readJsonObject(req, res);\n if (!body) return;\n const ctx = isObject(body.context) ? body.context : {};\n const format = formats.find(f => f.format_id === cr.format_id && f.network_code === cr.network_code);\n if (!format) {\n writeJson(res, 500, {\n code: 'format_not_found',\n message: `Creative ${cr.creative_id} references unknown format ${cr.format_id}.`,\n });\n return;\n }\n const template = cr.snippet ?? format.snippet_template;\n // POST /render returns substituted HTML in the response body; the buyer\n // is expected to apply their own context (signed clickthroughs, viewability\n // shims) before serving. Escape values defensively because the same\n // bytes can land in a publisher's iframe via `tag_url` if the buyer\n // skips the secondary binding step.\n const substituted = substituteMacros(template, cr, format, ctx, true);\n const tagUrl = `${url}/serve/${encodeURIComponent(cr.creative_id)}?ctx=${encodeURIComponent(serializeCtx(ctx))}`;\n writeJson(res, 200, {\n creative_id: cr.creative_id,\n format_id: cr.format_id,\n tag_html: substituted,\n tag_url: tagUrl,\n preview_url: tagUrl,\n });\n }\n\n // ────────────────────────────────────────────────────────────\n // Delivery — synth impressions/clicks scaled by days-active\n // ────────────────────────────────────────────────────────────\n\n function handleGetDelivery(reqUrl: URL, cr: CreativeState, res: ServerResponse): void {\n const startStr = reqUrl.searchParams.get('start');\n const endStr = reqUrl.searchParams.get('end');\n const now = Date.now();\n const start = startStr ? Date.parse(startStr) : Date.parse(cr.created_at);\n const end = endStr ? Date.parse(endStr) : now;\n if (!Number.isFinite(start) || !Number.isFinite(end) || end < start) {\n writeJson(res, 400, { code: 'invalid_request', message: 'start/end must be ISO 8601 with end ≥ start.' });\n return;\n }\n\n const format = formats.find(f => f.format_id === cr.format_id && f.network_code === cr.network_code);\n const channel = format?.channel ?? 'display';\n // Per-format CTR baselines (industry-typical):\n // display ~0.10%, video ~1.5%, ctv ~3%, audio ~0.5%\n const ctrBaseline = channel === 'video' ? 0.015 : channel === 'ctv' ? 0.03 : channel === 'audio' ? 0.005 : 0.001;\n\n const days = Math.max(1, Math.ceil((end - start) / (24 * 60 * 60 * 1000)));\n const breakdown: Array<{ date: string; impressions: number; clicks: number }> = [];\n let totalImpressions = 0;\n let totalClicks = 0;\n for (let d = 0; d < days; d++) {\n const dayStart = new Date(start + d * 24 * 60 * 60 * 1000);\n const dateIso = dayStart.toISOString().slice(0, 10);\n const seedHex = sha256(`${cr.creative_id}::${dateIso}`).slice(0, 8);\n const seed = parseInt(seedHex, 16);\n // Deterministic pseudo-random impressions in [10_000, 100_000].\n const impressions = 10_000 + (seed % 90_001);\n const clicks = Math.round(impressions * ctrBaseline);\n breakdown.push({ date: dateIso, impressions, clicks });\n totalImpressions += impressions;\n totalClicks += clicks;\n }\n writeJson(res, 200, {\n creative_id: cr.creative_id,\n reporting_period: {\n start: new Date(start).toISOString(),\n end: new Date(end).toISOString(),\n },\n totals: {\n impressions: totalImpressions,\n clicks: totalClicks,\n ctr: totalImpressions > 0 ? totalClicks / totalImpressions : 0,\n },\n breakdown,\n });\n }\n}\n\n// ────────────────────────────────────────────────────────────\n// Helpers\n// ────────────────────────────────────────────────────────────\n\nfunction writeJson(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(body));\n}\n\nasync function readJsonObject(req: IncomingMessage, res: ServerResponse): Promise<Record<string, unknown> | null> {\n const text = await new Promise<string>((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on('data', c => chunks.push(c));\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));\n req.on('error', reject);\n });\n if (!text) return {};\n try {\n const parsed = JSON.parse(text);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n writeJson(res, 400, { code: 'invalid_request', message: 'request body must be a JSON object.' });\n return null;\n }\n return parsed as Record<string, unknown>;\n } catch {\n writeJson(res, 400, { code: 'invalid_request', message: 'request body is not valid JSON.' });\n return null;\n }\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v);\n}\n\nfunction parsePositiveNumber(s: string | null): number | undefined {\n if (s === null) return undefined;\n const n = Number(s);\n return Number.isFinite(n) && n > 0 ? n : undefined;\n}\n\nfunction sha256(s: string): string {\n return createHash('sha256').update(s).digest('hex');\n}\n\nfunction stripFingerprint(cr: CreativeState): MockCreative {\n const { body_fingerprint: _bf, ...rest } = cr;\n void _bf;\n return rest;\n}\n\n/** Substitute `{macro}` placeholders into the template.\n *\n * When `htmlEscapeValues` is true, every macro value is HTML-escaped before\n * substitution. The raw-substitution path (htmlEscapeValues=false) returns\n * values verbatim — used by `POST /v1/creatives/{id}/render` callers who\n * apply their own context binding (signed clickthroughs, viewability shims).\n * The escape path is used by `GET /serve/{id}` because that endpoint emits\n * the substituted HTML directly to the browser with no caller intervention,\n * so caller-controlled `ctx` values (e.g. `click_url`) must NOT be able to\n * break out of attribute context and inject `<script>`.\n */\nfunction substituteMacros(\n template: string,\n cr: CreativeState,\n format: MockFormat,\n ctx: Record<string, unknown>,\n htmlEscapeValues: boolean\n): string {\n const click = typeof ctx['click_url'] === 'string' ? ctx['click_url'] : (cr.click_url ?? 'https://example.com/click');\n const assetUrl =\n typeof ctx['asset_url'] === 'string'\n ? ctx['asset_url']\n : 'https://test-assets.adcontextprotocol.org/placeholder.jpg';\n const impressionPixel =\n typeof ctx['impression_pixel'] === 'string'\n ? ctx['impression_pixel']\n : `https://imp.example/i?cr=${encodeURIComponent(cr.creative_id)}`;\n const cb = typeof ctx['cb'] === 'string' ? ctx['cb'] : String(Date.now());\n const macros: Record<string, string> = {\n click_url: String(click),\n asset_url: String(assetUrl),\n impression_pixel: String(impressionPixel),\n cb: String(cb),\n advertiser_id: cr.advertiser_id,\n creative_id: cr.creative_id,\n width: String(format.width ?? 0),\n height: String(format.height ?? 0),\n duration_seconds: String(format.duration_seconds ?? 0),\n };\n return template.replace(/\\{(\\w+)\\}/g, (m, key: string) => {\n const value = macros[key];\n if (value === undefined) return m;\n return htmlEscapeValues ? escapeHtml(value) : value;\n });\n}\n\nfunction serializeCtx(ctx: Record<string, unknown>): string {\n // Compact deterministic serialization for the /serve URL — sorted\n // keys + JSON. Real ad servers use a binary keyed lookup; this is\n // human-debuggable for storyboard output.\n const sorted: Record<string, unknown> = {};\n for (const k of Object.keys(ctx).sort()) sorted[k] = ctx[k];\n return JSON.stringify(sorted);\n}\n\nfunction renderServeHtml(cr: CreativeState, formats: MockFormat[], baseUrl: string, ctxRaw: string): string {\n const format = formats.find(f => f.format_id === cr.format_id && f.network_code === cr.network_code);\n let ctx: Record<string, unknown> = {};\n try {\n if (ctxRaw) ctx = JSON.parse(ctxRaw) as Record<string, unknown>;\n } catch {\n // best-effort — treat as empty ctx\n }\n const template = cr.snippet ?? format?.snippet_template ?? '';\n // Escape macro values when rendering for the auth-free /serve endpoint.\n // Caller-controlled `ctx` (click_url, impression_pixel, etc.) flows\n // straight into attribute context; without escaping, a value like\n // `\"><script>...</script>` breaks out and executes under this origin.\n const body = format ? substituteMacros(template, cr, format, ctx, true) : template;\n return `<!doctype html>\n<html><head><meta charset=\"utf-8\"><title>${escapeHtml(cr.name)} — preview</title></head>\n<body style=\"margin:0;padding:0\">\n<!-- creative_id=${escapeHtml(cr.creative_id)} format_id=${escapeHtml(cr.format_id)} served from ${escapeHtml(baseUrl)} -->\n${body}\n</body></html>`;\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/[&<>\"']/g, c => {\n switch (c) {\n case '&':\n return '&';\n case '<':\n return '<';\n case '>':\n return '>';\n case '\"':\n return '"';\n case \"'\":\n return ''';\n default:\n return c;\n }\n });\n}\n\n// Re-export for adapters that want to drive Format projection from the\n// upstream catalog directly (rare — most adapters consume `GET /v1/formats`).\nexport { projectFormat };\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
const TEMPLATES = [
|
|
8
2
|
{
|
|
9
3
|
template_id: "tpl_celtra_display_medrec_v2",
|