@adcp/sdk 12.0.0 → 12.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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.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.mjs +0 -6
- 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.mjs +0 -6
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/server/legacy/v5/index.mjs +0 -6
- package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
- package/dist/lib/server/mcp-modern-server.mjs +0 -6
- package/dist/lib/server/mcp-modern-server.mjs.map +1 -1
- package/dist/lib/server/media-buy-actions.mjs +0 -6
- package/dist/lib/server/media-buy-actions.mjs.map +1 -1
- package/dist/lib/server/media-buy-helpers.mjs +0 -6
- package/dist/lib/server/media-buy-helpers.mjs.map +1 -1
- package/dist/lib/server/media-buy-store.mjs +0 -6
- package/dist/lib/server/media-buy-store.mjs.map +1 -1
- package/dist/lib/server/normalize-errors.mjs +0 -6
- package/dist/lib/server/normalize-errors.mjs.map +1 -1
- package/dist/lib/server/operational-platform.mjs +0 -6
- package/dist/lib/server/operational-platform.mjs.map +1 -1
- package/dist/lib/server/pick-safe-details.mjs +0 -6
- package/dist/lib/server/pick-safe-details.mjs.map +1 -1
- package/dist/lib/server/pin-and-bind-fetch.mjs +0 -6
- package/dist/lib/server/pin-and-bind-fetch.mjs.map +1 -1
- package/dist/lib/server/postgres-state-store.mjs +0 -6
- package/dist/lib/server/postgres-state-store.mjs.map +1 -1
- package/dist/lib/server/postgres-task-store.mjs +0 -6
- package/dist/lib/server/postgres-task-store.mjs.map +1 -1
- package/dist/lib/server/product-defaults.mjs +0 -6
- package/dist/lib/server/product-defaults.mjs.map +1 -1
- package/dist/lib/server/redact.mjs +0 -6
- package/dist/lib/server/redact.mjs.map +1 -1
- package/dist/lib/server/responses.mjs +0 -6
- package/dist/lib/server/responses.mjs.map +1 -1
- package/dist/lib/server/serve.mjs +0 -6
- package/dist/lib/server/serve.mjs.map +1 -1
- package/dist/lib/server/socket-mode/conformance-client.mjs +0 -6
- package/dist/lib/server/socket-mode/conformance-client.mjs.map +1 -1
- package/dist/lib/server/socket-mode/index.mjs +0 -6
- package/dist/lib/server/socket-mode/index.mjs.map +1 -1
- package/dist/lib/server/socket-mode/ws-transport.mjs +0 -6
- package/dist/lib/server/socket-mode/ws-transport.mjs.map +1 -1
- package/dist/lib/server/state-machine.mjs +0 -6
- package/dist/lib/server/state-machine.mjs.map +1 -1
- package/dist/lib/server/state-store.mjs +0 -6
- package/dist/lib/server/state-store.mjs.map +1 -1
- package/dist/lib/server/structured-serialize.mjs +0 -6
- package/dist/lib/server/structured-serialize.mjs.map +1 -1
- package/dist/lib/server/targeting-helpers.mjs +0 -6
- package/dist/lib/server/targeting-helpers.mjs.map +1 -1
- package/dist/lib/server/tasks.mjs +0 -6
- package/dist/lib/server/tasks.mjs.map +1 -1
- package/dist/lib/server/test-controller-bridge.mjs +0 -6
- package/dist/lib/server/test-controller-bridge.mjs.map +1 -1
- package/dist/lib/server/test-controller.mjs +0 -6
- package/dist/lib/server/test-controller.mjs.map +1 -1
- package/dist/lib/server/upstream-helpers.mjs +0 -6
- package/dist/lib/server/upstream-helpers.mjs.map +1 -1
- package/dist/lib/server/webhook-emitter.mjs +0 -6
- package/dist/lib/server/webhook-emitter.mjs.map +1 -1
- package/dist/lib/server/wire-safe.mjs +0 -6
- package/dist/lib/server/wire-safe.mjs.map +1 -1
- package/dist/lib/server/wire-spec-fields.generated.mjs +0 -6
- package/dist/lib/server/wire-spec-fields.generated.mjs.map +1 -1
- package/dist/lib/server/wrap-envelope.mjs +0 -6
- package/dist/lib/server/wrap-envelope.mjs.map +1 -1
- package/dist/lib/signing/agent-context.mjs +0 -6
- package/dist/lib/signing/agent-context.mjs.map +1 -1
- package/dist/lib/signing/agent-fetch.mjs +0 -6
- package/dist/lib/signing/agent-fetch.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/canonicalize.mjs +0 -6
- package/dist/lib/signing/agent-resolver/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs +0 -6
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/consistency.mjs +0 -6
- package/dist/lib/signing/agent-resolver/consistency.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/errors.mjs +0 -6
- package/dist/lib/signing/agent-resolver/errors.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/etld.mjs +0 -6
- package/dist/lib/signing/agent-resolver/etld.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +0 -6
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/index.mjs +0 -6
- package/dist/lib/signing/agent-resolver/index.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/jwks-set.mjs +0 -6
- package/dist/lib/signing/agent-resolver/jwks-set.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/select-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/select-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/strict-json.mjs +0 -6
- package/dist/lib/signing/agent-resolver/strict-json.mjs.map +1 -1
- package/dist/lib/signing/brand-jwks.mjs +0 -6
- package/dist/lib/signing/brand-jwks.mjs.map +1 -1
- package/dist/lib/signing/canonicalize.mjs +0 -6
- package/dist/lib/signing/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/capability-cache.mjs +0 -6
- package/dist/lib/signing/capability-cache.mjs.map +1 -1
- package/dist/lib/signing/capability-priming.mjs +0 -6
- package/dist/lib/signing/capability-priming.mjs.map +1 -1
- package/dist/lib/signing/client.mjs +0 -6
- package/dist/lib/signing/client.mjs.map +1 -1
- package/dist/lib/signing/content-digest.mjs +0 -6
- package/dist/lib/signing/content-digest.mjs.map +1 -1
- package/dist/lib/signing/crypto.mjs +0 -6
- package/dist/lib/signing/crypto.mjs.map +1 -1
- package/dist/lib/signing/ecdsa-encoding.mjs +0 -6
- package/dist/lib/signing/ecdsa-encoding.mjs.map +1 -1
- package/dist/lib/signing/errors.mjs +0 -6
- package/dist/lib/signing/errors.mjs.map +1 -1
- package/dist/lib/signing/fetch-async.mjs +0 -6
- package/dist/lib/signing/fetch-async.mjs.map +1 -1
- package/dist/lib/signing/fetch.mjs +0 -6
- package/dist/lib/signing/fetch.mjs.map +1 -1
- package/dist/lib/signing/index.mjs +0 -6
- package/dist/lib/signing/index.mjs.map +1 -1
- package/dist/lib/signing/jwks-helpers.mjs +0 -6
- package/dist/lib/signing/jwks-helpers.mjs.map +1 -1
- package/dist/lib/signing/jwks-https.mjs +0 -6
- package/dist/lib/signing/jwks-https.mjs.map +1 -1
- package/dist/lib/signing/jwks.mjs +0 -6
- package/dist/lib/signing/jwks.mjs.map +1 -1
- package/dist/lib/signing/middleware.mjs +0 -6
- package/dist/lib/signing/middleware.mjs.map +1 -1
- package/dist/lib/signing/parser.mjs +0 -6
- package/dist/lib/signing/parser.mjs.map +1 -1
- package/dist/lib/signing/postgres-replay-store.mjs +0 -6
- package/dist/lib/signing/postgres-replay-store.mjs.map +1 -1
- package/dist/lib/signing/protocol-response.mjs +0 -6
- package/dist/lib/signing/protocol-response.mjs.map +1 -1
- package/dist/lib/signing/provider.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs.map +1 -1
- package/dist/lib/signing/replay.mjs +0 -6
- package/dist/lib/signing/replay.mjs.map +1 -1
- package/dist/lib/signing/request-context.mjs +0 -6
- package/dist/lib/signing/request-context.mjs.map +1 -1
- package/dist/lib/signing/revocation-https.mjs +0 -6
- package/dist/lib/signing/revocation-https.mjs.map +1 -1
- package/dist/lib/signing/revocation.mjs +0 -6
- package/dist/lib/signing/revocation.mjs.map +1 -1
- package/dist/lib/signing/server.mjs +0 -6
- package/dist/lib/signing/server.mjs.map +1 -1
- package/dist/lib/signing/signer-async.mjs +0 -6
- package/dist/lib/signing/signer-async.mjs.map +1 -1
- package/dist/lib/signing/signer.mjs +0 -6
- package/dist/lib/signing/signer.mjs.map +1 -1
- package/dist/lib/signing/testing.mjs +0 -6
- package/dist/lib/signing/testing.mjs.map +1 -1
- package/dist/lib/signing/types.mjs +0 -6
- package/dist/lib/signing/types.mjs.map +1 -1
- package/dist/lib/signing/verifier.mjs +0 -6
- package/dist/lib/signing/verifier.mjs.map +1 -1
- package/dist/lib/signing/webhook-auth-detection.mjs +0 -6
- package/dist/lib/signing/webhook-auth-detection.mjs.map +1 -1
- package/dist/lib/signing/webhook-verifier.mjs +0 -6
- package/dist/lib/signing/webhook-verifier.mjs.map +1 -1
- package/dist/lib/storage/MemoryStorage.mjs +0 -6
- package/dist/lib/storage/MemoryStorage.mjs.map +1 -1
- package/dist/lib/storage/interfaces.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs.map +1 -1
- package/dist/lib/substitution/encoder/index.mjs +0 -6
- package/dist/lib/substitution/encoder/index.mjs.map +1 -1
- package/dist/lib/substitution/index.mjs +0 -6
- package/dist/lib/substitution/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs +0 -6
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs.map +1 -1
- package/dist/lib/substitution/observer/alignment.mjs +0 -6
- package/dist/lib/substitution/observer/alignment.mjs.map +1 -1
- package/dist/lib/substitution/observer/assertions.mjs +0 -6
- package/dist/lib/substitution/observer/assertions.mjs.map +1 -1
- package/dist/lib/substitution/observer/html-parser.mjs +0 -6
- package/dist/lib/substitution/observer/html-parser.mjs.map +1 -1
- package/dist/lib/substitution/observer/index.mjs +0 -6
- package/dist/lib/substitution/observer/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/ssrf.mjs +0 -6
- package/dist/lib/substitution/observer/ssrf.mjs.map +1 -1
- package/dist/lib/substitution/rfc3986.mjs +0 -6
- package/dist/lib/substitution/rfc3986.mjs.map +1 -1
- package/dist/lib/substitution/translate.mjs +0 -6
- package/dist/lib/substitution/translate.mjs.map +1 -1
- package/dist/lib/substitution/types.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs.map +1 -1
- package/dist/lib/testing/agent-tester.mjs +0 -6
- package/dist/lib/testing/agent-tester.mjs.map +1 -1
- package/dist/lib/testing/client.mjs +0 -6
- package/dist/lib/testing/client.mjs.map +1 -1
- package/dist/lib/testing/compliance/briefs.mjs +0 -6
- package/dist/lib/testing/compliance/briefs.mjs.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +0 -6
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/compliance/index.mjs +0 -6
- package/dist/lib/testing/compliance/index.mjs.map +1 -1
- package/dist/lib/testing/compliance/spec-conformance.mjs +0 -6
- package/dist/lib/testing/compliance/spec-conformance.mjs.map +1 -1
- package/dist/lib/testing/compliance/storyboard-tracks.mjs +0 -6
- package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
- package/dist/lib/testing/compliance/summary.mjs +0 -6
- package/dist/lib/testing/compliance/summary.mjs.map +1 -1
- package/dist/lib/testing/compliance/types.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs.map +1 -1
- package/dist/lib/testing/controller-assertions.mjs +0 -6
- package/dist/lib/testing/controller-assertions.mjs.map +1 -1
- package/dist/lib/testing/formatter.mjs +0 -6
- package/dist/lib/testing/formatter.mjs.map +1 -1
- package/dist/lib/testing/index.mjs +0 -6
- package/dist/lib/testing/index.mjs.map +1 -1
- package/dist/lib/testing/local-agent-runner.mjs +0 -6
- package/dist/lib/testing/local-agent-runner.mjs.map +1 -1
- package/dist/lib/testing/orchestrator.mjs +0 -6
- package/dist/lib/testing/orchestrator.mjs.map +1 -1
- package/dist/lib/testing/personas/index.mjs +0 -6
- package/dist/lib/testing/personas/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/brand-rights.mjs +0 -6
- package/dist/lib/testing/scenarios/brand-rights.mjs.map +1 -1
- package/dist/lib/testing/scenarios/capabilities.mjs +0 -6
- package/dist/lib/testing/scenarios/capabilities.mjs.map +1 -1
- package/dist/lib/testing/scenarios/creative.mjs +0 -6
- package/dist/lib/testing/scenarios/creative.mjs.map +1 -1
- package/dist/lib/testing/scenarios/deterministic.mjs +0 -6
- package/dist/lib/testing/scenarios/deterministic.mjs.map +1 -1
- package/dist/lib/testing/scenarios/discovery.mjs +0 -6
- package/dist/lib/testing/scenarios/discovery.mjs.map +1 -1
- package/dist/lib/testing/scenarios/edge-cases.mjs +0 -6
- package/dist/lib/testing/scenarios/edge-cases.mjs.map +1 -1
- package/dist/lib/testing/scenarios/error-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/error-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/governance.mjs +0 -6
- package/dist/lib/testing/scenarios/governance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/health.mjs +0 -6
- package/dist/lib/testing/scenarios/health.mjs.map +1 -1
- package/dist/lib/testing/scenarios/index.mjs +0 -6
- package/dist/lib/testing/scenarios/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.mjs +0 -6
- package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/schema-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/signals.mjs +0 -6
- package/dist/lib/testing/scenarios/signals.mjs.map +1 -1
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs +0 -6
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs.map +1 -1
- package/dist/lib/testing/scenarios/trusted-match.mjs +0 -6
- package/dist/lib/testing/scenarios/trusted-match.mjs.map +1 -1
- package/dist/lib/testing/seed-merge.mjs +0 -6
- package/dist/lib/testing/seed-merge.mjs.map +1 -1
- package/dist/lib/testing/storyboard/agent-routing.mjs +0 -6
- package/dist/lib/testing/storyboard/agent-routing.mjs.map +1 -1
- package/dist/lib/testing/storyboard/assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +0 -6
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs.map +1 -1
- package/dist/lib/testing/storyboard/compliance.mjs +5 -6
- package/dist/lib/testing/storyboard/compliance.mjs.map +1 -1
- package/dist/lib/testing/storyboard/context.mjs +0 -6
- package/dist/lib/testing/storyboard/context.mjs.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.mjs +0 -6
- package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
- package/dist/lib/testing/storyboard/index.mjs +0 -6
- package/dist/lib/testing/storyboard/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/junit.mjs +0 -6
- package/dist/lib/testing/storyboard/junit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/loader.mjs +0 -6
- package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/path.mjs +0 -6
- package/dist/lib/testing/storyboard/path.mjs.map +1 -1
- package/dist/lib/testing/storyboard/probes.mjs +0 -6
- package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs +0 -6
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rejection-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/rejection-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/index.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/types.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +0 -6
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/sandbox-entities.mjs +0 -6
- package/dist/lib/testing/storyboard/sandbox-entities.mjs.map +1 -1
- package/dist/lib/testing/storyboard/seeding.mjs +0 -6
- package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/index.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/types.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/task-map.mjs +0 -6
- package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
- package/dist/lib/testing/storyboard/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/types.mjs +0 -6
- package/dist/lib/testing/storyboard/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.mjs +0 -6
- package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
- package/dist/lib/testing/stubs/governance-agent-stub.mjs +0 -6
- package/dist/lib/testing/stubs/governance-agent-stub.mjs.map +1 -1
- package/dist/lib/testing/stubs/index.mjs +0 -6
- package/dist/lib/testing/stubs/index.mjs.map +1 -1
- package/dist/lib/testing/test-controller.mjs +0 -6
- package/dist/lib/testing/test-controller.mjs.map +1 -1
- package/dist/lib/testing/test-helpers.mjs +0 -6
- package/dist/lib/testing/test-helpers.mjs.map +1 -1
- package/dist/lib/testing/types.mjs +0 -6
- package/dist/lib/types/adcp.mjs +0 -6
- package/dist/lib/types/adcp.mjs.map +1 -1
- package/dist/lib/types/asset-instances.mjs +0 -6
- package/dist/lib/types/compat.mjs +0 -6
- package/dist/lib/types/compat.mjs.map +1 -1
- package/dist/lib/types/core.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs.map +1 -1
- package/dist/lib/types/error-codes.mjs +0 -6
- package/dist/lib/types/error-codes.mjs.map +1 -1
- package/dist/lib/types/error-details.aliases.mjs +0 -6
- package/dist/lib/types/error-details.aliases.mjs.map +1 -1
- package/dist/lib/types/format-asset-slots.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs.map +1 -1
- package/dist/lib/types/index.mjs +0 -6
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/types/inline-enums.aliases.mjs +0 -6
- package/dist/lib/types/inline-enums.aliases.mjs.map +1 -1
- package/dist/lib/types/inline-enums.generated.mjs +0 -6
- package/dist/lib/types/inline-enums.generated.mjs.map +1 -1
- package/dist/lib/types/manifest.generated.mjs +0 -6
- package/dist/lib/types/manifest.generated.mjs.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +0 -6
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/server-payload-aliases.mjs +0 -6
- package/dist/lib/types/server-payload.mjs +0 -6
- package/dist/lib/types/sync-rows.mjs +0 -6
- package/dist/lib/types/tools.generated.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs.map +1 -1
- package/dist/lib/types/v2-5/tools.generated.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs.map +1 -1
- package/dist/lib/types/v3-1-beta/tools.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs.map +1 -1
- package/dist/lib/upstream-recorder/constants.mjs +0 -6
- package/dist/lib/upstream-recorder/constants.mjs.map +1 -1
- package/dist/lib/upstream-recorder/index.mjs +0 -6
- package/dist/lib/upstream-recorder/index.mjs.map +1 -1
- package/dist/lib/upstream-recorder/recorder.mjs +0 -6
- package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
- package/dist/lib/upstream-recorder/types.mjs +0 -6
- package/dist/lib/upstream-recorder/types.mjs.map +1 -1
- package/dist/lib/utils/a2a-artifacts.mjs +0 -6
- package/dist/lib/utils/a2a-artifacts.mjs.map +1 -1
- package/dist/lib/utils/a2a-discovery.mjs +0 -6
- package/dist/lib/utils/a2a-discovery.mjs.map +1 -1
- package/dist/lib/utils/activation-key-builders.mjs +0 -6
- package/dist/lib/utils/activation-key-builders.mjs.map +1 -1
- package/dist/lib/utils/adcp-version-config.mjs +0 -6
- package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
- package/dist/lib/utils/asset-builders.mjs +0 -6
- package/dist/lib/utils/asset-builders.mjs.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.mjs +0 -6
- package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
- package/dist/lib/utils/buyer-retry-policy.mjs +0 -6
- package/dist/lib/utils/buyer-retry-policy.mjs.map +1 -1
- package/dist/lib/utils/capabilities.mjs +0 -6
- package/dist/lib/utils/capabilities.mjs.map +1 -1
- package/dist/lib/utils/capability-rollups.mjs +0 -6
- package/dist/lib/utils/capability-rollups.mjs.map +1 -1
- package/dist/lib/utils/creative-adapter.mjs +0 -6
- package/dist/lib/utils/creative-adapter.mjs.map +1 -1
- package/dist/lib/utils/creative-delivery.mjs +0 -6
- package/dist/lib/utils/creative-delivery.mjs.map +1 -1
- package/dist/lib/utils/deprecation.mjs +0 -6
- package/dist/lib/utils/deprecation.mjs.map +1 -1
- package/dist/lib/utils/envelope-status-compat.mjs +0 -6
- package/dist/lib/utils/envelope-status-compat.mjs.map +1 -1
- package/dist/lib/utils/error-extraction.mjs +0 -6
- package/dist/lib/utils/error-extraction.mjs.map +1 -1
- package/dist/lib/utils/extract-result.mjs +0 -6
- package/dist/lib/utils/extract-result.mjs.map +1 -1
- package/dist/lib/utils/format-asset-slot-builders.mjs +0 -6
- package/dist/lib/utils/format-asset-slot-builders.mjs.map +1 -1
- package/dist/lib/utils/format-assets.mjs +0 -6
- package/dist/lib/utils/format-assets.mjs.map +1 -1
- package/dist/lib/utils/format-render-builders.mjs +0 -6
- package/dist/lib/utils/format-render-builders.mjs.map +1 -1
- package/dist/lib/utils/format-renders.mjs +0 -6
- package/dist/lib/utils/format-renders.mjs.map +1 -1
- package/dist/lib/utils/get-products-cache-scope.mjs +0 -6
- package/dist/lib/utils/get-products-cache-scope.mjs.map +1 -1
- package/dist/lib/utils/glob.mjs +0 -6
- package/dist/lib/utils/glob.mjs.map +1 -1
- package/dist/lib/utils/global-async-local-storage.mjs +0 -6
- package/dist/lib/utils/global-async-local-storage.mjs.map +1 -1
- package/dist/lib/utils/idempotency.mjs +0 -6
- package/dist/lib/utils/idempotency.mjs.map +1 -1
- package/dist/lib/utils/index.mjs +0 -6
- package/dist/lib/utils/index.mjs.map +1 -1
- package/dist/lib/utils/jcs.mjs +0 -6
- package/dist/lib/utils/jcs.mjs.map +1 -1
- package/dist/lib/utils/json-depth.mjs +0 -6
- package/dist/lib/utils/json-depth.mjs.map +1 -1
- package/dist/lib/utils/logger.mjs +0 -6
- package/dist/lib/utils/logger.mjs.map +1 -1
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs +0 -6
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs.map +1 -1
- package/dist/lib/utils/media-buy-status.mjs +0 -6
- package/dist/lib/utils/media-buy-status.mjs.map +1 -1
- package/dist/lib/utils/pagination.mjs +0 -6
- package/dist/lib/utils/pagination.mjs.map +1 -1
- package/dist/lib/utils/preview-creative-builders.mjs +0 -6
- package/dist/lib/utils/preview-creative-builders.mjs.map +1 -1
- package/dist/lib/utils/preview-normalizer.mjs +0 -6
- package/dist/lib/utils/preview-normalizer.mjs.map +1 -1
- package/dist/lib/utils/preview-utils.mjs +0 -6
- package/dist/lib/utils/preview-utils.mjs.map +1 -1
- package/dist/lib/utils/pricing-adapter.mjs +0 -6
- package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
- package/dist/lib/utils/probe-policy.mjs +0 -6
- package/dist/lib/utils/probe-policy.mjs.map +1 -1
- package/dist/lib/utils/protocol-detection.mjs +0 -6
- package/dist/lib/utils/protocol-detection.mjs.map +1 -1
- package/dist/lib/utils/redact-secrets.mjs +0 -6
- package/dist/lib/utils/redact-secrets.mjs.map +1 -1
- package/dist/lib/utils/redis-default-prefix-warn.mjs +0 -6
- package/dist/lib/utils/redis-default-prefix-warn.mjs.map +1 -1
- package/dist/lib/utils/render-builders.mjs +0 -6
- package/dist/lib/utils/render-builders.mjs.map +1 -1
- package/dist/lib/utils/request-normalizer.mjs +0 -6
- package/dist/lib/utils/request-normalizer.mjs.map +1 -1
- package/dist/lib/utils/response-schemas.mjs +0 -6
- package/dist/lib/utils/response-schemas.mjs.map +1 -1
- package/dist/lib/utils/response-unwrapper.mjs +0 -6
- package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
- package/dist/lib/utils/retry.mjs +0 -6
- package/dist/lib/utils/retry.mjs.map +1 -1
- package/dist/lib/utils/signal-discovery-helpers.mjs +0 -6
- package/dist/lib/utils/signal-discovery-helpers.mjs.map +1 -1
- package/dist/lib/utils/signal-id-builders.mjs +0 -6
- package/dist/lib/utils/signal-id-builders.mjs.map +1 -1
- package/dist/lib/utils/sync-creatives-adapter.mjs +0 -6
- package/dist/lib/utils/sync-creatives-adapter.mjs.map +1 -1
- package/dist/lib/utils/task-state.mjs +0 -6
- package/dist/lib/utils/task-state.mjs.map +1 -1
- package/dist/lib/utils/tool-request-schemas.mjs +0 -6
- package/dist/lib/utils/tool-request-schemas.mjs.map +1 -1
- package/dist/lib/utils/typeGuards.mjs +0 -6
- package/dist/lib/utils/typeGuards.mjs.map +1 -1
- package/dist/lib/utils/union-errors.mjs +0 -6
- package/dist/lib/utils/union-errors.mjs.map +1 -1
- package/dist/lib/utils/validate-user-agent.mjs +0 -6
- package/dist/lib/utils/validate-user-agent.mjs.map +1 -1
- package/dist/lib/v2/format-schema/fetch.mjs +0 -6
- package/dist/lib/v2/format-schema/fetch.mjs.map +1 -1
- package/dist/lib/v2/format-schema/index.mjs +0 -6
- package/dist/lib/v2/format-schema/index.mjs.map +1 -1
- package/dist/lib/v2/format-schema/regex-safety.mjs +0 -6
- package/dist/lib/v2/format-schema/regex-safety.mjs.map +1 -1
- package/dist/lib/v2/format-schema/resolver.mjs +7 -8
- package/dist/lib/v2/format-schema/resolver.mjs.map +1 -1
- package/dist/lib/v2/format-schema/sandbox-refs.mjs +0 -6
- package/dist/lib/v2/format-schema/sandbox-refs.mjs.map +1 -1
- package/dist/lib/v2/projection/augment-response.mjs +0 -6
- package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
- package/dist/lib/v2/projection/builders.mjs +0 -6
- package/dist/lib/v2/projection/builders.mjs.map +1 -1
- package/dist/lib/v2/projection/cache-versions.mjs +0 -6
- package/dist/lib/v2/projection/cache-versions.mjs.map +1 -1
- package/dist/lib/v2/projection/canonical-properties.mjs +5 -6
- package/dist/lib/v2/projection/canonical-properties.mjs.map +1 -1
- package/dist/lib/v2/projection/catalog.mjs +5 -6
- package/dist/lib/v2/projection/catalog.mjs.map +1 -1
- package/dist/lib/v2/projection/constants.mjs +0 -6
- package/dist/lib/v2/projection/constants.mjs.map +1 -1
- package/dist/lib/v2/projection/index.mjs +0 -6
- package/dist/lib/v2/projection/index.mjs.map +1 -1
- package/dist/lib/v2/projection/registry.mjs +5 -6
- package/dist/lib/v2/projection/registry.mjs.map +1 -1
- package/dist/lib/v2/projection/types.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
- package/dist/lib/v2/projection/v2-to-v1.mjs +0 -6
- package/dist/lib/v2/projection/v2-to-v1.mjs.map +1 -1
- package/dist/lib/v2/projection/write-side.mjs +0 -6
- package/dist/lib/v2/projection/write-side.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/formats.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/formats.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/index.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/index.mjs.map +1 -1
- package/dist/lib/validation/client-hooks.mjs +0 -6
- package/dist/lib/validation/client-hooks.mjs.map +1 -1
- package/dist/lib/validation/hints.mjs +0 -6
- package/dist/lib/validation/hints.mjs.map +1 -1
- package/dist/lib/validation/index.mjs +0 -6
- package/dist/lib/validation/index.mjs.map +1 -1
- package/dist/lib/validation/schema-errors.mjs +0 -6
- package/dist/lib/validation/schema-errors.mjs.map +1 -1
- package/dist/lib/validation/schema-loader.mjs +5 -6
- package/dist/lib/validation/schema-loader.mjs.map +1 -1
- package/dist/lib/validation/schema-validator.mjs +0 -6
- package/dist/lib/validation/schema-validator.mjs.map +1 -1
- package/dist/lib/validation/sync-creatives.mjs +0 -6
- package/dist/lib/validation/sync-creatives.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -9
- package/dist/lib/version.mjs.map +1 -1
- package/dist/lib/webhooks/index.mjs +0 -6
- package/dist/lib/webhooks/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/index.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/sync.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/sync.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/types.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/builder.ts"],"sourcesContent":["import { createPrivateKey, randomBytes, randomUUID, sign as nodeSign, type JsonWebKey } from 'crypto';\nimport {\n buildSignatureBase,\n finalizeRequestSignature,\n formatSignatureParams,\n prepareRequestSignature,\n REQUEST_SIGNING_TAG,\n type AdcpJsonWebKey,\n type RequestLike,\n type SignatureParams,\n type SignerKey,\n} from '../../../signing';\nimport { findKey } from './vector-loader';\nimport type { NegativeVector, PositiveVector, TestKeyset, TestKeypair } from './types';\n\nexport interface BuildOptions {\n /** Override the signer clock (unix seconds). Defaults to `Date.now()/1000`. */\n now?: number;\n /** Override the nonce. Defaults to freshly-generated. */\n nonce?: string;\n /** Override the `expires - created` window (seconds). Defaults to 300. */\n windowSeconds?: number;\n /**\n * Agent base URL. When set, the vector's request URL has its origin replaced\n * with this base before signing — the vectors point at `seller.example.com`\n * but real agents live elsewhere. The path and query are preserved so the\n * operation intent (e.g., `/adcp/create_media_buy`) is unchanged.\n *\n * Canonicalization-edge vectors (005 default-port, 006 dot-segment path,\n * 007 query preservation, 008 percent-encoded path) bake their edge case\n * into the vector URL; replacing the origin keeps that edge intact in the\n * path/query, but vectors sensitive to the port or scheme will no longer\n * exercise the edge against a mismatched agent base.\n */\n baseUrl?: string;\n /**\n * Transport-layer framing. `'raw'` (default) sends the vector body to the\n * retargeted vector URL verbatim — matches the conformance vectors' intent\n * of testing a per-operation HTTP endpoint. `'mcp'` wraps the vector body\n * in a JSON-RPC `tools/call` envelope and posts to `baseUrl` as-is (no\n * path join); operation name comes from the vector URL's last segment.\n *\n * MCP mode trades the canonicalization-edge coverage for reach: vectors\n * 005–008 fold into plain POSTs against the MCP endpoint, but the grader\n * works against any MCP agent that wires a verifier at the HTTP layer.\n */\n transport?: 'raw' | 'mcp';\n /**\n * JSON-RPC `id` for the MCP envelope. Defaults to `crypto.randomUUID()`\n * so concurrent runs never collide. Override for tests that need a stable\n * id — JSON-RPC 2.0 permits number, string, or null.\n */\n mcpJsonRpcId?: number | string;\n}\n\nexport interface SignedHttpRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\nexport function buildPositiveRequest(\n vector: PositiveVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, {\n coverContentDigest: vector.verifier_capability.covers_content_digest === 'required',\n ...options,\n });\n}\n\n/**\n * Apply the adversarial mutation documented for a negative vector.\n *\n * Black-box grader: the positive/001 signature bytes sitting in most negative\n * fixtures are placeholders; we re-sign dynamically, then mutate. Covers all\n * 20 current negative vectors. Stateful contract vectors (016 replay, 017\n * revoked, 020 rate abuse) produce a single well-formed request; the\n * storyboard runner orchestrates the repeat/flood/revoked-keyid behavior\n * around that request per the signed-requests-runner test-kit.\n */\nexport function buildNegativeRequest(\n vector: NegativeVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const mutation = MUTATIONS[vector.id];\n if (!mutation) {\n throw new Error(`No adversarial builder registered for negative vector \"${vector.id}\"`);\n }\n return mutation(vector, keys, options);\n}\n\nexport function listSupportedNegativeVectors(): string[] {\n return Object.keys(MUTATIONS);\n}\n\ntype Mutator = (vector: NegativeVector, keys: TestKeyset, options: BuildOptions) => SignedHttpRequest;\n\nconst MUTATIONS: Record<string, Mutator> = {\n '001-no-signature-header': (vector, _keys, options) => {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: stripSignatureHeaders(shaped.headers),\n body: shaped.body,\n };\n },\n\n '002-wrong-tag': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { tag: 'example-org/signing/v1' });\n },\n\n '003-expired-signature': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const now = nowSeconds(options);\n return sign(key, vector, { ...options, now: now - 600, windowSeconds: 300 });\n },\n\n '004-window-too-long': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, {\n expiresDelta: 301,\n });\n },\n\n '005-alg-not-allowed': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { alg: 'rsa-pss-sha512' });\n },\n\n '006-missing-covered-component': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithComponents(key, vector, options, ['@method', '@target-uri', 'content-type']);\n },\n\n '007-missing-content-digest': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: false });\n },\n\n '008-unknown-keyid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { keyid: 'unknown-key-9999' });\n },\n\n '009-key-ops-missing-verify': (vector, keys, options) => {\n // Vector 009 pins `jwks_ref: [\"test-gov-2026\"]` (adcp_use:\n // governance-signing, not request-signing) — use it directly instead of\n // inferring. Honors the vector's intent if future keysets add a second\n // non-request-signing keypair.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '010-content-digest-mismatch': (vector, keys, options) => {\n // Vector 010 tests \"signer committed a wrong Content-Digest value\" — the\n // signature IS valid over the base that includes that wrong value, so the\n // verifier passes the signature check (step 10) and then fails the\n // digest-vs-body recompute (step 11). Do NOT mutate the body post-sign —\n // that tests a different bug (body-tampered-in-transit) and a verifier\n // that recomputes digest from sent body would not catch the \"lying\n // signer\" path this vector exercises.\n const key = signerKeyFor(vector, keys);\n // Zero-byte digest: guaranteed not to match the actual body.\n const zeroDigest = 'sha-256=:' + Buffer.alloc(32).toString('base64') + ':';\n const headersWithBadDigest = { ...vector.request.headers, 'Content-Digest': zeroDigest };\n const vectorWithBadDigest = {\n ...vector,\n request: { ...vector.request, headers: headersWithBadDigest },\n };\n // Sign the request WITH content-digest in covered components, without\n // letting `signRequest` recompute the digest over the real body.\n return signWithComponents(key, vectorWithBadDigest, options, [\n '@method',\n '@target-uri',\n '@authority',\n 'content-type',\n 'content-digest',\n ]);\n },\n\n '011-malformed-header': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n return {\n ...signed,\n headers: {\n ...signed.headers,\n 'Signature-Input': 'sig1=not a valid structured-field value!!!',\n },\n };\n },\n\n '012-missing-expires-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitExpires: true });\n },\n\n '013-expires-le-created': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { expiresDelta: 0 });\n },\n\n '014-missing-nonce-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitNonce: true });\n },\n\n '015-signature-invalid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const zeroSig = Buffer.alloc(64).toString('base64url');\n return {\n ...signed,\n headers: {\n ...signed.headers,\n Signature: `sig1=:${zeroSig}:`,\n },\n };\n },\n\n '016-replayed-nonce': (vector, keys, options) => {\n // Black-box runner sends the request twice; first accepted, second rejected.\n // Builder produces the single well-formed request used for both submissions.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '017-key-revoked': (vector, keys, options) => {\n // Use the dedicated revoked key (`test-revoked-2026`) declared by the\n // signed-requests-runner test-kit. For current pre-#2353 caches, vector 017\n // still references test-ed25519-2026; fall back to whatever the vector says.\n const kid = vector.jwks_ref?.[0];\n if (!kid) throw new Error(`${vector.id}: jwks_ref missing`);\n const key = keyFor(keys, kid);\n return sign(key, vector, options);\n },\n\n '018-digest-covered-when-forbidden': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: true });\n },\n\n '019-signature-without-signature-input': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const { 'Signature-Input': _drop, ...rest } = signed.headers;\n return { ...signed, headers: rest };\n },\n\n '020-rate-abuse': (vector, keys, options) => {\n // Runner floods the agent with distinct-nonce requests from the same keyid.\n // Builder produces a single well-formed request; the runner generates N\n // distinct nonces by calling this builder repeatedly with `options.nonce`.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n // Vectors 021-026 ship their exact malformed headers in the fixture — the\n // adversarial shape (duplicate sig-input label, multi-valued content-type\n // / content-digest, unquoted string param, malformed JWK, non-ASCII host)\n // lives in the vector itself, not in a programmatic mutation. Builder just\n // preserves the fixture's headers verbatim after applying transport.\n '021-duplicate-signature-input-label': (vector, _keys, options) => passthrough(vector, options),\n '022-multi-valued-content-type': (vector, _keys, options) => passthrough(vector, options),\n '023-multi-valued-content-digest': (vector, _keys, options) => passthrough(vector, options),\n '024-unquoted-string-param': (vector, _keys, options) => passthrough(vector, options),\n '025-jwk-alg-crv-mismatch': (vector, _keys, options) => passthrough(vector, options),\n '026-non-ascii-host': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 027 tests the \"webhook authentication MUST trigger signing\" rule:\n // the fixture is a plain bearer-auth request with zero signature headers,\n // and the adversarial shape is precisely that absence. Passthrough preserves\n // the fixture bytes; retargeting still works via applyTransport.\n '027-webhook-registration-authentication-unsigned': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 028 grades the `protocol_methods_required_for` namespace\n // (adcp#4326). The fixture body is already a JSON-RPC envelope with\n // `method: \"tasks/cancel\"` — NOT a `tools/call` envelope — so the standard\n // MCP-mode `applyTransport` (which would wrap the body in `tools/call`)\n // is wrong here. Use `protocolMethodPassthrough` which keeps the body\n // verbatim and targets `baseUrl` directly when set, matching how an\n // agent's MCP endpoint routes JSON-RPC `tasks/*` methods.\n '028-unsigned-protocol-method-required': (vector, _keys, options) => protocolMethodPassthrough(vector, options),\n};\n\nfunction passthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n}\n\n/**\n * Passthrough for vectors whose body is already a JSON-RPC envelope with a\n * non-`tools/call` `method` (e.g., `tasks/cancel`). MCP-mode `applyTransport`\n * would wrap the body in `tools/call`, which is wrong: the protocol_methods\n * namespace matches against the JSON-RPC envelope's `method` field, so\n * wrapping in `tools/call` would route the request to MCP tool dispatch\n * (looking up a tool literally named \"tasks/cancel\"; 404) instead of the\n * SDK's auto-registered `tasks/cancel` JSON-RPC handler.\n *\n * Targets `options.baseUrl` directly when set (the MCP endpoint URL), or\n * the vector's URL verbatim otherwise.\n */\nfunction protocolMethodPassthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n const url = options.baseUrl ?? vector.request.url;\n const headers = { ...vector.request.headers };\n // MCP Streamable HTTP requires this Accept negotiation header on JSON-RPC\n // probes — match the wrapping path's behavior.\n if (options.transport === 'mcp') {\n headers['Accept'] = 'application/json, text/event-stream';\n }\n return {\n method: vector.request.method,\n url,\n headers,\n body: vector.request.body,\n };\n}\n\n// ── Primitives ────────────────────────────────────────────────\n\ninterface SignArgs extends BuildOptions {\n coverContentDigest?: boolean;\n}\n\nfunction sign(key: SignerKey, vector: PositiveVector | NegativeVector, args: SignArgs): SignedHttpRequest {\n const shaped = applyTransport(vector, args);\n const request: RequestLike = {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n // Negative-vector 009 deliberately signs with a wrong-purpose key\n // (`adcp_use: 'governance-signing'`) to exercise the verifier's step-8\n // purpose check. The signer-side `signRequest` gate refuses wrong-purpose\n // keys to prevent the more common operator footgun; bypass it here by\n // composing `prepareRequestSignature` (which takes `SignatureIdentity`\n // and runs no gate) with this file's local `produceSignature` helper.\n // The bypass is intentional and confined to test-vector authoring.\n const prepared = prepareRequestSignature(\n request,\n { keyid: key.keyid, alg: key.alg },\n {\n coverContentDigest: args.coverContentDigest === true,\n now: args.now !== undefined ? () => args.now! : undefined,\n nonce: args.nonce,\n windowSeconds: args.windowSeconds,\n }\n );\n const signature = produceSignature(key, Buffer.from(prepared.base, 'utf8'));\n const signed = finalizeRequestSignature(prepared, signature);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: mergeHeaders(shaped.headers, signed.headers),\n body: shaped.body,\n };\n}\n\nfunction retargetUrl(vectorUrl: string, baseUrl: string | undefined): string {\n if (!baseUrl) return vectorUrl;\n const v = new URL(vectorUrl);\n const b = new URL(baseUrl);\n v.protocol = b.protocol;\n v.host = b.host;\n // Prefix the agent's mount path (from baseUrl) ahead of the vector's path\n // so agents mounted at e.g. `/v1/adcp/*` receive requests at\n // `/v1/adcp/create_media_buy` rather than the bare `/adcp/create_media_buy`\n // the vector carries. When baseUrl has no path (or just `/`), this is a\n // no-op. Canonicalization-edge vectors (005–008) bake their edge into the\n // vector's path/query; we preserve those bytes by joining, not replacing.\n if (b.pathname && b.pathname !== '/') {\n const mount = b.pathname.replace(/\\/+$/, '');\n const vectorPath = v.pathname.startsWith('/') ? v.pathname : `/${v.pathname}`;\n v.pathname = `${mount}${vectorPath}`;\n }\n return v.toString();\n}\n\ninterface TransportShapedRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\n/**\n * Apply the transport transform to a vector's request shape. In `'raw'` mode\n * (default) this is just origin-swap path-merge. In `'mcp'` mode:\n * - URL becomes `baseUrl` exactly (no path join — MCP agents expose a single\n * JSON-RPC endpoint; the operation is named in the body).\n * - Body is wrapped in a JSON-RPC `tools/call` envelope; the operation name\n * comes from the vector's last URL segment.\n * - `Accept: application/json, text/event-stream` added so MCP Streamable\n * HTTP servers don't 406 on the probe.\n *\n * Shared call site for `sign`, `signWithParamOverride`, `signWithComponents`\n * so every mutation path produces MCP-shaped requests when requested.\n */\nfunction applyTransport(vector: PositiveVector | NegativeVector, options: BuildOptions): TransportShapedRequest {\n const headers = { ...vector.request.headers };\n if (options.transport === 'mcp') {\n if (!options.baseUrl) {\n throw new Error(`transport: 'mcp' requires a baseUrl (the MCP endpoint, e.g. http://agent/mcp)`);\n }\n const operation = extractOperationFromVectorUrl(vector.request.url);\n const envelope = wrapMcpEnvelope(operation, vector.request.body, options.mcpJsonRpcId);\n // Accept header added for MCP Streamable HTTP negotiation. Not in the\n // signed components list (MANDATORY_COMPONENTS doesn't include `accept`),\n // so adding it after the vector's headers doesn't affect the signature.\n headers['Accept'] = 'application/json, text/event-stream';\n return {\n method: vector.request.method,\n url: options.baseUrl,\n headers,\n body: envelope,\n };\n }\n return {\n method: vector.request.method,\n url: retargetUrl(vector.request.url, options.baseUrl),\n headers,\n body: vector.request.body,\n };\n}\n\n// AdCP operation names are spec-defined identifiers (lowercase alnum +\n// underscore — `create_media_buy`, `sync_creatives`, `si_send_message`,\n// etc.; verified against every `task:` value shipped in\n// `compliance/cache/{version}/protocols/**/*.yaml`). Constrain the extractor\n// output to that shape so a compromised compliance cache can't smuggle\n// arbitrary bytes into `params.name` via a weird vector URL.\nconst OPERATION_NAME_SAFE = /^[a-z][a-z0-9_]*$/;\n\nfunction extractOperationFromVectorUrl(vectorUrl: string): string {\n const parsed = new URL(vectorUrl);\n const segments = parsed.pathname.split('/').filter(Boolean);\n const last = segments[segments.length - 1];\n if (!last) throw new Error(`Cannot extract operation from vector URL: ${vectorUrl}`);\n if (!OPERATION_NAME_SAFE.test(last)) {\n throw new Error(\n `Operation name \"${last}\" extracted from ${vectorUrl} fails identifier check. ` +\n `AdCP operations are lowercase_snake_case; this is likely a corrupted compliance cache.`\n );\n }\n return last;\n}\n\nfunction wrapMcpEnvelope(\n operation: string,\n rawBody: string | undefined,\n idOverride: number | string | undefined\n): string {\n const id = idOverride ?? randomUUID();\n // Conformance vectors' bodies are spec-typed as JSON. A parse failure is\n // a vector drift, not a runtime input-validation case — let it surface.\n const args = rawBody && rawBody.length > 0 ? JSON.parse(rawBody) : {};\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n method: 'tools/call',\n params: { name: operation, arguments: args },\n });\n}\n\ninterface ParamOverride {\n tag?: string;\n alg?: string;\n keyid?: string;\n expiresDelta?: number;\n omitExpires?: boolean;\n omitNonce?: boolean;\n}\n\n/**\n * Build a signature base with overridden params, sign it directly, and emit\n * the headers. Needed when the mutation lives in `@signature-params` itself\n * (tag, alg, keyid, expires, nonce) — signRequest won't emit those exact\n * malformations.\n */\nfunction signWithParamOverride(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n override: ParamOverride\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const hasBody = (request.body ?? '').length > 0;\n const components = hasBody\n ? ['@method', '@target-uri', '@authority', 'content-type']\n : ['@method', '@target-uri', '@authority'];\n\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + (override.expiresDelta ?? windowSeconds),\n nonce: options.nonce ?? randomNonce(),\n keyid: override.keyid ?? key.keyid,\n alg: override.alg ?? key.alg,\n tag: override.tag ?? REQUEST_SIGNING_TAG,\n };\n\n const paramsString = formatParamsWithOmissions(components, params, override);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction signWithComponents(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n components: string[]\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + windowSeconds,\n nonce: options.nonce ?? randomNonce(),\n keyid: key.keyid,\n alg: key.alg,\n tag: REQUEST_SIGNING_TAG,\n };\n const paramsString = formatSignatureParams(components, params);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction formatParamsWithOmissions(\n components: ReadonlyArray<string>,\n params: SignatureParams,\n override: ParamOverride\n): string {\n const componentList = components.map(c => `\"${c}\"`).join(' ');\n const pairs: string[] = [];\n pairs.push(`created=${params.created}`);\n if (!override.omitExpires) pairs.push(`expires=${params.expires}`);\n if (!override.omitNonce) pairs.push(`nonce=\"${params.nonce}\"`);\n pairs.push(`keyid=\"${params.keyid}\"`);\n pairs.push(`alg=\"${params.alg}\"`);\n pairs.push(`tag=\"${params.tag}\"`);\n return `(${componentList});${pairs.join(';')}`;\n}\n\nfunction produceSignature(key: SignerKey, data: Buffer): Uint8Array {\n const privateKey = createPrivateKey({ key: key.privateKey as JsonWebKey, format: 'jwk' });\n if (key.alg === 'ed25519') {\n return new Uint8Array(nodeSign(null, data, privateKey));\n }\n return new Uint8Array(nodeSign('sha256', data, { key: privateKey, dsaEncoding: 'ieee-p1363' }));\n}\n\n// ── Helpers ───────────────────────────────────────────────────\n\nfunction signerKeyFor(vector: PositiveVector | NegativeVector, keys: TestKeyset): SignerKey {\n const kid = vector.jwks_ref?.[0];\n if (!kid) {\n throw new Error(\n `${vector.id}: jwks_ref missing — vectors signed dynamically by the builder must declare a keys.json kid. ` +\n `Vectors shipping an inline jwks_override must use a passthrough mutator (no re-signing).`\n );\n }\n return keyFor(keys, kid);\n}\n\nfunction keyFor(keys: TestKeyset, kid: string): SignerKey {\n const keypair = findKey(keys, kid);\n return toSignerKey(keypair);\n}\n\nfunction toSignerKey(keypair: TestKeypair): SignerKey {\n const alg: SignerKey['alg'] = keypair.crv === 'Ed25519' ? 'ed25519' : 'ecdsa-p256-sha256';\n const privateKey: AdcpJsonWebKey = {\n kid: keypair.kid,\n kty: keypair.kty,\n crv: keypair.crv,\n alg: keypair.alg,\n use: keypair.use,\n key_ops: ['sign'],\n adcp_use: keypair.adcp_use,\n x: keypair.x,\n y: keypair.y,\n d: keypair.private_d,\n };\n return { keyid: keypair.kid, alg, privateKey };\n}\n\nfunction stripSignatureHeaders(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n const lower = k.toLowerCase();\n if (lower === 'signature' || lower === 'signature-input' || lower === 'content-digest') continue;\n out[k] = v;\n }\n return out;\n}\n\nfunction mergeHeaders(from: Record<string, string>, signed: Record<string, string>): Record<string, string> {\n // Drop original Signature/Signature-Input/Content-Digest before overlaying fresh ones.\n const base = stripSignatureHeaders(from);\n return { ...base, ...signed };\n}\n\nfunction nowSeconds(options: BuildOptions): number {\n return options.now ?? Math.floor(Date.now() / 1000);\n}\n\nfunction randomNonce(): string {\n return randomBytes(16).toString('base64url');\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/builder.ts"],"sourcesContent":["import { createPrivateKey, randomBytes, randomUUID, sign as nodeSign, type JsonWebKey } from 'crypto';\nimport {\n buildSignatureBase,\n finalizeRequestSignature,\n formatSignatureParams,\n prepareRequestSignature,\n REQUEST_SIGNING_TAG,\n type AdcpJsonWebKey,\n type RequestLike,\n type SignatureParams,\n type SignerKey,\n} from '../../../signing';\nimport { findKey } from './vector-loader';\nimport type { NegativeVector, PositiveVector, TestKeyset, TestKeypair } from './types';\n\nexport interface BuildOptions {\n /** Override the signer clock (unix seconds). Defaults to `Date.now()/1000`. */\n now?: number;\n /** Override the nonce. Defaults to freshly-generated. */\n nonce?: string;\n /** Override the `expires - created` window (seconds). Defaults to 300. */\n windowSeconds?: number;\n /**\n * Agent base URL. When set, the vector's request URL has its origin replaced\n * with this base before signing — the vectors point at `seller.example.com`\n * but real agents live elsewhere. The path and query are preserved so the\n * operation intent (e.g., `/adcp/create_media_buy`) is unchanged.\n *\n * Canonicalization-edge vectors (005 default-port, 006 dot-segment path,\n * 007 query preservation, 008 percent-encoded path) bake their edge case\n * into the vector URL; replacing the origin keeps that edge intact in the\n * path/query, but vectors sensitive to the port or scheme will no longer\n * exercise the edge against a mismatched agent base.\n */\n baseUrl?: string;\n /**\n * Transport-layer framing. `'raw'` (default) sends the vector body to the\n * retargeted vector URL verbatim — matches the conformance vectors' intent\n * of testing a per-operation HTTP endpoint. `'mcp'` wraps the vector body\n * in a JSON-RPC `tools/call` envelope and posts to `baseUrl` as-is (no\n * path join); operation name comes from the vector URL's last segment.\n *\n * MCP mode trades the canonicalization-edge coverage for reach: vectors\n * 005–008 fold into plain POSTs against the MCP endpoint, but the grader\n * works against any MCP agent that wires a verifier at the HTTP layer.\n */\n transport?: 'raw' | 'mcp';\n /**\n * JSON-RPC `id` for the MCP envelope. Defaults to `crypto.randomUUID()`\n * so concurrent runs never collide. Override for tests that need a stable\n * id — JSON-RPC 2.0 permits number, string, or null.\n */\n mcpJsonRpcId?: number | string;\n}\n\nexport interface SignedHttpRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\nexport function buildPositiveRequest(\n vector: PositiveVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, {\n coverContentDigest: vector.verifier_capability.covers_content_digest === 'required',\n ...options,\n });\n}\n\n/**\n * Apply the adversarial mutation documented for a negative vector.\n *\n * Black-box grader: the positive/001 signature bytes sitting in most negative\n * fixtures are placeholders; we re-sign dynamically, then mutate. Covers all\n * 20 current negative vectors. Stateful contract vectors (016 replay, 017\n * revoked, 020 rate abuse) produce a single well-formed request; the\n * storyboard runner orchestrates the repeat/flood/revoked-keyid behavior\n * around that request per the signed-requests-runner test-kit.\n */\nexport function buildNegativeRequest(\n vector: NegativeVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const mutation = MUTATIONS[vector.id];\n if (!mutation) {\n throw new Error(`No adversarial builder registered for negative vector \"${vector.id}\"`);\n }\n return mutation(vector, keys, options);\n}\n\nexport function listSupportedNegativeVectors(): string[] {\n return Object.keys(MUTATIONS);\n}\n\ntype Mutator = (vector: NegativeVector, keys: TestKeyset, options: BuildOptions) => SignedHttpRequest;\n\nconst MUTATIONS: Record<string, Mutator> = {\n '001-no-signature-header': (vector, _keys, options) => {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: stripSignatureHeaders(shaped.headers),\n body: shaped.body,\n };\n },\n\n '002-wrong-tag': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { tag: 'example-org/signing/v1' });\n },\n\n '003-expired-signature': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const now = nowSeconds(options);\n return sign(key, vector, { ...options, now: now - 600, windowSeconds: 300 });\n },\n\n '004-window-too-long': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, {\n expiresDelta: 301,\n });\n },\n\n '005-alg-not-allowed': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { alg: 'rsa-pss-sha512' });\n },\n\n '006-missing-covered-component': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithComponents(key, vector, options, ['@method', '@target-uri', 'content-type']);\n },\n\n '007-missing-content-digest': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: false });\n },\n\n '008-unknown-keyid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { keyid: 'unknown-key-9999' });\n },\n\n '009-key-ops-missing-verify': (vector, keys, options) => {\n // Vector 009 pins `jwks_ref: [\"test-gov-2026\"]` (adcp_use:\n // governance-signing, not request-signing) — use it directly instead of\n // inferring. Honors the vector's intent if future keysets add a second\n // non-request-signing keypair.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '010-content-digest-mismatch': (vector, keys, options) => {\n // Vector 010 tests \"signer committed a wrong Content-Digest value\" — the\n // signature IS valid over the base that includes that wrong value, so the\n // verifier passes the signature check (step 10) and then fails the\n // digest-vs-body recompute (step 11). Do NOT mutate the body post-sign —\n // that tests a different bug (body-tampered-in-transit) and a verifier\n // that recomputes digest from sent body would not catch the \"lying\n // signer\" path this vector exercises.\n const key = signerKeyFor(vector, keys);\n // Zero-byte digest: guaranteed not to match the actual body.\n const zeroDigest = 'sha-256=:' + Buffer.alloc(32).toString('base64') + ':';\n const headersWithBadDigest = { ...vector.request.headers, 'Content-Digest': zeroDigest };\n const vectorWithBadDigest = {\n ...vector,\n request: { ...vector.request, headers: headersWithBadDigest },\n };\n // Sign the request WITH content-digest in covered components, without\n // letting `signRequest` recompute the digest over the real body.\n return signWithComponents(key, vectorWithBadDigest, options, [\n '@method',\n '@target-uri',\n '@authority',\n 'content-type',\n 'content-digest',\n ]);\n },\n\n '011-malformed-header': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n return {\n ...signed,\n headers: {\n ...signed.headers,\n 'Signature-Input': 'sig1=not a valid structured-field value!!!',\n },\n };\n },\n\n '012-missing-expires-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitExpires: true });\n },\n\n '013-expires-le-created': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { expiresDelta: 0 });\n },\n\n '014-missing-nonce-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitNonce: true });\n },\n\n '015-signature-invalid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const zeroSig = Buffer.alloc(64).toString('base64url');\n return {\n ...signed,\n headers: {\n ...signed.headers,\n Signature: `sig1=:${zeroSig}:`,\n },\n };\n },\n\n '016-replayed-nonce': (vector, keys, options) => {\n // Black-box runner sends the request twice; first accepted, second rejected.\n // Builder produces the single well-formed request used for both submissions.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '017-key-revoked': (vector, keys, options) => {\n // Use the dedicated revoked key (`test-revoked-2026`) declared by the\n // signed-requests-runner test-kit. For current pre-#2353 caches, vector 017\n // still references test-ed25519-2026; fall back to whatever the vector says.\n const kid = vector.jwks_ref?.[0];\n if (!kid) throw new Error(`${vector.id}: jwks_ref missing`);\n const key = keyFor(keys, kid);\n return sign(key, vector, options);\n },\n\n '018-digest-covered-when-forbidden': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: true });\n },\n\n '019-signature-without-signature-input': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const { 'Signature-Input': _drop, ...rest } = signed.headers;\n return { ...signed, headers: rest };\n },\n\n '020-rate-abuse': (vector, keys, options) => {\n // Runner floods the agent with distinct-nonce requests from the same keyid.\n // Builder produces a single well-formed request; the runner generates N\n // distinct nonces by calling this builder repeatedly with `options.nonce`.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n // Vectors 021-026 ship their exact malformed headers in the fixture — the\n // adversarial shape (duplicate sig-input label, multi-valued content-type\n // / content-digest, unquoted string param, malformed JWK, non-ASCII host)\n // lives in the vector itself, not in a programmatic mutation. Builder just\n // preserves the fixture's headers verbatim after applying transport.\n '021-duplicate-signature-input-label': (vector, _keys, options) => passthrough(vector, options),\n '022-multi-valued-content-type': (vector, _keys, options) => passthrough(vector, options),\n '023-multi-valued-content-digest': (vector, _keys, options) => passthrough(vector, options),\n '024-unquoted-string-param': (vector, _keys, options) => passthrough(vector, options),\n '025-jwk-alg-crv-mismatch': (vector, _keys, options) => passthrough(vector, options),\n '026-non-ascii-host': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 027 tests the \"webhook authentication MUST trigger signing\" rule:\n // the fixture is a plain bearer-auth request with zero signature headers,\n // and the adversarial shape is precisely that absence. Passthrough preserves\n // the fixture bytes; retargeting still works via applyTransport.\n '027-webhook-registration-authentication-unsigned': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 028 grades the `protocol_methods_required_for` namespace\n // (adcp#4326). The fixture body is already a JSON-RPC envelope with\n // `method: \"tasks/cancel\"` — NOT a `tools/call` envelope — so the standard\n // MCP-mode `applyTransport` (which would wrap the body in `tools/call`)\n // is wrong here. Use `protocolMethodPassthrough` which keeps the body\n // verbatim and targets `baseUrl` directly when set, matching how an\n // agent's MCP endpoint routes JSON-RPC `tasks/*` methods.\n '028-unsigned-protocol-method-required': (vector, _keys, options) => protocolMethodPassthrough(vector, options),\n};\n\nfunction passthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n}\n\n/**\n * Passthrough for vectors whose body is already a JSON-RPC envelope with a\n * non-`tools/call` `method` (e.g., `tasks/cancel`). MCP-mode `applyTransport`\n * would wrap the body in `tools/call`, which is wrong: the protocol_methods\n * namespace matches against the JSON-RPC envelope's `method` field, so\n * wrapping in `tools/call` would route the request to MCP tool dispatch\n * (looking up a tool literally named \"tasks/cancel\"; 404) instead of the\n * SDK's auto-registered `tasks/cancel` JSON-RPC handler.\n *\n * Targets `options.baseUrl` directly when set (the MCP endpoint URL), or\n * the vector's URL verbatim otherwise.\n */\nfunction protocolMethodPassthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n const url = options.baseUrl ?? vector.request.url;\n const headers = { ...vector.request.headers };\n // MCP Streamable HTTP requires this Accept negotiation header on JSON-RPC\n // probes — match the wrapping path's behavior.\n if (options.transport === 'mcp') {\n headers['Accept'] = 'application/json, text/event-stream';\n }\n return {\n method: vector.request.method,\n url,\n headers,\n body: vector.request.body,\n };\n}\n\n// ── Primitives ────────────────────────────────────────────────\n\ninterface SignArgs extends BuildOptions {\n coverContentDigest?: boolean;\n}\n\nfunction sign(key: SignerKey, vector: PositiveVector | NegativeVector, args: SignArgs): SignedHttpRequest {\n const shaped = applyTransport(vector, args);\n const request: RequestLike = {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n // Negative-vector 009 deliberately signs with a wrong-purpose key\n // (`adcp_use: 'governance-signing'`) to exercise the verifier's step-8\n // purpose check. The signer-side `signRequest` gate refuses wrong-purpose\n // keys to prevent the more common operator footgun; bypass it here by\n // composing `prepareRequestSignature` (which takes `SignatureIdentity`\n // and runs no gate) with this file's local `produceSignature` helper.\n // The bypass is intentional and confined to test-vector authoring.\n const prepared = prepareRequestSignature(\n request,\n { keyid: key.keyid, alg: key.alg },\n {\n coverContentDigest: args.coverContentDigest === true,\n now: args.now !== undefined ? () => args.now! : undefined,\n nonce: args.nonce,\n windowSeconds: args.windowSeconds,\n }\n );\n const signature = produceSignature(key, Buffer.from(prepared.base, 'utf8'));\n const signed = finalizeRequestSignature(prepared, signature);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: mergeHeaders(shaped.headers, signed.headers),\n body: shaped.body,\n };\n}\n\nfunction retargetUrl(vectorUrl: string, baseUrl: string | undefined): string {\n if (!baseUrl) return vectorUrl;\n const v = new URL(vectorUrl);\n const b = new URL(baseUrl);\n v.protocol = b.protocol;\n v.host = b.host;\n // Prefix the agent's mount path (from baseUrl) ahead of the vector's path\n // so agents mounted at e.g. `/v1/adcp/*` receive requests at\n // `/v1/adcp/create_media_buy` rather than the bare `/adcp/create_media_buy`\n // the vector carries. When baseUrl has no path (or just `/`), this is a\n // no-op. Canonicalization-edge vectors (005–008) bake their edge into the\n // vector's path/query; we preserve those bytes by joining, not replacing.\n if (b.pathname && b.pathname !== '/') {\n const mount = b.pathname.replace(/\\/+$/, '');\n const vectorPath = v.pathname.startsWith('/') ? v.pathname : `/${v.pathname}`;\n v.pathname = `${mount}${vectorPath}`;\n }\n return v.toString();\n}\n\ninterface TransportShapedRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\n/**\n * Apply the transport transform to a vector's request shape. In `'raw'` mode\n * (default) this is just origin-swap path-merge. In `'mcp'` mode:\n * - URL becomes `baseUrl` exactly (no path join — MCP agents expose a single\n * JSON-RPC endpoint; the operation is named in the body).\n * - Body is wrapped in a JSON-RPC `tools/call` envelope; the operation name\n * comes from the vector's last URL segment.\n * - `Accept: application/json, text/event-stream` added so MCP Streamable\n * HTTP servers don't 406 on the probe.\n *\n * Shared call site for `sign`, `signWithParamOverride`, `signWithComponents`\n * so every mutation path produces MCP-shaped requests when requested.\n */\nfunction applyTransport(vector: PositiveVector | NegativeVector, options: BuildOptions): TransportShapedRequest {\n const headers = { ...vector.request.headers };\n if (options.transport === 'mcp') {\n if (!options.baseUrl) {\n throw new Error(`transport: 'mcp' requires a baseUrl (the MCP endpoint, e.g. http://agent/mcp)`);\n }\n const operation = extractOperationFromVectorUrl(vector.request.url);\n const envelope = wrapMcpEnvelope(operation, vector.request.body, options.mcpJsonRpcId);\n // Accept header added for MCP Streamable HTTP negotiation. Not in the\n // signed components list (MANDATORY_COMPONENTS doesn't include `accept`),\n // so adding it after the vector's headers doesn't affect the signature.\n headers['Accept'] = 'application/json, text/event-stream';\n return {\n method: vector.request.method,\n url: options.baseUrl,\n headers,\n body: envelope,\n };\n }\n return {\n method: vector.request.method,\n url: retargetUrl(vector.request.url, options.baseUrl),\n headers,\n body: vector.request.body,\n };\n}\n\n// AdCP operation names are spec-defined identifiers (lowercase alnum +\n// underscore — `create_media_buy`, `sync_creatives`, `si_send_message`,\n// etc.; verified against every `task:` value shipped in\n// `compliance/cache/{version}/protocols/**/*.yaml`). Constrain the extractor\n// output to that shape so a compromised compliance cache can't smuggle\n// arbitrary bytes into `params.name` via a weird vector URL.\nconst OPERATION_NAME_SAFE = /^[a-z][a-z0-9_]*$/;\n\nfunction extractOperationFromVectorUrl(vectorUrl: string): string {\n const parsed = new URL(vectorUrl);\n const segments = parsed.pathname.split('/').filter(Boolean);\n const last = segments[segments.length - 1];\n if (!last) throw new Error(`Cannot extract operation from vector URL: ${vectorUrl}`);\n if (!OPERATION_NAME_SAFE.test(last)) {\n throw new Error(\n `Operation name \"${last}\" extracted from ${vectorUrl} fails identifier check. ` +\n `AdCP operations are lowercase_snake_case; this is likely a corrupted compliance cache.`\n );\n }\n return last;\n}\n\nfunction wrapMcpEnvelope(\n operation: string,\n rawBody: string | undefined,\n idOverride: number | string | undefined\n): string {\n const id = idOverride ?? randomUUID();\n // Conformance vectors' bodies are spec-typed as JSON. A parse failure is\n // a vector drift, not a runtime input-validation case — let it surface.\n const args = rawBody && rawBody.length > 0 ? JSON.parse(rawBody) : {};\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n method: 'tools/call',\n params: { name: operation, arguments: args },\n });\n}\n\ninterface ParamOverride {\n tag?: string;\n alg?: string;\n keyid?: string;\n expiresDelta?: number;\n omitExpires?: boolean;\n omitNonce?: boolean;\n}\n\n/**\n * Build a signature base with overridden params, sign it directly, and emit\n * the headers. Needed when the mutation lives in `@signature-params` itself\n * (tag, alg, keyid, expires, nonce) — signRequest won't emit those exact\n * malformations.\n */\nfunction signWithParamOverride(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n override: ParamOverride\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const hasBody = (request.body ?? '').length > 0;\n const components = hasBody\n ? ['@method', '@target-uri', '@authority', 'content-type']\n : ['@method', '@target-uri', '@authority'];\n\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + (override.expiresDelta ?? windowSeconds),\n nonce: options.nonce ?? randomNonce(),\n keyid: override.keyid ?? key.keyid,\n alg: override.alg ?? key.alg,\n tag: override.tag ?? REQUEST_SIGNING_TAG,\n };\n\n const paramsString = formatParamsWithOmissions(components, params, override);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction signWithComponents(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n components: string[]\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + windowSeconds,\n nonce: options.nonce ?? randomNonce(),\n keyid: key.keyid,\n alg: key.alg,\n tag: REQUEST_SIGNING_TAG,\n };\n const paramsString = formatSignatureParams(components, params);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction formatParamsWithOmissions(\n components: ReadonlyArray<string>,\n params: SignatureParams,\n override: ParamOverride\n): string {\n const componentList = components.map(c => `\"${c}\"`).join(' ');\n const pairs: string[] = [];\n pairs.push(`created=${params.created}`);\n if (!override.omitExpires) pairs.push(`expires=${params.expires}`);\n if (!override.omitNonce) pairs.push(`nonce=\"${params.nonce}\"`);\n pairs.push(`keyid=\"${params.keyid}\"`);\n pairs.push(`alg=\"${params.alg}\"`);\n pairs.push(`tag=\"${params.tag}\"`);\n return `(${componentList});${pairs.join(';')}`;\n}\n\nfunction produceSignature(key: SignerKey, data: Buffer): Uint8Array {\n const privateKey = createPrivateKey({ key: key.privateKey as JsonWebKey, format: 'jwk' });\n if (key.alg === 'ed25519') {\n return new Uint8Array(nodeSign(null, data, privateKey));\n }\n return new Uint8Array(nodeSign('sha256', data, { key: privateKey, dsaEncoding: 'ieee-p1363' }));\n}\n\n// ── Helpers ───────────────────────────────────────────────────\n\nfunction signerKeyFor(vector: PositiveVector | NegativeVector, keys: TestKeyset): SignerKey {\n const kid = vector.jwks_ref?.[0];\n if (!kid) {\n throw new Error(\n `${vector.id}: jwks_ref missing — vectors signed dynamically by the builder must declare a keys.json kid. ` +\n `Vectors shipping an inline jwks_override must use a passthrough mutator (no re-signing).`\n );\n }\n return keyFor(keys, kid);\n}\n\nfunction keyFor(keys: TestKeyset, kid: string): SignerKey {\n const keypair = findKey(keys, kid);\n return toSignerKey(keypair);\n}\n\nfunction toSignerKey(keypair: TestKeypair): SignerKey {\n const alg: SignerKey['alg'] = keypair.crv === 'Ed25519' ? 'ed25519' : 'ecdsa-p256-sha256';\n const privateKey: AdcpJsonWebKey = {\n kid: keypair.kid,\n kty: keypair.kty,\n crv: keypair.crv,\n alg: keypair.alg,\n use: keypair.use,\n key_ops: ['sign'],\n adcp_use: keypair.adcp_use,\n x: keypair.x,\n y: keypair.y,\n d: keypair.private_d,\n };\n return { keyid: keypair.kid, alg, privateKey };\n}\n\nfunction stripSignatureHeaders(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n const lower = k.toLowerCase();\n if (lower === 'signature' || lower === 'signature-input' || lower === 'content-digest') continue;\n out[k] = v;\n }\n return out;\n}\n\nfunction mergeHeaders(from: Record<string, string>, signed: Record<string, string>): Record<string, string> {\n // Drop original Signature/Signature-Input/Content-Digest before overlaying fresh ones.\n const base = stripSignatureHeaders(from);\n return { ...base, ...signed };\n}\n\nfunction nowSeconds(options: BuildOptions): number {\n return options.now ?? Math.floor(Date.now() / 1000);\n}\n\nfunction randomNonce(): string {\n return randomBytes(16).toString('base64url');\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
import { randomBytes } from "crypto";
|
|
8
2
|
import { buildNegativeRequest, buildPositiveRequest } from "./builder.mjs";
|
|
9
3
|
import { probeSignedRequest } from "./probe.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/grader.ts"],"sourcesContent":["import { randomBytes } from 'crypto';\nimport { buildNegativeRequest, buildPositiveRequest, type BuildOptions, type SignedHttpRequest } from './builder';\nimport { probeSignedRequest, type ProbeResult } from './probe';\nimport { loadRequestSigningVectors, type LoadVectorsOptions } from './vector-loader';\nimport { loadSignedRequestsRunnerContract, type SignedRequestsRunnerContract } from './test-kit';\nimport {\n InMemoryReplayStore,\n InMemoryRevocationStore,\n RequestSignatureError,\n StaticJwksResolver,\n verifyRequestSignature,\n type AdcpJsonWebKey,\n} from '../../../signing';\nimport { parseSignatureInput } from '../../../signing/parser';\nimport type { NegativeVector, PositiveVector, VerifierCapabilityFixture } from './types';\n\nexport interface GradeOptions extends LoadVectorsOptions {\n /** Allow http:// and private-IP destinations. Off by default (match fetchProbe). */\n allowPrivateIp?: boolean;\n /** Skip the rate-abuse vector (it sends 100+ requests; slow). Defaults to false. */\n skipRateAbuse?: boolean;\n /**\n * Override the rate-abuse cap the grader targets. Defaults to the contract's\n * `grading_target_per_keyid_cap_requests`. Agents that advertise a smaller\n * per-keyid cap for the test counterparty MAY lower this so grading finishes\n * in a reasonable time — see test-kits/signed-requests-runner.yaml.\n */\n rateAbuseCap?: number;\n /**\n * Vector IDs to skip for operator-driven reasons (SDK-internal vectors,\n * environment-specific quirks, etc.). Capability-profile mismatches\n * don't belong here — pass {@link agentCapability} and the grader auto-\n * skips vectors whose `verifier_capability` can't match the agent.\n */\n skipVectors?: string[];\n /**\n * Agent's declared `request_signing` capability block — exactly the shape\n * in `get_adcp_capabilities.response.request_signing`. When provided, the\n * grader pre-flights every vector's `verifier_capability` against this\n * profile and auto-skips any vector that asserts a policy the agent\n * didn't advertise (e.g., vector 007 requires `covers_content_digest:\n * 'required'`; agent declares `'either'` — auto-skipped with\n * `skip_reason: 'capability_profile_mismatch'`). The grader also parses\n * each vector's `Signature-Input` and auto-skips vectors whose actual\n * signed components are structurally incompatible with the agent's\n * policy (uncovered `content-digest` against a `'required'` verifier,\n * or covered `content-digest` against a `'forbidden'` verifier).\n *\n * Without this option, every vector runs and cap-profile mismatches\n * produce failed vectors that the operator has to manually translate\n * into `skipVectors` entries — fragile and easy to get wrong per\n * profile. Set `agentCapability` and `skipVectors` collapses to just\n * the handful of operator-specific overrides (like vector 025, which\n * exercises the SDK library rather than the agent).\n */\n agentCapability?: VerifierCapabilityFixture;\n /**\n * When set, run only the named vector ids (all others auto-skip). Takes\n * precedence over `skipVectors`. Useful for isolated regression tests\n * against a single vector without hand-maintaining an inverted skip list.\n */\n onlyVectors?: string[];\n /**\n * Opt in to running vectors that produce live agent-side effects — vector\n * 016 (replay_window) sends a valid `create_media_buy`-shaped request the\n * agent will accept, and vector 020 (rate_abuse) floods cap+1 requests.\n * Required unless the test-kit contract declares `endpoint_scope: sandbox`\n * (in which case the agent asserts the operation is side-effect-free).\n * Default: false — side-effectful vectors auto-skip against non-sandbox\n * endpoints.\n */\n allowLiveSideEffects?: boolean;\n /**\n * Agent's declared `covers_content_digest` policy from\n * `get_adcp_capabilities.request_signing.covers_content_digest`. When set\n * without `agentCapability`, the grader auto-skips both positive and\n * negative vectors whose signature shape is structurally incompatible\n * with the agent's policy:\n *\n * - Vectors whose `verifier_capability.covers_content_digest` asserts\n * a strict policy the agent didn't advertise (e.g. `'either'` →\n * skips neg/007 (`'required'`) and neg/018 (`'forbidden'`)).\n * - Vectors whose actual `Signature-Input` covers `content-digest`\n * against a `'forbidden'` agent (rejected with\n * `request_signature_components_unexpected` before the intended\n * error path).\n * - Vectors whose actual `Signature-Input` does not cover\n * `content-digest` against a `'required'` agent (rejected with\n * `request_signature_components_incomplete` before the intended\n * error path).\n *\n * Skipped vectors use `skip_reason: 'capability_profile_mismatch'`.\n *\n * Has no effect when `agentCapability` is provided — the full\n * capability fixture's `covers_content_digest` field governs via\n * `capabilityMismatch()`, which performs the same shape check. Use\n * `agentCapability` when you also need `required_for` skip behavior.\n */\n agentContentDigestPolicy?: 'required' | 'forbidden' | 'either';\n /**\n * Transport shape the agent speaks. `'raw'` (default) POSTs per-operation\n * AdCP endpoints matching the vectors' URL shape. `'mcp'` wraps each\n * vector body in a JSON-RPC `tools/call` envelope and POSTs to the MCP\n * mount path (`agentUrl`) — use when grading an MCP agent whose verifier\n * sits as transport-layer middleware ahead of MCP dispatch.\n *\n * See adcontextprotocol/adcp-client#612 for the MCP-mode rationale.\n */\n transport?: 'raw' | 'mcp';\n /**\n * Override the agent's base URL used for the grader's HTTP targets. When set,\n * each vector's `request.url` is rewritten by swapping origin+path under this\n * base — useful when the vectors point at `seller.example.com` but the agent\n * is reachable at a sandbox URL.\n */\n agentUrl?: string;\n /** Per-probe timeout. Default 10s. */\n timeoutMs?: number;\n /**\n * Number of (probe1, probe2) pairs to run for vector neg/016\n * (replayed-nonce). Each pair uses a fresh nonce and a new TCP\n * connection, so on a multi-instance deployment the two probes\n * may land on different instances. K pairs make the failure\n * deterministic: if any second probe is accepted the count and\n * the cross-instance hypothesis surface in the diagnostic.\n * Must be ≥ 2. Default 10.\n */\n replayProbePairs?: number;\n}\n\nexport interface VectorGradeResult {\n vector_id: string;\n kind: 'positive' | 'negative';\n passed: boolean;\n skipped?: boolean;\n skip_reason?: string;\n /** For negatives: the error code the agent returned (from WWW-Authenticate). */\n actual_error_code?: string;\n /** For negatives: the error code the spec says we should see. */\n expected_error_code?: string;\n http_status: number;\n diagnostic?: string;\n probe_duration_ms: number;\n /**\n * For neg/016 (replayed-nonce) only: total number of (probe1, probe2)\n * pairs attempted by the K-pair grader.\n */\n replay_pairs_tried?: number;\n /**\n * For neg/016 (replayed-nonce) only: number of pairs where the second\n * probe was correctly rejected with `request_signature_replayed`.\n * Equal to `replay_pairs_tried` on a passing run.\n */\n replay_pairs_rejected?: number;\n}\n\nexport interface GradeReport {\n agent_url: string;\n harness_mode: 'black_box';\n /**\n * `true` when the test-kit contract declares an endpoint_scope other than\n * `sandbox` — vectors 016 and 020 produce live side effects (a real\n * `create_media_buy` for 016, cap+1 flooding for 020). Treat as a warning\n * to the operator.\n */\n live_endpoint_warning: boolean;\n contract_loaded: boolean;\n positive: VectorGradeResult[];\n negative: VectorGradeResult[];\n passed: boolean;\n passed_count: number;\n failed_count: number;\n skipped_count: number;\n total_duration_ms: number;\n}\n\n/**\n * Grade an agent's RFC 9421 verifier against the 28 conformance vectors.\n *\n * Preconditions the caller owns:\n * - Agent advertises `request_signing.supported: true` in `get_adcp_capabilities`.\n * - Agent has pre-configured its verifier per `test-kits/signed-requests-runner.yaml`:\n * - Runner's signing keyids (`test-ed25519-2026`, `test-es256-2026`) accepted.\n * - `test-revoked-2026` pre-revoked.\n * - Per-keyid rate cap within grading_target_per_keyid_cap_requests.\n * - `agentUrl` targets a sandbox endpoint — the replay-window contract sends\n * a live valid request that will be accepted before the second (rejected)\n * copy fires.\n */\nexport async function gradeRequestSigning(agentUrl: string, options: GradeOptions = {}): Promise<GradeReport> {\n const start = Date.now();\n const loaded = loadRequestSigningVectors(options);\n const contract = loadSignedRequestsRunnerContract(options);\n\n const probeOpts = {\n allowPrivateIp: options.allowPrivateIp === true,\n timeoutMs: options.timeoutMs,\n };\n\n const buildOpts: BuildOptions = { baseUrl: agentUrl, transport: options.transport ?? 'raw' };\n\n const positive: VectorGradeResult[] = [];\n for (const vector of loaded.positive) {\n const skip = preflightSkip(vector, 'positive', contract, options);\n if (skip) {\n positive.push(skip);\n continue;\n }\n const signed = buildPositiveRequest(vector, loaded.keys, buildOpts);\n const probed = await probeSignedRequest(signed, probeOpts);\n positive.push(gradePositive(vector, probed));\n }\n\n const negative: VectorGradeResult[] = [];\n for (const vector of loaded.negative) {\n const skip = preflightSkip(vector, 'negative', contract, options);\n if (skip) {\n negative.push(skip);\n continue;\n }\n negative.push(await gradeNegative(vector, loaded, contract, probeOpts, buildOpts, options));\n }\n\n const all = [...positive, ...negative];\n const passed_count = all.filter(r => r.passed && !r.skipped).length;\n const skipped_count = all.filter(r => r.skipped).length;\n const failed_count = all.filter(r => !r.passed && !r.skipped).length;\n const passed = failed_count === 0;\n\n return {\n agent_url: agentUrl,\n harness_mode: 'black_box',\n // Default to TRUE when no contract is loaded — we can't prove the endpoint\n // is sandbox, so warn the operator that 016/020 could produce live side\n // effects. Only FALSE when a contract is loaded AND declares sandbox.\n live_endpoint_warning: !contract || contract.endpoint_scope !== 'sandbox',\n contract_loaded: Boolean(contract),\n positive,\n negative,\n passed,\n passed_count,\n failed_count,\n skipped_count,\n total_duration_ms: Date.now() - start,\n };\n}\n\n// Positive vectors whose edge-case coverage survives only under raw transport\n// (per-operation endpoint URLs). Listed explicitly rather than heuristically\n// so a spec author adding a new canonicalization-edge vector has to opt into\n// the skip.\nconst MCP_FLATTENED_VECTORS = new Set([\n '005-default-port-stripped',\n '006-dot-segment-path',\n '007-query-byte-preserved',\n '008-percent-encoded-path',\n]);\n\n// Vectors whose failure mode can't reach a live agent through HTTP. Document\n// why each entry can't be graded via probe so adding a new entry isn't a\n// silent coverage loss.\nconst TRANSPORT_UNGRADABLE: Record<string, string> = {\n // fetch() and the Node URL parser normalize U-labels to A-labels before\n // the request leaves the client. A raw non-ASCII Host header reaches the\n // agent as Punycode, defeating the parse-time check. Direct verifier\n // tests exercise this edge.\n '026-non-ascii-host':\n 'HTTP transport punycodes U-labels before the request leaves the client; verified at the library level.',\n};\n\n/**\n * Centralized skip decisions. Checks (in order): onlyVectors filter,\n * operator skipVectors, agent-capability-profile mismatch\n * (`agentCapability` wired), transport-ungradable, MCP-mode URL-edge\n * flattening, rate-abuse opt-out, stateful-contract missing, and the\n * live-side-effect gate.\n */\nfunction preflightSkip(\n vector: PositiveVector | NegativeVector,\n kind: 'positive' | 'negative',\n contract: SignedRequestsRunnerContract | undefined,\n options: GradeOptions\n): VectorGradeResult | undefined {\n const expected_error_code = kind === 'negative' ? (vector as NegativeVector).expected_error_code : undefined;\n const base = {\n vector_id: vector.id,\n kind,\n passed: true, // skipped ≠ failed; overall pass/fail excludes skipped\n http_status: 0,\n probe_duration_ms: 0,\n ...(expected_error_code ? { expected_error_code } : {}),\n } as const;\n\n if (options.onlyVectors && !options.onlyVectors.includes(vector.id)) {\n return { ...base, skipped: true, skip_reason: 'not_in_only_vectors' };\n }\n if (options.skipVectors?.includes(vector.id)) {\n return { ...base, skipped: true, skip_reason: 'operator_skip' };\n }\n if (options.agentCapability) {\n const mismatch = capabilityMismatch(vector, options.agentCapability);\n if (mismatch) {\n // Surface the mismatch in the diagnostic so operators can audit\n // which vectors were dodged. An agent that under-declares its\n // capability (claims `required_for: []` while it actually\n // enforces on multiple ops) would hide negative-vector failures\n // here — the operator needs to see the skip count to catch that\n // pattern. The caller inspects `report.skipped_count` plus the\n // individual `skip_reason`/`diagnostic` pairs.\n return {\n ...base,\n skipped: true,\n skip_reason: 'capability_profile_mismatch',\n diagnostic: mismatch,\n };\n }\n }\n if (!options.agentCapability && options.agentContentDigestPolicy) {\n const policyMismatch = contentDigestPolicyMismatch(vector, kind, options.agentContentDigestPolicy);\n if (policyMismatch) {\n return {\n ...base,\n skipped: true,\n skip_reason: 'capability_profile_mismatch',\n diagnostic: policyMismatch,\n };\n }\n }\n const transportReason = TRANSPORT_UNGRADABLE[vector.id];\n if (transportReason) {\n return { ...base, skipped: true, skip_reason: 'transport_ungradable', diagnostic: transportReason };\n }\n // Canonicalization-edge positive vectors (005–008) bake their edge case\n // into the vector URL path, query, or port. MCP mode flattens every vector\n // to the same baseUrl (JSON-RPC single endpoint), so these vectors become\n // indistinguishable from vector 001 — passing under MCP is not evidence\n // the edge was tested. Skip with a distinct reason so the report doesn't\n // claim coverage it didn't deliver.\n if (kind === 'positive' && options.transport === 'mcp' && MCP_FLATTENED_VECTORS.has(vector.id)) {\n return {\n ...base,\n skipped: true,\n skip_reason: 'mcp_mode_flattens_url_edges',\n diagnostic:\n `Vector ${vector.id} tests a URL-canonicalization edge (port/path/query/encoding) ` +\n `that MCP mode neutralizes by routing every vector to the MCP endpoint. ` +\n `Grade this edge with \\`--transport raw\\` against a per-operation AdCP agent.`,\n };\n }\n if (kind === 'negative') {\n const neg = vector as NegativeVector;\n if (neg.requires_contract === 'rate_abuse' && options.skipRateAbuse) {\n return { ...base, skipped: true, skip_reason: 'rate_abuse_opt_out' };\n }\n if (neg.requires_contract && !contract) {\n return {\n ...base,\n skipped: true,\n skip_reason: 'missing_test_kit_contract',\n diagnostic:\n 'Stateful vector requires `test-kits/signed-requests-runner.yaml` in the compliance cache. Run `npm run sync-schemas`.',\n };\n }\n // Sandbox opt-in: vectors 016 (replay_window) and 020 (rate_abuse) produce\n // live side effects on the agent. Refuse to run unless the contract says\n // sandbox OR the operator explicitly accepts the side effects.\n if (\n (neg.requires_contract === 'replay_window' || neg.requires_contract === 'rate_abuse') &&\n !options.allowLiveSideEffects &&\n contract?.endpoint_scope !== 'sandbox'\n ) {\n return {\n ...base,\n skipped: true,\n skip_reason: 'live_side_effect_opt_in_required',\n diagnostic:\n `Vector ${vector.id} produces live agent-side effects. Pass allowLiveSideEffects: true ` +\n `(or point the grader at an endpoint whose signed-requests-runner contract declares ` +\n `endpoint_scope: sandbox) to run it.`,\n };\n }\n }\n return undefined;\n}\n\n/**\n * Grade a single vector. Loads the vectors+keys+contract on every call; for\n * the storyboard-runner dispatch path where the caller runs many vectors in\n * sequence, prefer `gradeRequestSigning` which loads once.\n */\nexport async function gradeOneVector(\n vectorId: string,\n kind: 'positive' | 'negative',\n agentUrl: string,\n options: GradeOptions = {}\n): Promise<VectorGradeResult> {\n const loaded = loadRequestSigningVectors(options);\n const contract = loadSignedRequestsRunnerContract(options);\n const probeOpts = {\n allowPrivateIp: options.allowPrivateIp === true,\n timeoutMs: options.timeoutMs,\n };\n const buildOpts: BuildOptions = { baseUrl: agentUrl, transport: options.transport ?? 'raw' };\n\n const vector =\n kind === 'positive' ? loaded.positive.find(v => v.id === vectorId) : loaded.negative.find(v => v.id === vectorId);\n if (!vector) throw new Error(`Unknown ${kind} vector \"${vectorId}\"`);\n\n const skip = preflightSkip(vector, kind, contract, options);\n if (skip) return skip;\n\n if (kind === 'positive') {\n const signed = buildPositiveRequest(vector as PositiveVector, loaded.keys, buildOpts);\n const probe = await probeSignedRequest(signed, probeOpts);\n return gradePositive(vector as PositiveVector, probe);\n }\n return gradeNegative(vector as NegativeVector, loaded, contract, probeOpts, buildOpts, options);\n}\n\n// ── Phase helpers ─────────────────────────────────────────────\n\nfunction gradePositive(vector: PositiveVector, probe: ProbeResult): VectorGradeResult {\n const accepted = probe.status >= 200 && probe.status < 300;\n return {\n vector_id: vector.id,\n kind: 'positive',\n passed: accepted && !probe.error,\n http_status: probe.status,\n diagnostic: accepted ? undefined : buildPositiveDiagnostic(vector, probe),\n probe_duration_ms: probe.duration_ms,\n };\n}\n\nfunction buildPositiveDiagnostic(vector: PositiveVector, probe: ProbeResult): string {\n if (probe.error) return `probe error: ${probe.error}`;\n const expected = 'a 2xx status';\n const sigError = probe.wwwAuthenticateErrorCode;\n if (sigError) {\n return `expected ${expected}, got ${probe.status} with WWW-Authenticate error=\"${sigError}\" — signer or agent-side JWKS likely mismatched. Vector: ${vector.name}`;\n }\n return `expected ${expected}, got ${probe.status}. Vector: ${vector.name}`;\n}\n\nasync function gradeNegative(\n vector: NegativeVector,\n loaded: ReturnType<typeof loadRequestSigningVectors>,\n contract: SignedRequestsRunnerContract | undefined,\n probeOpts: { allowPrivateIp: boolean; timeoutMs?: number },\n buildOpts: BuildOptions,\n options: GradeOptions\n): Promise<VectorGradeResult> {\n if (vector.jwks_override) {\n return gradeJwksOverrideNegative(vector);\n }\n switch (vector.requires_contract) {\n case 'replay_window':\n return gradeReplayWindow(vector, loaded, probeOpts, buildOpts, options.replayProbePairs ?? 10);\n case 'rate_abuse':\n return gradeRateAbuse(vector, loaded, contract!, probeOpts, buildOpts, options);\n case 'revocation':\n default:\n return gradeStaticNegative(vector, loaded, probeOpts, buildOpts);\n }\n}\n\n/**\n * Grade vectors that ship an inline `jwks_override` against the library\n * verifier directly. The agent's JWKS can't be mutated per-vector at probe\n * time, so a black-box HTTP grade can't surface these failure modes.\n * Grading the library verifier is the only path that exercises what the\n * vector is testing — the inline JWK's kty/crv/alg consistency rules.\n */\nasync function gradeJwksOverrideNegative(vector: NegativeVector): Promise<VectorGradeResult> {\n const override = vector.jwks_override!;\n const start = Date.now();\n const jwks = new StaticJwksResolver(override.keys as unknown as AdcpJsonWebKey[]);\n const replayStore = new InMemoryReplayStore();\n const revocationStore = new InMemoryRevocationStore();\n const operation = new URL(vector.request.url).pathname.split('/').filter(Boolean).pop() ?? '';\n try {\n await verifyRequestSignature(vector.request, {\n capability: vector.verifier_capability,\n jwks,\n replayStore,\n revocationStore,\n now: () => vector.reference_now,\n operation,\n });\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed: false,\n http_status: 0,\n expected_error_code: vector.expected_error_code,\n diagnostic: `library verifier accepted a request expected to fail with error=\"${vector.expected_error_code}\"`,\n probe_duration_ms: Date.now() - start,\n };\n } catch (err) {\n if (err instanceof RequestSignatureError) {\n const passed = err.code === vector.expected_error_code;\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed,\n http_status: 0,\n expected_error_code: vector.expected_error_code,\n actual_error_code: err.code,\n diagnostic: passed\n ? undefined\n : `library verifier rejected with error=\"${err.code}\" but vector expects \"${vector.expected_error_code}\"`,\n probe_duration_ms: Date.now() - start,\n };\n }\n throw err;\n }\n}\n\nfunction gradeStaticNegative(\n vector: NegativeVector,\n loaded: ReturnType<typeof loadRequestSigningVectors>,\n probeOpts: { allowPrivateIp: boolean; timeoutMs?: number },\n buildOpts: BuildOptions\n): Promise<VectorGradeResult> {\n const signed = buildNegativeRequest(vector, loaded.keys, buildOpts);\n return probeSignedRequest(signed, probeOpts).then(probe => ({\n vector_id: vector.id,\n kind: 'negative',\n passed: negativeAcceptedErrorCode(vector, probe),\n http_status: probe.status,\n expected_error_code: vector.expected_error_code,\n actual_error_code: probe.wwwAuthenticateErrorCode,\n diagnostic: buildNegativeDiagnostic(vector, probe),\n probe_duration_ms: probe.duration_ms,\n }));\n}\n\nasync function gradeReplayWindow(\n vector: NegativeVector,\n loaded: ReturnType<typeof loadRequestSigningVectors>,\n probeOpts: { allowPrivateIp: boolean; timeoutMs?: number },\n buildOpts: BuildOptions,\n pairCount: number\n): Promise<VectorGradeResult> {\n // Run pairCount independent (probe1, probe2) pairs. Each pair uses a fresh\n // nonce so pair N's probe1 doesn't consume pair N+1's replay-window slot.\n // probeSignedRequest already closes its undici Agent on completion, so each\n // call gets a new TCP connection — no keep-alive pinning to the same upstream.\n let totalDurationMs = 0;\n let rejectedCount = 0;\n let lastSecondStatus = 0;\n let lastSecondErrorCode: string | undefined;\n\n for (let i = 0; i < pairCount; i++) {\n const nonce = randomBytes(16).toString('base64url');\n const signed = buildPositiveRequestFromNegative(vector, loaded, { ...buildOpts, nonce });\n\n const first = await probeSignedRequest(signed, probeOpts);\n totalDurationMs += first.duration_ms;\n\n if (first.status < 200 || first.status >= 300) {\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed: false,\n http_status: first.status,\n expected_error_code: vector.expected_error_code,\n actual_error_code: first.wwwAuthenticateErrorCode,\n diagnostic:\n `replay_window contract: first submission MUST be accepted but agent returned ${first.status}` +\n (first.wwwAuthenticateErrorCode ? ` (error=\"${first.wwwAuthenticateErrorCode}\")` : '') +\n '. Check runner JWKS registration with the agent.',\n probe_duration_ms: totalDurationMs,\n replay_pairs_tried: i + 1,\n replay_pairs_rejected: rejectedCount,\n };\n }\n\n const second = await probeSignedRequest(signed, probeOpts);\n totalDurationMs += second.duration_ms;\n lastSecondStatus = second.status;\n lastSecondErrorCode = second.wwwAuthenticateErrorCode;\n\n if (negativeAcceptedErrorCode(vector, second)) {\n rejectedCount++;\n }\n }\n\n if (rejectedCount === pairCount) {\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed: true,\n http_status: lastSecondStatus,\n expected_error_code: vector.expected_error_code,\n actual_error_code: lastSecondErrorCode,\n probe_duration_ms: totalDurationMs,\n replay_pairs_tried: pairCount,\n replay_pairs_rejected: pairCount,\n };\n }\n\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed: false,\n http_status: lastSecondStatus,\n expected_error_code: vector.expected_error_code,\n actual_error_code: lastSecondErrorCode,\n diagnostic: buildReplayWindowFailDiagnostic(vector, rejectedCount, pairCount),\n probe_duration_ms: totalDurationMs,\n replay_pairs_tried: pairCount,\n replay_pairs_rejected: rejectedCount,\n };\n}\n\nfunction buildReplayWindowFailDiagnostic(vector: NegativeVector, rejectedCount: number, pairCount: number): string {\n if (rejectedCount === 0) {\n return (\n `expected 401 with error=\"${vector.expected_error_code}\" on replayed nonce, but all ${pairCount} probe ` +\n `pairs were accepted (got 200 on second submission every time). Verifier has no replay protection for this nonce. ` +\n `If your verifier runs more than one process or machine instance, confirm the replay store is shared across ` +\n `the pool — the default \\`InMemoryReplayStore\\` is per-process. For distributed deployments use ` +\n `\\`PostgresReplayStore\\` from \\`@adcp/sdk/signing/server\\` or a Redis-backed \\`ReplayStore\\` ` +\n `implementation. See https://github.com/adcontextprotocol/adcp-client/pull/1018`\n );\n }\n return (\n `${rejectedCount} of ${pairCount} probe pairs were correctly rejected; ` +\n `${pairCount - rejectedCount} pair(s) had the second submission accepted. ` +\n `This is the classic multi-instance \\`InMemoryReplayStore\\` pattern — the two probes in an ` +\n `accepted pair landed on different load-balanced instances, each with its own per-process replay store. ` +\n `For distributed deployments use \\`PostgresReplayStore\\` from \\`@adcp/sdk/signing/server\\` ` +\n `or a Redis-backed \\`ReplayStore\\` implementation so all instances share one replay cache. ` +\n `See https://github.com/adcontextprotocol/adcp-client/pull/1018`\n );\n}\n\nasync function gradeRateAbuse(\n vector: NegativeVector,\n loaded: ReturnType<typeof loadRequestSigningVectors>,\n contract: SignedRequestsRunnerContract,\n probeOpts: { allowPrivateIp: boolean; timeoutMs?: number },\n buildOpts: BuildOptions,\n options: GradeOptions\n): Promise<VectorGradeResult> {\n const cap =\n options.rateAbuseCap ?? contract.stateful_vector_contract.rate_abuse.grading_target_per_keyid_cap_requests;\n // Fill the cap with cap distinct-nonce requests, then probe one more — that\n // (cap+1)th request is what the vector expects to be rejected.\n let durationMs = 0;\n for (let i = 0; i < cap; i++) {\n const nonce = randomBytes(16).toString('base64url');\n const signed = buildNegativeRequest(vector, loaded.keys, { nonce, ...buildOpts });\n const probe = await probeSignedRequest(signed, probeOpts);\n durationMs += probe.duration_ms;\n }\n const finalNonce = randomBytes(16).toString('base64url');\n const capPlusOne = buildNegativeRequest(vector, loaded.keys, { nonce: finalNonce, ...buildOpts });\n const probe = await probeSignedRequest(capPlusOne, probeOpts);\n durationMs += probe.duration_ms;\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed: negativeAcceptedErrorCode(vector, probe),\n http_status: probe.status,\n expected_error_code: vector.expected_error_code,\n actual_error_code: probe.wwwAuthenticateErrorCode,\n diagnostic: buildNegativeDiagnostic(vector, probe),\n probe_duration_ms: durationMs,\n };\n}\n\nfunction buildPositiveRequestFromNegative(\n vector: NegativeVector,\n loaded: ReturnType<typeof loadRequestSigningVectors>,\n options: BuildOptions & { nonce: string }\n): SignedHttpRequest {\n // Vector 016 is structurally identical to positive/001 — sign it as a positive.\n const pseudoPositive: PositiveVector = {\n kind: 'positive',\n id: vector.id,\n name: vector.name,\n reference_now: vector.reference_now,\n request: vector.request,\n verifier_capability: vector.verifier_capability,\n jwks_ref: vector.jwks_ref,\n jwks_override: vector.jwks_override,\n };\n return buildPositiveRequest(pseudoPositive, loaded.keys, options);\n}\n\nfunction negativeAcceptedErrorCode(vector: NegativeVector, probe: ProbeResult): boolean {\n return probe.status === 401 && probe.wwwAuthenticateErrorCode === vector.expected_error_code;\n}\n\n/**\n * Inspect the vector's `Signature-Input` header to determine whether the\n * signed components cover `content-digest`. Returns `undefined` when the\n * header is absent or unparseable — the vector exercises a no-signature or\n * malformed-header failure path, so the digest shape check doesn't apply\n * (the verifier short-circuits before the components check).\n *\n * Header lookup is canonical-PascalCase + lowercase only. Test fixtures\n * use canonical PascalCase headers; this isn't a general-purpose\n * header-name normalizer.\n */\nfunction vectorSignsContentDigest(vector: PositiveVector | NegativeVector): boolean | undefined {\n const headers = vector.request.headers;\n const sigInput = headers['Signature-Input'] ?? headers['signature-input'];\n if (!sigInput) return undefined;\n try {\n const parsed = parseSignatureInput(sigInput);\n return parsed.components.includes('content-digest');\n } catch {\n return undefined;\n }\n}\n\n/**\n * Return a diagnostic when the vector's actual signed shape is\n * structurally incompatible with `agentCoversContentDigest` — i.e. the\n * verifier rejects the request shape before the vector's intended error\n * path can fire. Returns `undefined` when the shapes can coexist (or the\n * vector exercises a header-absent/malformed path where this check\n * doesn't apply).\n */\nfunction contentDigestStructuralMismatch(\n vector: PositiveVector | NegativeVector,\n agentCoversContentDigest: 'required' | 'forbidden' | 'either'\n): string | undefined {\n const signsCd = vectorSignsContentDigest(vector);\n if (signsCd === undefined) return undefined;\n if (signsCd && agentCoversContentDigest === 'forbidden') {\n return (\n `Vector's Signature-Input covers content-digest but agent declares ` +\n `covers_content_digest='forbidden'. The verifier rejects with ` +\n `request_signature_components_unexpected before the vector's intended ` +\n `error path can fire.`\n );\n }\n if (!signsCd && agentCoversContentDigest === 'required') {\n return (\n `Vector's Signature-Input does not cover content-digest but agent declares ` +\n `covers_content_digest='required'. The verifier rejects with ` +\n `request_signature_components_incomplete before the vector's intended ` +\n `error path can fire.`\n );\n }\n return undefined;\n}\n\n/**\n * Capability-profile mismatch resolver used when the operator passes\n * `agentContentDigestPolicy` without a full `agentCapability` fixture.\n * Combines two checks:\n * - Declared-policy check (negatives only): a negative vector that\n * asserts a strict policy the agent didn't advertise can't surface\n * its intended error path — the agent never rejects the shape the\n * vector is exercising. Positives are unaffected because acceptance\n * under a permissive agent still demonstrates the verifier's\n * acceptance contract.\n * - Structural shape check (positives and negatives): the vector's\n * actual `Signature-Input` shape must coexist with the agent's\n * policy — otherwise the verifier short-circuits with a\n * `request_signature_components_*` error before any other path can\n * fire.\n */\nfunction contentDigestPolicyMismatch(\n vector: PositiveVector | NegativeVector,\n kind: 'positive' | 'negative',\n agentPolicy: 'required' | 'forbidden' | 'either'\n): string | undefined {\n if (kind === 'negative') {\n const vectorCd = vector.verifier_capability.covers_content_digest;\n if (vectorCd !== 'either' && vectorCd !== agentPolicy) {\n return (\n `Vector asserts covers_content_digest='${vectorCd}' but agent declares '${agentPolicy}'. ` +\n `The agent's policy is incompatible with the vector's expected verifier behavior.`\n );\n }\n }\n return contentDigestStructuralMismatch(vector, agentPolicy);\n}\n\n/**\n * Compare a vector's `verifier_capability` fixture and actual signed shape\n * against the agent's declared capability profile. Returns a\n * human-readable diagnostic when the vector can't grade against this\n * profile — or `undefined` when the vector is gradable.\n *\n * Rules (all four must hold for a graded run):\n * - `supported`: must match. A vector with `supported: true` doesn't\n * grade against an agent that declares `supported: false` (the\n * conformance storyboard already skips such agents outright, but\n * defense-in-depth).\n * - `covers_content_digest`: asymmetric. Vector-side `'either'` is\n * permissive only at the declaration level — the structural shape\n * check below still applies. Agent-side `'either'` is NOT permissive\n * against a strict vector — an agent that declares `'either'`\n * accepts covered AND uncovered requests, so it can't pass vectors\n * 007 (`'required'`) or 018 (`'forbidden'`). Those auto-skip with\n * `capability_profile_mismatch`.\n * - structural shape: the vector's actual `Signature-Input` must\n * coexist with the agent's policy regardless of what\n * `verifier_capability.covers_content_digest` declares. A vector\n * signing without `content-digest` can't grade a `'required'`\n * verifier; a vector signing with `content-digest` can't grade a\n * `'forbidden'` verifier. Either short-circuits with a\n * `request_signature_components_*` error before the vector's\n * intended assertion fires.\n * - `required_for` / `protocol_methods_required_for`: if the vector\n * asserts a required_for operation or method, the agent's\n * `required_for` / `protocol_methods_required_for` must include it.\n * The reverse is fine — an agent that requires MORE operations is\n * still conformant against a vector that asserts fewer.\n */\nfunction capabilityMismatch(\n vector: PositiveVector | NegativeVector,\n agentCap: VerifierCapabilityFixture\n): string | undefined {\n const vectorCap = vector.verifier_capability;\n if (vectorCap.supported !== agentCap.supported) {\n return (\n `Vector asserts supported=${vectorCap.supported} but agent declares supported=${agentCap.supported}. ` +\n `Verify the agent's request_signing capability block.`\n );\n }\n // `covers_content_digest` asymmetry: vector-side `'either'` is\n // permissive only if the vector's actual signed shape is compatible\n // with the agent's policy (handled by the structural check below).\n // Agent-side `'either'` is NOT permissive against a strict vector —\n // an agent that declares `'either'` accepts requests with OR without\n // Content-Digest, so vector 007's \"MUST reject uncovered request\"\n // and vector 018's \"MUST reject covered-when-forbidden\" are\n // structurally incompatible with the agent's stance.\n if (\n vectorCap.covers_content_digest !== 'either' &&\n vectorCap.covers_content_digest !== agentCap.covers_content_digest\n ) {\n return (\n `Vector asserts covers_content_digest='${vectorCap.covers_content_digest}' but agent declares '${agentCap.covers_content_digest}'. ` +\n `The vector can't grade against this profile — its expected verifier behavior doesn't match what the agent implements.`\n );\n }\n // Structural shape check: even when vectorCap is permissive (`'either'`),\n // the vector's actual `Signature-Input` either covers `content-digest` or\n // not. A `'required'` verifier rejects every uncovered request with\n // `request_signature_components_incomplete`; a `'forbidden'` verifier\n // rejects every covered request with `request_signature_components_unexpected`.\n // Both fire before the vector's intended error path, masking the result.\n const structural = contentDigestStructuralMismatch(vector, agentCap.covers_content_digest);\n if (structural) return structural;\n // `required_for` on the vector: every op the vector expects to be\n // required must also be required by the agent. Otherwise a negative\n // vector (e.g., missing signature on `create_media_buy`) would test a\n // rejection path the agent didn't opt into.\n const vectorRequiredFor = vectorCap.required_for ?? [];\n const agentRequiredForSet = new Set(agentCap.required_for ?? []);\n const missingRequiredFor = vectorRequiredFor.filter(op => !agentRequiredForSet.has(op));\n if (missingRequiredFor.length > 0) {\n return (\n `Vector asserts required_for includes [${missingRequiredFor.join(', ')}] but agent's required_for does not. ` +\n `Either add the operation to the agent's request_signing.required_for, or accept the skip.`\n );\n }\n // Same check for `protocol_methods_required_for` (adcp#4326 namespace).\n // Negative vectors that grade JSON-RPC protocol methods (e.g. unsigned\n // `tasks/cancel`) auto-skip when the agent doesn't declare the bucket —\n // matching the behavior of `required_for` for AdCP-tool vectors.\n const vectorProtocolMethodsRequiredFor = vectorCap.protocol_methods_required_for ?? [];\n const agentProtocolMethodsRequiredForSet = new Set(agentCap.protocol_methods_required_for ?? []);\n const missingProtocolMethodsRequiredFor = vectorProtocolMethodsRequiredFor.filter(\n method => !agentProtocolMethodsRequiredForSet.has(method)\n );\n if (missingProtocolMethodsRequiredFor.length > 0) {\n return (\n `Vector asserts protocol_methods_required_for includes [${missingProtocolMethodsRequiredFor.join(', ')}] ` +\n `but agent's protocol_methods_required_for does not. Either add the method to the agent's ` +\n `request_signing.protocol_methods_required_for, or accept the skip.`\n );\n }\n return undefined;\n}\n\nfunction buildNegativeDiagnostic(vector: NegativeVector, probe: ProbeResult): string | undefined {\n if (probe.error) return `probe error: ${probe.error}`;\n if (probe.status === 401 && probe.wwwAuthenticateErrorCode === vector.expected_error_code) {\n return undefined;\n }\n const actual = probe.wwwAuthenticateErrorCode ?? '(none)';\n if (probe.status !== 401) {\n return `expected 401 with error=\"${vector.expected_error_code}\", got ${probe.status} (error=\"${actual}\"). Vector: ${vector.name}`;\n }\n return `expected error=\"${vector.expected_error_code}\", got error=\"${actual}\". Check verifier step ordering — several vectors (015/017/020) depend on revocation/cap checks firing BEFORE crypto verify.`;\n}\n"],"mappings":"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","names":["probe"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/grader.ts"],"sourcesContent":["import { randomBytes } from 'crypto';\nimport { buildNegativeRequest, buildPositiveRequest, type BuildOptions, type SignedHttpRequest } from './builder';\nimport { probeSignedRequest, type ProbeResult } from './probe';\nimport { loadRequestSigningVectors, type LoadVectorsOptions } from './vector-loader';\nimport { loadSignedRequestsRunnerContract, type SignedRequestsRunnerContract } from './test-kit';\nimport {\n InMemoryReplayStore,\n InMemoryRevocationStore,\n RequestSignatureError,\n StaticJwksResolver,\n verifyRequestSignature,\n type AdcpJsonWebKey,\n} from '../../../signing';\nimport { parseSignatureInput } from '../../../signing/parser';\nimport type { NegativeVector, PositiveVector, VerifierCapabilityFixture } from './types';\n\nexport interface GradeOptions extends LoadVectorsOptions {\n /** Allow http:// and private-IP destinations. Off by default (match fetchProbe). */\n allowPrivateIp?: boolean;\n /** Skip the rate-abuse vector (it sends 100+ requests; slow). Defaults to false. */\n skipRateAbuse?: boolean;\n /**\n * Override the rate-abuse cap the grader targets. Defaults to the contract's\n * `grading_target_per_keyid_cap_requests`. Agents that advertise a smaller\n * per-keyid cap for the test counterparty MAY lower this so grading finishes\n * in a reasonable time — see test-kits/signed-requests-runner.yaml.\n */\n rateAbuseCap?: number;\n /**\n * Vector IDs to skip for operator-driven reasons (SDK-internal vectors,\n * environment-specific quirks, etc.). Capability-profile mismatches\n * don't belong here — pass {@link agentCapability} and the grader auto-\n * skips vectors whose `verifier_capability` can't match the agent.\n */\n skipVectors?: string[];\n /**\n * Agent's declared `request_signing` capability block — exactly the shape\n * in `get_adcp_capabilities.response.request_signing`. When provided, the\n * grader pre-flights every vector's `verifier_capability` against this\n * profile and auto-skips any vector that asserts a policy the agent\n * didn't advertise (e.g., vector 007 requires `covers_content_digest:\n * 'required'`; agent declares `'either'` — auto-skipped with\n * `skip_reason: 'capability_profile_mismatch'`). The grader also parses\n * each vector's `Signature-Input` and auto-skips vectors whose actual\n * signed components are structurally incompatible with the agent's\n * policy (uncovered `content-digest` against a `'required'` verifier,\n * or covered `content-digest` against a `'forbidden'` verifier).\n *\n * Without this option, every vector runs and cap-profile mismatches\n * produce failed vectors that the operator has to manually translate\n * into `skipVectors` entries — fragile and easy to get wrong per\n * profile. Set `agentCapability` and `skipVectors` collapses to just\n * the handful of operator-specific overrides (like vector 025, which\n * exercises the SDK library rather than the agent).\n */\n agentCapability?: VerifierCapabilityFixture;\n /**\n * When set, run only the named vector ids (all others auto-skip). Takes\n * precedence over `skipVectors`. Useful for isolated regression tests\n * against a single vector without hand-maintaining an inverted skip list.\n */\n onlyVectors?: string[];\n /**\n * Opt in to running vectors that produce live agent-side effects — vector\n * 016 (replay_window) sends a valid `create_media_buy`-shaped request the\n * agent will accept, and vector 020 (rate_abuse) floods cap+1 requests.\n * Required unless the test-kit contract declares `endpoint_scope: sandbox`\n * (in which case the agent asserts the operation is side-effect-free).\n * Default: false — side-effectful vectors auto-skip against non-sandbox\n * endpoints.\n */\n allowLiveSideEffects?: boolean;\n /**\n * Agent's declared `covers_content_digest` policy from\n * `get_adcp_capabilities.request_signing.covers_content_digest`. When set\n * without `agentCapability`, the grader auto-skips both positive and\n * negative vectors whose signature shape is structurally incompatible\n * with the agent's policy:\n *\n * - Vectors whose `verifier_capability.covers_content_digest` asserts\n * a strict policy the agent didn't advertise (e.g. `'either'` →\n * skips neg/007 (`'required'`) and neg/018 (`'forbidden'`)).\n * - Vectors whose actual `Signature-Input` covers `content-digest`\n * against a `'forbidden'` agent (rejected with\n * `request_signature_components_unexpected` before the intended\n * error path).\n * - Vectors whose actual `Signature-Input` does not cover\n * `content-digest` against a `'required'` agent (rejected with\n * `request_signature_components_incomplete` before the intended\n * error path).\n *\n * Skipped vectors use `skip_reason: 'capability_profile_mismatch'`.\n *\n * Has no effect when `agentCapability` is provided — the full\n * capability fixture's `covers_content_digest` field governs via\n * `capabilityMismatch()`, which performs the same shape check. Use\n * `agentCapability` when you also need `required_for` skip behavior.\n */\n agentContentDigestPolicy?: 'required' | 'forbidden' | 'either';\n /**\n * Transport shape the agent speaks. `'raw'` (default) POSTs per-operation\n * AdCP endpoints matching the vectors' URL shape. `'mcp'` wraps each\n * vector body in a JSON-RPC `tools/call` envelope and POSTs to the MCP\n * mount path (`agentUrl`) — use when grading an MCP agent whose verifier\n * sits as transport-layer middleware ahead of MCP dispatch.\n *\n * See adcontextprotocol/adcp-client#612 for the MCP-mode rationale.\n */\n transport?: 'raw' | 'mcp';\n /**\n * Override the agent's base URL used for the grader's HTTP targets. When set,\n * each vector's `request.url` is rewritten by swapping origin+path under this\n * base — useful when the vectors point at `seller.example.com` but the agent\n * is reachable at a sandbox URL.\n */\n agentUrl?: string;\n /** Per-probe timeout. Default 10s. */\n timeoutMs?: number;\n /**\n * Number of (probe1, probe2) pairs to run for vector neg/016\n * (replayed-nonce). Each pair uses a fresh nonce and a new TCP\n * connection, so on a multi-instance deployment the two probes\n * may land on different instances. K pairs make the failure\n * deterministic: if any second probe is accepted the count and\n * the cross-instance hypothesis surface in the diagnostic.\n * Must be ≥ 2. Default 10.\n */\n replayProbePairs?: number;\n}\n\nexport interface VectorGradeResult {\n vector_id: string;\n kind: 'positive' | 'negative';\n passed: boolean;\n skipped?: boolean;\n skip_reason?: string;\n /** For negatives: the error code the agent returned (from WWW-Authenticate). */\n actual_error_code?: string;\n /** For negatives: the error code the spec says we should see. */\n expected_error_code?: string;\n http_status: number;\n diagnostic?: string;\n probe_duration_ms: number;\n /**\n * For neg/016 (replayed-nonce) only: total number of (probe1, probe2)\n * pairs attempted by the K-pair grader.\n */\n replay_pairs_tried?: number;\n /**\n * For neg/016 (replayed-nonce) only: number of pairs where the second\n * probe was correctly rejected with `request_signature_replayed`.\n * Equal to `replay_pairs_tried` on a passing run.\n */\n replay_pairs_rejected?: number;\n}\n\nexport interface GradeReport {\n agent_url: string;\n harness_mode: 'black_box';\n /**\n * `true` when the test-kit contract declares an endpoint_scope other than\n * `sandbox` — vectors 016 and 020 produce live side effects (a real\n * `create_media_buy` for 016, cap+1 flooding for 020). Treat as a warning\n * to the operator.\n */\n live_endpoint_warning: boolean;\n contract_loaded: boolean;\n positive: VectorGradeResult[];\n negative: VectorGradeResult[];\n passed: boolean;\n passed_count: number;\n failed_count: number;\n skipped_count: number;\n total_duration_ms: number;\n}\n\n/**\n * Grade an agent's RFC 9421 verifier against the 28 conformance vectors.\n *\n * Preconditions the caller owns:\n * - Agent advertises `request_signing.supported: true` in `get_adcp_capabilities`.\n * - Agent has pre-configured its verifier per `test-kits/signed-requests-runner.yaml`:\n * - Runner's signing keyids (`test-ed25519-2026`, `test-es256-2026`) accepted.\n * - `test-revoked-2026` pre-revoked.\n * - Per-keyid rate cap within grading_target_per_keyid_cap_requests.\n * - `agentUrl` targets a sandbox endpoint — the replay-window contract sends\n * a live valid request that will be accepted before the second (rejected)\n * copy fires.\n */\nexport async function gradeRequestSigning(agentUrl: string, options: GradeOptions = {}): Promise<GradeReport> {\n const start = Date.now();\n const loaded = loadRequestSigningVectors(options);\n const contract = loadSignedRequestsRunnerContract(options);\n\n const probeOpts = {\n allowPrivateIp: options.allowPrivateIp === true,\n timeoutMs: options.timeoutMs,\n };\n\n const buildOpts: BuildOptions = { baseUrl: agentUrl, transport: options.transport ?? 'raw' };\n\n const positive: VectorGradeResult[] = [];\n for (const vector of loaded.positive) {\n const skip = preflightSkip(vector, 'positive', contract, options);\n if (skip) {\n positive.push(skip);\n continue;\n }\n const signed = buildPositiveRequest(vector, loaded.keys, buildOpts);\n const probed = await probeSignedRequest(signed, probeOpts);\n positive.push(gradePositive(vector, probed));\n }\n\n const negative: VectorGradeResult[] = [];\n for (const vector of loaded.negative) {\n const skip = preflightSkip(vector, 'negative', contract, options);\n if (skip) {\n negative.push(skip);\n continue;\n }\n negative.push(await gradeNegative(vector, loaded, contract, probeOpts, buildOpts, options));\n }\n\n const all = [...positive, ...negative];\n const passed_count = all.filter(r => r.passed && !r.skipped).length;\n const skipped_count = all.filter(r => r.skipped).length;\n const failed_count = all.filter(r => !r.passed && !r.skipped).length;\n const passed = failed_count === 0;\n\n return {\n agent_url: agentUrl,\n harness_mode: 'black_box',\n // Default to TRUE when no contract is loaded — we can't prove the endpoint\n // is sandbox, so warn the operator that 016/020 could produce live side\n // effects. Only FALSE when a contract is loaded AND declares sandbox.\n live_endpoint_warning: !contract || contract.endpoint_scope !== 'sandbox',\n contract_loaded: Boolean(contract),\n positive,\n negative,\n passed,\n passed_count,\n failed_count,\n skipped_count,\n total_duration_ms: Date.now() - start,\n };\n}\n\n// Positive vectors whose edge-case coverage survives only under raw transport\n// (per-operation endpoint URLs). Listed explicitly rather than heuristically\n// so a spec author adding a new canonicalization-edge vector has to opt into\n// the skip.\nconst MCP_FLATTENED_VECTORS = new Set([\n '005-default-port-stripped',\n '006-dot-segment-path',\n '007-query-byte-preserved',\n '008-percent-encoded-path',\n]);\n\n// Vectors whose failure mode can't reach a live agent through HTTP. Document\n// why each entry can't be graded via probe so adding a new entry isn't a\n// silent coverage loss.\nconst TRANSPORT_UNGRADABLE: Record<string, string> = {\n // fetch() and the Node URL parser normalize U-labels to A-labels before\n // the request leaves the client. A raw non-ASCII Host header reaches the\n // agent as Punycode, defeating the parse-time check. Direct verifier\n // tests exercise this edge.\n '026-non-ascii-host':\n 'HTTP transport punycodes U-labels before the request leaves the client; verified at the library level.',\n};\n\n/**\n * Centralized skip decisions. Checks (in order): onlyVectors filter,\n * operator skipVectors, agent-capability-profile mismatch\n * (`agentCapability` wired), transport-ungradable, MCP-mode URL-edge\n * flattening, rate-abuse opt-out, stateful-contract missing, and the\n * live-side-effect gate.\n */\nfunction preflightSkip(\n vector: PositiveVector | NegativeVector,\n kind: 'positive' | 'negative',\n contract: SignedRequestsRunnerContract | undefined,\n options: GradeOptions\n): VectorGradeResult | undefined {\n const expected_error_code = kind === 'negative' ? (vector as NegativeVector).expected_error_code : undefined;\n const base = {\n vector_id: vector.id,\n kind,\n passed: true, // skipped ≠ failed; overall pass/fail excludes skipped\n http_status: 0,\n probe_duration_ms: 0,\n ...(expected_error_code ? { expected_error_code } : {}),\n } as const;\n\n if (options.onlyVectors && !options.onlyVectors.includes(vector.id)) {\n return { ...base, skipped: true, skip_reason: 'not_in_only_vectors' };\n }\n if (options.skipVectors?.includes(vector.id)) {\n return { ...base, skipped: true, skip_reason: 'operator_skip' };\n }\n if (options.agentCapability) {\n const mismatch = capabilityMismatch(vector, options.agentCapability);\n if (mismatch) {\n // Surface the mismatch in the diagnostic so operators can audit\n // which vectors were dodged. An agent that under-declares its\n // capability (claims `required_for: []` while it actually\n // enforces on multiple ops) would hide negative-vector failures\n // here — the operator needs to see the skip count to catch that\n // pattern. The caller inspects `report.skipped_count` plus the\n // individual `skip_reason`/`diagnostic` pairs.\n return {\n ...base,\n skipped: true,\n skip_reason: 'capability_profile_mismatch',\n diagnostic: mismatch,\n };\n }\n }\n if (!options.agentCapability && options.agentContentDigestPolicy) {\n const policyMismatch = contentDigestPolicyMismatch(vector, kind, options.agentContentDigestPolicy);\n if (policyMismatch) {\n return {\n ...base,\n skipped: true,\n skip_reason: 'capability_profile_mismatch',\n diagnostic: policyMismatch,\n };\n }\n }\n const transportReason = TRANSPORT_UNGRADABLE[vector.id];\n if (transportReason) {\n return { ...base, skipped: true, skip_reason: 'transport_ungradable', diagnostic: transportReason };\n }\n // Canonicalization-edge positive vectors (005–008) bake their edge case\n // into the vector URL path, query, or port. MCP mode flattens every vector\n // to the same baseUrl (JSON-RPC single endpoint), so these vectors become\n // indistinguishable from vector 001 — passing under MCP is not evidence\n // the edge was tested. Skip with a distinct reason so the report doesn't\n // claim coverage it didn't deliver.\n if (kind === 'positive' && options.transport === 'mcp' && MCP_FLATTENED_VECTORS.has(vector.id)) {\n return {\n ...base,\n skipped: true,\n skip_reason: 'mcp_mode_flattens_url_edges',\n diagnostic:\n `Vector ${vector.id} tests a URL-canonicalization edge (port/path/query/encoding) ` +\n `that MCP mode neutralizes by routing every vector to the MCP endpoint. ` +\n `Grade this edge with \\`--transport raw\\` against a per-operation AdCP agent.`,\n };\n }\n if (kind === 'negative') {\n const neg = vector as NegativeVector;\n if (neg.requires_contract === 'rate_abuse' && options.skipRateAbuse) {\n return { ...base, skipped: true, skip_reason: 'rate_abuse_opt_out' };\n }\n if (neg.requires_contract && !contract) {\n return {\n ...base,\n skipped: true,\n skip_reason: 'missing_test_kit_contract',\n diagnostic:\n 'Stateful vector requires `test-kits/signed-requests-runner.yaml` in the compliance cache. Run `npm run sync-schemas`.',\n };\n }\n // Sandbox opt-in: vectors 016 (replay_window) and 020 (rate_abuse) produce\n // live side effects on the agent. Refuse to run unless the contract says\n // sandbox OR the operator explicitly accepts the side effects.\n if (\n (neg.requires_contract === 'replay_window' || neg.requires_contract === 'rate_abuse') &&\n !options.allowLiveSideEffects &&\n contract?.endpoint_scope !== 'sandbox'\n ) {\n return {\n ...base,\n skipped: true,\n skip_reason: 'live_side_effect_opt_in_required',\n diagnostic:\n `Vector ${vector.id} produces live agent-side effects. Pass allowLiveSideEffects: true ` +\n `(or point the grader at an endpoint whose signed-requests-runner contract declares ` +\n `endpoint_scope: sandbox) to run it.`,\n };\n }\n }\n return undefined;\n}\n\n/**\n * Grade a single vector. Loads the vectors+keys+contract on every call; for\n * the storyboard-runner dispatch path where the caller runs many vectors in\n * sequence, prefer `gradeRequestSigning` which loads once.\n */\nexport async function gradeOneVector(\n vectorId: string,\n kind: 'positive' | 'negative',\n agentUrl: string,\n options: GradeOptions = {}\n): Promise<VectorGradeResult> {\n const loaded = loadRequestSigningVectors(options);\n const contract = loadSignedRequestsRunnerContract(options);\n const probeOpts = {\n allowPrivateIp: options.allowPrivateIp === true,\n timeoutMs: options.timeoutMs,\n };\n const buildOpts: BuildOptions = { baseUrl: agentUrl, transport: options.transport ?? 'raw' };\n\n const vector =\n kind === 'positive' ? loaded.positive.find(v => v.id === vectorId) : loaded.negative.find(v => v.id === vectorId);\n if (!vector) throw new Error(`Unknown ${kind} vector \"${vectorId}\"`);\n\n const skip = preflightSkip(vector, kind, contract, options);\n if (skip) return skip;\n\n if (kind === 'positive') {\n const signed = buildPositiveRequest(vector as PositiveVector, loaded.keys, buildOpts);\n const probe = await probeSignedRequest(signed, probeOpts);\n return gradePositive(vector as PositiveVector, probe);\n }\n return gradeNegative(vector as NegativeVector, loaded, contract, probeOpts, buildOpts, options);\n}\n\n// ── Phase helpers ─────────────────────────────────────────────\n\nfunction gradePositive(vector: PositiveVector, probe: ProbeResult): VectorGradeResult {\n const accepted = probe.status >= 200 && probe.status < 300;\n return {\n vector_id: vector.id,\n kind: 'positive',\n passed: accepted && !probe.error,\n http_status: probe.status,\n diagnostic: accepted ? undefined : buildPositiveDiagnostic(vector, probe),\n probe_duration_ms: probe.duration_ms,\n };\n}\n\nfunction buildPositiveDiagnostic(vector: PositiveVector, probe: ProbeResult): string {\n if (probe.error) return `probe error: ${probe.error}`;\n const expected = 'a 2xx status';\n const sigError = probe.wwwAuthenticateErrorCode;\n if (sigError) {\n return `expected ${expected}, got ${probe.status} with WWW-Authenticate error=\"${sigError}\" — signer or agent-side JWKS likely mismatched. Vector: ${vector.name}`;\n }\n return `expected ${expected}, got ${probe.status}. Vector: ${vector.name}`;\n}\n\nasync function gradeNegative(\n vector: NegativeVector,\n loaded: ReturnType<typeof loadRequestSigningVectors>,\n contract: SignedRequestsRunnerContract | undefined,\n probeOpts: { allowPrivateIp: boolean; timeoutMs?: number },\n buildOpts: BuildOptions,\n options: GradeOptions\n): Promise<VectorGradeResult> {\n if (vector.jwks_override) {\n return gradeJwksOverrideNegative(vector);\n }\n switch (vector.requires_contract) {\n case 'replay_window':\n return gradeReplayWindow(vector, loaded, probeOpts, buildOpts, options.replayProbePairs ?? 10);\n case 'rate_abuse':\n return gradeRateAbuse(vector, loaded, contract!, probeOpts, buildOpts, options);\n case 'revocation':\n default:\n return gradeStaticNegative(vector, loaded, probeOpts, buildOpts);\n }\n}\n\n/**\n * Grade vectors that ship an inline `jwks_override` against the library\n * verifier directly. The agent's JWKS can't be mutated per-vector at probe\n * time, so a black-box HTTP grade can't surface these failure modes.\n * Grading the library verifier is the only path that exercises what the\n * vector is testing — the inline JWK's kty/crv/alg consistency rules.\n */\nasync function gradeJwksOverrideNegative(vector: NegativeVector): Promise<VectorGradeResult> {\n const override = vector.jwks_override!;\n const start = Date.now();\n const jwks = new StaticJwksResolver(override.keys as unknown as AdcpJsonWebKey[]);\n const replayStore = new InMemoryReplayStore();\n const revocationStore = new InMemoryRevocationStore();\n const operation = new URL(vector.request.url).pathname.split('/').filter(Boolean).pop() ?? '';\n try {\n await verifyRequestSignature(vector.request, {\n capability: vector.verifier_capability,\n jwks,\n replayStore,\n revocationStore,\n now: () => vector.reference_now,\n operation,\n });\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed: false,\n http_status: 0,\n expected_error_code: vector.expected_error_code,\n diagnostic: `library verifier accepted a request expected to fail with error=\"${vector.expected_error_code}\"`,\n probe_duration_ms: Date.now() - start,\n };\n } catch (err) {\n if (err instanceof RequestSignatureError) {\n const passed = err.code === vector.expected_error_code;\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed,\n http_status: 0,\n expected_error_code: vector.expected_error_code,\n actual_error_code: err.code,\n diagnostic: passed\n ? undefined\n : `library verifier rejected with error=\"${err.code}\" but vector expects \"${vector.expected_error_code}\"`,\n probe_duration_ms: Date.now() - start,\n };\n }\n throw err;\n }\n}\n\nfunction gradeStaticNegative(\n vector: NegativeVector,\n loaded: ReturnType<typeof loadRequestSigningVectors>,\n probeOpts: { allowPrivateIp: boolean; timeoutMs?: number },\n buildOpts: BuildOptions\n): Promise<VectorGradeResult> {\n const signed = buildNegativeRequest(vector, loaded.keys, buildOpts);\n return probeSignedRequest(signed, probeOpts).then(probe => ({\n vector_id: vector.id,\n kind: 'negative',\n passed: negativeAcceptedErrorCode(vector, probe),\n http_status: probe.status,\n expected_error_code: vector.expected_error_code,\n actual_error_code: probe.wwwAuthenticateErrorCode,\n diagnostic: buildNegativeDiagnostic(vector, probe),\n probe_duration_ms: probe.duration_ms,\n }));\n}\n\nasync function gradeReplayWindow(\n vector: NegativeVector,\n loaded: ReturnType<typeof loadRequestSigningVectors>,\n probeOpts: { allowPrivateIp: boolean; timeoutMs?: number },\n buildOpts: BuildOptions,\n pairCount: number\n): Promise<VectorGradeResult> {\n // Run pairCount independent (probe1, probe2) pairs. Each pair uses a fresh\n // nonce so pair N's probe1 doesn't consume pair N+1's replay-window slot.\n // probeSignedRequest already closes its undici Agent on completion, so each\n // call gets a new TCP connection — no keep-alive pinning to the same upstream.\n let totalDurationMs = 0;\n let rejectedCount = 0;\n let lastSecondStatus = 0;\n let lastSecondErrorCode: string | undefined;\n\n for (let i = 0; i < pairCount; i++) {\n const nonce = randomBytes(16).toString('base64url');\n const signed = buildPositiveRequestFromNegative(vector, loaded, { ...buildOpts, nonce });\n\n const first = await probeSignedRequest(signed, probeOpts);\n totalDurationMs += first.duration_ms;\n\n if (first.status < 200 || first.status >= 300) {\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed: false,\n http_status: first.status,\n expected_error_code: vector.expected_error_code,\n actual_error_code: first.wwwAuthenticateErrorCode,\n diagnostic:\n `replay_window contract: first submission MUST be accepted but agent returned ${first.status}` +\n (first.wwwAuthenticateErrorCode ? ` (error=\"${first.wwwAuthenticateErrorCode}\")` : '') +\n '. Check runner JWKS registration with the agent.',\n probe_duration_ms: totalDurationMs,\n replay_pairs_tried: i + 1,\n replay_pairs_rejected: rejectedCount,\n };\n }\n\n const second = await probeSignedRequest(signed, probeOpts);\n totalDurationMs += second.duration_ms;\n lastSecondStatus = second.status;\n lastSecondErrorCode = second.wwwAuthenticateErrorCode;\n\n if (negativeAcceptedErrorCode(vector, second)) {\n rejectedCount++;\n }\n }\n\n if (rejectedCount === pairCount) {\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed: true,\n http_status: lastSecondStatus,\n expected_error_code: vector.expected_error_code,\n actual_error_code: lastSecondErrorCode,\n probe_duration_ms: totalDurationMs,\n replay_pairs_tried: pairCount,\n replay_pairs_rejected: pairCount,\n };\n }\n\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed: false,\n http_status: lastSecondStatus,\n expected_error_code: vector.expected_error_code,\n actual_error_code: lastSecondErrorCode,\n diagnostic: buildReplayWindowFailDiagnostic(vector, rejectedCount, pairCount),\n probe_duration_ms: totalDurationMs,\n replay_pairs_tried: pairCount,\n replay_pairs_rejected: rejectedCount,\n };\n}\n\nfunction buildReplayWindowFailDiagnostic(vector: NegativeVector, rejectedCount: number, pairCount: number): string {\n if (rejectedCount === 0) {\n return (\n `expected 401 with error=\"${vector.expected_error_code}\" on replayed nonce, but all ${pairCount} probe ` +\n `pairs were accepted (got 200 on second submission every time). Verifier has no replay protection for this nonce. ` +\n `If your verifier runs more than one process or machine instance, confirm the replay store is shared across ` +\n `the pool — the default \\`InMemoryReplayStore\\` is per-process. For distributed deployments use ` +\n `\\`PostgresReplayStore\\` from \\`@adcp/sdk/signing/server\\` or a Redis-backed \\`ReplayStore\\` ` +\n `implementation. See https://github.com/adcontextprotocol/adcp-client/pull/1018`\n );\n }\n return (\n `${rejectedCount} of ${pairCount} probe pairs were correctly rejected; ` +\n `${pairCount - rejectedCount} pair(s) had the second submission accepted. ` +\n `This is the classic multi-instance \\`InMemoryReplayStore\\` pattern — the two probes in an ` +\n `accepted pair landed on different load-balanced instances, each with its own per-process replay store. ` +\n `For distributed deployments use \\`PostgresReplayStore\\` from \\`@adcp/sdk/signing/server\\` ` +\n `or a Redis-backed \\`ReplayStore\\` implementation so all instances share one replay cache. ` +\n `See https://github.com/adcontextprotocol/adcp-client/pull/1018`\n );\n}\n\nasync function gradeRateAbuse(\n vector: NegativeVector,\n loaded: ReturnType<typeof loadRequestSigningVectors>,\n contract: SignedRequestsRunnerContract,\n probeOpts: { allowPrivateIp: boolean; timeoutMs?: number },\n buildOpts: BuildOptions,\n options: GradeOptions\n): Promise<VectorGradeResult> {\n const cap =\n options.rateAbuseCap ?? contract.stateful_vector_contract.rate_abuse.grading_target_per_keyid_cap_requests;\n // Fill the cap with cap distinct-nonce requests, then probe one more — that\n // (cap+1)th request is what the vector expects to be rejected.\n let durationMs = 0;\n for (let i = 0; i < cap; i++) {\n const nonce = randomBytes(16).toString('base64url');\n const signed = buildNegativeRequest(vector, loaded.keys, { nonce, ...buildOpts });\n const probe = await probeSignedRequest(signed, probeOpts);\n durationMs += probe.duration_ms;\n }\n const finalNonce = randomBytes(16).toString('base64url');\n const capPlusOne = buildNegativeRequest(vector, loaded.keys, { nonce: finalNonce, ...buildOpts });\n const probe = await probeSignedRequest(capPlusOne, probeOpts);\n durationMs += probe.duration_ms;\n return {\n vector_id: vector.id,\n kind: 'negative',\n passed: negativeAcceptedErrorCode(vector, probe),\n http_status: probe.status,\n expected_error_code: vector.expected_error_code,\n actual_error_code: probe.wwwAuthenticateErrorCode,\n diagnostic: buildNegativeDiagnostic(vector, probe),\n probe_duration_ms: durationMs,\n };\n}\n\nfunction buildPositiveRequestFromNegative(\n vector: NegativeVector,\n loaded: ReturnType<typeof loadRequestSigningVectors>,\n options: BuildOptions & { nonce: string }\n): SignedHttpRequest {\n // Vector 016 is structurally identical to positive/001 — sign it as a positive.\n const pseudoPositive: PositiveVector = {\n kind: 'positive',\n id: vector.id,\n name: vector.name,\n reference_now: vector.reference_now,\n request: vector.request,\n verifier_capability: vector.verifier_capability,\n jwks_ref: vector.jwks_ref,\n jwks_override: vector.jwks_override,\n };\n return buildPositiveRequest(pseudoPositive, loaded.keys, options);\n}\n\nfunction negativeAcceptedErrorCode(vector: NegativeVector, probe: ProbeResult): boolean {\n return probe.status === 401 && probe.wwwAuthenticateErrorCode === vector.expected_error_code;\n}\n\n/**\n * Inspect the vector's `Signature-Input` header to determine whether the\n * signed components cover `content-digest`. Returns `undefined` when the\n * header is absent or unparseable — the vector exercises a no-signature or\n * malformed-header failure path, so the digest shape check doesn't apply\n * (the verifier short-circuits before the components check).\n *\n * Header lookup is canonical-PascalCase + lowercase only. Test fixtures\n * use canonical PascalCase headers; this isn't a general-purpose\n * header-name normalizer.\n */\nfunction vectorSignsContentDigest(vector: PositiveVector | NegativeVector): boolean | undefined {\n const headers = vector.request.headers;\n const sigInput = headers['Signature-Input'] ?? headers['signature-input'];\n if (!sigInput) return undefined;\n try {\n const parsed = parseSignatureInput(sigInput);\n return parsed.components.includes('content-digest');\n } catch {\n return undefined;\n }\n}\n\n/**\n * Return a diagnostic when the vector's actual signed shape is\n * structurally incompatible with `agentCoversContentDigest` — i.e. the\n * verifier rejects the request shape before the vector's intended error\n * path can fire. Returns `undefined` when the shapes can coexist (or the\n * vector exercises a header-absent/malformed path where this check\n * doesn't apply).\n */\nfunction contentDigestStructuralMismatch(\n vector: PositiveVector | NegativeVector,\n agentCoversContentDigest: 'required' | 'forbidden' | 'either'\n): string | undefined {\n const signsCd = vectorSignsContentDigest(vector);\n if (signsCd === undefined) return undefined;\n if (signsCd && agentCoversContentDigest === 'forbidden') {\n return (\n `Vector's Signature-Input covers content-digest but agent declares ` +\n `covers_content_digest='forbidden'. The verifier rejects with ` +\n `request_signature_components_unexpected before the vector's intended ` +\n `error path can fire.`\n );\n }\n if (!signsCd && agentCoversContentDigest === 'required') {\n return (\n `Vector's Signature-Input does not cover content-digest but agent declares ` +\n `covers_content_digest='required'. The verifier rejects with ` +\n `request_signature_components_incomplete before the vector's intended ` +\n `error path can fire.`\n );\n }\n return undefined;\n}\n\n/**\n * Capability-profile mismatch resolver used when the operator passes\n * `agentContentDigestPolicy` without a full `agentCapability` fixture.\n * Combines two checks:\n * - Declared-policy check (negatives only): a negative vector that\n * asserts a strict policy the agent didn't advertise can't surface\n * its intended error path — the agent never rejects the shape the\n * vector is exercising. Positives are unaffected because acceptance\n * under a permissive agent still demonstrates the verifier's\n * acceptance contract.\n * - Structural shape check (positives and negatives): the vector's\n * actual `Signature-Input` shape must coexist with the agent's\n * policy — otherwise the verifier short-circuits with a\n * `request_signature_components_*` error before any other path can\n * fire.\n */\nfunction contentDigestPolicyMismatch(\n vector: PositiveVector | NegativeVector,\n kind: 'positive' | 'negative',\n agentPolicy: 'required' | 'forbidden' | 'either'\n): string | undefined {\n if (kind === 'negative') {\n const vectorCd = vector.verifier_capability.covers_content_digest;\n if (vectorCd !== 'either' && vectorCd !== agentPolicy) {\n return (\n `Vector asserts covers_content_digest='${vectorCd}' but agent declares '${agentPolicy}'. ` +\n `The agent's policy is incompatible with the vector's expected verifier behavior.`\n );\n }\n }\n return contentDigestStructuralMismatch(vector, agentPolicy);\n}\n\n/**\n * Compare a vector's `verifier_capability` fixture and actual signed shape\n * against the agent's declared capability profile. Returns a\n * human-readable diagnostic when the vector can't grade against this\n * profile — or `undefined` when the vector is gradable.\n *\n * Rules (all four must hold for a graded run):\n * - `supported`: must match. A vector with `supported: true` doesn't\n * grade against an agent that declares `supported: false` (the\n * conformance storyboard already skips such agents outright, but\n * defense-in-depth).\n * - `covers_content_digest`: asymmetric. Vector-side `'either'` is\n * permissive only at the declaration level — the structural shape\n * check below still applies. Agent-side `'either'` is NOT permissive\n * against a strict vector — an agent that declares `'either'`\n * accepts covered AND uncovered requests, so it can't pass vectors\n * 007 (`'required'`) or 018 (`'forbidden'`). Those auto-skip with\n * `capability_profile_mismatch`.\n * - structural shape: the vector's actual `Signature-Input` must\n * coexist with the agent's policy regardless of what\n * `verifier_capability.covers_content_digest` declares. A vector\n * signing without `content-digest` can't grade a `'required'`\n * verifier; a vector signing with `content-digest` can't grade a\n * `'forbidden'` verifier. Either short-circuits with a\n * `request_signature_components_*` error before the vector's\n * intended assertion fires.\n * - `required_for` / `protocol_methods_required_for`: if the vector\n * asserts a required_for operation or method, the agent's\n * `required_for` / `protocol_methods_required_for` must include it.\n * The reverse is fine — an agent that requires MORE operations is\n * still conformant against a vector that asserts fewer.\n */\nfunction capabilityMismatch(\n vector: PositiveVector | NegativeVector,\n agentCap: VerifierCapabilityFixture\n): string | undefined {\n const vectorCap = vector.verifier_capability;\n if (vectorCap.supported !== agentCap.supported) {\n return (\n `Vector asserts supported=${vectorCap.supported} but agent declares supported=${agentCap.supported}. ` +\n `Verify the agent's request_signing capability block.`\n );\n }\n // `covers_content_digest` asymmetry: vector-side `'either'` is\n // permissive only if the vector's actual signed shape is compatible\n // with the agent's policy (handled by the structural check below).\n // Agent-side `'either'` is NOT permissive against a strict vector —\n // an agent that declares `'either'` accepts requests with OR without\n // Content-Digest, so vector 007's \"MUST reject uncovered request\"\n // and vector 018's \"MUST reject covered-when-forbidden\" are\n // structurally incompatible with the agent's stance.\n if (\n vectorCap.covers_content_digest !== 'either' &&\n vectorCap.covers_content_digest !== agentCap.covers_content_digest\n ) {\n return (\n `Vector asserts covers_content_digest='${vectorCap.covers_content_digest}' but agent declares '${agentCap.covers_content_digest}'. ` +\n `The vector can't grade against this profile — its expected verifier behavior doesn't match what the agent implements.`\n );\n }\n // Structural shape check: even when vectorCap is permissive (`'either'`),\n // the vector's actual `Signature-Input` either covers `content-digest` or\n // not. A `'required'` verifier rejects every uncovered request with\n // `request_signature_components_incomplete`; a `'forbidden'` verifier\n // rejects every covered request with `request_signature_components_unexpected`.\n // Both fire before the vector's intended error path, masking the result.\n const structural = contentDigestStructuralMismatch(vector, agentCap.covers_content_digest);\n if (structural) return structural;\n // `required_for` on the vector: every op the vector expects to be\n // required must also be required by the agent. Otherwise a negative\n // vector (e.g., missing signature on `create_media_buy`) would test a\n // rejection path the agent didn't opt into.\n const vectorRequiredFor = vectorCap.required_for ?? [];\n const agentRequiredForSet = new Set(agentCap.required_for ?? []);\n const missingRequiredFor = vectorRequiredFor.filter(op => !agentRequiredForSet.has(op));\n if (missingRequiredFor.length > 0) {\n return (\n `Vector asserts required_for includes [${missingRequiredFor.join(', ')}] but agent's required_for does not. ` +\n `Either add the operation to the agent's request_signing.required_for, or accept the skip.`\n );\n }\n // Same check for `protocol_methods_required_for` (adcp#4326 namespace).\n // Negative vectors that grade JSON-RPC protocol methods (e.g. unsigned\n // `tasks/cancel`) auto-skip when the agent doesn't declare the bucket —\n // matching the behavior of `required_for` for AdCP-tool vectors.\n const vectorProtocolMethodsRequiredFor = vectorCap.protocol_methods_required_for ?? [];\n const agentProtocolMethodsRequiredForSet = new Set(agentCap.protocol_methods_required_for ?? []);\n const missingProtocolMethodsRequiredFor = vectorProtocolMethodsRequiredFor.filter(\n method => !agentProtocolMethodsRequiredForSet.has(method)\n );\n if (missingProtocolMethodsRequiredFor.length > 0) {\n return (\n `Vector asserts protocol_methods_required_for includes [${missingProtocolMethodsRequiredFor.join(', ')}] ` +\n `but agent's protocol_methods_required_for does not. Either add the method to the agent's ` +\n `request_signing.protocol_methods_required_for, or accept the skip.`\n );\n }\n return undefined;\n}\n\nfunction buildNegativeDiagnostic(vector: NegativeVector, probe: ProbeResult): string | undefined {\n if (probe.error) return `probe error: ${probe.error}`;\n if (probe.status === 401 && probe.wwwAuthenticateErrorCode === vector.expected_error_code) {\n return undefined;\n }\n const actual = probe.wwwAuthenticateErrorCode ?? '(none)';\n if (probe.status !== 401) {\n return `expected 401 with error=\"${vector.expected_error_code}\", got ${probe.status} (error=\"${actual}\"). Vector: ${vector.name}`;\n }\n return `expected error=\"${vector.expected_error_code}\", got error=\"${actual}\". Check verifier step ordering — several vectors (015/017/020) depend on revocation/cap checks firing BEFORE crypto verify.`;\n}\n"],"mappings":"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","names":["probe"]}
|
|
@@ -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
|
gradeRequestSigning,
|
|
9
3
|
gradeOneVector
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/index.ts"],"sourcesContent":["/**\n * RFC 9421 request-signing conformance grader.\n *\n * Tests any agent advertising `request_signing.supported: true` against the\n * 28 conformance vectors shipped under\n * `compliance/cache/{version}/test-vectors/request-signing/`. Grading is\n * black-box and observable-behavior only — we construct signed HTTP requests\n * (dynamically, using the test keypairs in keys.json) and compare the\n * agent's responses to each vector's `expected_outcome`.\n *\n * @example\n * ```ts\n * import { gradeRequestSigning } from '@adcp/sdk/testing/storyboard/request-signing';\n *\n * const report = await gradeRequestSigning('https://sandbox.seller.com/adcp', {\n * skipRateAbuse: true, // skip the 101-request flood in routine runs\n * });\n * if (!report.passed) {\n * for (const r of [...report.positive, ...report.negative]) {\n * if (!r.passed && !r.skipped) console.log(`${r.vector_id}: ${r.diagnostic}`);\n * }\n * }\n * ```\n *\n * For storyboard-runner integration (synthesized per-vector steps dispatched\n * through `runStoryboard` / `runStoryboardStep`), see\n * `StoryboardRunOptions.request_signing` on the runner options.\n */\n\n// ── Public API ────────────────────────────────────────────────────\n// These are what 95% of consumers need. Start here.\n\nexport {\n gradeRequestSigning,\n gradeOneVector,\n type GradeOptions,\n type GradeReport,\n type VectorGradeResult,\n} from './grader';\n\n// ── Storyboard-runner hooks ───────────────────────────────────────\n// Surfaces used internally by the runner; exported so external runners and\n// custom harnesses can wire them the same way.\n\nexport {\n synthesizeRequestSigningSteps,\n parseRequestSigningStepId,\n REQUEST_SIGNING_PROBE_TASK,\n POSITIVE_STEP_PREFIX,\n NEGATIVE_STEP_PREFIX,\n type SynthesizeOptions,\n} from './synthesize';\n\nexport { probeRequestSigningVector } from './probe-dispatch';\n\n// ── Advanced: custom harness building blocks ──────────────────────\n// Escape hatches for constructing custom graders (alternate probe transports,\n// pre-flight staging, etc.). Most consumers should not need these.\n\nexport type {\n NegativeVector,\n PositiveVector,\n TestKeypair,\n TestKeyset,\n VectorRequest,\n VerifierCapabilityFixture,\n Vector,\n ContractId,\n} from './types';\n\nexport { CONTRACT_IDS } from './types';\n\nexport { loadRequestSigningVectors, findKey, type LoadVectorsOptions, type LoadedVectors } from './vector-loader';\n\nexport {\n buildPositiveRequest,\n buildNegativeRequest,\n listSupportedNegativeVectors,\n type BuildOptions,\n type SignedHttpRequest,\n} from './builder';\n\nexport {\n loadSignedRequestsRunnerContract,\n type LoadTestKitOptions,\n type RateAbuseContract,\n type ReplayWindowContract,\n type RevocationContract,\n type RunnerSigningKey,\n type SignedRequestsRunnerContract,\n} from './test-kit';\n\nexport { probeSignedRequest, extractSignatureErrorCode, type ProbeOptions, type ProbeResult } from './probe';\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/index.ts"],"sourcesContent":["/**\n * RFC 9421 request-signing conformance grader.\n *\n * Tests any agent advertising `request_signing.supported: true` against the\n * 28 conformance vectors shipped under\n * `compliance/cache/{version}/test-vectors/request-signing/`. Grading is\n * black-box and observable-behavior only — we construct signed HTTP requests\n * (dynamically, using the test keypairs in keys.json) and compare the\n * agent's responses to each vector's `expected_outcome`.\n *\n * @example\n * ```ts\n * import { gradeRequestSigning } from '@adcp/sdk/testing/storyboard/request-signing';\n *\n * const report = await gradeRequestSigning('https://sandbox.seller.com/adcp', {\n * skipRateAbuse: true, // skip the 101-request flood in routine runs\n * });\n * if (!report.passed) {\n * for (const r of [...report.positive, ...report.negative]) {\n * if (!r.passed && !r.skipped) console.log(`${r.vector_id}: ${r.diagnostic}`);\n * }\n * }\n * ```\n *\n * For storyboard-runner integration (synthesized per-vector steps dispatched\n * through `runStoryboard` / `runStoryboardStep`), see\n * `StoryboardRunOptions.request_signing` on the runner options.\n */\n\n// ── Public API ────────────────────────────────────────────────────\n// These are what 95% of consumers need. Start here.\n\nexport {\n gradeRequestSigning,\n gradeOneVector,\n type GradeOptions,\n type GradeReport,\n type VectorGradeResult,\n} from './grader';\n\n// ── Storyboard-runner hooks ───────────────────────────────────────\n// Surfaces used internally by the runner; exported so external runners and\n// custom harnesses can wire them the same way.\n\nexport {\n synthesizeRequestSigningSteps,\n parseRequestSigningStepId,\n REQUEST_SIGNING_PROBE_TASK,\n POSITIVE_STEP_PREFIX,\n NEGATIVE_STEP_PREFIX,\n type SynthesizeOptions,\n} from './synthesize';\n\nexport { probeRequestSigningVector } from './probe-dispatch';\n\n// ── Advanced: custom harness building blocks ──────────────────────\n// Escape hatches for constructing custom graders (alternate probe transports,\n// pre-flight staging, etc.). Most consumers should not need these.\n\nexport type {\n NegativeVector,\n PositiveVector,\n TestKeypair,\n TestKeyset,\n VectorRequest,\n VerifierCapabilityFixture,\n Vector,\n ContractId,\n} from './types';\n\nexport { CONTRACT_IDS } from './types';\n\nexport { loadRequestSigningVectors, findKey, type LoadVectorsOptions, type LoadedVectors } from './vector-loader';\n\nexport {\n buildPositiveRequest,\n buildNegativeRequest,\n listSupportedNegativeVectors,\n type BuildOptions,\n type SignedHttpRequest,\n} from './builder';\n\nexport {\n loadSignedRequestsRunnerContract,\n type LoadTestKitOptions,\n type RateAbuseContract,\n type ReplayWindowContract,\n type RevocationContract,\n type RunnerSigningKey,\n type SignedRequestsRunnerContract,\n} from './test-kit';\n\nexport { probeSignedRequest, extractSignatureErrorCode, type ProbeOptions, type ProbeResult } from './probe';\n"],"mappings":"AAgCA;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAMP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAEP,SAAS,iCAAiC;AAiB1C,SAAS,oBAAoB;AAE7B,SAAS,2BAA2B,eAA4D;AAEhG;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AAEP;AAAA,EACE;AAAA,OAOK;AAEP,SAAS,oBAAoB,iCAAsE;","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 { gradeOneVector } from "./grader.mjs";
|
|
8
2
|
import { parseRequestSigningStepId } from "./synthesize.mjs";
|
|
9
3
|
import { loadRequestSigningVectors } from "./vector-loader.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/probe-dispatch.ts"],"sourcesContent":["import type { HttpProbeResult, RunnerDetailedSkipReason, StoryboardRunOptions } from '../types';\nimport { gradeOneVector } from './grader';\nimport { parseRequestSigningStepId } from './synthesize';\nimport { loadRequestSigningVectors } from './vector-loader';\n\n/**\n * Dispatch a synthesized request-signing step. The step ID encodes the vector\n * (`positive-<id>` / `negative-<id>`); this helper decodes it, runs the\n * grader's per-vector logic, and maps the `VectorGradeResult` to an\n * `HttpProbeResult`-shaped return so the existing validation pipeline\n * (`http_status`, `http_status_in`) works unchanged.\n */\nexport async function probeRequestSigningVector(\n stepId: string,\n agentUrl: string,\n options: StoryboardRunOptions\n): Promise<HttpProbeResult> {\n const parsed = parseRequestSigningStepId(stepId);\n if (!parsed) {\n return {\n url: agentUrl,\n status: 0,\n headers: {},\n body: null,\n error: `request_signing_probe: step id \"${stepId}\" does not match positive-/negative- prefix`,\n };\n }\n const rsOpts = options.request_signing ?? {};\n // Vector-id lookup so we skip by the vector's `requires_contract`, not by\n // hardcoded vector id. Keeps the dispatch resilient to upstream renames.\n if (parsed.kind === 'negative' && rsOpts.skipRateAbuse) {\n try {\n const loaded = loadRequestSigningVectors();\n const vector = loaded.negative.find(v => v.id === parsed.vector_id);\n if (vector?.requires_contract === 'rate_abuse') {\n return skipProbe(agentUrl, 'rate_abuse_opt_out');\n }\n } catch {\n // fall through — surfaces as a grader error below\n }\n }\n if (rsOpts.skipVectors?.includes(parsed.vector_id)) {\n return skipProbe(agentUrl, 'operator_skip');\n }\n try {\n const result = await gradeOneVector(parsed.vector_id, parsed.kind, agentUrl, {\n allowPrivateIp: options.allow_http === true,\n rateAbuseCap: rsOpts.rateAbuseCap,\n allowLiveSideEffects: rsOpts.allowLiveSideEffects,\n onlyVectors: rsOpts.onlyVectors,\n skipVectors: rsOpts.skipVectors,\n skipRateAbuse: rsOpts.skipRateAbuse,\n ...(rsOpts.transport && { transport: rsOpts.transport }),\n });\n if (result.skipped) {\n return skipProbe(agentUrl, (result.skip_reason as RunnerDetailedSkipReason | undefined) ?? 'grader_skipped');\n }\n const headers: Record<string, string> = {};\n if (result.actual_error_code) {\n headers['www-authenticate'] = `Signature error=\"${result.actual_error_code}\"`;\n }\n return {\n url: agentUrl,\n status: result.http_status,\n headers,\n body: result.diagnostic ?? null,\n error: result.passed ? undefined : (result.diagnostic ?? 'vector grade failed'),\n };\n } catch (err) {\n return {\n url: agentUrl,\n status: 0,\n headers: {},\n body: null,\n error: `request_signing_probe threw: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n}\n\nfunction skipProbe(url: string, reason: RunnerDetailedSkipReason): HttpProbeResult {\n return { url, status: 0, headers: {}, body: null, skipped: true, skip_reason: reason };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/probe-dispatch.ts"],"sourcesContent":["import type { HttpProbeResult, RunnerDetailedSkipReason, StoryboardRunOptions } from '../types';\nimport { gradeOneVector } from './grader';\nimport { parseRequestSigningStepId } from './synthesize';\nimport { loadRequestSigningVectors } from './vector-loader';\n\n/**\n * Dispatch a synthesized request-signing step. The step ID encodes the vector\n * (`positive-<id>` / `negative-<id>`); this helper decodes it, runs the\n * grader's per-vector logic, and maps the `VectorGradeResult` to an\n * `HttpProbeResult`-shaped return so the existing validation pipeline\n * (`http_status`, `http_status_in`) works unchanged.\n */\nexport async function probeRequestSigningVector(\n stepId: string,\n agentUrl: string,\n options: StoryboardRunOptions\n): Promise<HttpProbeResult> {\n const parsed = parseRequestSigningStepId(stepId);\n if (!parsed) {\n return {\n url: agentUrl,\n status: 0,\n headers: {},\n body: null,\n error: `request_signing_probe: step id \"${stepId}\" does not match positive-/negative- prefix`,\n };\n }\n const rsOpts = options.request_signing ?? {};\n // Vector-id lookup so we skip by the vector's `requires_contract`, not by\n // hardcoded vector id. Keeps the dispatch resilient to upstream renames.\n if (parsed.kind === 'negative' && rsOpts.skipRateAbuse) {\n try {\n const loaded = loadRequestSigningVectors();\n const vector = loaded.negative.find(v => v.id === parsed.vector_id);\n if (vector?.requires_contract === 'rate_abuse') {\n return skipProbe(agentUrl, 'rate_abuse_opt_out');\n }\n } catch {\n // fall through — surfaces as a grader error below\n }\n }\n if (rsOpts.skipVectors?.includes(parsed.vector_id)) {\n return skipProbe(agentUrl, 'operator_skip');\n }\n try {\n const result = await gradeOneVector(parsed.vector_id, parsed.kind, agentUrl, {\n allowPrivateIp: options.allow_http === true,\n rateAbuseCap: rsOpts.rateAbuseCap,\n allowLiveSideEffects: rsOpts.allowLiveSideEffects,\n onlyVectors: rsOpts.onlyVectors,\n skipVectors: rsOpts.skipVectors,\n skipRateAbuse: rsOpts.skipRateAbuse,\n ...(rsOpts.transport && { transport: rsOpts.transport }),\n });\n if (result.skipped) {\n return skipProbe(agentUrl, (result.skip_reason as RunnerDetailedSkipReason | undefined) ?? 'grader_skipped');\n }\n const headers: Record<string, string> = {};\n if (result.actual_error_code) {\n headers['www-authenticate'] = `Signature error=\"${result.actual_error_code}\"`;\n }\n return {\n url: agentUrl,\n status: result.http_status,\n headers,\n body: result.diagnostic ?? null,\n error: result.passed ? undefined : (result.diagnostic ?? 'vector grade failed'),\n };\n } catch (err) {\n return {\n url: agentUrl,\n status: 0,\n headers: {},\n body: null,\n error: `request_signing_probe threw: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n}\n\nfunction skipProbe(url: string, reason: RunnerDetailedSkipReason): HttpProbeResult {\n return { url, status: 0, headers: {}, body: null, skipped: true, skip_reason: reason };\n}\n"],"mappings":"AACA,SAAS,sBAAsB;AAC/B,SAAS,iCAAiC;AAC1C,SAAS,iCAAiC;AAS1C,eAAsB,0BACpB,QACA,UACA,SAC0B;AAC1B,QAAM,SAAS,0BAA0B,MAAM;AAC/C,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,MACL,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,SAAS,CAAC;AAAA,MACV,MAAM;AAAA,MACN,OAAO,mCAAmC,MAAM;AAAA,IAClD;AAAA,EACF;AACA,QAAM,SAAS,QAAQ,mBAAmB,CAAC;AAG3C,MAAI,OAAO,SAAS,cAAc,OAAO,eAAe;AACtD,QAAI;AACF,YAAM,SAAS,0BAA0B;AACzC,YAAM,SAAS,OAAO,SAAS,KAAK,OAAK,EAAE,OAAO,OAAO,SAAS;AAClE,UAAI,QAAQ,sBAAsB,cAAc;AAC9C,eAAO,UAAU,UAAU,oBAAoB;AAAA,MACjD;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACA,MAAI,OAAO,aAAa,SAAS,OAAO,SAAS,GAAG;AAClD,WAAO,UAAU,UAAU,eAAe;AAAA,EAC5C;AACA,MAAI;AACF,UAAM,SAAS,MAAM,eAAe,OAAO,WAAW,OAAO,MAAM,UAAU;AAAA,MAC3E,gBAAgB,QAAQ,eAAe;AAAA,MACvC,cAAc,OAAO;AAAA,MACrB,sBAAsB,OAAO;AAAA,MAC7B,aAAa,OAAO;AAAA,MACpB,aAAa,OAAO;AAAA,MACpB,eAAe,OAAO;AAAA,MACtB,GAAI,OAAO,aAAa,EAAE,WAAW,OAAO,UAAU;AAAA,IACxD,CAAC;AACD,QAAI,OAAO,SAAS;AAClB,aAAO,UAAU,UAAW,OAAO,eAAwD,gBAAgB;AAAA,IAC7G;AACA,UAAM,UAAkC,CAAC;AACzC,QAAI,OAAO,mBAAmB;AAC5B,cAAQ,kBAAkB,IAAI,oBAAoB,OAAO,iBAAiB;AAAA,IAC5E;AACA,WAAO;AAAA,MACL,KAAK;AAAA,MACL,QAAQ,OAAO;AAAA,MACf;AAAA,MACA,MAAM,OAAO,cAAc;AAAA,MAC3B,OAAO,OAAO,SAAS,SAAa,OAAO,cAAc;AAAA,IAC3D;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,SAAS,CAAC;AAAA,MACV,MAAM;AAAA,MACN,OAAO,gCAAgC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACzF;AAAA,EACF;AACF;AAEA,SAAS,UAAU,KAAa,QAAmD;AACjF,SAAO,EAAE,KAAK,QAAQ,GAAG,SAAS,CAAC,GAAG,MAAM,MAAM,SAAS,MAAM,aAAa,OAAO;AACvF;","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 { lookup as dnsLookup } from "dns/promises";
|
|
8
2
|
import { Agent, fetch as undiciFetch } from "undici";
|
|
9
3
|
import { isAlwaysBlocked, isPrivateIp } from "../probes.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/probe.ts"],"sourcesContent":["import { type LookupAddress, type LookupOptions } from 'dns';\nimport { lookup as dnsLookup } from 'dns/promises';\nimport { Agent, fetch as undiciFetch } from 'undici';\nimport { isAlwaysBlocked, isPrivateIp } from '../probes';\nimport type { SignedHttpRequest } from './builder';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst MAX_BODY_BYTES = 64 * 1024;\n\nexport interface ProbeOptions {\n /** Allow http:// and private-IP destinations. Default false. */\n allowPrivateIp?: boolean;\n /** Per-call timeout override (ms). */\n timeoutMs?: number;\n}\n\nexport interface ProbeResult {\n url: string;\n status: number;\n headers: Record<string, string>;\n /** Error code extracted from `WWW-Authenticate: Signature error=\"<code>\"`. */\n wwwAuthenticateErrorCode?: string;\n /** Truncated response body (first 64 KiB, JSON-parsed if applicable). */\n body: unknown;\n /** Network-level error; non-undefined means the request didn't complete. */\n error?: string;\n duration_ms: number;\n}\n\n/**\n * Send a signed HTTP request to an AdCP agent and capture the response fields\n * needed for conformance grading (status, WWW-Authenticate error code, body).\n *\n * Reuses the SSRF guards from the address classifiers — scheme check,\n * `isAlwaysBlocked`, `isPrivateIp` — then pins the outbound connection to the\n * pre-validated address via an undici dispatcher, defeating DNS rebinding.\n * Bodies are capped at 64 KiB and parsed as JSON when content-type matches;\n * otherwise returned as text. `redirect: 'manual'` is enforced so an agent\n * that 301s can't smuggle the grader elsewhere.\n */\nexport async function probeSignedRequest(signed: SignedHttpRequest, options: ProbeOptions = {}): Promise<ProbeResult> {\n const start = Date.now();\n const timeout = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const result: ProbeResult = { url: signed.url, status: 0, headers: {}, body: null, duration_ms: 0 };\n\n let parsed: URL;\n try {\n parsed = new URL(signed.url);\n } catch {\n result.error = `Invalid URL: ${signed.url}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n result.error = `Refusing to probe URL with unsupported scheme: ${parsed.protocol}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n if (parsed.protocol !== 'https:' && !options.allowPrivateIp) {\n result.error = `Refusing to probe non-HTTPS URL: ${signed.url}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n\n // Strip URL brackets from IPv6 literals (`[::1]` → `::1`) before DNS lookup\n // and address classification. `URL.hostname` wraps IPv6 in brackets; both\n // `dns.lookup` and the address classifiers need the bare form.\n const hostname = parsed.hostname.replace(/^\\[|\\]$/g, '');\n\n let addresses: { address: string; family: number }[];\n try {\n addresses = await dnsLookup(hostname, { all: true });\n } catch (err) {\n result.error = `DNS lookup failed for ${hostname}: ${err instanceof Error ? err.message : String(err)}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n if (addresses.length === 0) {\n result.error = `DNS returned no addresses for ${hostname}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n for (const a of addresses) {\n if (isAlwaysBlocked(a.address)) {\n result.error = `Refusing to probe always-blocked address ${a.address} for ${hostname}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n }\n if (!options.allowPrivateIp) {\n for (const a of addresses) {\n if (isPrivateIp(a.address)) {\n result.error = `Refusing to probe private/loopback address ${a.address} for ${hostname}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n }\n }\n const pinned = addresses[0]!;\n const pinnedFamily = pinned.family === 6 ? 6 : 4;\n // undici calls lookup with { all: true } for HTTPS targets on Node 22+, which\n // expects the array form of the callback. Handle both shapes so the pin works\n // across Node versions.\n const dispatcher = new Agent({\n connect: {\n lookup: (\n _h: string,\n opts: LookupOptions | undefined,\n cb: (err: NodeJS.ErrnoException | null, address: string | LookupAddress[], family?: number) => void\n ) => {\n if (opts?.all) {\n cb(null, [{ address: pinned.address, family: pinnedFamily }]);\n } else {\n cb(null, pinned.address, pinnedFamily);\n }\n },\n },\n });\n\n const ac = new AbortController();\n const timer = setTimeout(() => ac.abort(), timeout);\n try {\n const res = await undiciFetch(signed.url, {\n method: signed.method,\n redirect: 'manual',\n signal: ac.signal,\n headers: signed.headers,\n body: signed.body,\n dispatcher,\n });\n result.status = res.status;\n const headers: Record<string, string> = {};\n res.headers.forEach((v, k) => {\n headers[k.toLowerCase()] = v;\n });\n result.headers = headers;\n\n const wwwAuth = headers['www-authenticate'];\n if (wwwAuth) {\n result.wwwAuthenticateErrorCode = extractSignatureErrorCode(wwwAuth);\n }\n\n const reader = res.body?.getReader();\n if (reader) {\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n bytes += value.byteLength;\n if (bytes > MAX_BODY_BYTES) {\n await reader.cancel();\n result.error = `Response body exceeded ${MAX_BODY_BYTES} bytes`;\n return result;\n }\n chunks.push(value);\n }\n const buf = Buffer.concat(chunks.map(c => Buffer.from(c.buffer, c.byteOffset, c.byteLength)));\n const contentType = headers['content-type'] ?? '';\n if (contentType.includes('application/json')) {\n try {\n result.body = JSON.parse(buf.toString('utf8'));\n } catch {\n result.body = buf.toString('utf8');\n }\n } else {\n result.body = buf.toString('utf8');\n }\n }\n return result;\n } catch (err) {\n result.error = err instanceof Error ? err.message : String(err);\n return result;\n } finally {\n clearTimeout(timer);\n result.duration_ms = Date.now() - start;\n await dispatcher.close().catch(() => {});\n }\n}\n\n/**\n * Extract `error=\"<code>\"` from a `WWW-Authenticate: Signature ...` header.\n * Returns undefined when the header isn't a Signature challenge, the param\n * is absent, or the extracted value isn't a well-formed spec error code\n * (a token in `[a-z0-9_]+`). Sanitizing at source keeps downstream\n * diagnostics / LLM-consumption paths safe from smuggled content in\n * attacker-controlled header values.\n */\nexport function extractSignatureErrorCode(headerValue: string): string | undefined {\n // `WWW-Authenticate` may carry multiple challenges concatenated with commas.\n // We only grade Signature challenges; ignore Basic/Bearer/etc.\n const challenges = splitChallenges(headerValue);\n for (const challenge of challenges) {\n if (!/^Signature\\b/i.test(challenge)) continue;\n const m = /\\berror\\s*=\\s*\"([^\"]*)\"/.exec(challenge);\n if (!m) continue;\n const value = m[1];\n // Spec error codes are `request_signature_*` — all lowercase-alnum +\n // underscore. Reject anything else so quotes/newlines/HTML/LLM-poisoning\n // content can't flow into diagnostic strings or rendered reports.\n if (value && /^[a-z0-9_]+$/.test(value)) return value;\n return undefined;\n }\n return undefined;\n}\n\n/**\n * Split a `WWW-Authenticate` header into per-challenge chunks. RFC 7235 §4.1\n * lets multiple challenges coexist separated by commas, and challenge params\n * are `k=\"v\"` where `v` can contain commas. Track quote state so an\n * adversarial `error=\"foo, Bar baz\"` doesn't spuriously split mid-value.\n */\nfunction splitChallenges(headerValue: string): string[] {\n const parts: string[] = [];\n let current = '';\n let inQuotes = false;\n for (let i = 0; i < headerValue.length; i++) {\n const ch = headerValue[i]!;\n if (ch === '\"' && headerValue[i - 1] !== '\\\\') {\n inQuotes = !inQuotes;\n current += ch;\n continue;\n }\n if (!inQuotes && ch === ',') {\n // Look ahead for a scheme-like token (`<name><whitespace>`) — only\n // then treat this comma as a challenge boundary; otherwise it's a\n // param-list separator inside the current challenge.\n const rest = headerValue.slice(i + 1);\n if (/^\\s*[A-Za-z][A-Za-z0-9-]*\\s+/.test(rest)) {\n parts.push(current.trim());\n current = '';\n continue;\n }\n }\n current += ch;\n }\n if (current.trim().length > 0) parts.push(current.trim());\n return parts.filter(p => p.length > 0);\n}\n"],"mappings":";;;;;;AACA,SAAS,UAAU,iBAAiB;AACpC,SAAS,OAAO,SAAS,mBAAmB;AAC5C,SAAS,iBAAiB,mBAAmB;AAG7C,MAAM,qBAAqB;AAC3B,MAAM,iBAAiB,KAAK;AAiC5B,eAAsB,mBAAmB,QAA2B,UAAwB,CAAC,GAAyB;AACpH,QAAM,QAAQ,KAAK,IAAI;AACvB,QAAM,UAAU,QAAQ,aAAa;AACrC,QAAM,SAAsB,EAAE,KAAK,OAAO,KAAK,QAAQ,GAAG,SAAS,CAAC,GAAG,MAAM,MAAM,aAAa,EAAE;AAElG,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,OAAO,GAAG;AAAA,EAC7B,QAAQ;AACN,WAAO,QAAQ,gBAAgB,OAAO,GAAG;AACzC,WAAO,cAAc,KAAK,IAAI,IAAI;AAClC,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,aAAa,YAAY,OAAO,aAAa,SAAS;AAC/D,WAAO,QAAQ,kDAAkD,OAAO,QAAQ;AAChF,WAAO,cAAc,KAAK,IAAI,IAAI;AAClC,WAAO;AAAA,EACT;AACA,MAAI,OAAO,aAAa,YAAY,CAAC,QAAQ,gBAAgB;AAC3D,WAAO,QAAQ,oCAAoC,OAAO,GAAG;AAC7D,WAAO,cAAc,KAAK,IAAI,IAAI;AAClC,WAAO;AAAA,EACT;AAKA,QAAM,WAAW,OAAO,SAAS,QAAQ,YAAY,EAAE;AAEvD,MAAI;AACJ,MAAI;AACF,gBAAY,MAAM,UAAU,UAAU,EAAE,KAAK,KAAK,CAAC;AAAA,EACrD,SAAS,KAAK;AACZ,WAAO,QAAQ,yBAAyB,QAAQ,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AACrG,WAAO,cAAc,KAAK,IAAI,IAAI;AAClC,WAAO;AAAA,EACT;AACA,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO,QAAQ,iCAAiC,QAAQ;AACxD,WAAO,cAAc,KAAK,IAAI,IAAI;AAClC,WAAO;AAAA,EACT;AACA,aAAW,KAAK,WAAW;AACzB,QAAI,gBAAgB,EAAE,OAAO,GAAG;AAC9B,aAAO,QAAQ,4CAA4C,EAAE,OAAO,QAAQ,QAAQ;AACpF,aAAO,cAAc,KAAK,IAAI,IAAI;AAClC,aAAO;AAAA,IACT;AAAA,EACF;AACA,MAAI,CAAC,QAAQ,gBAAgB;AAC3B,eAAW,KAAK,WAAW;AACzB,UAAI,YAAY,EAAE,OAAO,GAAG;AAC1B,eAAO,QAAQ,8CAA8C,EAAE,OAAO,QAAQ,QAAQ;AACtF,eAAO,cAAc,KAAK,IAAI,IAAI;AAClC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,QAAM,SAAS,UAAU,CAAC;AAC1B,QAAM,eAAe,OAAO,WAAW,IAAI,IAAI;AAI/C,QAAM,aAAa,IAAI,MAAM;AAAA,IAC3B,SAAS;AAAA,MACP,QAAQ,CACN,IACA,MACA,OACG;AACH,YAAI,MAAM,KAAK;AACb,aAAG,MAAM,CAAC,EAAE,SAAS,OAAO,SAAS,QAAQ,aAAa,CAAC,CAAC;AAAA,QAC9D,OAAO;AACL,aAAG,MAAM,OAAO,SAAS,YAAY;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,KAAK,IAAI,gBAAgB;AAC/B,QAAM,QAAQ,WAAW,MAAM,GAAG,MAAM,GAAG,OAAO;AAClD,MAAI;AACF,UAAM,MAAM,MAAM,YAAY,OAAO,KAAK;AAAA,MACxC,QAAQ,OAAO;AAAA,MACf,UAAU;AAAA,MACV,QAAQ,GAAG;AAAA,MACX,SAAS,OAAO;AAAA,MAChB,MAAM,OAAO;AAAA,MACb;AAAA,IACF,CAAC;AACD,WAAO,SAAS,IAAI;AACpB,UAAM,UAAkC,CAAC;AACzC,QAAI,QAAQ,QAAQ,CAAC,GAAG,MAAM;AAC5B,cAAQ,EAAE,YAAY,CAAC,IAAI;AAAA,IAC7B,CAAC;AACD,WAAO,UAAU;AAEjB,UAAM,UAAU,QAAQ,kBAAkB;AAC1C,QAAI,SAAS;AACX,aAAO,2BAA2B,0BAA0B,OAAO;AAAA,IACrE;AAEA,UAAM,SAAS,IAAI,MAAM,UAAU;AACnC,QAAI,QAAQ;AACV,YAAM,SAAuB,CAAC;AAC9B,UAAI,QAAQ;AACZ,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI,KAAM;AACV,iBAAS,MAAM;AACf,YAAI,QAAQ,gBAAgB;AAC1B,gBAAM,OAAO,OAAO;AACpB,iBAAO,QAAQ,0BAA0B,cAAc;AACvD,iBAAO;AAAA,QACT;AACA,eAAO,KAAK,KAAK;AAAA,MACnB;AACA,YAAM,MAAM,OAAO,OAAO,OAAO,IAAI,OAAK,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;AAC5F,YAAM,cAAc,QAAQ,cAAc,KAAK;AAC/C,UAAI,YAAY,SAAS,kBAAkB,GAAG;AAC5C,YAAI;AACF,iBAAO,OAAO,KAAK,MAAM,IAAI,SAAS,MAAM,CAAC;AAAA,QAC/C,QAAQ;AACN,iBAAO,OAAO,IAAI,SAAS,MAAM;AAAA,QACnC;AAAA,MACF,OAAO;AACL,eAAO,OAAO,IAAI,SAAS,MAAM;AAAA,MACnC;AAAA,IACF;AACA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,WAAO,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,WAAO;AAAA,EACT,UAAE;AACA,iBAAa,KAAK;AAClB,WAAO,cAAc,KAAK,IAAI,IAAI;AAClC,UAAM,WAAW,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACzC;AACF;AAUO,SAAS,0BAA0B,aAAyC;AAGjF,QAAM,aAAa,gBAAgB,WAAW;AAC9C,aAAW,aAAa,YAAY;AAClC,QAAI,CAAC,gBAAgB,KAAK,SAAS,EAAG;AACtC,UAAM,IAAI,0BAA0B,KAAK,SAAS;AAClD,QAAI,CAAC,EAAG;AACR,UAAM,QAAQ,EAAE,CAAC;AAIjB,QAAI,SAAS,eAAe,KAAK,KAAK,EAAG,QAAO;AAChD,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAQA,SAAS,gBAAgB,aAA+B;AACtD,QAAM,QAAkB,CAAC;AACzB,MAAI,UAAU;AACd,MAAI,WAAW;AACf,WAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,UAAM,KAAK,YAAY,CAAC;AACxB,QAAI,OAAO,OAAO,YAAY,IAAI,CAAC,MAAM,MAAM;AAC7C,iBAAW,CAAC;AACZ,iBAAW;AACX;AAAA,IACF;AACA,QAAI,CAAC,YAAY,OAAO,KAAK;AAI3B,YAAM,OAAO,YAAY,MAAM,IAAI,CAAC;AACpC,UAAI,+BAA+B,KAAK,IAAI,GAAG;AAC7C,cAAM,KAAK,QAAQ,KAAK,CAAC;AACzB,kBAAU;AACV;AAAA,MACF;AAAA,IACF;AACA,eAAW;AAAA,EACb;AACA,MAAI,QAAQ,KAAK,EAAE,SAAS,EAAG,OAAM,KAAK,QAAQ,KAAK,CAAC;AACxD,SAAO,MAAM,OAAO,OAAK,EAAE,SAAS,CAAC;AACvC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/probe.ts"],"sourcesContent":["import { type LookupAddress, type LookupOptions } from 'dns';\nimport { lookup as dnsLookup } from 'dns/promises';\nimport { Agent, fetch as undiciFetch } from 'undici';\nimport { isAlwaysBlocked, isPrivateIp } from '../probes';\nimport type { SignedHttpRequest } from './builder';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst MAX_BODY_BYTES = 64 * 1024;\n\nexport interface ProbeOptions {\n /** Allow http:// and private-IP destinations. Default false. */\n allowPrivateIp?: boolean;\n /** Per-call timeout override (ms). */\n timeoutMs?: number;\n}\n\nexport interface ProbeResult {\n url: string;\n status: number;\n headers: Record<string, string>;\n /** Error code extracted from `WWW-Authenticate: Signature error=\"<code>\"`. */\n wwwAuthenticateErrorCode?: string;\n /** Truncated response body (first 64 KiB, JSON-parsed if applicable). */\n body: unknown;\n /** Network-level error; non-undefined means the request didn't complete. */\n error?: string;\n duration_ms: number;\n}\n\n/**\n * Send a signed HTTP request to an AdCP agent and capture the response fields\n * needed for conformance grading (status, WWW-Authenticate error code, body).\n *\n * Reuses the SSRF guards from the address classifiers — scheme check,\n * `isAlwaysBlocked`, `isPrivateIp` — then pins the outbound connection to the\n * pre-validated address via an undici dispatcher, defeating DNS rebinding.\n * Bodies are capped at 64 KiB and parsed as JSON when content-type matches;\n * otherwise returned as text. `redirect: 'manual'` is enforced so an agent\n * that 301s can't smuggle the grader elsewhere.\n */\nexport async function probeSignedRequest(signed: SignedHttpRequest, options: ProbeOptions = {}): Promise<ProbeResult> {\n const start = Date.now();\n const timeout = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const result: ProbeResult = { url: signed.url, status: 0, headers: {}, body: null, duration_ms: 0 };\n\n let parsed: URL;\n try {\n parsed = new URL(signed.url);\n } catch {\n result.error = `Invalid URL: ${signed.url}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n result.error = `Refusing to probe URL with unsupported scheme: ${parsed.protocol}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n if (parsed.protocol !== 'https:' && !options.allowPrivateIp) {\n result.error = `Refusing to probe non-HTTPS URL: ${signed.url}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n\n // Strip URL brackets from IPv6 literals (`[::1]` → `::1`) before DNS lookup\n // and address classification. `URL.hostname` wraps IPv6 in brackets; both\n // `dns.lookup` and the address classifiers need the bare form.\n const hostname = parsed.hostname.replace(/^\\[|\\]$/g, '');\n\n let addresses: { address: string; family: number }[];\n try {\n addresses = await dnsLookup(hostname, { all: true });\n } catch (err) {\n result.error = `DNS lookup failed for ${hostname}: ${err instanceof Error ? err.message : String(err)}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n if (addresses.length === 0) {\n result.error = `DNS returned no addresses for ${hostname}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n for (const a of addresses) {\n if (isAlwaysBlocked(a.address)) {\n result.error = `Refusing to probe always-blocked address ${a.address} for ${hostname}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n }\n if (!options.allowPrivateIp) {\n for (const a of addresses) {\n if (isPrivateIp(a.address)) {\n result.error = `Refusing to probe private/loopback address ${a.address} for ${hostname}`;\n result.duration_ms = Date.now() - start;\n return result;\n }\n }\n }\n const pinned = addresses[0]!;\n const pinnedFamily = pinned.family === 6 ? 6 : 4;\n // undici calls lookup with { all: true } for HTTPS targets on Node 22+, which\n // expects the array form of the callback. Handle both shapes so the pin works\n // across Node versions.\n const dispatcher = new Agent({\n connect: {\n lookup: (\n _h: string,\n opts: LookupOptions | undefined,\n cb: (err: NodeJS.ErrnoException | null, address: string | LookupAddress[], family?: number) => void\n ) => {\n if (opts?.all) {\n cb(null, [{ address: pinned.address, family: pinnedFamily }]);\n } else {\n cb(null, pinned.address, pinnedFamily);\n }\n },\n },\n });\n\n const ac = new AbortController();\n const timer = setTimeout(() => ac.abort(), timeout);\n try {\n const res = await undiciFetch(signed.url, {\n method: signed.method,\n redirect: 'manual',\n signal: ac.signal,\n headers: signed.headers,\n body: signed.body,\n dispatcher,\n });\n result.status = res.status;\n const headers: Record<string, string> = {};\n res.headers.forEach((v, k) => {\n headers[k.toLowerCase()] = v;\n });\n result.headers = headers;\n\n const wwwAuth = headers['www-authenticate'];\n if (wwwAuth) {\n result.wwwAuthenticateErrorCode = extractSignatureErrorCode(wwwAuth);\n }\n\n const reader = res.body?.getReader();\n if (reader) {\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n bytes += value.byteLength;\n if (bytes > MAX_BODY_BYTES) {\n await reader.cancel();\n result.error = `Response body exceeded ${MAX_BODY_BYTES} bytes`;\n return result;\n }\n chunks.push(value);\n }\n const buf = Buffer.concat(chunks.map(c => Buffer.from(c.buffer, c.byteOffset, c.byteLength)));\n const contentType = headers['content-type'] ?? '';\n if (contentType.includes('application/json')) {\n try {\n result.body = JSON.parse(buf.toString('utf8'));\n } catch {\n result.body = buf.toString('utf8');\n }\n } else {\n result.body = buf.toString('utf8');\n }\n }\n return result;\n } catch (err) {\n result.error = err instanceof Error ? err.message : String(err);\n return result;\n } finally {\n clearTimeout(timer);\n result.duration_ms = Date.now() - start;\n await dispatcher.close().catch(() => {});\n }\n}\n\n/**\n * Extract `error=\"<code>\"` from a `WWW-Authenticate: Signature ...` header.\n * Returns undefined when the header isn't a Signature challenge, the param\n * is absent, or the extracted value isn't a well-formed spec error code\n * (a token in `[a-z0-9_]+`). Sanitizing at source keeps downstream\n * diagnostics / LLM-consumption paths safe from smuggled content in\n * attacker-controlled header values.\n */\nexport function extractSignatureErrorCode(headerValue: string): string | undefined {\n // `WWW-Authenticate` may carry multiple challenges concatenated with commas.\n // We only grade Signature challenges; ignore Basic/Bearer/etc.\n const challenges = splitChallenges(headerValue);\n for (const challenge of challenges) {\n if (!/^Signature\\b/i.test(challenge)) continue;\n const m = /\\berror\\s*=\\s*\"([^\"]*)\"/.exec(challenge);\n if (!m) continue;\n const value = m[1];\n // Spec error codes are `request_signature_*` — all lowercase-alnum +\n // underscore. Reject anything else so quotes/newlines/HTML/LLM-poisoning\n // content can't flow into diagnostic strings or rendered reports.\n if (value && /^[a-z0-9_]+$/.test(value)) return value;\n return undefined;\n }\n return undefined;\n}\n\n/**\n * Split a `WWW-Authenticate` header into per-challenge chunks. RFC 7235 §4.1\n * lets multiple challenges coexist separated by commas, and challenge params\n * are `k=\"v\"` where `v` can contain commas. Track quote state so an\n * adversarial `error=\"foo, Bar baz\"` doesn't spuriously split mid-value.\n */\nfunction splitChallenges(headerValue: string): string[] {\n const parts: string[] = [];\n let current = '';\n let inQuotes = false;\n for (let i = 0; i < headerValue.length; i++) {\n const ch = headerValue[i]!;\n if (ch === '\"' && headerValue[i - 1] !== '\\\\') {\n inQuotes = !inQuotes;\n current += ch;\n continue;\n }\n if (!inQuotes && ch === ',') {\n // Look ahead for a scheme-like token (`<name><whitespace>`) — only\n // then treat this comma as a challenge boundary; otherwise it's a\n // param-list separator inside the current challenge.\n const rest = headerValue.slice(i + 1);\n if (/^\\s*[A-Za-z][A-Za-z0-9-]*\\s+/.test(rest)) {\n parts.push(current.trim());\n current = '';\n continue;\n }\n }\n current += ch;\n }\n if (current.trim().length > 0) parts.push(current.trim());\n return parts.filter(p => p.length > 0);\n}\n"],"mappings":"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","names":[]}
|