@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,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 IDENTIFIER_DIGEST_LIMIT = 64;
|
|
8
2
|
export {
|
|
9
3
|
IDENTIFIER_DIGEST_LIMIT
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/upstream-recorder/constants.ts"],"sourcesContent":["export const IDENTIFIER_DIGEST_LIMIT = 64;\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/upstream-recorder/constants.ts"],"sourcesContent":["export const IDENTIFIER_DIGEST_LIMIT = 64;\n"],"mappings":"AAAO,MAAM,0BAA0B;","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 {
|
|
8
2
|
PayloadDigestError,
|
|
9
3
|
computePayloadDigestSha256,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/upstream-recorder/index.ts"],"sourcesContent":["/**\n * `@adcp/sdk/upstream-recorder` — producer-side reference middleware.\n *\n * Adopters who want to opt into the AdCP `upstream_traffic` storyboard\n * check (spec PR adcontextprotocol/adcp#3816) need to record their\n * outbound HTTP calls in a session-scoped buffer and surface them to\n * storyboard runners via their `comply_test_controller`'s\n * `query_upstream_traffic` scenario. This module is the recording\n * primitive: a small, sandbox-only-by-default helper that wraps the\n * adapter's HTTP layer, applies redaction at recording time (so\n * plaintext secrets never sit in the buffer in memory), enforces\n * per-principal isolation (the spec's security HIGH requirement), and\n * exposes a `query()` method that maps directly onto the controller's\n * `UpstreamTrafficSuccess` response shape.\n *\n * Minimal adopter wire-up:\n *\n * ```ts\n * import { createUpstreamRecorder } from '@adcp/sdk/upstream-recorder';\n *\n * const recorder = createUpstreamRecorder({\n * enabled: process.env.NODE_ENV !== 'production',\n * });\n *\n * // 1. Wrap whatever HTTP client your adapter uses\n * const fetch = recorder.wrapFetch(globalThis.fetch);\n *\n * // 2. At your AdCP request handler boundary, scope every outbound call\n * // inside the handler to the resolving principal:\n * await recorder.runWithPrincipal(account.id, async () => {\n * await syncAudienceUpstream(...); // every fetch() inside is recorded\n * });\n *\n * // 3. In your `comply_test_controller` handler for scenario:\n * // `query_upstream_traffic`, project the recorder's query result\n * // onto the controller response shape:\n * function handleQueryUpstreamTraffic(req, principal) {\n * return toQueryUpstreamTrafficResponse(\n * recorder.query({\n * principal,\n * sinceTimestamp: req.params.since_timestamp,\n * endpointPattern: req.params.endpoint_pattern,\n * limit: req.params.limit,\n * attestationMode: req.params.attestation_mode,\n * identifierValueDigests: req.params.identifier_value_digests,\n * })\n * );\n * }\n * ```\n *\n * Digest-mode queries canonicalize JSON payloads before hashing. If a\n * recorded JSON payload cannot be canonicalized (for example because it\n * exceeds the recorder's depth cap), `query()` omits that entry and emits\n * `digest_canonicalization_failed` through `onError` rather than returning a\n * non-canonical digest.\n *\n * Production builds with `enabled: false` get a no-op recorder — every\n * method is a pass-through / empty-result, zero per-call overhead.\n *\n * Companion to issue adcp-client#1290; runner-side consumer is\n * `@adcp/sdk`'s storyboard runner (PR adcp-client#1289).\n */\n\nexport {\n PayloadDigestError,\n computePayloadDigestSha256,\n createUpstreamRecorder,\n toQueryUpstreamTrafficResponse,\n} from './recorder';\nexport type { PayloadDigestOptions } from './recorder';\nexport { UpstreamRecorderScopeError } from './types';\nexport type {\n PurposeClassifier,\n QueryUpstreamTrafficResponse,\n RecordInput,\n RecordedCall,\n UpstreamRecorder,\n UpstreamRecorderDebugInfo,\n UpstreamRecorderErrorEvent,\n UpstreamRecorderOptions,\n UpstreamRecorderQueryParams,\n UpstreamRecorderQueryResult,\n} from './types';\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/upstream-recorder/index.ts"],"sourcesContent":["/**\n * `@adcp/sdk/upstream-recorder` — producer-side reference middleware.\n *\n * Adopters who want to opt into the AdCP `upstream_traffic` storyboard\n * check (spec PR adcontextprotocol/adcp#3816) need to record their\n * outbound HTTP calls in a session-scoped buffer and surface them to\n * storyboard runners via their `comply_test_controller`'s\n * `query_upstream_traffic` scenario. This module is the recording\n * primitive: a small, sandbox-only-by-default helper that wraps the\n * adapter's HTTP layer, applies redaction at recording time (so\n * plaintext secrets never sit in the buffer in memory), enforces\n * per-principal isolation (the spec's security HIGH requirement), and\n * exposes a `query()` method that maps directly onto the controller's\n * `UpstreamTrafficSuccess` response shape.\n *\n * Minimal adopter wire-up:\n *\n * ```ts\n * import { createUpstreamRecorder } from '@adcp/sdk/upstream-recorder';\n *\n * const recorder = createUpstreamRecorder({\n * enabled: process.env.NODE_ENV !== 'production',\n * });\n *\n * // 1. Wrap whatever HTTP client your adapter uses\n * const fetch = recorder.wrapFetch(globalThis.fetch);\n *\n * // 2. At your AdCP request handler boundary, scope every outbound call\n * // inside the handler to the resolving principal:\n * await recorder.runWithPrincipal(account.id, async () => {\n * await syncAudienceUpstream(...); // every fetch() inside is recorded\n * });\n *\n * // 3. In your `comply_test_controller` handler for scenario:\n * // `query_upstream_traffic`, project the recorder's query result\n * // onto the controller response shape:\n * function handleQueryUpstreamTraffic(req, principal) {\n * return toQueryUpstreamTrafficResponse(\n * recorder.query({\n * principal,\n * sinceTimestamp: req.params.since_timestamp,\n * endpointPattern: req.params.endpoint_pattern,\n * limit: req.params.limit,\n * attestationMode: req.params.attestation_mode,\n * identifierValueDigests: req.params.identifier_value_digests,\n * })\n * );\n * }\n * ```\n *\n * Digest-mode queries canonicalize JSON payloads before hashing. If a\n * recorded JSON payload cannot be canonicalized (for example because it\n * exceeds the recorder's depth cap), `query()` omits that entry and emits\n * `digest_canonicalization_failed` through `onError` rather than returning a\n * non-canonical digest.\n *\n * Production builds with `enabled: false` get a no-op recorder — every\n * method is a pass-through / empty-result, zero per-call overhead.\n *\n * Companion to issue adcp-client#1290; runner-side consumer is\n * `@adcp/sdk`'s storyboard runner (PR adcp-client#1289).\n */\n\nexport {\n PayloadDigestError,\n computePayloadDigestSha256,\n createUpstreamRecorder,\n toQueryUpstreamTrafficResponse,\n} from './recorder';\nexport type { PayloadDigestOptions } from './recorder';\nexport { UpstreamRecorderScopeError } from './types';\nexport type {\n PurposeClassifier,\n QueryUpstreamTrafficResponse,\n RecordInput,\n RecordedCall,\n UpstreamRecorder,\n UpstreamRecorderDebugInfo,\n UpstreamRecorderErrorEvent,\n UpstreamRecorderOptions,\n UpstreamRecorderQueryParams,\n UpstreamRecorderQueryResult,\n} from './types';\n"],"mappings":"AA+DA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,kCAAkC;","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 { AsyncLocalStorage } from "node:async_hooks";
|
|
8
2
|
import { createHash } from "node:crypto";
|
|
9
3
|
import {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/upstream-recorder/recorder.ts"],"sourcesContent":["/**\n * `createUpstreamRecorder` implementation. See `./types.ts` for the public\n * surface and `./README` (file header on `index.ts`) for the why.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { createHash } from 'node:crypto';\nimport {\n normalizeSecretKeyPattern,\n redactSecrets,\n secretKeyPatternMatches,\n SECRET_KEY_PATTERN,\n} from '../utils/redact-secrets';\nimport { globToRegExp } from '../utils/glob';\nimport { canonicalize } from '../utils/jcs';\nimport { MAX_JSON_DEPTH } from '../utils/json-depth';\nimport { IDENTIFIER_DIGEST_LIMIT } from './constants';\nimport {\n UpstreamRecorderScopeError,\n type QueryUpstreamTrafficResponse,\n type RecordInput,\n type RawRecordedCall,\n type RecordedCall,\n type UpstreamRecorder,\n type UpstreamRecorderDebugInfo,\n type UpstreamRecorderErrorEvent,\n type UpstreamRecorderOptions,\n type UpstreamRecorderQueryParams,\n type UpstreamRecorderQueryResult,\n} from './types';\n\nconst DEFAULT_BUFFER_SIZE = 1000;\nconst DEFAULT_TTL_MS = 60 * 60 * 1000; // 1h\nconst DEFAULT_QUERY_LIMIT = 100;\nconst DEFAULT_MAX_PAYLOAD_BYTES = 65_536; // mirrors spec's `recorded_calls[].payload.maxLength`\nconst MAX_BUFFER_SIZE = 100_000;\nconst MAX_TTL_MS = 24 * 60 * 60 * 1000; // 24h\nconst VALID_PURPOSES = new Set([\n 'platform_primary',\n 'measurement',\n 'attribution',\n 'creative_serving',\n 'identity',\n 'other',\n]);\n\nexport class PayloadDigestError extends Error {\n cause: unknown;\n\n constructor(message: string, cause?: unknown) {\n super(message);\n this.name = 'PayloadDigestError';\n this.cause = cause;\n }\n}\n\n/**\n * Wrapped per-call entry stored in the buffer. Carries the public\n * `RecordedCall` plus the principal it was recorded under (kept off the\n * public type so cross-principal isolation is enforced at query time and\n * the principal never appears in the controller-response payload).\n */\ninterface InternalEntry {\n call: RawRecordedCall;\n principal: string;\n /** ms-since-epoch cached for TTL eviction; computed at insert time. */\n recordedAtMs: number;\n}\n\nfunction clamp(n: number | undefined, lo: number, hi: number, fallback: number): number {\n if (typeof n !== 'number' || !Number.isFinite(n)) return fallback;\n // Out-of-range values (zero / negative / above ceiling) revert to the\n // default rather than silently saturating at the limit — a typo'd\n // `bufferSize: -10` silently saturating to `1` would drop nearly\n // everything; the default is a much safer failure mode.\n if (n < lo || n > hi) return fallback;\n return n;\n}\n\nfunction isPrincipalString(p: unknown): p is string {\n return typeof p === 'string' && p.length > 0;\n}\n\n/**\n * Build the recorder. Producer-side companion to the\n * `runner-output-contract.yaml` v2.0.0 `upstream_traffic` storyboard\n * check (spec PR adcontextprotocol/adcp#3816).\n */\nexport function createUpstreamRecorder(options: UpstreamRecorderOptions = {}): UpstreamRecorder {\n const enabled = options.enabled ?? true;\n // Disabled-recorder fast-path: skip every wrapping cost. Production\n // builds get a no-op object whose methods compile to inlinable returns.\n if (!enabled) return makeNoopRecorder();\n\n // Production-enable footgun guard: when adopters ship with `enabled:\n // true` in `NODE_ENV=production` (forgot the gate, or the gate is\n // mis-evaluated), emit a one-time warning. ADCP_RECORDER_PRODUCTION_ACK=1\n // is the explicit acknowledgment escape hatch for the rare adopters\n // who legitimately want recording in prod.\n warnIfEnabledInProduction();\n\n const redactPattern = normalizeSecretKeyPattern(options.redactPattern ?? SECRET_KEY_PATTERN);\n const bufferSize = clamp(options.bufferSize, 1, MAX_BUFFER_SIZE, DEFAULT_BUFFER_SIZE);\n const ttlMs = clamp(options.ttlMs, 1, MAX_TTL_MS, DEFAULT_TTL_MS);\n const maxPayloadBytes = clamp(options.maxPayloadBytes, 0, 16 * 1024 * 1024, DEFAULT_MAX_PAYLOAD_BYTES);\n const purpose = options.purpose;\n const strict = options.strict === true;\n const onError = options.onError;\n\n // Buffer: ordered by insertion (== timestamp ascending). Eviction is\n // FIFO when full or TTL-prune at record time.\n const buffer: InternalEntry[] = [];\n\n // Active-principal context. Set by `runWithPrincipal`; read by the\n // wrapped fetch and by `record` when no explicit principal is passed.\n const principalStorage = new AsyncLocalStorage<string>();\n\n // ────────────────────────────────────────────────────────────\n // Internal helpers\n // ────────────────────────────────────────────────────────────\n\n function emitError(event: UpstreamRecorderErrorEvent): void {\n if (!onError) return;\n try {\n onError(event);\n } catch {\n // onError MUST NOT crash the recorder — silent.\n }\n }\n\n function evictExpired(nowMs: number): void {\n if (buffer.length === 0) return;\n const cutoff = nowMs - ttlMs;\n let idx = 0;\n while (idx < buffer.length && buffer[idx]!.recordedAtMs < cutoff) idx++;\n if (idx > 0) buffer.splice(0, idx);\n }\n\n function pushEntry(entry: InternalEntry): void {\n buffer.push(entry);\n while (buffer.length > bufferSize) buffer.shift();\n }\n\n function applyRedactionToHeaders(headers: Record<string, string> | undefined): Record<string, string> {\n if (!headers) return {};\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n const lower = k.toLowerCase();\n out[lower] = secretKeyPatternMatches(redactPattern, lower) ? '[redacted]' : v;\n }\n return out;\n }\n\n /**\n * Apply per-key redaction to the body. JSON bodies (objects + arrays)\n * walk through `redactSecrets`. Form-urlencoded strings parse +\n * key-redact + re-stringify so `access_token=xxx` is caught without\n * the adopter pre-redacting. Other string types pass through. Binary\n * types (Buffer / Blob / ArrayBuffer / TypedArray) are replaced with\n * a marker — the buffer should not hold raw bytes whose JSON-shape\n * is misleading downstream.\n */\n function applyRedactionToPayload(payload: unknown, contentType: string): { value: unknown; bytes: number } {\n const value = normalizeRecordedPayload(payload, contentType, redactPattern, maxPayloadBytes);\n return { value, bytes: payloadWireLength(value) };\n }\n\n function classifyPurpose(\n method: string,\n url: string,\n host: string,\n path: string,\n headers: Record<string, string>\n ): string | undefined {\n if (!purpose) return undefined;\n try {\n const value = purpose({ method, url, host, path, headers }) as unknown;\n if (value === undefined) return undefined;\n if (typeof value === 'string' && VALID_PURPOSES.has(value)) return value;\n emitError({ kind: 'classifier_invalid_purpose', purpose: typeof value === 'string' ? value : String(value) });\n return undefined;\n } catch (err) {\n emitError({ kind: 'classifier_threw', err });\n return undefined;\n }\n }\n\n function buildRecordedCall(input: RecordInput, nowMs: number): RawRecordedCall | null {\n try {\n const url = input.url;\n let host = '';\n let pathPart = '';\n try {\n const parsed = new URL(url);\n host = parsed.host;\n pathPart = parsed.pathname;\n } catch {\n emitError({ kind: 'url_parse_failed', url });\n }\n const redactedHeaders = applyRedactionToHeaders(input.headers);\n const purposeTag = classifyPurpose(input.method, url, host, pathPart, redactedHeaders);\n const { value: payload, bytes: payloadLength } = applyRedactionToPayload(input.payload, input.content_type);\n return {\n method: input.method,\n endpoint: `${input.method} ${url}`,\n url,\n host,\n path: pathPart,\n content_type: input.content_type,\n attestation_mode: 'raw',\n payload,\n payload_length: payloadLength,\n timestamp: new Date(nowMs).toISOString(),\n ...(input.status_code !== undefined && { status_code: input.status_code }),\n ...(purposeTag !== undefined && { purpose: purposeTag }),\n };\n } catch (err) {\n // Hostile / buggy payload (throwing getter, etc.). Recording MUST\n // never break the adapter call site.\n emitError({ kind: 'payload_build_failed', err });\n return null;\n }\n }\n\n // ────────────────────────────────────────────────────────────\n // Public methods\n // ────────────────────────────────────────────────────────────\n\n function runWithPrincipal<T>(principal: string, fn: () => T | Promise<T>): Promise<T> {\n if (!isPrincipalString(principal)) {\n return Promise.reject(\n new UpstreamRecorderScopeError(\n 'runWithPrincipal: principal MUST be a non-empty string. Pass the same identifier you receive in your comply_test_controller handler.'\n )\n );\n }\n return Promise.resolve(principalStorage.run(principal, fn));\n }\n\n function record(input: RecordInput, explicitPrincipal?: string): void {\n const principal = explicitPrincipal ?? principalStorage.getStore();\n if (!isPrincipalString(principal)) {\n if (strict) {\n throw new UpstreamRecorderScopeError(\n `record() called outside runWithPrincipal scope (method=${input.method}, url=${input.url}). Wrap the call site or pass an explicit principal.`\n );\n }\n emitError({ kind: 'unscoped_record', method: input.method, url: input.url });\n return;\n }\n const nowMs = Date.now();\n evictExpired(nowMs);\n const call = buildRecordedCall(input, nowMs);\n if (!call) return;\n pushEntry({ call, principal, recordedAtMs: nowMs });\n }\n\n function wrapFetch(originalFetch: typeof globalThis.fetch): typeof globalThis.fetch {\n return async function wrappedFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n const principal = principalStorage.getStore();\n // No active principal: pass through unchanged in non-strict mode.\n // In strict mode, a fetch outside scope is the same authoring bug\n // as `record()` outside scope and surfaces the same way.\n if (!principal) {\n if (strict) {\n throw new UpstreamRecorderScopeError(\n `wrapFetch invoked outside runWithPrincipal scope (input=${typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url}). Wrap the call site.`\n );\n }\n return originalFetch(input as Parameters<typeof globalThis.fetch>[0], init);\n }\n\n const method = (init?.method ?? (input instanceof Request ? input.method : 'GET')).toUpperCase();\n const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;\n\n // Header normalization — fetch's Headers form vs init.headers Record vs Request body.\n const headerObj: Record<string, string> = {};\n if (init?.headers) {\n const h = init.headers;\n if (h instanceof Headers) {\n h.forEach((v, k) => {\n headerObj[k.toLowerCase()] = v;\n });\n } else if (Array.isArray(h)) {\n for (const [k, v] of h) headerObj[k.toLowerCase()] = v;\n } else {\n for (const [k, v] of Object.entries(h as Record<string, string>)) headerObj[k.toLowerCase()] = v;\n }\n } else if (input instanceof Request) {\n input.headers.forEach((v, k) => {\n headerObj[k.toLowerCase()] = v;\n });\n }\n\n const contentType = headerObj['content-type'] ?? '';\n const payload = await readBody(input, init, contentType);\n\n // Fire the actual call; record after we have a status_code. On\n // throw, we still record the attempt with no status_code so the\n // adopter can see the call was made.\n let response: Response | undefined;\n let thrown: unknown;\n try {\n response = await originalFetch(input as Parameters<typeof globalThis.fetch>[0], init);\n } catch (err) {\n thrown = err;\n }\n\n record(\n {\n method,\n url,\n content_type: contentType,\n headers: headerObj,\n payload,\n ...(response && { status_code: response.status }),\n },\n principal\n );\n\n if (thrown) throw thrown;\n return response!;\n };\n }\n\n function query(params: UpstreamRecorderQueryParams): UpstreamRecorderQueryResult {\n if (!isPrincipalString(params.principal)) {\n throw new UpstreamRecorderScopeError(\n 'query({ principal }): principal MUST be a non-empty string. Cross-principal isolation depends on this — passing an empty / non-string value would silently match no entries and conceal misconfiguration.'\n );\n }\n const nowMs = Date.now();\n evictExpired(nowMs);\n const limit = clamp(params.limit, 1, bufferSize, DEFAULT_QUERY_LIMIT);\n const sinceMs = params.sinceTimestamp ? Date.parse(params.sinceTimestamp) : 0;\n const endpointMatcher = params.endpointPattern ? globToRegExp(params.endpointPattern) : undefined;\n\n const matched = buffer.filter(entry => {\n if (entry.principal !== params.principal) return false; // hard isolation\n if (entry.recordedAtMs < sinceMs) return false;\n if (endpointMatcher && !endpointMatcher.test(entry.call.endpoint)) return false;\n return true;\n });\n\n const items: RecordedCall[] = [];\n let total = 0;\n let dropped_count = 0;\n for (const entry of matched) {\n const projected = safeProjectRecordedCall(entry.call, params, emitError);\n if (!projected) {\n if (params.attestationMode === 'digest') dropped_count++;\n continue;\n }\n total++;\n if (items.length < limit) items.push(projected);\n }\n const since_timestamp =\n params.sinceTimestamp ?? matched[0]?.call.timestamp ?? new Date(nowMs - ttlMs).toISOString();\n return {\n items,\n total,\n truncated: total > items.length,\n since_timestamp,\n dropped_count,\n };\n }\n\n function clear(): void {\n buffer.length = 0;\n }\n\n function debug(): UpstreamRecorderDebugInfo {\n const principals = Array.from(new Set(buffer.map(e => e.principal))).sort();\n const last = buffer[buffer.length - 1];\n return {\n enabled: true,\n bufferSize,\n bufferedEntries: buffer.length,\n principals,\n lastRecordedAt: last ? last.call.timestamp : null,\n activePrincipal: principalStorage.getStore() ?? null,\n strict,\n };\n }\n\n return {\n runWithPrincipal,\n wrapFetch,\n record,\n query,\n clear,\n debug,\n enabled: true,\n };\n}\n\nfunction safeProjectRecordedCall(\n call: RawRecordedCall,\n params: UpstreamRecorderQueryParams,\n emitError?: (event: UpstreamRecorderErrorEvent) => void\n): RecordedCall | null {\n try {\n return projectRecordedCall(call, params, emitError);\n } catch (err) {\n emitError?.({ kind: 'digest_canonicalization_failed', method: call.method, endpoint: call.endpoint, err });\n return null;\n }\n}\n\nfunction projectRecordedCall(\n call: RawRecordedCall,\n params: UpstreamRecorderQueryParams,\n emitError?: (event: UpstreamRecorderErrorEvent) => void\n): RecordedCall {\n if (params.attestationMode !== 'digest') return call;\n const payloadBytes = canonicalPayloadBytes(call.payload, call.content_type);\n const payloadDigest = sha256Hex(payloadBytes);\n const identifierDigests = normalizeIdentifierDigests(params.identifierValueDigests);\n const identifierScanPayload =\n identifierDigests.length > 0\n ? parseJsonStringPayloadForScan(call.payload, call.content_type, emitError)\n : undefined;\n const matchedIdentifierDigests =\n identifierDigests.length > 0 && identifierScanPayload !== undefined\n ? collectMatchedStringLeafDigests(identifierScanPayload, new Set(identifierDigests))\n : undefined;\n const identifier_match_proofs =\n identifierDigests.length > 0 && matchedIdentifierDigests\n ? identifierDigests.map(digest => ({\n identifier_value_sha256: digest,\n found: matchedIdentifierDigests.has(digest),\n }))\n : undefined;\n\n return {\n method: call.method,\n endpoint: call.endpoint,\n url: call.url,\n host: call.host,\n path: call.path,\n content_type: call.content_type,\n attestation_mode: 'digest',\n payload_digest_sha256: payloadDigest,\n payload_length: byteLengthOf(payloadBytes),\n timestamp: call.timestamp,\n ...(call.status_code !== undefined && { status_code: call.status_code }),\n ...(call.purpose !== undefined && { purpose: call.purpose }),\n ...(identifier_match_proofs !== undefined && { identifier_match_proofs }),\n };\n}\n\nfunction normalizeIdentifierDigests(input: string[] | undefined): string[] {\n if (!Array.isArray(input)) return [];\n const out: string[] = [];\n for (const value of input) {\n if (typeof value !== 'string' || !/^[a-f0-9]{64}$/.test(value)) continue;\n if (!out.includes(value)) out.push(value);\n if (out.length >= IDENTIFIER_DIGEST_LIMIT) break;\n }\n return out;\n}\n\nfunction collectMatchedStringLeafDigests(root: unknown, wantedDigests: Set<string>): Set<string> {\n const matched = new Set<string>();\n const stack: Array<{ value: unknown; depth: number }> = [{ value: root, depth: 0 }];\n while (stack.length > 0) {\n const { value, depth } = stack.pop()!;\n if (depth > MAX_JSON_DEPTH) continue;\n if (typeof value === 'string') {\n const digest = sha256Hex(value);\n if (wantedDigests.has(digest)) {\n matched.add(digest);\n if (matched.size === wantedDigests.size) break;\n }\n } else if (Array.isArray(value)) {\n for (const item of value) stack.push({ value: item, depth: depth + 1 });\n } else if (value !== null && typeof value === 'object') {\n for (const item of Object.values(value as Record<string, unknown>)) {\n stack.push({ value: item, depth: depth + 1 });\n }\n }\n }\n return matched;\n}\n\nfunction parseJsonStringPayloadForScan(\n payload: unknown,\n contentType: string,\n emitError?: (event: UpstreamRecorderErrorEvent) => void\n): unknown | undefined {\n if (!isJsonContentType(contentType)) return undefined;\n if (typeof payload !== 'string') return payload;\n try {\n return JSON.parse(payload);\n } catch (err) {\n emitError?.({ kind: 'json_payload_parse_failed', content_type: contentType, err });\n return payload;\n }\n}\n\nfunction canonicalPayloadBytes(payload: unknown, contentType: string): string {\n if (isJsonContentType(contentType)) {\n if (typeof payload === 'string') {\n let parsed: unknown;\n try {\n parsed = JSON.parse(payload);\n } catch {\n return payload;\n }\n return canonicalJsonStringify(parsed);\n }\n return canonicalJsonStringify(payload);\n }\n if (typeof payload === 'string') return payload;\n return safeStringify(payload) ?? '';\n}\n\nfunction canonicalJsonStringify(value: unknown): string {\n assertJsonDepth(value);\n return canonicalize(value);\n}\n\nfunction assertJsonDepth(root: unknown): void {\n const stack: Array<{ value: unknown; depth: number }> = [{ value: root, depth: 0 }];\n while (stack.length > 0) {\n const { value, depth } = stack.pop()!;\n if (depth > MAX_JSON_DEPTH) {\n throw new RangeError(`JSON payload exceeds max canonicalization depth ${MAX_JSON_DEPTH}`);\n }\n if (Array.isArray(value)) {\n for (const item of value) stack.push({ value: item, depth: depth + 1 });\n } else if (value !== null && typeof value === 'object') {\n for (const item of Object.values(value as Record<string, unknown>)) {\n stack.push({ value: item, depth: depth + 1 });\n }\n }\n }\n}\n\nfunction sha256Hex(value: string): string {\n return createHash('sha256').update(value, 'utf8').digest('hex');\n}\n\n/**\n * Compute the `RecordedCall.payload_digest_sha256` value. By default this\n * applies the same body snapshot normalization, payload normalization, and\n * canonical secret-key redaction used by the recorder before hashing; pass a\n * custom redaction pattern and `maxPayloadBytes` when your recorder uses matching\n * options:\n *\n * - `createUpstreamRecorder({ redactPattern })` → `computePayloadDigestSha256(..., { redactPattern })`\n * - `createUpstreamRecorder({ maxPayloadBytes })` → `computePayloadDigestSha256(..., { maxPayloadBytes })`\n *\n * Prefer `{ prenormalized: true }` only when the payload has already been\n * normalized/redacted exactly as the recorder would store it; legacy `false`\n * remains accepted as the same prenormalized sentinel. The prenormalized path\n * skips redaction, so the helper rejects secret-shaped keys whose values are\n * not already the literal `\"[redacted]\"` marker or an explicit null\n * placeholder. For form-encoded bodies, duplicate secret-shaped keys are also\n * rejected because last-wins maps cannot prove that every original value was\n * inspected before hashing.\n *\n * JSON content is serialized with RFC 8785 JCS before hashing. When\n * `contentType` is JSON-shaped and `payload` is a string, the helper parses\n * it first so semantically equivalent JSON strings and objects hash to the\n * same value. On the normalizing path, an unparseable JSON-shaped string is\n * treated as the emitted body bytes and hashed verbatim after best-effort\n * redaction. On the prenormalized path, malformed JSON strings throw because\n * their secret-key structure cannot be proven safe. Unsupported JSON values\n * and payloads deeper than the recorder's depth cap throw rather than\n * producing a non-canonical digest.\n *\n * The returned digest is lowercase hex, matching the 3.1\n * `query_upstream_traffic` wire contract.\n */\nexport function computePayloadDigestSha256(\n payload: unknown,\n contentType?: string,\n options?: PayloadDigestOptions\n): string;\n/**\n * @deprecated Pass `{ redactPattern: /.../ }` instead of the bare `RegExp`\n * form. The legacy form remains accepted for this major.\n */\nexport function computePayloadDigestSha256(payload: unknown, contentType: string | undefined, options: RegExp): string;\n/**\n * @deprecated Pass `{ prenormalized: true }` instead of `false`. The legacy\n * form remains accepted for this major.\n */\nexport function computePayloadDigestSha256(payload: unknown, contentType: string | undefined, options: false): string;\nexport function computePayloadDigestSha256(\n payload: unknown,\n contentType = 'application/json',\n options: RegExp | false | PayloadDigestOptions = SECRET_KEY_PATTERN\n): string {\n const redactPattern =\n options instanceof RegExp || options === false\n ? options === false\n ? false\n : normalizeSecretKeyPattern(options)\n : options?.prenormalized\n ? false\n : options?.redactPattern === false\n ? false\n : normalizeSecretKeyPattern(options?.redactPattern ?? SECRET_KEY_PATTERN);\n const prenormalizedSafetyPattern =\n typeof options === 'object' &&\n options !== null &&\n !(options instanceof RegExp) &&\n options.redactPattern instanceof RegExp\n ? normalizeSecretKeyPattern(options.redactPattern)\n : SECRET_KEY_PATTERN;\n const maxPayloadBytes =\n typeof options === 'object' && options !== null && !(options instanceof RegExp)\n ? clamp(options.maxPayloadBytes, 0, 16 * 1024 * 1024, DEFAULT_MAX_PAYLOAD_BYTES)\n : DEFAULT_MAX_PAYLOAD_BYTES;\n try {\n if (\n typeof options === 'object' &&\n options !== null &&\n !(options instanceof RegExp) &&\n options.redactPattern === false &&\n options.prenormalized !== true\n ) {\n throw new PayloadDigestError('PayloadDigestOptions.redactPattern=false requires prenormalized=true');\n }\n const payloadForDigest =\n redactPattern === false\n ? assertPrenormalizedPayloadSafe(payload, contentType, prenormalizedSafetyPattern)\n : normalizeRecordedPayload(\n normalizeFetchPayloadInput(payload, contentType),\n contentType,\n redactPattern,\n maxPayloadBytes\n );\n return sha256Hex(canonicalPayloadBytes(payloadForDigest, contentType));\n } catch (err) {\n if (err instanceof PayloadDigestError) throw err;\n throw new PayloadDigestError(err instanceof Error ? err.message : 'Payload digest canonicalization failed', err);\n }\n}\n\nexport type PayloadDigestOptions = {\n /**\n * Custom redaction pattern. Passing `false` is accepted only with\n * `prenormalized: true`; otherwise it would silently bypass redaction.\n */\n redactPattern?: RegExp | false;\n /**\n * Match `createUpstreamRecorder({ maxPayloadBytes })` when computing\n * digests outside the recorder.\n */\n maxPayloadBytes?: number;\n /**\n * Set only for payloads that have already been normalized and redacted.\n * The helper skips redaction but still scans secret-shaped keys, rejects\n * malformed JSON strings, and rejects duplicate secret-shaped form keys.\n */\n prenormalized?: boolean;\n};\n\nfunction assertPrenormalizedPayloadSafe(payload: unknown, contentType: string, pattern: RegExp): unknown {\n let scanTarget = payload;\n if (typeof payload === 'string' && isJsonContentType(contentType)) {\n try {\n scanTarget = JSON.parse(payload);\n } catch {\n throw new PayloadDigestError(\n 'Prenormalized JSON payload is malformed; hash the recorder-normalized payload or omit prenormalized.'\n );\n }\n } else if (typeof payload === 'string' && isFormUrlEncoded(contentType)) {\n assertPrenormalizedFormUrlEncodedSafe(payload, pattern);\n return payload;\n }\n const unsafePath = findUnredactedSecretPath(scanTarget, pattern);\n if (unsafePath) {\n throw new PayloadDigestError(\n `Prenormalized payload contains unredacted secret-shaped key \"${unsafePath}\"; hash the recorder-normalized payload or omit prenormalized.`\n );\n }\n return payload;\n}\n\nfunction assertPrenormalizedFormUrlEncodedSafe(body: string, pattern: RegExp): void {\n const seenSecretKeys = new Set<string>();\n const params = Array.from(new URLSearchParams(body));\n for (const [key] of params) {\n if (!secretKeyPatternMatches(pattern, key)) continue;\n const normalizedKey = key.toLowerCase();\n if (seenSecretKeys.has(normalizedKey)) {\n throw new PayloadDigestError(\n `Prenormalized form payload contains duplicate secret-shaped key \"${key}\"; hash the recorder-normalized payload or omit prenormalized.`\n );\n }\n seenSecretKeys.add(normalizedKey);\n }\n for (const [key, value] of params) {\n if (!secretKeyPatternMatches(pattern, key)) continue;\n if (!isSafelyRedactedSecretValue(value)) {\n throw new PayloadDigestError(\n `Prenormalized payload contains unredacted secret-shaped key \"${key}\"; hash the recorder-normalized payload or omit prenormalized.`\n );\n }\n }\n}\n\nfunction findUnredactedSecretPath(value: unknown, pattern: RegExp): string | null {\n const stack: Array<{ value: unknown; path: string }> = [{ value, path: '' }];\n const seen = new WeakSet<object>();\n while (stack.length > 0) {\n const { value: current, path } = stack.pop()!;\n if (!current || typeof current !== 'object') continue;\n if (seen.has(current)) continue;\n seen.add(current);\n\n if (Array.isArray(current)) {\n for (let i = current.length - 1; i >= 0; i--) {\n stack.push({ value: current[i], path: `${path}[${i}]` });\n }\n continue;\n }\n\n const entries = Object.entries(current as Record<string, unknown>);\n for (let i = entries.length - 1; i >= 0; i--) {\n const [key, childValue] = entries[i]!;\n const childPath = path ? `${path}.${key}` : key;\n if (secretKeyPatternMatches(pattern, key) && !isSafelyRedactedSecretValue(childValue)) return childPath;\n stack.push({ value: childValue, path: childPath });\n }\n }\n return null;\n}\n\nfunction isSafelyRedactedSecretValue(value: unknown): boolean {\n return value === '[redacted]' || value === null;\n}\n\nfunction normalizeFetchPayloadInput(payload: unknown, contentType: string): unknown {\n if (payload === undefined) return undefined;\n if (typeof payload === 'string') {\n if (!isJsonContentType(contentType)) return payload;\n try {\n return JSON.parse(payload);\n } catch {\n return payload;\n }\n }\n if (payload instanceof URLSearchParams) return payload.toString();\n if (typeof FormData !== 'undefined' && payload instanceof FormData) {\n const out: Record<string, unknown> = {};\n payload.forEach((v, k) => {\n out[k] = typeof v === 'string' ? v : '[file]';\n });\n return out;\n }\n return payload;\n}\n\nfunction normalizeRecordedPayload(\n payload: unknown,\n contentType: string,\n redactPattern: RegExp,\n maxPayloadBytes: number\n): unknown {\n if (payload === undefined) {\n // Raw-mode `RecordedCall.payload` is required by the 3.1 controller\n // response schema. GET/HEAD-style calls with no body therefore emit an\n // empty object instead of omitting the field.\n return {};\n }\n if (payload === null) return payload;\n\n // Binary-shaped bodies — replace with a marker. Adopters that need\n // the raw bytes recorded for diagnostics can stringify before\n // calling `record()`.\n if (typeof Buffer !== 'undefined' && Buffer.isBuffer(payload)) {\n return `[binary ${payload.length} bytes]`;\n }\n if (typeof Blob !== 'undefined' && payload instanceof Blob) {\n return `[binary ${payload.size} bytes]`;\n }\n if (payload instanceof ArrayBuffer) {\n return `[binary ${payload.byteLength} bytes]`;\n }\n if (ArrayBuffer.isView(payload)) {\n return `[binary ${payload.byteLength} bytes]`;\n }\n\n if (typeof payload === 'string') {\n if (isJsonContentType(contentType)) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(payload);\n } catch {\n // Malformed JSON strings remain raw strings so diagnostics keep the\n // original body shape instead of pretending the payload was absent.\n return cap(redactJsonLikeSecretValues(payload, redactPattern), maxPayloadBytes);\n }\n const redacted = redactSecrets(parsed, redactPattern);\n assertJsonDepth(redacted);\n const json = safeStringify(redacted);\n if (json && maxPayloadBytes > 0 && byteLengthOf(json) > maxPayloadBytes) {\n return `[truncated ${byteLengthOf(json)} bytes]`;\n }\n return redacted;\n }\n // Form-urlencoded redaction: parse, redact, re-stringify so\n // `access_token=...` bodies don't slip through unredacted.\n if (isFormUrlEncoded(contentType)) {\n return cap(redactFormUrlEncoded(payload, redactPattern), maxPayloadBytes);\n }\n return cap(payload, maxPayloadBytes);\n }\n\n const redacted = redactSecrets(payload, redactPattern);\n assertJsonDepth(redacted);\n const json = safeStringify(redacted);\n if (json && maxPayloadBytes > 0 && byteLengthOf(json) > maxPayloadBytes) {\n return `[truncated ${byteLengthOf(json)} bytes]`;\n }\n return redacted;\n}\n\n/**\n * Project a `recorder.query()` result onto the spec wire shape returned\n * by `comply_test_controller`'s `query_upstream_traffic` scenario\n * (`UpstreamTrafficSuccess` in `comply-test-controller-response.json`,\n * spec PR adcontextprotocol/adcp#3816). Eliminates the\n * `items → recorded_calls` / `total → total_count` field-rename footgun\n * — adopters return this directly:\n *\n * ```ts\n * scenarios: {\n * query_upstream_traffic: ({ params }, ctx) =>\n * toQueryUpstreamTrafficResponse(\n * recorder.query({\n * principal: resolvePrincipal(ctx),\n * sinceTimestamp: params?.since_timestamp,\n * endpointPattern: params?.endpoint_pattern,\n * limit: params?.limit,\n * })\n * ),\n * }\n * ```\n */\nexport function toQueryUpstreamTrafficResponse(result: UpstreamRecorderQueryResult): QueryUpstreamTrafficResponse {\n return {\n success: true,\n recorded_calls: result.items,\n total_count: result.total,\n truncated: result.truncated,\n since_timestamp: result.since_timestamp,\n };\n}\n\n/**\n * No-op recorder returned when `enabled: false`. Every method is a\n * pass-through / empty-result. Production builds drop in this object\n * with zero per-call overhead beyond the initial factory call.\n */\nfunction makeNoopRecorder(): UpstreamRecorder {\n return {\n runWithPrincipal: <T>(_p: string, fn: () => T | Promise<T>): Promise<T> => Promise.resolve(fn()),\n wrapFetch: (originalFetch: typeof globalThis.fetch): typeof globalThis.fetch => originalFetch,\n record: () => undefined,\n query: (params: UpstreamRecorderQueryParams): UpstreamRecorderQueryResult => ({\n items: [],\n total: 0,\n truncated: false,\n since_timestamp: params.sinceTimestamp ?? new Date(0).toISOString(),\n dropped_count: 0,\n }),\n clear: () => undefined,\n debug: (): UpstreamRecorderDebugInfo => ({\n enabled: false,\n bufferSize: 0,\n bufferedEntries: 0,\n principals: [],\n lastRecordedAt: null,\n activePrincipal: null,\n strict: false,\n }),\n enabled: false,\n };\n}\n\nlet warnedAboutProduction = false;\nfunction warnIfEnabledInProduction(): void {\n if (warnedAboutProduction) return;\n if (typeof process === 'undefined' || !process.env) return;\n if (process.env.NODE_ENV !== 'production') return;\n if (process.env.ADCP_RECORDER_PRODUCTION_ACK === '1') return;\n warnedAboutProduction = true;\n // eslint-disable-next-line no-console\n console.warn(\n '[adcp/upstream-recorder] enabled: true in NODE_ENV=production. ' +\n 'The recorder buffers outbound HTTP calls in-memory — sandbox-only by design. ' +\n 'Set enabled: false (recommended) or ADCP_RECORDER_PRODUCTION_ACK=1 to silence.'\n );\n}\n\n/**\n * Read the request body off a fetch call site without consuming the\n * input (when the input is a `Request`, we'd lock its stream by reading\n * directly). Returns `undefined` for bodies the recorder can't snapshot\n * cheaply.\n */\nasync function readBody(\n input: RequestInfo | URL,\n init: RequestInit | undefined,\n contentType: string\n): Promise<unknown> {\n let raw: unknown;\n\n if (init?.body !== undefined && init.body !== null) {\n raw = init.body;\n } else if (input instanceof Request) {\n try {\n const clone = input.clone();\n if (contentTypeBase(contentType) === 'multipart/form-data') {\n raw = await clone.formData();\n } else {\n raw = await clone.text();\n }\n } catch {\n raw = undefined;\n }\n } else {\n raw = undefined;\n }\n\n if (raw === undefined) return undefined;\n if (typeof raw === 'string') {\n if (!isJsonContentType(contentType)) return raw;\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n }\n // FormData / URLSearchParams stringify cleanly enough for diagnostic value.\n if (raw instanceof URLSearchParams) return raw.toString();\n if (typeof FormData !== 'undefined' && raw instanceof FormData) {\n const out: Record<string, unknown> = {};\n raw.forEach((v, k) => {\n out[k] = typeof v === 'string' ? v : '[file]';\n });\n return out;\n }\n // Object / array literal already, or a Buffer / Blob / TypedArray /\n // ArrayBuffer the adopter passed in directly. Pass through — the\n // redaction step below detects binary types and substitutes markers\n // before they sit in the buffer.\n if (typeof raw === 'object') return raw;\n return String(raw);\n}\n\nfunction isJsonContentType(contentType: string | undefined): boolean {\n const base = contentTypeBase(contentType);\n return base === 'application/json' || /\\+json$/.test(base);\n}\n\nfunction isFormUrlEncoded(contentType: string | undefined): boolean {\n return contentTypeBase(contentType) === 'application/x-www-form-urlencoded';\n}\n\nfunction contentTypeBase(contentType: string | undefined): string {\n if (!contentType) return '';\n return contentType.split(';')[0]?.trim().toLowerCase() ?? '';\n}\n\nfunction redactFormUrlEncoded(body: string, pattern: RegExp): string {\n try {\n const params = new URLSearchParams(body);\n const out = new URLSearchParams();\n params.forEach((v, k) => {\n out.append(k, secretKeyPatternMatches(pattern, k.toLowerCase()) ? '[redacted]' : v);\n });\n return out.toString();\n } catch {\n return body;\n }\n}\n\nfunction redactJsonLikeSecretValues(body: string, pattern: RegExp): string {\n // Best-effort diagnostic scrub for malformed JSON strings. The output is\n // not guaranteed to be valid JSON; the invariant is that secret-shaped keys\n // with scalar/string values are not stored verbatim. Because malformed JSON\n // has no trustworthy parse tree, object/array-valued secret entries are\n // replaced wholesale rather than traversed.\n let out = '';\n let i = 0;\n while (i < body.length) {\n if (body[i] !== '\"') {\n out += body[i++];\n continue;\n }\n\n const keyToken = readJsonStringToken(body, i);\n if (!keyToken) {\n out += body.slice(i);\n break;\n }\n\n let colon = keyToken.end;\n while (colon < body.length && isJsonWhitespace(body[colon])) colon++;\n if (body[colon] !== ':') {\n out += body.slice(i, keyToken.end);\n i = keyToken.end;\n continue;\n }\n\n let key: unknown;\n try {\n key = JSON.parse(keyToken.literal);\n } catch {\n out += body.slice(i, keyToken.end);\n i = keyToken.end;\n continue;\n }\n\n const valueStart = colon + 1;\n let value = valueStart;\n while (value < body.length && isJsonWhitespace(body[value])) value++;\n out += body.slice(i, value);\n if (typeof key !== 'string' || !secretKeyPatternMatches(pattern, key)) {\n i = value;\n continue;\n }\n\n out += '\"[redacted]\"';\n i = skipJsonLikeValue(body, value);\n }\n return out;\n}\n\nfunction readJsonStringToken(input: string, start: number): { literal: string; end: number } | null {\n for (let i = start + 1; i < input.length; i++) {\n const ch = input[i];\n if (ch === '\"') return { literal: input.slice(start, i + 1), end: i + 1 };\n if (ch === '\\\\') i++;\n }\n return null;\n}\n\nfunction skipJsonLikeValue(input: string, start: number): number {\n if (input[start] === '\"') {\n const token = readJsonStringToken(input, start);\n return token?.end ?? input.length;\n }\n if (input[start] === '[' || input[start] === '{') {\n const opener = input[start];\n const closer = opener === '[' ? ']' : '}';\n let depth = 0;\n for (let i = start; i < input.length; i++) {\n const ch = input[i];\n if (ch === '\"') {\n const token = readJsonStringToken(input, i);\n if (!token) return input.length;\n i = token.end - 1;\n continue;\n }\n if (ch === opener) depth++;\n if (ch === closer) {\n depth--;\n if (depth === 0) return i + 1;\n }\n }\n return input.length;\n }\n let i = start;\n while (i < input.length && input[i] !== ',' && input[i] !== '}' && input[i] !== ']' && !isJsonWhitespace(input[i])) {\n i++;\n }\n return i;\n}\n\nfunction isJsonWhitespace(ch: string | undefined): boolean {\n return ch === ' ' || ch === '\\n' || ch === '\\r' || ch === '\\t';\n}\n\nfunction safeStringify(value: unknown): string | undefined {\n try {\n return JSON.stringify(value);\n } catch {\n return undefined;\n }\n}\n\nfunction byteLengthOf(s: string): number {\n if (typeof Buffer !== 'undefined') return Buffer.byteLength(s, 'utf8');\n // Fallback — rough UTF-16 count.\n return s.length;\n}\n\nfunction payloadWireLength(value: unknown): number {\n if (typeof value === 'string') return byteLengthOf(value);\n const json = safeStringify(value);\n return json ? byteLengthOf(json) : 0;\n}\n\nfunction cap(s: string, maxBytes: number): string {\n if (maxBytes <= 0) return s;\n if (byteLengthOf(s) <= maxBytes) return s;\n return `[truncated ${byteLengthOf(s)} bytes]`;\n}\n"],"mappings":"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","names":["redacted","json","i"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/upstream-recorder/recorder.ts"],"sourcesContent":["/**\n * `createUpstreamRecorder` implementation. See `./types.ts` for the public\n * surface and `./README` (file header on `index.ts`) for the why.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { createHash } from 'node:crypto';\nimport {\n normalizeSecretKeyPattern,\n redactSecrets,\n secretKeyPatternMatches,\n SECRET_KEY_PATTERN,\n} from '../utils/redact-secrets';\nimport { globToRegExp } from '../utils/glob';\nimport { canonicalize } from '../utils/jcs';\nimport { MAX_JSON_DEPTH } from '../utils/json-depth';\nimport { IDENTIFIER_DIGEST_LIMIT } from './constants';\nimport {\n UpstreamRecorderScopeError,\n type QueryUpstreamTrafficResponse,\n type RecordInput,\n type RawRecordedCall,\n type RecordedCall,\n type UpstreamRecorder,\n type UpstreamRecorderDebugInfo,\n type UpstreamRecorderErrorEvent,\n type UpstreamRecorderOptions,\n type UpstreamRecorderQueryParams,\n type UpstreamRecorderQueryResult,\n} from './types';\n\nconst DEFAULT_BUFFER_SIZE = 1000;\nconst DEFAULT_TTL_MS = 60 * 60 * 1000; // 1h\nconst DEFAULT_QUERY_LIMIT = 100;\nconst DEFAULT_MAX_PAYLOAD_BYTES = 65_536; // mirrors spec's `recorded_calls[].payload.maxLength`\nconst MAX_BUFFER_SIZE = 100_000;\nconst MAX_TTL_MS = 24 * 60 * 60 * 1000; // 24h\nconst VALID_PURPOSES = new Set([\n 'platform_primary',\n 'measurement',\n 'attribution',\n 'creative_serving',\n 'identity',\n 'other',\n]);\n\nexport class PayloadDigestError extends Error {\n cause: unknown;\n\n constructor(message: string, cause?: unknown) {\n super(message);\n this.name = 'PayloadDigestError';\n this.cause = cause;\n }\n}\n\n/**\n * Wrapped per-call entry stored in the buffer. Carries the public\n * `RecordedCall` plus the principal it was recorded under (kept off the\n * public type so cross-principal isolation is enforced at query time and\n * the principal never appears in the controller-response payload).\n */\ninterface InternalEntry {\n call: RawRecordedCall;\n principal: string;\n /** ms-since-epoch cached for TTL eviction; computed at insert time. */\n recordedAtMs: number;\n}\n\nfunction clamp(n: number | undefined, lo: number, hi: number, fallback: number): number {\n if (typeof n !== 'number' || !Number.isFinite(n)) return fallback;\n // Out-of-range values (zero / negative / above ceiling) revert to the\n // default rather than silently saturating at the limit — a typo'd\n // `bufferSize: -10` silently saturating to `1` would drop nearly\n // everything; the default is a much safer failure mode.\n if (n < lo || n > hi) return fallback;\n return n;\n}\n\nfunction isPrincipalString(p: unknown): p is string {\n return typeof p === 'string' && p.length > 0;\n}\n\n/**\n * Build the recorder. Producer-side companion to the\n * `runner-output-contract.yaml` v2.0.0 `upstream_traffic` storyboard\n * check (spec PR adcontextprotocol/adcp#3816).\n */\nexport function createUpstreamRecorder(options: UpstreamRecorderOptions = {}): UpstreamRecorder {\n const enabled = options.enabled ?? true;\n // Disabled-recorder fast-path: skip every wrapping cost. Production\n // builds get a no-op object whose methods compile to inlinable returns.\n if (!enabled) return makeNoopRecorder();\n\n // Production-enable footgun guard: when adopters ship with `enabled:\n // true` in `NODE_ENV=production` (forgot the gate, or the gate is\n // mis-evaluated), emit a one-time warning. ADCP_RECORDER_PRODUCTION_ACK=1\n // is the explicit acknowledgment escape hatch for the rare adopters\n // who legitimately want recording in prod.\n warnIfEnabledInProduction();\n\n const redactPattern = normalizeSecretKeyPattern(options.redactPattern ?? SECRET_KEY_PATTERN);\n const bufferSize = clamp(options.bufferSize, 1, MAX_BUFFER_SIZE, DEFAULT_BUFFER_SIZE);\n const ttlMs = clamp(options.ttlMs, 1, MAX_TTL_MS, DEFAULT_TTL_MS);\n const maxPayloadBytes = clamp(options.maxPayloadBytes, 0, 16 * 1024 * 1024, DEFAULT_MAX_PAYLOAD_BYTES);\n const purpose = options.purpose;\n const strict = options.strict === true;\n const onError = options.onError;\n\n // Buffer: ordered by insertion (== timestamp ascending). Eviction is\n // FIFO when full or TTL-prune at record time.\n const buffer: InternalEntry[] = [];\n\n // Active-principal context. Set by `runWithPrincipal`; read by the\n // wrapped fetch and by `record` when no explicit principal is passed.\n const principalStorage = new AsyncLocalStorage<string>();\n\n // ────────────────────────────────────────────────────────────\n // Internal helpers\n // ────────────────────────────────────────────────────────────\n\n function emitError(event: UpstreamRecorderErrorEvent): void {\n if (!onError) return;\n try {\n onError(event);\n } catch {\n // onError MUST NOT crash the recorder — silent.\n }\n }\n\n function evictExpired(nowMs: number): void {\n if (buffer.length === 0) return;\n const cutoff = nowMs - ttlMs;\n let idx = 0;\n while (idx < buffer.length && buffer[idx]!.recordedAtMs < cutoff) idx++;\n if (idx > 0) buffer.splice(0, idx);\n }\n\n function pushEntry(entry: InternalEntry): void {\n buffer.push(entry);\n while (buffer.length > bufferSize) buffer.shift();\n }\n\n function applyRedactionToHeaders(headers: Record<string, string> | undefined): Record<string, string> {\n if (!headers) return {};\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n const lower = k.toLowerCase();\n out[lower] = secretKeyPatternMatches(redactPattern, lower) ? '[redacted]' : v;\n }\n return out;\n }\n\n /**\n * Apply per-key redaction to the body. JSON bodies (objects + arrays)\n * walk through `redactSecrets`. Form-urlencoded strings parse +\n * key-redact + re-stringify so `access_token=xxx` is caught without\n * the adopter pre-redacting. Other string types pass through. Binary\n * types (Buffer / Blob / ArrayBuffer / TypedArray) are replaced with\n * a marker — the buffer should not hold raw bytes whose JSON-shape\n * is misleading downstream.\n */\n function applyRedactionToPayload(payload: unknown, contentType: string): { value: unknown; bytes: number } {\n const value = normalizeRecordedPayload(payload, contentType, redactPattern, maxPayloadBytes);\n return { value, bytes: payloadWireLength(value) };\n }\n\n function classifyPurpose(\n method: string,\n url: string,\n host: string,\n path: string,\n headers: Record<string, string>\n ): string | undefined {\n if (!purpose) return undefined;\n try {\n const value = purpose({ method, url, host, path, headers }) as unknown;\n if (value === undefined) return undefined;\n if (typeof value === 'string' && VALID_PURPOSES.has(value)) return value;\n emitError({ kind: 'classifier_invalid_purpose', purpose: typeof value === 'string' ? value : String(value) });\n return undefined;\n } catch (err) {\n emitError({ kind: 'classifier_threw', err });\n return undefined;\n }\n }\n\n function buildRecordedCall(input: RecordInput, nowMs: number): RawRecordedCall | null {\n try {\n const url = input.url;\n let host = '';\n let pathPart = '';\n try {\n const parsed = new URL(url);\n host = parsed.host;\n pathPart = parsed.pathname;\n } catch {\n emitError({ kind: 'url_parse_failed', url });\n }\n const redactedHeaders = applyRedactionToHeaders(input.headers);\n const purposeTag = classifyPurpose(input.method, url, host, pathPart, redactedHeaders);\n const { value: payload, bytes: payloadLength } = applyRedactionToPayload(input.payload, input.content_type);\n return {\n method: input.method,\n endpoint: `${input.method} ${url}`,\n url,\n host,\n path: pathPart,\n content_type: input.content_type,\n attestation_mode: 'raw',\n payload,\n payload_length: payloadLength,\n timestamp: new Date(nowMs).toISOString(),\n ...(input.status_code !== undefined && { status_code: input.status_code }),\n ...(purposeTag !== undefined && { purpose: purposeTag }),\n };\n } catch (err) {\n // Hostile / buggy payload (throwing getter, etc.). Recording MUST\n // never break the adapter call site.\n emitError({ kind: 'payload_build_failed', err });\n return null;\n }\n }\n\n // ────────────────────────────────────────────────────────────\n // Public methods\n // ────────────────────────────────────────────────────────────\n\n function runWithPrincipal<T>(principal: string, fn: () => T | Promise<T>): Promise<T> {\n if (!isPrincipalString(principal)) {\n return Promise.reject(\n new UpstreamRecorderScopeError(\n 'runWithPrincipal: principal MUST be a non-empty string. Pass the same identifier you receive in your comply_test_controller handler.'\n )\n );\n }\n return Promise.resolve(principalStorage.run(principal, fn));\n }\n\n function record(input: RecordInput, explicitPrincipal?: string): void {\n const principal = explicitPrincipal ?? principalStorage.getStore();\n if (!isPrincipalString(principal)) {\n if (strict) {\n throw new UpstreamRecorderScopeError(\n `record() called outside runWithPrincipal scope (method=${input.method}, url=${input.url}). Wrap the call site or pass an explicit principal.`\n );\n }\n emitError({ kind: 'unscoped_record', method: input.method, url: input.url });\n return;\n }\n const nowMs = Date.now();\n evictExpired(nowMs);\n const call = buildRecordedCall(input, nowMs);\n if (!call) return;\n pushEntry({ call, principal, recordedAtMs: nowMs });\n }\n\n function wrapFetch(originalFetch: typeof globalThis.fetch): typeof globalThis.fetch {\n return async function wrappedFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n const principal = principalStorage.getStore();\n // No active principal: pass through unchanged in non-strict mode.\n // In strict mode, a fetch outside scope is the same authoring bug\n // as `record()` outside scope and surfaces the same way.\n if (!principal) {\n if (strict) {\n throw new UpstreamRecorderScopeError(\n `wrapFetch invoked outside runWithPrincipal scope (input=${typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url}). Wrap the call site.`\n );\n }\n return originalFetch(input as Parameters<typeof globalThis.fetch>[0], init);\n }\n\n const method = (init?.method ?? (input instanceof Request ? input.method : 'GET')).toUpperCase();\n const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;\n\n // Header normalization — fetch's Headers form vs init.headers Record vs Request body.\n const headerObj: Record<string, string> = {};\n if (init?.headers) {\n const h = init.headers;\n if (h instanceof Headers) {\n h.forEach((v, k) => {\n headerObj[k.toLowerCase()] = v;\n });\n } else if (Array.isArray(h)) {\n for (const [k, v] of h) headerObj[k.toLowerCase()] = v;\n } else {\n for (const [k, v] of Object.entries(h as Record<string, string>)) headerObj[k.toLowerCase()] = v;\n }\n } else if (input instanceof Request) {\n input.headers.forEach((v, k) => {\n headerObj[k.toLowerCase()] = v;\n });\n }\n\n const contentType = headerObj['content-type'] ?? '';\n const payload = await readBody(input, init, contentType);\n\n // Fire the actual call; record after we have a status_code. On\n // throw, we still record the attempt with no status_code so the\n // adopter can see the call was made.\n let response: Response | undefined;\n let thrown: unknown;\n try {\n response = await originalFetch(input as Parameters<typeof globalThis.fetch>[0], init);\n } catch (err) {\n thrown = err;\n }\n\n record(\n {\n method,\n url,\n content_type: contentType,\n headers: headerObj,\n payload,\n ...(response && { status_code: response.status }),\n },\n principal\n );\n\n if (thrown) throw thrown;\n return response!;\n };\n }\n\n function query(params: UpstreamRecorderQueryParams): UpstreamRecorderQueryResult {\n if (!isPrincipalString(params.principal)) {\n throw new UpstreamRecorderScopeError(\n 'query({ principal }): principal MUST be a non-empty string. Cross-principal isolation depends on this — passing an empty / non-string value would silently match no entries and conceal misconfiguration.'\n );\n }\n const nowMs = Date.now();\n evictExpired(nowMs);\n const limit = clamp(params.limit, 1, bufferSize, DEFAULT_QUERY_LIMIT);\n const sinceMs = params.sinceTimestamp ? Date.parse(params.sinceTimestamp) : 0;\n const endpointMatcher = params.endpointPattern ? globToRegExp(params.endpointPattern) : undefined;\n\n const matched = buffer.filter(entry => {\n if (entry.principal !== params.principal) return false; // hard isolation\n if (entry.recordedAtMs < sinceMs) return false;\n if (endpointMatcher && !endpointMatcher.test(entry.call.endpoint)) return false;\n return true;\n });\n\n const items: RecordedCall[] = [];\n let total = 0;\n let dropped_count = 0;\n for (const entry of matched) {\n const projected = safeProjectRecordedCall(entry.call, params, emitError);\n if (!projected) {\n if (params.attestationMode === 'digest') dropped_count++;\n continue;\n }\n total++;\n if (items.length < limit) items.push(projected);\n }\n const since_timestamp =\n params.sinceTimestamp ?? matched[0]?.call.timestamp ?? new Date(nowMs - ttlMs).toISOString();\n return {\n items,\n total,\n truncated: total > items.length,\n since_timestamp,\n dropped_count,\n };\n }\n\n function clear(): void {\n buffer.length = 0;\n }\n\n function debug(): UpstreamRecorderDebugInfo {\n const principals = Array.from(new Set(buffer.map(e => e.principal))).sort();\n const last = buffer[buffer.length - 1];\n return {\n enabled: true,\n bufferSize,\n bufferedEntries: buffer.length,\n principals,\n lastRecordedAt: last ? last.call.timestamp : null,\n activePrincipal: principalStorage.getStore() ?? null,\n strict,\n };\n }\n\n return {\n runWithPrincipal,\n wrapFetch,\n record,\n query,\n clear,\n debug,\n enabled: true,\n };\n}\n\nfunction safeProjectRecordedCall(\n call: RawRecordedCall,\n params: UpstreamRecorderQueryParams,\n emitError?: (event: UpstreamRecorderErrorEvent) => void\n): RecordedCall | null {\n try {\n return projectRecordedCall(call, params, emitError);\n } catch (err) {\n emitError?.({ kind: 'digest_canonicalization_failed', method: call.method, endpoint: call.endpoint, err });\n return null;\n }\n}\n\nfunction projectRecordedCall(\n call: RawRecordedCall,\n params: UpstreamRecorderQueryParams,\n emitError?: (event: UpstreamRecorderErrorEvent) => void\n): RecordedCall {\n if (params.attestationMode !== 'digest') return call;\n const payloadBytes = canonicalPayloadBytes(call.payload, call.content_type);\n const payloadDigest = sha256Hex(payloadBytes);\n const identifierDigests = normalizeIdentifierDigests(params.identifierValueDigests);\n const identifierScanPayload =\n identifierDigests.length > 0\n ? parseJsonStringPayloadForScan(call.payload, call.content_type, emitError)\n : undefined;\n const matchedIdentifierDigests =\n identifierDigests.length > 0 && identifierScanPayload !== undefined\n ? collectMatchedStringLeafDigests(identifierScanPayload, new Set(identifierDigests))\n : undefined;\n const identifier_match_proofs =\n identifierDigests.length > 0 && matchedIdentifierDigests\n ? identifierDigests.map(digest => ({\n identifier_value_sha256: digest,\n found: matchedIdentifierDigests.has(digest),\n }))\n : undefined;\n\n return {\n method: call.method,\n endpoint: call.endpoint,\n url: call.url,\n host: call.host,\n path: call.path,\n content_type: call.content_type,\n attestation_mode: 'digest',\n payload_digest_sha256: payloadDigest,\n payload_length: byteLengthOf(payloadBytes),\n timestamp: call.timestamp,\n ...(call.status_code !== undefined && { status_code: call.status_code }),\n ...(call.purpose !== undefined && { purpose: call.purpose }),\n ...(identifier_match_proofs !== undefined && { identifier_match_proofs }),\n };\n}\n\nfunction normalizeIdentifierDigests(input: string[] | undefined): string[] {\n if (!Array.isArray(input)) return [];\n const out: string[] = [];\n for (const value of input) {\n if (typeof value !== 'string' || !/^[a-f0-9]{64}$/.test(value)) continue;\n if (!out.includes(value)) out.push(value);\n if (out.length >= IDENTIFIER_DIGEST_LIMIT) break;\n }\n return out;\n}\n\nfunction collectMatchedStringLeafDigests(root: unknown, wantedDigests: Set<string>): Set<string> {\n const matched = new Set<string>();\n const stack: Array<{ value: unknown; depth: number }> = [{ value: root, depth: 0 }];\n while (stack.length > 0) {\n const { value, depth } = stack.pop()!;\n if (depth > MAX_JSON_DEPTH) continue;\n if (typeof value === 'string') {\n const digest = sha256Hex(value);\n if (wantedDigests.has(digest)) {\n matched.add(digest);\n if (matched.size === wantedDigests.size) break;\n }\n } else if (Array.isArray(value)) {\n for (const item of value) stack.push({ value: item, depth: depth + 1 });\n } else if (value !== null && typeof value === 'object') {\n for (const item of Object.values(value as Record<string, unknown>)) {\n stack.push({ value: item, depth: depth + 1 });\n }\n }\n }\n return matched;\n}\n\nfunction parseJsonStringPayloadForScan(\n payload: unknown,\n contentType: string,\n emitError?: (event: UpstreamRecorderErrorEvent) => void\n): unknown | undefined {\n if (!isJsonContentType(contentType)) return undefined;\n if (typeof payload !== 'string') return payload;\n try {\n return JSON.parse(payload);\n } catch (err) {\n emitError?.({ kind: 'json_payload_parse_failed', content_type: contentType, err });\n return payload;\n }\n}\n\nfunction canonicalPayloadBytes(payload: unknown, contentType: string): string {\n if (isJsonContentType(contentType)) {\n if (typeof payload === 'string') {\n let parsed: unknown;\n try {\n parsed = JSON.parse(payload);\n } catch {\n return payload;\n }\n return canonicalJsonStringify(parsed);\n }\n return canonicalJsonStringify(payload);\n }\n if (typeof payload === 'string') return payload;\n return safeStringify(payload) ?? '';\n}\n\nfunction canonicalJsonStringify(value: unknown): string {\n assertJsonDepth(value);\n return canonicalize(value);\n}\n\nfunction assertJsonDepth(root: unknown): void {\n const stack: Array<{ value: unknown; depth: number }> = [{ value: root, depth: 0 }];\n while (stack.length > 0) {\n const { value, depth } = stack.pop()!;\n if (depth > MAX_JSON_DEPTH) {\n throw new RangeError(`JSON payload exceeds max canonicalization depth ${MAX_JSON_DEPTH}`);\n }\n if (Array.isArray(value)) {\n for (const item of value) stack.push({ value: item, depth: depth + 1 });\n } else if (value !== null && typeof value === 'object') {\n for (const item of Object.values(value as Record<string, unknown>)) {\n stack.push({ value: item, depth: depth + 1 });\n }\n }\n }\n}\n\nfunction sha256Hex(value: string): string {\n return createHash('sha256').update(value, 'utf8').digest('hex');\n}\n\n/**\n * Compute the `RecordedCall.payload_digest_sha256` value. By default this\n * applies the same body snapshot normalization, payload normalization, and\n * canonical secret-key redaction used by the recorder before hashing; pass a\n * custom redaction pattern and `maxPayloadBytes` when your recorder uses matching\n * options:\n *\n * - `createUpstreamRecorder({ redactPattern })` → `computePayloadDigestSha256(..., { redactPattern })`\n * - `createUpstreamRecorder({ maxPayloadBytes })` → `computePayloadDigestSha256(..., { maxPayloadBytes })`\n *\n * Prefer `{ prenormalized: true }` only when the payload has already been\n * normalized/redacted exactly as the recorder would store it; legacy `false`\n * remains accepted as the same prenormalized sentinel. The prenormalized path\n * skips redaction, so the helper rejects secret-shaped keys whose values are\n * not already the literal `\"[redacted]\"` marker or an explicit null\n * placeholder. For form-encoded bodies, duplicate secret-shaped keys are also\n * rejected because last-wins maps cannot prove that every original value was\n * inspected before hashing.\n *\n * JSON content is serialized with RFC 8785 JCS before hashing. When\n * `contentType` is JSON-shaped and `payload` is a string, the helper parses\n * it first so semantically equivalent JSON strings and objects hash to the\n * same value. On the normalizing path, an unparseable JSON-shaped string is\n * treated as the emitted body bytes and hashed verbatim after best-effort\n * redaction. On the prenormalized path, malformed JSON strings throw because\n * their secret-key structure cannot be proven safe. Unsupported JSON values\n * and payloads deeper than the recorder's depth cap throw rather than\n * producing a non-canonical digest.\n *\n * The returned digest is lowercase hex, matching the 3.1\n * `query_upstream_traffic` wire contract.\n */\nexport function computePayloadDigestSha256(\n payload: unknown,\n contentType?: string,\n options?: PayloadDigestOptions\n): string;\n/**\n * @deprecated Pass `{ redactPattern: /.../ }` instead of the bare `RegExp`\n * form. The legacy form remains accepted for this major.\n */\nexport function computePayloadDigestSha256(payload: unknown, contentType: string | undefined, options: RegExp): string;\n/**\n * @deprecated Pass `{ prenormalized: true }` instead of `false`. The legacy\n * form remains accepted for this major.\n */\nexport function computePayloadDigestSha256(payload: unknown, contentType: string | undefined, options: false): string;\nexport function computePayloadDigestSha256(\n payload: unknown,\n contentType = 'application/json',\n options: RegExp | false | PayloadDigestOptions = SECRET_KEY_PATTERN\n): string {\n const redactPattern =\n options instanceof RegExp || options === false\n ? options === false\n ? false\n : normalizeSecretKeyPattern(options)\n : options?.prenormalized\n ? false\n : options?.redactPattern === false\n ? false\n : normalizeSecretKeyPattern(options?.redactPattern ?? SECRET_KEY_PATTERN);\n const prenormalizedSafetyPattern =\n typeof options === 'object' &&\n options !== null &&\n !(options instanceof RegExp) &&\n options.redactPattern instanceof RegExp\n ? normalizeSecretKeyPattern(options.redactPattern)\n : SECRET_KEY_PATTERN;\n const maxPayloadBytes =\n typeof options === 'object' && options !== null && !(options instanceof RegExp)\n ? clamp(options.maxPayloadBytes, 0, 16 * 1024 * 1024, DEFAULT_MAX_PAYLOAD_BYTES)\n : DEFAULT_MAX_PAYLOAD_BYTES;\n try {\n if (\n typeof options === 'object' &&\n options !== null &&\n !(options instanceof RegExp) &&\n options.redactPattern === false &&\n options.prenormalized !== true\n ) {\n throw new PayloadDigestError('PayloadDigestOptions.redactPattern=false requires prenormalized=true');\n }\n const payloadForDigest =\n redactPattern === false\n ? assertPrenormalizedPayloadSafe(payload, contentType, prenormalizedSafetyPattern)\n : normalizeRecordedPayload(\n normalizeFetchPayloadInput(payload, contentType),\n contentType,\n redactPattern,\n maxPayloadBytes\n );\n return sha256Hex(canonicalPayloadBytes(payloadForDigest, contentType));\n } catch (err) {\n if (err instanceof PayloadDigestError) throw err;\n throw new PayloadDigestError(err instanceof Error ? err.message : 'Payload digest canonicalization failed', err);\n }\n}\n\nexport type PayloadDigestOptions = {\n /**\n * Custom redaction pattern. Passing `false` is accepted only with\n * `prenormalized: true`; otherwise it would silently bypass redaction.\n */\n redactPattern?: RegExp | false;\n /**\n * Match `createUpstreamRecorder({ maxPayloadBytes })` when computing\n * digests outside the recorder.\n */\n maxPayloadBytes?: number;\n /**\n * Set only for payloads that have already been normalized and redacted.\n * The helper skips redaction but still scans secret-shaped keys, rejects\n * malformed JSON strings, and rejects duplicate secret-shaped form keys.\n */\n prenormalized?: boolean;\n};\n\nfunction assertPrenormalizedPayloadSafe(payload: unknown, contentType: string, pattern: RegExp): unknown {\n let scanTarget = payload;\n if (typeof payload === 'string' && isJsonContentType(contentType)) {\n try {\n scanTarget = JSON.parse(payload);\n } catch {\n throw new PayloadDigestError(\n 'Prenormalized JSON payload is malformed; hash the recorder-normalized payload or omit prenormalized.'\n );\n }\n } else if (typeof payload === 'string' && isFormUrlEncoded(contentType)) {\n assertPrenormalizedFormUrlEncodedSafe(payload, pattern);\n return payload;\n }\n const unsafePath = findUnredactedSecretPath(scanTarget, pattern);\n if (unsafePath) {\n throw new PayloadDigestError(\n `Prenormalized payload contains unredacted secret-shaped key \"${unsafePath}\"; hash the recorder-normalized payload or omit prenormalized.`\n );\n }\n return payload;\n}\n\nfunction assertPrenormalizedFormUrlEncodedSafe(body: string, pattern: RegExp): void {\n const seenSecretKeys = new Set<string>();\n const params = Array.from(new URLSearchParams(body));\n for (const [key] of params) {\n if (!secretKeyPatternMatches(pattern, key)) continue;\n const normalizedKey = key.toLowerCase();\n if (seenSecretKeys.has(normalizedKey)) {\n throw new PayloadDigestError(\n `Prenormalized form payload contains duplicate secret-shaped key \"${key}\"; hash the recorder-normalized payload or omit prenormalized.`\n );\n }\n seenSecretKeys.add(normalizedKey);\n }\n for (const [key, value] of params) {\n if (!secretKeyPatternMatches(pattern, key)) continue;\n if (!isSafelyRedactedSecretValue(value)) {\n throw new PayloadDigestError(\n `Prenormalized payload contains unredacted secret-shaped key \"${key}\"; hash the recorder-normalized payload or omit prenormalized.`\n );\n }\n }\n}\n\nfunction findUnredactedSecretPath(value: unknown, pattern: RegExp): string | null {\n const stack: Array<{ value: unknown; path: string }> = [{ value, path: '' }];\n const seen = new WeakSet<object>();\n while (stack.length > 0) {\n const { value: current, path } = stack.pop()!;\n if (!current || typeof current !== 'object') continue;\n if (seen.has(current)) continue;\n seen.add(current);\n\n if (Array.isArray(current)) {\n for (let i = current.length - 1; i >= 0; i--) {\n stack.push({ value: current[i], path: `${path}[${i}]` });\n }\n continue;\n }\n\n const entries = Object.entries(current as Record<string, unknown>);\n for (let i = entries.length - 1; i >= 0; i--) {\n const [key, childValue] = entries[i]!;\n const childPath = path ? `${path}.${key}` : key;\n if (secretKeyPatternMatches(pattern, key) && !isSafelyRedactedSecretValue(childValue)) return childPath;\n stack.push({ value: childValue, path: childPath });\n }\n }\n return null;\n}\n\nfunction isSafelyRedactedSecretValue(value: unknown): boolean {\n return value === '[redacted]' || value === null;\n}\n\nfunction normalizeFetchPayloadInput(payload: unknown, contentType: string): unknown {\n if (payload === undefined) return undefined;\n if (typeof payload === 'string') {\n if (!isJsonContentType(contentType)) return payload;\n try {\n return JSON.parse(payload);\n } catch {\n return payload;\n }\n }\n if (payload instanceof URLSearchParams) return payload.toString();\n if (typeof FormData !== 'undefined' && payload instanceof FormData) {\n const out: Record<string, unknown> = {};\n payload.forEach((v, k) => {\n out[k] = typeof v === 'string' ? v : '[file]';\n });\n return out;\n }\n return payload;\n}\n\nfunction normalizeRecordedPayload(\n payload: unknown,\n contentType: string,\n redactPattern: RegExp,\n maxPayloadBytes: number\n): unknown {\n if (payload === undefined) {\n // Raw-mode `RecordedCall.payload` is required by the 3.1 controller\n // response schema. GET/HEAD-style calls with no body therefore emit an\n // empty object instead of omitting the field.\n return {};\n }\n if (payload === null) return payload;\n\n // Binary-shaped bodies — replace with a marker. Adopters that need\n // the raw bytes recorded for diagnostics can stringify before\n // calling `record()`.\n if (typeof Buffer !== 'undefined' && Buffer.isBuffer(payload)) {\n return `[binary ${payload.length} bytes]`;\n }\n if (typeof Blob !== 'undefined' && payload instanceof Blob) {\n return `[binary ${payload.size} bytes]`;\n }\n if (payload instanceof ArrayBuffer) {\n return `[binary ${payload.byteLength} bytes]`;\n }\n if (ArrayBuffer.isView(payload)) {\n return `[binary ${payload.byteLength} bytes]`;\n }\n\n if (typeof payload === 'string') {\n if (isJsonContentType(contentType)) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(payload);\n } catch {\n // Malformed JSON strings remain raw strings so diagnostics keep the\n // original body shape instead of pretending the payload was absent.\n return cap(redactJsonLikeSecretValues(payload, redactPattern), maxPayloadBytes);\n }\n const redacted = redactSecrets(parsed, redactPattern);\n assertJsonDepth(redacted);\n const json = safeStringify(redacted);\n if (json && maxPayloadBytes > 0 && byteLengthOf(json) > maxPayloadBytes) {\n return `[truncated ${byteLengthOf(json)} bytes]`;\n }\n return redacted;\n }\n // Form-urlencoded redaction: parse, redact, re-stringify so\n // `access_token=...` bodies don't slip through unredacted.\n if (isFormUrlEncoded(contentType)) {\n return cap(redactFormUrlEncoded(payload, redactPattern), maxPayloadBytes);\n }\n return cap(payload, maxPayloadBytes);\n }\n\n const redacted = redactSecrets(payload, redactPattern);\n assertJsonDepth(redacted);\n const json = safeStringify(redacted);\n if (json && maxPayloadBytes > 0 && byteLengthOf(json) > maxPayloadBytes) {\n return `[truncated ${byteLengthOf(json)} bytes]`;\n }\n return redacted;\n}\n\n/**\n * Project a `recorder.query()` result onto the spec wire shape returned\n * by `comply_test_controller`'s `query_upstream_traffic` scenario\n * (`UpstreamTrafficSuccess` in `comply-test-controller-response.json`,\n * spec PR adcontextprotocol/adcp#3816). Eliminates the\n * `items → recorded_calls` / `total → total_count` field-rename footgun\n * — adopters return this directly:\n *\n * ```ts\n * scenarios: {\n * query_upstream_traffic: ({ params }, ctx) =>\n * toQueryUpstreamTrafficResponse(\n * recorder.query({\n * principal: resolvePrincipal(ctx),\n * sinceTimestamp: params?.since_timestamp,\n * endpointPattern: params?.endpoint_pattern,\n * limit: params?.limit,\n * })\n * ),\n * }\n * ```\n */\nexport function toQueryUpstreamTrafficResponse(result: UpstreamRecorderQueryResult): QueryUpstreamTrafficResponse {\n return {\n success: true,\n recorded_calls: result.items,\n total_count: result.total,\n truncated: result.truncated,\n since_timestamp: result.since_timestamp,\n };\n}\n\n/**\n * No-op recorder returned when `enabled: false`. Every method is a\n * pass-through / empty-result. Production builds drop in this object\n * with zero per-call overhead beyond the initial factory call.\n */\nfunction makeNoopRecorder(): UpstreamRecorder {\n return {\n runWithPrincipal: <T>(_p: string, fn: () => T | Promise<T>): Promise<T> => Promise.resolve(fn()),\n wrapFetch: (originalFetch: typeof globalThis.fetch): typeof globalThis.fetch => originalFetch,\n record: () => undefined,\n query: (params: UpstreamRecorderQueryParams): UpstreamRecorderQueryResult => ({\n items: [],\n total: 0,\n truncated: false,\n since_timestamp: params.sinceTimestamp ?? new Date(0).toISOString(),\n dropped_count: 0,\n }),\n clear: () => undefined,\n debug: (): UpstreamRecorderDebugInfo => ({\n enabled: false,\n bufferSize: 0,\n bufferedEntries: 0,\n principals: [],\n lastRecordedAt: null,\n activePrincipal: null,\n strict: false,\n }),\n enabled: false,\n };\n}\n\nlet warnedAboutProduction = false;\nfunction warnIfEnabledInProduction(): void {\n if (warnedAboutProduction) return;\n if (typeof process === 'undefined' || !process.env) return;\n if (process.env.NODE_ENV !== 'production') return;\n if (process.env.ADCP_RECORDER_PRODUCTION_ACK === '1') return;\n warnedAboutProduction = true;\n // eslint-disable-next-line no-console\n console.warn(\n '[adcp/upstream-recorder] enabled: true in NODE_ENV=production. ' +\n 'The recorder buffers outbound HTTP calls in-memory — sandbox-only by design. ' +\n 'Set enabled: false (recommended) or ADCP_RECORDER_PRODUCTION_ACK=1 to silence.'\n );\n}\n\n/**\n * Read the request body off a fetch call site without consuming the\n * input (when the input is a `Request`, we'd lock its stream by reading\n * directly). Returns `undefined` for bodies the recorder can't snapshot\n * cheaply.\n */\nasync function readBody(\n input: RequestInfo | URL,\n init: RequestInit | undefined,\n contentType: string\n): Promise<unknown> {\n let raw: unknown;\n\n if (init?.body !== undefined && init.body !== null) {\n raw = init.body;\n } else if (input instanceof Request) {\n try {\n const clone = input.clone();\n if (contentTypeBase(contentType) === 'multipart/form-data') {\n raw = await clone.formData();\n } else {\n raw = await clone.text();\n }\n } catch {\n raw = undefined;\n }\n } else {\n raw = undefined;\n }\n\n if (raw === undefined) return undefined;\n if (typeof raw === 'string') {\n if (!isJsonContentType(contentType)) return raw;\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n }\n // FormData / URLSearchParams stringify cleanly enough for diagnostic value.\n if (raw instanceof URLSearchParams) return raw.toString();\n if (typeof FormData !== 'undefined' && raw instanceof FormData) {\n const out: Record<string, unknown> = {};\n raw.forEach((v, k) => {\n out[k] = typeof v === 'string' ? v : '[file]';\n });\n return out;\n }\n // Object / array literal already, or a Buffer / Blob / TypedArray /\n // ArrayBuffer the adopter passed in directly. Pass through — the\n // redaction step below detects binary types and substitutes markers\n // before they sit in the buffer.\n if (typeof raw === 'object') return raw;\n return String(raw);\n}\n\nfunction isJsonContentType(contentType: string | undefined): boolean {\n const base = contentTypeBase(contentType);\n return base === 'application/json' || /\\+json$/.test(base);\n}\n\nfunction isFormUrlEncoded(contentType: string | undefined): boolean {\n return contentTypeBase(contentType) === 'application/x-www-form-urlencoded';\n}\n\nfunction contentTypeBase(contentType: string | undefined): string {\n if (!contentType) return '';\n return contentType.split(';')[0]?.trim().toLowerCase() ?? '';\n}\n\nfunction redactFormUrlEncoded(body: string, pattern: RegExp): string {\n try {\n const params = new URLSearchParams(body);\n const out = new URLSearchParams();\n params.forEach((v, k) => {\n out.append(k, secretKeyPatternMatches(pattern, k.toLowerCase()) ? '[redacted]' : v);\n });\n return out.toString();\n } catch {\n return body;\n }\n}\n\nfunction redactJsonLikeSecretValues(body: string, pattern: RegExp): string {\n // Best-effort diagnostic scrub for malformed JSON strings. The output is\n // not guaranteed to be valid JSON; the invariant is that secret-shaped keys\n // with scalar/string values are not stored verbatim. Because malformed JSON\n // has no trustworthy parse tree, object/array-valued secret entries are\n // replaced wholesale rather than traversed.\n let out = '';\n let i = 0;\n while (i < body.length) {\n if (body[i] !== '\"') {\n out += body[i++];\n continue;\n }\n\n const keyToken = readJsonStringToken(body, i);\n if (!keyToken) {\n out += body.slice(i);\n break;\n }\n\n let colon = keyToken.end;\n while (colon < body.length && isJsonWhitespace(body[colon])) colon++;\n if (body[colon] !== ':') {\n out += body.slice(i, keyToken.end);\n i = keyToken.end;\n continue;\n }\n\n let key: unknown;\n try {\n key = JSON.parse(keyToken.literal);\n } catch {\n out += body.slice(i, keyToken.end);\n i = keyToken.end;\n continue;\n }\n\n const valueStart = colon + 1;\n let value = valueStart;\n while (value < body.length && isJsonWhitespace(body[value])) value++;\n out += body.slice(i, value);\n if (typeof key !== 'string' || !secretKeyPatternMatches(pattern, key)) {\n i = value;\n continue;\n }\n\n out += '\"[redacted]\"';\n i = skipJsonLikeValue(body, value);\n }\n return out;\n}\n\nfunction readJsonStringToken(input: string, start: number): { literal: string; end: number } | null {\n for (let i = start + 1; i < input.length; i++) {\n const ch = input[i];\n if (ch === '\"') return { literal: input.slice(start, i + 1), end: i + 1 };\n if (ch === '\\\\') i++;\n }\n return null;\n}\n\nfunction skipJsonLikeValue(input: string, start: number): number {\n if (input[start] === '\"') {\n const token = readJsonStringToken(input, start);\n return token?.end ?? input.length;\n }\n if (input[start] === '[' || input[start] === '{') {\n const opener = input[start];\n const closer = opener === '[' ? ']' : '}';\n let depth = 0;\n for (let i = start; i < input.length; i++) {\n const ch = input[i];\n if (ch === '\"') {\n const token = readJsonStringToken(input, i);\n if (!token) return input.length;\n i = token.end - 1;\n continue;\n }\n if (ch === opener) depth++;\n if (ch === closer) {\n depth--;\n if (depth === 0) return i + 1;\n }\n }\n return input.length;\n }\n let i = start;\n while (i < input.length && input[i] !== ',' && input[i] !== '}' && input[i] !== ']' && !isJsonWhitespace(input[i])) {\n i++;\n }\n return i;\n}\n\nfunction isJsonWhitespace(ch: string | undefined): boolean {\n return ch === ' ' || ch === '\\n' || ch === '\\r' || ch === '\\t';\n}\n\nfunction safeStringify(value: unknown): string | undefined {\n try {\n return JSON.stringify(value);\n } catch {\n return undefined;\n }\n}\n\nfunction byteLengthOf(s: string): number {\n if (typeof Buffer !== 'undefined') return Buffer.byteLength(s, 'utf8');\n // Fallback — rough UTF-16 count.\n return s.length;\n}\n\nfunction payloadWireLength(value: unknown): number {\n if (typeof value === 'string') return byteLengthOf(value);\n const json = safeStringify(value);\n return json ? byteLengthOf(json) : 0;\n}\n\nfunction cap(s: string, maxBytes: number): string {\n if (maxBytes <= 0) return s;\n if (byteLengthOf(s) <= maxBytes) return s;\n return `[truncated ${byteLengthOf(s)} bytes]`;\n}\n"],"mappings":"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","names":["redacted","json","i"]}
|
|
@@ -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
|
class UpstreamRecorderScopeError extends Error {
|
|
8
2
|
constructor(message) {
|
|
9
3
|
super(message);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/upstream-recorder/types.ts"],"sourcesContent":["/**\n * Public types for `@adcp/sdk/upstream-recorder`.\n *\n * Producer-side companion to the runner-output-contract v2.0.0\n * `upstream_traffic` storyboard check (spec PR adcontextprotocol/adcp#3816).\n * The recorder captures outbound HTTP calls an adapter makes during a\n * sandbox session and surfaces them to the adopter's\n * `comply_test_controller` `query_upstream_traffic` handler so storyboard\n * runners can verify side-effects against the adopter's real upstream\n * platform (the load-bearing anti-façade contract).\n *\n * Adopter-facing API. The recorder itself is sandbox-only — `enabled: false`\n * short-circuits every wrapping adapter to a pass-through.\n */\n\n/**\n * Single recorded outbound HTTP call. Mirrors\n * `comply-test-controller-response.json > UpstreamTrafficSuccess.recorded_calls[]`\n * so adopter handlers can return query results verbatim.\n *\n * Redaction is applied at recording time, not query time, so the in-memory\n * buffer never holds plaintext secrets even briefly.\n */\ninterface RecordedCallBase {\n /**\n * Forward-compatibility for future additive spec fields on recorded call\n * items; adopter-defined fields are still rejected by the current 3.1 wire\n * schema.\n */\n [key: string]: unknown;\n method: string;\n /** Composed `<METHOD> <URL>` for `endpoint_pattern` matching. */\n endpoint: string;\n url: string;\n /** Parsed from `url` when URL parsing succeeds; the recorder emits `''` on parse failure. */\n host: string;\n /** Parsed from `url` when URL parsing succeeds; the recorder emits `''` on parse failure. */\n path: string;\n /**\n * Media type of the recorded `payload`, mirroring the adapter's outbound\n * `Content-Type` header. Required by the contract — runners use this to\n * pick the right matcher (JSONPath for JSON-shaped, substring fallback\n * for other types).\n */\n content_type: string;\n /**\n * Byte length of the emitted payload representation after redaction. Raw\n * calls measure the raw emitted payload representation; digest calls\n * measure the same canonical byte stream covered by\n * `payload_digest_sha256`.\n */\n payload_length: number;\n timestamp: string;\n status_code?: number;\n /**\n * Optional classifier — set when the `purpose` callback was supplied.\n * Mirrors adcp#3830 item 3 (purpose tagging) so storyboards can scope\n * `endpoint_pattern` matching to platform-primary calls vs. measurement\n * vendors when the spec adopts that field.\n */\n purpose?: string;\n}\n\nexport interface RawRecordedCall extends RecordedCallBase {\n attestation_mode: 'raw';\n /** Decoded JSON object when content_type is JSON-shaped; raw string otherwise. */\n payload: unknown;\n payload_digest_sha256?: never;\n identifier_match_proofs?: never;\n}\n\nexport interface DigestRecordedCall extends RecordedCallBase {\n attestation_mode: 'digest';\n payload?: never;\n /**\n * Lowercase hex SHA-256 of the post-redaction payload bytes. JSON object\n * and array payloads use RFC 8785 JCS canonicalization before hashing.\n * JSON strings are parsed and canonicalized when they contain valid JSON;\n * malformed JSON strings and non-JSON payloads use the post-redaction\n * emitted body bytes. Unsupported JSON values cannot produce a canonical\n * digest. Malformed JSON strings are treated as one opaque string for\n * identifier proof scanning, so substring identifiers inside invalid JSON\n * are not discoverable. String-only identifier proofs are deliberately low\n * entropy when adopters use short or guessable synthetic values; do not run\n * digest-mode attestations over production identifiers.\n */\n payload_digest_sha256: string;\n identifier_match_proofs?: Array<{\n /** Lowercase hex SHA-256 of a runner-supplied string identifier value. */\n identifier_value_sha256: string;\n /**\n * True when the digest matched a string leaf in the redacted JSON\n * payload. Non-string identifier vectors cannot be proven in digest\n * mode and should grade not_applicable rather than missing.\n */\n found: boolean;\n }>;\n}\n\nexport type RecordedCall = RawRecordedCall | DigestRecordedCall;\n\n/**\n * Optional classifier callback. Invoked at recording time on each call so\n * the recorder can stamp a `purpose` tag without the adopter wiring it\n * through their HTTP layer manually. Return one of\n * `platform_primary`, `measurement`, `attribution`, `creative_serving`,\n * `identity`, or `other`. Returning `undefined` leaves the `purpose` field\n * unset; returning any other string omits `purpose` and emits\n * `classifier_invalid_purpose` through `onError`.\n */\nexport type PurposeClassifier = (input: {\n method: string;\n url: string;\n host: string;\n path: string;\n /** Outbound headers (lowercased keys), with secrets already redacted. */\n headers: Record<string, string>;\n}) => string | undefined;\n\n/**\n * Configuration for `createUpstreamRecorder`. Every field is optional;\n * the defaults match the spec's recommended conformance posture.\n */\nexport interface UpstreamRecorderOptions {\n /**\n * Master switch. Defaults to `true`. Adopters MUST gate this against\n * their sandbox / non-production environment (e.g.\n * `enabled: process.env.NODE_ENV !== 'production'`). When `false`, the\n * factory returns a no-op recorder — `wrapFetch` returns the input fetch\n * unchanged, `record` is a no-op, `query` always returns empty results.\n * Zero overhead in production.\n */\n enabled?: boolean;\n /**\n * Override the canonical secret-key redaction pattern. Adopters MAY\n * extend the contract floor with internal vendor-specific keys. Adopters\n * MUST NOT narrow it — passing a pattern that omits a contract-required\n * key is a security regression.\n */\n redactPattern?: RegExp;\n /**\n * Maximum recorded calls retained in the buffer (across all principals).\n * Defaults to 1000. When the buffer is full, the oldest entry is evicted\n * before recording the new call. Storyboards generally exercise tens of\n * calls per assertion window — 1000 is a safe upper bound for a single\n * sandbox session.\n */\n bufferSize?: number;\n /**\n * Time-to-live for recorded calls, in milliseconds. Defaults to 1 hour.\n * Calls older than `ttlMs` at query time are excluded from results AND\n * pruned eagerly on the next record. Bounds the buffer's exposure\n * window — a stale recorder shouldn't surface yesterday's traffic on\n * today's compliance run.\n */\n ttlMs?: number;\n /**\n * Optional classifier — see `PurposeClassifier`. Invoked on every record\n * with the redacted-headers view of the outbound call.\n */\n purpose?: PurposeClassifier;\n /**\n * When `true`, calling `record()` or invoking the wrapped fetch outside a\n * `runWithPrincipal(p, fn)` scope throws an `UpstreamRecorderScopeError`\n * instead of silently dropping the call. Default `false` — silent drop\n * matches the recorder's \"don't break the adapter\" posture in production.\n * Adopters writing or debugging integration tests SHOULD enable this so\n * forgotten scope wrappers surface as a stack trace pointing at the\n * unwrapped call site, not as mysterious \"controller present, observed\n * nothing\" storyboard failures.\n */\n strict?: boolean;\n /**\n * Maximum bytes retained in `RecordedCall.payload` per entry. Adopter\n * payloads exceeding this limit are replaced with the marker string\n * `'[truncated <n> bytes]'` so the buffer ceiling stays bounded even\n * when an adopter records bulk uploads. Default 65 536 (64 KiB —\n * mirrors the spec's `recorded_calls[].payload` `maxLength`).\n * Set to 0 to disable truncation.\n */\n maxPayloadBytes?: number;\n /**\n * Optional observability hook. Invoked when the recorder swallows an\n * error that would otherwise be invisible (purpose classifier throw,\n * invalid purpose tag, URL parse failure, malformed JSON diagnostic path,\n * payload-build throw on a hostile getter, record outside scope when\n * `strict: false`). Adopters wire this to their logger so silent failures\n * surface in dev sessions. Throwing inside `onError` is itself swallowed —\n * the hook MUST NOT crash the recorder.\n */\n onError?: (event: UpstreamRecorderErrorEvent) => void;\n}\n\n/**\n * Surfaced through `UpstreamRecorderOptions.onError` for adopter\n * observability. Each kind names a specific swallow site in the recorder.\n */\nexport type UpstreamRecorderErrorEvent =\n | { kind: 'classifier_threw'; err: unknown }\n | { kind: 'classifier_invalid_purpose'; purpose: string }\n | { kind: 'url_parse_failed'; url: string }\n | { kind: 'payload_build_failed'; err: unknown }\n | { kind: 'digest_canonicalization_failed'; method: string; endpoint: string; err: unknown }\n | { kind: 'json_payload_parse_failed'; content_type: string; err: unknown }\n | { kind: 'unscoped_record'; method: string; url: string };\n\n/**\n * Thrown by `record()` and the wrapped fetch when invoked outside a\n * `runWithPrincipal` scope and `strict: true` is set. Subclasses `Error`\n * so adopter test runners surface the stack trace.\n */\nexport class UpstreamRecorderScopeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UpstreamRecorderScopeError';\n }\n}\n\n/**\n * Parameters accepted by `recorder.query`. Mirrors the\n * `query_upstream_traffic` controller scenario shape so the adopter can\n * pass-through their controller request directly.\n */\nexport interface UpstreamRecorderQueryParams {\n /**\n * Caller principal — REQUIRED. Cross-principal isolation is the spec's\n * security HIGH requirement: a controller call from principal A MUST NOT\n * surface principal B's traffic. Adopters resolve this from their auth\n * context (e.g., the `account` block on the controller request, or the\n * adopter's session principal).\n */\n principal: string;\n /**\n * ISO 8601 timestamp lower bound. Only calls recorded at or after this\n * time are returned. The runner subtracts a 250 ms clock-skew tolerance\n * before sending the bound — adopter MAY also widen the window if it\n * knows its own clock drifts.\n */\n sinceTimestamp?: string;\n /**\n * Glob pattern matched against `<METHOD> <URL>` (i.e. `endpoint`). `*`\n * matches zero-or-more characters of any kind including `/`; all other\n * characters are literal. Adopter-side filter — equivalent to filtering\n * on the runner side after the response, but reduces response size.\n */\n endpointPattern?: string;\n /**\n * Maximum recorded calls to return. Defaults to 100, capped at the\n * buffer size. When the un-capped result would have exceeded `limit`,\n * `truncated: true` is set on the response so the runner can detect\n * overflow.\n */\n limit?: number;\n /**\n * Requested attestation mode for returned calls. `raw` (default) returns\n * the redacted payload; `digest` returns `payload_digest_sha256` plus\n * optional identifier echo proofs. Digest projection canonicalizes JSON\n * payloads before hashing; when a matched JSON payload cannot be\n * canonicalized, `query()` omits that entry and emits\n * `digest_canonicalization_failed` through `onError`.\n */\n attestationMode?: 'raw' | 'digest';\n /**\n * SHA-256 digests of identifier string values the caller wants verified\n * in digest mode. Ignored for raw-mode projection.\n */\n identifierValueDigests?: string[];\n}\n\n/**\n * Result of `recorder.query`. Adopter-side ergonomic shape (camelCase\n * field names, `items` not `recorded_calls`). Use\n * `toQueryUpstreamTrafficResponse(result)` to project this onto the\n * spec's `UpstreamTrafficSuccess` controller-response wire shape rather\n * than reinventing the field renames in every adopter's handler.\n */\nexport interface UpstreamRecorderQueryResult {\n /** Calls matching all filters, ordered by `timestamp` ascending. */\n items: RecordedCall[];\n /**\n * Total count BEFORE `limit` truncation. `items.length` may be smaller\n * when limit clipped the result. Digest-mode entries dropped by\n * canonicalization failure are excluded from this count and reported in\n * `dropped_count` instead.\n */\n total: number;\n /** True when `total > items.length`. */\n truncated: boolean;\n /**\n * Echo of the requested `sinceTimestamp` (or the recorder-substituted\n * default — the earliest record retained in the buffer when no\n * `sinceTimestamp` was passed; disabled no-op recorders use the Unix\n * epoch). Lets the runner verify the controller honored the bound.\n */\n since_timestamp: string;\n /**\n * Number of matched entries omitted from returned items after digest\n * projection failed; `digest_canonicalization_failed` is surfaced through\n * `onError` when that hook is configured. Only relevant when\n * `attestationMode: 'digest'` was requested; always `0` in raw mode. A\n * non-zero value means matched traffic existed but could not be attested\n * — the runner's\n * `upstream_traffic` check may grade it `missing` rather than `present`.\n * Not projected onto the current wire response (the spec's\n * `UpstreamTrafficSuccess` does not yet define this field); wire\n * projection will be added when the schema adopts it.\n */\n dropped_count: number;\n}\n\n/**\n * Wire shape returned by the `comply_test_controller`'s\n * `query_upstream_traffic` scenario, mirroring `UpstreamTrafficSuccess`\n * in `comply-test-controller-response.json` (spec PR\n * adcontextprotocol/adcp#3816). Adopter handlers can `return\n * toQueryUpstreamTrafficResponse(recorder.query(...))` directly.\n */\nexport interface QueryUpstreamTrafficResponse {\n success: true;\n recorded_calls: RecordedCall[];\n total_count: number;\n truncated: boolean;\n since_timestamp: string;\n}\n\n/**\n * Public recorder surface. Adopters get one of these from\n * `createUpstreamRecorder(options)`.\n */\nexport interface UpstreamRecorder {\n /**\n * Run `fn` with `principal` bound as the active recording principal.\n * Every wrapped HTTP call inside `fn` (including async tasks awaited\n * inside) records under that principal. Implemented via\n * AsyncLocalStorage — context propagates across `await` boundaries the\n * same way Node's stack trace does, so most adopters won't need to\n * thread the principal through their HTTP call sites manually.\n *\n * Re-entrant — nested `runWithPrincipal` calls override the parent's\n * principal for their inner scope only.\n */\n /**\n * The same string MUST be passed at record-time and query-time — record\n * happens inside `runWithPrincipal(p, fn)`, query is invoked from the\n * adopter's `comply_test_controller` handler with the principal it\n * receives in its auth context. The two ends MUST agree:\n *\n * - **OAuth client_credentials sellers**: pass the resolved `client_id`.\n * - **Session-token sellers**: pass the `account.id` (or whatever\n * stable per-adopter-account identifier the auth layer materializes).\n * - **Anonymous / public-sandbox sellers**: pass a stable per-session\n * identifier; literal-anonymous strings collide across tenants and\n * defeat isolation.\n *\n * Mismatch between record-time and query-time principal returns zero\n * results. That's the spec's security floor (cross-principal leakage\n * MUST NOT happen), not a bug — but it means a typo shows up as\n * \"controller present, observed nothing\" in storyboard output.\n */\n runWithPrincipal<T>(principal: string, fn: () => T | Promise<T>): Promise<T>;\n /**\n * Wrap a fetch implementation so calls inside `runWithPrincipal` flow\n * through this recorder. Returns a fetch with the same signature; the\n * wrapper is a pass-through when the recorder is `enabled: false` or\n * when no principal is active. Drop the wrapped fetch into your HTTP\n * layer (e.g. `globalThis.fetch = recorder.wrapFetch(globalThis.fetch)`)\n * or pass it explicitly to your HTTP client constructor.\n */\n wrapFetch(fetch: typeof globalThis.fetch): typeof globalThis.fetch;\n /**\n * Manually record a call. Escape hatch for adopters with custom\n * transports the recorder doesn't ship a wrapper for. The principal\n * is read from the active `runWithPrincipal` scope unless explicitly\n * passed. Redaction + timestamp + purpose tagging still apply.\n */\n record(call: RecordInput, principal?: string): void;\n /**\n * Return recorded calls scoped to the requesting principal, filtered by\n * `sinceTimestamp` and `endpointPattern`, and truncated to `limit`.\n * Adopters typically pass the result verbatim into their\n * `comply_test_controller`'s `query_upstream_traffic` response. In\n * digest mode, entries that cannot be canonicalized for\n * `payload_digest_sha256` are omitted and surfaced through `onError`.\n */\n query(params: UpstreamRecorderQueryParams): UpstreamRecorderQueryResult;\n /**\n * Drop every recorded call. Test cleanup helper — production code\n * should rely on TTL eviction instead.\n */\n clear(): void;\n /** Reflect the configured `enabled` flag — useful for adopter assertions. */\n readonly enabled: boolean;\n /**\n * Introspection helper for adopters debugging \"my storyboard says zero\n * calls but I see them in the logs\". Returns the recorder's current\n * state — buffer size, total entries, distinct principals, the\n * timestamp of the most recent record, and the active principal in the\n * caller's scope (when invoked from inside `runWithPrincipal`).\n * Diagnostic only; not a public conformance surface.\n */\n debug(): UpstreamRecorderDebugInfo;\n}\n\n/**\n * Snapshot returned by `recorder.debug()`. The shape is informational —\n * adopters are expected to log it, not match against it.\n */\nexport interface UpstreamRecorderDebugInfo {\n enabled: boolean;\n bufferSize: number;\n bufferedEntries: number;\n /** Distinct principals with at least one buffered entry. */\n principals: string[];\n /** ISO timestamp of the most recent record, or `null` if buffer is empty. */\n lastRecordedAt: string | null;\n /**\n * The principal active in the caller's `runWithPrincipal` scope at the\n * moment `debug()` was invoked. `null` when called outside any scope.\n */\n activePrincipal: string | null;\n /** Echo of the configured `strict` flag. */\n strict: boolean;\n}\n\n/**\n * Input shape for `recorder.record` / the wrapped fetch's internal call.\n * The recorder fills in `timestamp` and (optionally) `purpose` itself; the\n * caller supplies the wire-shape facts.\n */\nexport interface RecordInput {\n method: string;\n url: string;\n /**\n * Outbound `Content-Type` header value, mirrored verbatim onto\n * `RecordedCall.content_type`. Required because the runner's matcher\n * choice depends on it.\n */\n content_type: string;\n /**\n * Outbound headers — used by the redactor and the purpose classifier.\n * Keys are normalized to lowercase before redaction; values pass\n * through if not on a secret-shaped key.\n */\n headers?: Record<string, string>;\n /**\n * Outbound request body. Object when JSON-decodable (recorder will\n * apply per-key redaction); string for non-JSON (recorder applies\n * length-cap only). Pass `undefined` for GET / HEAD / DELETE without\n * a body.\n */\n payload?: unknown;\n /**\n * HTTP status code of the upstream response, when known. Adapters\n * MAY omit this for fire-and-forget calls instrumented before the\n * response arrives.\n */\n status_code?: number;\n}\n"],"mappings":";;;;;;AAmNO,MAAM,mCAAmC,MAAM;AAAA,EACpD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/upstream-recorder/types.ts"],"sourcesContent":["/**\n * Public types for `@adcp/sdk/upstream-recorder`.\n *\n * Producer-side companion to the runner-output-contract v2.0.0\n * `upstream_traffic` storyboard check (spec PR adcontextprotocol/adcp#3816).\n * The recorder captures outbound HTTP calls an adapter makes during a\n * sandbox session and surfaces them to the adopter's\n * `comply_test_controller` `query_upstream_traffic` handler so storyboard\n * runners can verify side-effects against the adopter's real upstream\n * platform (the load-bearing anti-façade contract).\n *\n * Adopter-facing API. The recorder itself is sandbox-only — `enabled: false`\n * short-circuits every wrapping adapter to a pass-through.\n */\n\n/**\n * Single recorded outbound HTTP call. Mirrors\n * `comply-test-controller-response.json > UpstreamTrafficSuccess.recorded_calls[]`\n * so adopter handlers can return query results verbatim.\n *\n * Redaction is applied at recording time, not query time, so the in-memory\n * buffer never holds plaintext secrets even briefly.\n */\ninterface RecordedCallBase {\n /**\n * Forward-compatibility for future additive spec fields on recorded call\n * items; adopter-defined fields are still rejected by the current 3.1 wire\n * schema.\n */\n [key: string]: unknown;\n method: string;\n /** Composed `<METHOD> <URL>` for `endpoint_pattern` matching. */\n endpoint: string;\n url: string;\n /** Parsed from `url` when URL parsing succeeds; the recorder emits `''` on parse failure. */\n host: string;\n /** Parsed from `url` when URL parsing succeeds; the recorder emits `''` on parse failure. */\n path: string;\n /**\n * Media type of the recorded `payload`, mirroring the adapter's outbound\n * `Content-Type` header. Required by the contract — runners use this to\n * pick the right matcher (JSONPath for JSON-shaped, substring fallback\n * for other types).\n */\n content_type: string;\n /**\n * Byte length of the emitted payload representation after redaction. Raw\n * calls measure the raw emitted payload representation; digest calls\n * measure the same canonical byte stream covered by\n * `payload_digest_sha256`.\n */\n payload_length: number;\n timestamp: string;\n status_code?: number;\n /**\n * Optional classifier — set when the `purpose` callback was supplied.\n * Mirrors adcp#3830 item 3 (purpose tagging) so storyboards can scope\n * `endpoint_pattern` matching to platform-primary calls vs. measurement\n * vendors when the spec adopts that field.\n */\n purpose?: string;\n}\n\nexport interface RawRecordedCall extends RecordedCallBase {\n attestation_mode: 'raw';\n /** Decoded JSON object when content_type is JSON-shaped; raw string otherwise. */\n payload: unknown;\n payload_digest_sha256?: never;\n identifier_match_proofs?: never;\n}\n\nexport interface DigestRecordedCall extends RecordedCallBase {\n attestation_mode: 'digest';\n payload?: never;\n /**\n * Lowercase hex SHA-256 of the post-redaction payload bytes. JSON object\n * and array payloads use RFC 8785 JCS canonicalization before hashing.\n * JSON strings are parsed and canonicalized when they contain valid JSON;\n * malformed JSON strings and non-JSON payloads use the post-redaction\n * emitted body bytes. Unsupported JSON values cannot produce a canonical\n * digest. Malformed JSON strings are treated as one opaque string for\n * identifier proof scanning, so substring identifiers inside invalid JSON\n * are not discoverable. String-only identifier proofs are deliberately low\n * entropy when adopters use short or guessable synthetic values; do not run\n * digest-mode attestations over production identifiers.\n */\n payload_digest_sha256: string;\n identifier_match_proofs?: Array<{\n /** Lowercase hex SHA-256 of a runner-supplied string identifier value. */\n identifier_value_sha256: string;\n /**\n * True when the digest matched a string leaf in the redacted JSON\n * payload. Non-string identifier vectors cannot be proven in digest\n * mode and should grade not_applicable rather than missing.\n */\n found: boolean;\n }>;\n}\n\nexport type RecordedCall = RawRecordedCall | DigestRecordedCall;\n\n/**\n * Optional classifier callback. Invoked at recording time on each call so\n * the recorder can stamp a `purpose` tag without the adopter wiring it\n * through their HTTP layer manually. Return one of\n * `platform_primary`, `measurement`, `attribution`, `creative_serving`,\n * `identity`, or `other`. Returning `undefined` leaves the `purpose` field\n * unset; returning any other string omits `purpose` and emits\n * `classifier_invalid_purpose` through `onError`.\n */\nexport type PurposeClassifier = (input: {\n method: string;\n url: string;\n host: string;\n path: string;\n /** Outbound headers (lowercased keys), with secrets already redacted. */\n headers: Record<string, string>;\n}) => string | undefined;\n\n/**\n * Configuration for `createUpstreamRecorder`. Every field is optional;\n * the defaults match the spec's recommended conformance posture.\n */\nexport interface UpstreamRecorderOptions {\n /**\n * Master switch. Defaults to `true`. Adopters MUST gate this against\n * their sandbox / non-production environment (e.g.\n * `enabled: process.env.NODE_ENV !== 'production'`). When `false`, the\n * factory returns a no-op recorder — `wrapFetch` returns the input fetch\n * unchanged, `record` is a no-op, `query` always returns empty results.\n * Zero overhead in production.\n */\n enabled?: boolean;\n /**\n * Override the canonical secret-key redaction pattern. Adopters MAY\n * extend the contract floor with internal vendor-specific keys. Adopters\n * MUST NOT narrow it — passing a pattern that omits a contract-required\n * key is a security regression.\n */\n redactPattern?: RegExp;\n /**\n * Maximum recorded calls retained in the buffer (across all principals).\n * Defaults to 1000. When the buffer is full, the oldest entry is evicted\n * before recording the new call. Storyboards generally exercise tens of\n * calls per assertion window — 1000 is a safe upper bound for a single\n * sandbox session.\n */\n bufferSize?: number;\n /**\n * Time-to-live for recorded calls, in milliseconds. Defaults to 1 hour.\n * Calls older than `ttlMs` at query time are excluded from results AND\n * pruned eagerly on the next record. Bounds the buffer's exposure\n * window — a stale recorder shouldn't surface yesterday's traffic on\n * today's compliance run.\n */\n ttlMs?: number;\n /**\n * Optional classifier — see `PurposeClassifier`. Invoked on every record\n * with the redacted-headers view of the outbound call.\n */\n purpose?: PurposeClassifier;\n /**\n * When `true`, calling `record()` or invoking the wrapped fetch outside a\n * `runWithPrincipal(p, fn)` scope throws an `UpstreamRecorderScopeError`\n * instead of silently dropping the call. Default `false` — silent drop\n * matches the recorder's \"don't break the adapter\" posture in production.\n * Adopters writing or debugging integration tests SHOULD enable this so\n * forgotten scope wrappers surface as a stack trace pointing at the\n * unwrapped call site, not as mysterious \"controller present, observed\n * nothing\" storyboard failures.\n */\n strict?: boolean;\n /**\n * Maximum bytes retained in `RecordedCall.payload` per entry. Adopter\n * payloads exceeding this limit are replaced with the marker string\n * `'[truncated <n> bytes]'` so the buffer ceiling stays bounded even\n * when an adopter records bulk uploads. Default 65 536 (64 KiB —\n * mirrors the spec's `recorded_calls[].payload` `maxLength`).\n * Set to 0 to disable truncation.\n */\n maxPayloadBytes?: number;\n /**\n * Optional observability hook. Invoked when the recorder swallows an\n * error that would otherwise be invisible (purpose classifier throw,\n * invalid purpose tag, URL parse failure, malformed JSON diagnostic path,\n * payload-build throw on a hostile getter, record outside scope when\n * `strict: false`). Adopters wire this to their logger so silent failures\n * surface in dev sessions. Throwing inside `onError` is itself swallowed —\n * the hook MUST NOT crash the recorder.\n */\n onError?: (event: UpstreamRecorderErrorEvent) => void;\n}\n\n/**\n * Surfaced through `UpstreamRecorderOptions.onError` for adopter\n * observability. Each kind names a specific swallow site in the recorder.\n */\nexport type UpstreamRecorderErrorEvent =\n | { kind: 'classifier_threw'; err: unknown }\n | { kind: 'classifier_invalid_purpose'; purpose: string }\n | { kind: 'url_parse_failed'; url: string }\n | { kind: 'payload_build_failed'; err: unknown }\n | { kind: 'digest_canonicalization_failed'; method: string; endpoint: string; err: unknown }\n | { kind: 'json_payload_parse_failed'; content_type: string; err: unknown }\n | { kind: 'unscoped_record'; method: string; url: string };\n\n/**\n * Thrown by `record()` and the wrapped fetch when invoked outside a\n * `runWithPrincipal` scope and `strict: true` is set. Subclasses `Error`\n * so adopter test runners surface the stack trace.\n */\nexport class UpstreamRecorderScopeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UpstreamRecorderScopeError';\n }\n}\n\n/**\n * Parameters accepted by `recorder.query`. Mirrors the\n * `query_upstream_traffic` controller scenario shape so the adopter can\n * pass-through their controller request directly.\n */\nexport interface UpstreamRecorderQueryParams {\n /**\n * Caller principal — REQUIRED. Cross-principal isolation is the spec's\n * security HIGH requirement: a controller call from principal A MUST NOT\n * surface principal B's traffic. Adopters resolve this from their auth\n * context (e.g., the `account` block on the controller request, or the\n * adopter's session principal).\n */\n principal: string;\n /**\n * ISO 8601 timestamp lower bound. Only calls recorded at or after this\n * time are returned. The runner subtracts a 250 ms clock-skew tolerance\n * before sending the bound — adopter MAY also widen the window if it\n * knows its own clock drifts.\n */\n sinceTimestamp?: string;\n /**\n * Glob pattern matched against `<METHOD> <URL>` (i.e. `endpoint`). `*`\n * matches zero-or-more characters of any kind including `/`; all other\n * characters are literal. Adopter-side filter — equivalent to filtering\n * on the runner side after the response, but reduces response size.\n */\n endpointPattern?: string;\n /**\n * Maximum recorded calls to return. Defaults to 100, capped at the\n * buffer size. When the un-capped result would have exceeded `limit`,\n * `truncated: true` is set on the response so the runner can detect\n * overflow.\n */\n limit?: number;\n /**\n * Requested attestation mode for returned calls. `raw` (default) returns\n * the redacted payload; `digest` returns `payload_digest_sha256` plus\n * optional identifier echo proofs. Digest projection canonicalizes JSON\n * payloads before hashing; when a matched JSON payload cannot be\n * canonicalized, `query()` omits that entry and emits\n * `digest_canonicalization_failed` through `onError`.\n */\n attestationMode?: 'raw' | 'digest';\n /**\n * SHA-256 digests of identifier string values the caller wants verified\n * in digest mode. Ignored for raw-mode projection.\n */\n identifierValueDigests?: string[];\n}\n\n/**\n * Result of `recorder.query`. Adopter-side ergonomic shape (camelCase\n * field names, `items` not `recorded_calls`). Use\n * `toQueryUpstreamTrafficResponse(result)` to project this onto the\n * spec's `UpstreamTrafficSuccess` controller-response wire shape rather\n * than reinventing the field renames in every adopter's handler.\n */\nexport interface UpstreamRecorderQueryResult {\n /** Calls matching all filters, ordered by `timestamp` ascending. */\n items: RecordedCall[];\n /**\n * Total count BEFORE `limit` truncation. `items.length` may be smaller\n * when limit clipped the result. Digest-mode entries dropped by\n * canonicalization failure are excluded from this count and reported in\n * `dropped_count` instead.\n */\n total: number;\n /** True when `total > items.length`. */\n truncated: boolean;\n /**\n * Echo of the requested `sinceTimestamp` (or the recorder-substituted\n * default — the earliest record retained in the buffer when no\n * `sinceTimestamp` was passed; disabled no-op recorders use the Unix\n * epoch). Lets the runner verify the controller honored the bound.\n */\n since_timestamp: string;\n /**\n * Number of matched entries omitted from returned items after digest\n * projection failed; `digest_canonicalization_failed` is surfaced through\n * `onError` when that hook is configured. Only relevant when\n * `attestationMode: 'digest'` was requested; always `0` in raw mode. A\n * non-zero value means matched traffic existed but could not be attested\n * — the runner's\n * `upstream_traffic` check may grade it `missing` rather than `present`.\n * Not projected onto the current wire response (the spec's\n * `UpstreamTrafficSuccess` does not yet define this field); wire\n * projection will be added when the schema adopts it.\n */\n dropped_count: number;\n}\n\n/**\n * Wire shape returned by the `comply_test_controller`'s\n * `query_upstream_traffic` scenario, mirroring `UpstreamTrafficSuccess`\n * in `comply-test-controller-response.json` (spec PR\n * adcontextprotocol/adcp#3816). Adopter handlers can `return\n * toQueryUpstreamTrafficResponse(recorder.query(...))` directly.\n */\nexport interface QueryUpstreamTrafficResponse {\n success: true;\n recorded_calls: RecordedCall[];\n total_count: number;\n truncated: boolean;\n since_timestamp: string;\n}\n\n/**\n * Public recorder surface. Adopters get one of these from\n * `createUpstreamRecorder(options)`.\n */\nexport interface UpstreamRecorder {\n /**\n * Run `fn` with `principal` bound as the active recording principal.\n * Every wrapped HTTP call inside `fn` (including async tasks awaited\n * inside) records under that principal. Implemented via\n * AsyncLocalStorage — context propagates across `await` boundaries the\n * same way Node's stack trace does, so most adopters won't need to\n * thread the principal through their HTTP call sites manually.\n *\n * Re-entrant — nested `runWithPrincipal` calls override the parent's\n * principal for their inner scope only.\n */\n /**\n * The same string MUST be passed at record-time and query-time — record\n * happens inside `runWithPrincipal(p, fn)`, query is invoked from the\n * adopter's `comply_test_controller` handler with the principal it\n * receives in its auth context. The two ends MUST agree:\n *\n * - **OAuth client_credentials sellers**: pass the resolved `client_id`.\n * - **Session-token sellers**: pass the `account.id` (or whatever\n * stable per-adopter-account identifier the auth layer materializes).\n * - **Anonymous / public-sandbox sellers**: pass a stable per-session\n * identifier; literal-anonymous strings collide across tenants and\n * defeat isolation.\n *\n * Mismatch between record-time and query-time principal returns zero\n * results. That's the spec's security floor (cross-principal leakage\n * MUST NOT happen), not a bug — but it means a typo shows up as\n * \"controller present, observed nothing\" in storyboard output.\n */\n runWithPrincipal<T>(principal: string, fn: () => T | Promise<T>): Promise<T>;\n /**\n * Wrap a fetch implementation so calls inside `runWithPrincipal` flow\n * through this recorder. Returns a fetch with the same signature; the\n * wrapper is a pass-through when the recorder is `enabled: false` or\n * when no principal is active. Drop the wrapped fetch into your HTTP\n * layer (e.g. `globalThis.fetch = recorder.wrapFetch(globalThis.fetch)`)\n * or pass it explicitly to your HTTP client constructor.\n */\n wrapFetch(fetch: typeof globalThis.fetch): typeof globalThis.fetch;\n /**\n * Manually record a call. Escape hatch for adopters with custom\n * transports the recorder doesn't ship a wrapper for. The principal\n * is read from the active `runWithPrincipal` scope unless explicitly\n * passed. Redaction + timestamp + purpose tagging still apply.\n */\n record(call: RecordInput, principal?: string): void;\n /**\n * Return recorded calls scoped to the requesting principal, filtered by\n * `sinceTimestamp` and `endpointPattern`, and truncated to `limit`.\n * Adopters typically pass the result verbatim into their\n * `comply_test_controller`'s `query_upstream_traffic` response. In\n * digest mode, entries that cannot be canonicalized for\n * `payload_digest_sha256` are omitted and surfaced through `onError`.\n */\n query(params: UpstreamRecorderQueryParams): UpstreamRecorderQueryResult;\n /**\n * Drop every recorded call. Test cleanup helper — production code\n * should rely on TTL eviction instead.\n */\n clear(): void;\n /** Reflect the configured `enabled` flag — useful for adopter assertions. */\n readonly enabled: boolean;\n /**\n * Introspection helper for adopters debugging \"my storyboard says zero\n * calls but I see them in the logs\". Returns the recorder's current\n * state — buffer size, total entries, distinct principals, the\n * timestamp of the most recent record, and the active principal in the\n * caller's scope (when invoked from inside `runWithPrincipal`).\n * Diagnostic only; not a public conformance surface.\n */\n debug(): UpstreamRecorderDebugInfo;\n}\n\n/**\n * Snapshot returned by `recorder.debug()`. The shape is informational —\n * adopters are expected to log it, not match against it.\n */\nexport interface UpstreamRecorderDebugInfo {\n enabled: boolean;\n bufferSize: number;\n bufferedEntries: number;\n /** Distinct principals with at least one buffered entry. */\n principals: string[];\n /** ISO timestamp of the most recent record, or `null` if buffer is empty. */\n lastRecordedAt: string | null;\n /**\n * The principal active in the caller's `runWithPrincipal` scope at the\n * moment `debug()` was invoked. `null` when called outside any scope.\n */\n activePrincipal: string | null;\n /** Echo of the configured `strict` flag. */\n strict: boolean;\n}\n\n/**\n * Input shape for `recorder.record` / the wrapped fetch's internal call.\n * The recorder fills in `timestamp` and (optionally) `purpose` itself; the\n * caller supplies the wire-shape facts.\n */\nexport interface RecordInput {\n method: string;\n url: string;\n /**\n * Outbound `Content-Type` header value, mirrored verbatim onto\n * `RecordedCall.content_type`. Required because the runner's matcher\n * choice depends on it.\n */\n content_type: string;\n /**\n * Outbound headers — used by the redactor and the purpose classifier.\n * Keys are normalized to lowercase before redaction; values pass\n * through if not on a secret-shaped key.\n */\n headers?: Record<string, string>;\n /**\n * Outbound request body. Object when JSON-decodable (recorder will\n * apply per-key redaction); string for non-JSON (recorder applies\n * length-cap only). Pass `undefined` for GET / HEAD / DELETE without\n * a body.\n */\n payload?: unknown;\n /**\n * HTTP status code of the upstream response, when known. Adapters\n * MAY omit this for fire-and-forget calls instrumented before the\n * response arrives.\n */\n status_code?: number;\n}\n"],"mappings":"AAmNO,MAAM,mCAAmC,MAAM;AAAA,EACpD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;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
|
function getLatestA2ADataPartFromTask(result) {
|
|
8
2
|
if (result == null || typeof result !== "object" || Array.isArray(result)) return void 0;
|
|
9
3
|
const artifacts = result.artifacts;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/a2a-artifacts.ts"],"sourcesContent":["/**\n * Shared A2A artifact extraction helpers.\n *\n * A2A conversational tasks append artifacts over time. The SDK's canonical\n * data path is the latest DataPart found by walking artifacts backward, then\n * parts backward. Trailing text-only artifacts can carry explanatory copy, but\n * they must not hide the latest structured AdCP payload.\n */\n\nexport interface A2ADataPartExtraction {\n artifact: Record<string, unknown>;\n part: Record<string, unknown>;\n data: Record<string, unknown>;\n}\n\nexport function getLatestA2ADataPartFromTask(result: unknown): A2ADataPartExtraction | undefined {\n if (result == null || typeof result !== 'object' || Array.isArray(result)) return undefined;\n\n const artifacts = (result as { artifacts?: unknown }).artifacts;\n if (!Array.isArray(artifacts) || artifacts.length === 0) return undefined;\n\n for (let artifactIndex = artifacts.length - 1; artifactIndex >= 0; artifactIndex -= 1) {\n const artifact = artifacts[artifactIndex];\n if (artifact == null || typeof artifact !== 'object' || Array.isArray(artifact)) continue;\n\n const parts = (artifact as { parts?: unknown }).parts;\n if (!Array.isArray(parts) || parts.length === 0) continue;\n\n for (let partIndex = parts.length - 1; partIndex >= 0; partIndex -= 1) {\n const part = parts[partIndex];\n if (part == null || typeof part !== 'object' || Array.isArray(part)) continue;\n const record = part as Record<string, unknown>;\n if (record.kind !== 'data') continue;\n const data = record.data;\n if (data == null || typeof data !== 'object' || Array.isArray(data)) continue;\n return {\n artifact: artifact as Record<string, unknown>,\n part: record,\n data: data as Record<string, unknown>,\n };\n }\n }\n\n return undefined;\n}\n\nexport function getLatestA2ADataPartFromResponse(response: unknown): A2ADataPartExtraction | undefined {\n if (response == null || typeof response !== 'object' || Array.isArray(response)) return undefined;\n return getLatestA2ADataPartFromTask((response as { result?: unknown }).result);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/a2a-artifacts.ts"],"sourcesContent":["/**\n * Shared A2A artifact extraction helpers.\n *\n * A2A conversational tasks append artifacts over time. The SDK's canonical\n * data path is the latest DataPart found by walking artifacts backward, then\n * parts backward. Trailing text-only artifacts can carry explanatory copy, but\n * they must not hide the latest structured AdCP payload.\n */\n\nexport interface A2ADataPartExtraction {\n artifact: Record<string, unknown>;\n part: Record<string, unknown>;\n data: Record<string, unknown>;\n}\n\nexport function getLatestA2ADataPartFromTask(result: unknown): A2ADataPartExtraction | undefined {\n if (result == null || typeof result !== 'object' || Array.isArray(result)) return undefined;\n\n const artifacts = (result as { artifacts?: unknown }).artifacts;\n if (!Array.isArray(artifacts) || artifacts.length === 0) return undefined;\n\n for (let artifactIndex = artifacts.length - 1; artifactIndex >= 0; artifactIndex -= 1) {\n const artifact = artifacts[artifactIndex];\n if (artifact == null || typeof artifact !== 'object' || Array.isArray(artifact)) continue;\n\n const parts = (artifact as { parts?: unknown }).parts;\n if (!Array.isArray(parts) || parts.length === 0) continue;\n\n for (let partIndex = parts.length - 1; partIndex >= 0; partIndex -= 1) {\n const part = parts[partIndex];\n if (part == null || typeof part !== 'object' || Array.isArray(part)) continue;\n const record = part as Record<string, unknown>;\n if (record.kind !== 'data') continue;\n const data = record.data;\n if (data == null || typeof data !== 'object' || Array.isArray(data)) continue;\n return {\n artifact: artifact as Record<string, unknown>,\n part: record,\n data: data as Record<string, unknown>,\n };\n }\n }\n\n return undefined;\n}\n\nexport function getLatestA2ADataPartFromResponse(response: unknown): A2ADataPartExtraction | undefined {\n if (response == null || typeof response !== 'object' || Array.isArray(response)) return undefined;\n return getLatestA2ADataPartFromTask((response as { result?: unknown }).result);\n}\n"],"mappings":"AAeO,SAAS,6BAA6B,QAAoD;AAC/F,MAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,EAAG,QAAO;AAElF,QAAM,YAAa,OAAmC;AACtD,MAAI,CAAC,MAAM,QAAQ,SAAS,KAAK,UAAU,WAAW,EAAG,QAAO;AAEhE,WAAS,gBAAgB,UAAU,SAAS,GAAG,iBAAiB,GAAG,iBAAiB,GAAG;AACrF,UAAM,WAAW,UAAU,aAAa;AACxC,QAAI,YAAY,QAAQ,OAAO,aAAa,YAAY,MAAM,QAAQ,QAAQ,EAAG;AAEjF,UAAM,QAAS,SAAiC;AAChD,QAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,EAAG;AAEjD,aAAS,YAAY,MAAM,SAAS,GAAG,aAAa,GAAG,aAAa,GAAG;AACrE,YAAM,OAAO,MAAM,SAAS;AAC5B,UAAI,QAAQ,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,EAAG;AACrE,YAAM,SAAS;AACf,UAAI,OAAO,SAAS,OAAQ;AAC5B,YAAM,OAAO,OAAO;AACpB,UAAI,QAAQ,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,EAAG;AACrE,aAAO;AAAA,QACL;AAAA,QACA,MAAM;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,iCAAiC,UAAsD;AACrG,MAAI,YAAY,QAAQ,OAAO,aAAa,YAAY,MAAM,QAAQ,QAAQ,EAAG,QAAO;AACxF,SAAO,6BAA8B,SAAkC,MAAM;AAC/E;","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 A2A_CARD_PATHS = ["/.well-known/agent.json", "/.well-known/agent-card.json"];
|
|
8
2
|
const AGENT_CARD_PATH_REGEX = /\/\.well-known\/agent(-card)?\.json$/i;
|
|
9
3
|
const TRANSPORT_SUFFIX_REGEX = /\/(?:mcp|a2a|sse)\/?$/i;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/a2a-discovery.ts"],"sourcesContent":["/**\n * A2A Agent Card Discovery Utilities\n *\n * Supports both /.well-known/agent.json (current A2A spec)\n * and /.well-known/agent-card.json (legacy) for agent card discovery.\n */\n\n/** A2A agent card well-known paths, preferred first */\nexport const A2A_CARD_PATHS = ['/.well-known/agent.json', '/.well-known/agent-card.json'] as const;\n\n/** Matches either well-known agent card path at end of string (case-insensitive) */\nconst AGENT_CARD_PATH_REGEX = /\\/\\.well-known\\/agent(-card)?\\.json$/i;\n\n/**\n * AdCP protocol transport suffixes that the runner appends to reach a\n * protocol endpoint. Kept here as the single source of truth — both\n * `SingleAgentClient.computeBaseUrl` and the storyboard scope canonicalizer\n * import this so new transports (e.g., future websocket) only need to be\n * added in one place.\n */\nexport const TRANSPORT_SUFFIX_REGEX = /\\/(?:mcp|a2a|sse)\\/?$/i;\n\n/** Strip a protocol transport suffix (`/mcp`, `/a2a`, `/sse`) from a URL path. */\nexport function stripTransportSuffix(url: string): string {\n return url.replace(TRANSPORT_SUFFIX_REGEX, '');\n}\n\n/** Matches a root-level well-known agent card URL (scheme://host/.well-known/agent[-card].json) */\nconst AGENT_CARD_URL_REGEX = /^https?:\\/\\/[^/]+\\/\\.well-known\\/agent(-card)?\\.json$/i;\n\n/**\n * Check if a URL string ends with an agent card well-known path\n */\nexport function isAgentCardPath(url: string): boolean {\n return AGENT_CARD_PATH_REGEX.test(url);\n}\n\n/**\n * Check if a URL is a root-level well-known agent card URL.\n *\n * Matches: https://example.com/.well-known/agent.json\n * Matches: https://example.com/.well-known/agent-card.json\n * Rejects: https://example.com/api/.well-known/agent.json\n */\nexport function isWellKnownAgentCardUrl(url: string): boolean {\n return AGENT_CARD_URL_REGEX.test(url);\n}\n\n/**\n * Build the list of agent card URLs to try for a given agent URL.\n *\n * If the URL already points to a well-known agent card path, returns it as-is.\n * Otherwise returns both paths (preferred first) appended to the base URL.\n */\nexport function buildCardUrls(agentUrl: string): string[] {\n if (isAgentCardPath(agentUrl)) {\n return [agentUrl];\n }\n const base = agentUrl.replace(/\\/$/, '');\n return A2A_CARD_PATHS.map(path => `${base}${path}`);\n}\n\n/**\n * Strip a well-known agent card path from a URL, returning the base URL.\n */\nexport function stripAgentCardPath(url: string): string {\n return url.replace(AGENT_CARD_PATH_REGEX, '');\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/a2a-discovery.ts"],"sourcesContent":["/**\n * A2A Agent Card Discovery Utilities\n *\n * Supports both /.well-known/agent.json (current A2A spec)\n * and /.well-known/agent-card.json (legacy) for agent card discovery.\n */\n\n/** A2A agent card well-known paths, preferred first */\nexport const A2A_CARD_PATHS = ['/.well-known/agent.json', '/.well-known/agent-card.json'] as const;\n\n/** Matches either well-known agent card path at end of string (case-insensitive) */\nconst AGENT_CARD_PATH_REGEX = /\\/\\.well-known\\/agent(-card)?\\.json$/i;\n\n/**\n * AdCP protocol transport suffixes that the runner appends to reach a\n * protocol endpoint. Kept here as the single source of truth — both\n * `SingleAgentClient.computeBaseUrl` and the storyboard scope canonicalizer\n * import this so new transports (e.g., future websocket) only need to be\n * added in one place.\n */\nexport const TRANSPORT_SUFFIX_REGEX = /\\/(?:mcp|a2a|sse)\\/?$/i;\n\n/** Strip a protocol transport suffix (`/mcp`, `/a2a`, `/sse`) from a URL path. */\nexport function stripTransportSuffix(url: string): string {\n return url.replace(TRANSPORT_SUFFIX_REGEX, '');\n}\n\n/** Matches a root-level well-known agent card URL (scheme://host/.well-known/agent[-card].json) */\nconst AGENT_CARD_URL_REGEX = /^https?:\\/\\/[^/]+\\/\\.well-known\\/agent(-card)?\\.json$/i;\n\n/**\n * Check if a URL string ends with an agent card well-known path\n */\nexport function isAgentCardPath(url: string): boolean {\n return AGENT_CARD_PATH_REGEX.test(url);\n}\n\n/**\n * Check if a URL is a root-level well-known agent card URL.\n *\n * Matches: https://example.com/.well-known/agent.json\n * Matches: https://example.com/.well-known/agent-card.json\n * Rejects: https://example.com/api/.well-known/agent.json\n */\nexport function isWellKnownAgentCardUrl(url: string): boolean {\n return AGENT_CARD_URL_REGEX.test(url);\n}\n\n/**\n * Build the list of agent card URLs to try for a given agent URL.\n *\n * If the URL already points to a well-known agent card path, returns it as-is.\n * Otherwise returns both paths (preferred first) appended to the base URL.\n */\nexport function buildCardUrls(agentUrl: string): string[] {\n if (isAgentCardPath(agentUrl)) {\n return [agentUrl];\n }\n const base = agentUrl.replace(/\\/$/, '');\n return A2A_CARD_PATHS.map(path => `${base}${path}`);\n}\n\n/**\n * Strip a well-known agent card path from a URL, returning the base URL.\n */\nexport function stripAgentCardPath(url: string): string {\n return url.replace(AGENT_CARD_PATH_REGEX, '');\n}\n"],"mappings":"AAQO,MAAM,iBAAiB,CAAC,2BAA2B,8BAA8B;AAGxF,MAAM,wBAAwB;AASvB,MAAM,yBAAyB;AAG/B,SAAS,qBAAqB,KAAqB;AACxD,SAAO,IAAI,QAAQ,wBAAwB,EAAE;AAC/C;AAGA,MAAM,uBAAuB;AAKtB,SAAS,gBAAgB,KAAsB;AACpD,SAAO,sBAAsB,KAAK,GAAG;AACvC;AASO,SAAS,wBAAwB,KAAsB;AAC5D,SAAO,qBAAqB,KAAK,GAAG;AACtC;AAQO,SAAS,cAAc,UAA4B;AACxD,MAAI,gBAAgB,QAAQ,GAAG;AAC7B,WAAO,CAAC,QAAQ;AAAA,EAClB;AACA,QAAM,OAAO,SAAS,QAAQ,OAAO,EAAE;AACvC,SAAO,eAAe,IAAI,UAAQ,GAAG,IAAI,GAAG,IAAI,EAAE;AACpD;AAKO,SAAS,mBAAmB,KAAqB;AACtD,SAAO,IAAI,QAAQ,uBAAuB,EAAE;AAC9C;","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
|
function segmentIdActivationKey(fields) {
|
|
8
2
|
return { ...fields, type: "segment_id" };
|
|
9
3
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/activation-key-builders.ts"],"sourcesContent":["// Typed factory helpers for `ActivationKey` — schema oneOf on\n// `type: \"segment_id\" | \"key_value\"`. The `key_value` arm is consistently\n// mis-shaped: adopters intuit a nested `{ key_value: { key, value } }` and\n// write that, even though the schema flattens `key`/`value` onto the\n// `ActivationKey` itself. SHAPE-GOTCHAS §1.\n//\n// Same pattern as `asset-builders.ts` / `render-builders.ts`: spread order\n// writes the discriminator last, so a runtime cast that smuggles `type`\n// in via `fields` cannot clobber it.\n\nimport type { ActivationKey } from '../types/core.generated';\n\ntype SegmentIdKey = Extract<ActivationKey, { type: 'segment_id' }>;\ntype KeyValueKey = Extract<ActivationKey, { type: 'key_value' }>;\ntype Tagged<T, Tag extends string> = Omit<T, 'type'> & { type: Tag };\n\n/** Build a `segment_id`-variant `ActivationKey`. */\nexport function segmentIdActivationKey(fields: Omit<SegmentIdKey, 'type'>): Tagged<SegmentIdKey, 'segment_id'> {\n return { ...fields, type: 'segment_id' };\n}\n\n/** Build a `key_value`-variant `ActivationKey`. `key`/`value` flatten on the top level. SHAPE-GOTCHAS §1. */\nexport function keyValueActivationKey(fields: Omit<KeyValueKey, 'type'>): Tagged<KeyValueKey, 'key_value'> {\n return { ...fields, type: 'key_value' };\n}\n\n/** Grouped accessor for both `ActivationKey` variants. */\nexport const activationKey = {\n segment: segmentIdActivationKey,\n keyValue: keyValueActivationKey,\n} as const;\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/activation-key-builders.ts"],"sourcesContent":["// Typed factory helpers for `ActivationKey` — schema oneOf on\n// `type: \"segment_id\" | \"key_value\"`. The `key_value` arm is consistently\n// mis-shaped: adopters intuit a nested `{ key_value: { key, value } }` and\n// write that, even though the schema flattens `key`/`value` onto the\n// `ActivationKey` itself. SHAPE-GOTCHAS §1.\n//\n// Same pattern as `asset-builders.ts` / `render-builders.ts`: spread order\n// writes the discriminator last, so a runtime cast that smuggles `type`\n// in via `fields` cannot clobber it.\n\nimport type { ActivationKey } from '../types/core.generated';\n\ntype SegmentIdKey = Extract<ActivationKey, { type: 'segment_id' }>;\ntype KeyValueKey = Extract<ActivationKey, { type: 'key_value' }>;\ntype Tagged<T, Tag extends string> = Omit<T, 'type'> & { type: Tag };\n\n/** Build a `segment_id`-variant `ActivationKey`. */\nexport function segmentIdActivationKey(fields: Omit<SegmentIdKey, 'type'>): Tagged<SegmentIdKey, 'segment_id'> {\n return { ...fields, type: 'segment_id' };\n}\n\n/** Build a `key_value`-variant `ActivationKey`. `key`/`value` flatten on the top level. SHAPE-GOTCHAS §1. */\nexport function keyValueActivationKey(fields: Omit<KeyValueKey, 'type'>): Tagged<KeyValueKey, 'key_value'> {\n return { ...fields, type: 'key_value' };\n}\n\n/** Grouped accessor for both `ActivationKey` variants. */\nexport const activationKey = {\n segment: segmentIdActivationKey,\n keyValue: keyValueActivationKey,\n} as const;\n"],"mappings":"AAiBO,SAAS,uBAAuB,QAAwE;AAC7G,SAAO,EAAE,GAAG,QAAQ,MAAM,aAAa;AACzC;AAGO,SAAS,sBAAsB,QAAqE;AACzG,SAAO,EAAE,GAAG,QAAQ,MAAM,YAAY;AACxC;AAGO,MAAM,gBAAgB;AAAA,EAC3B,SAAS;AAAA,EACT,UAAU;AACZ;","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 { ADCP_VERSION, COMPATIBLE_ADCP_VERSIONS, parseAdcpMajorVersion } from "../version.mjs";
|
|
8
2
|
import { ConfigurationError } from "../errors/index.mjs";
|
|
9
3
|
import { hasSchemaBundle, resolveBundleKey, toReleasePrecisionWire } from "../validation/schema-loader.mjs";
|