@adcp/sdk 14.0.0-beta.10 → 14.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adcp-storyboard-sandbox.js +16 -0
- package/bin/adcp.js +28 -30
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.d.mts +2 -1
- package/dist/lib/core/SingleAgentClient.d.ts +2 -1
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +113 -64
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +113 -64
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/protocols/a2a.d.mts +10 -3
- package/dist/lib/protocols/a2a.d.ts +10 -3
- package/dist/lib/protocols/a2a.d.ts.map +1 -1
- package/dist/lib/protocols/a2a.js +162 -34
- package/dist/lib/protocols/a2a.js.map +1 -1
- package/dist/lib/protocols/a2a.mjs +166 -34
- package/dist/lib/protocols/a2a.mjs.map +1 -1
- package/dist/lib/schemas/index.d.mts +385 -1
- package/dist/lib/schemas/index.d.ts +385 -1
- package/dist/lib/schemas/index.d.ts.map +1 -1
- package/dist/lib/schemas/index.js +13 -0
- package/dist/lib/schemas/index.js.map +1 -1
- package/dist/lib/schemas/index.mjs +11 -0
- 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.d.mts +59 -33
- package/dist/lib/server/a2a-adapter.d.ts +59 -33
- package/dist/lib/server/a2a-adapter.d.ts.map +1 -1
- package/dist/lib/server/a2a-adapter.js +278 -67
- package/dist/lib/server/a2a-adapter.js.map +1 -1
- package/dist/lib/server/a2a-adapter.mjs +280 -68
- package/dist/lib/server/a2a-adapter.mjs.map +1 -1
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +35 -108
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +37 -109
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.d.mts +2 -0
- package/dist/lib/server/decisioning/index.d.ts +2 -0
- package/dist/lib/server/decisioning/index.d.ts.map +1 -1
- package/dist/lib/server/decisioning/index.js +5 -2
- package/dist/lib/server/decisioning/index.js.map +1 -1
- package/dist/lib/server/decisioning/index.mjs +3 -1
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/response-summary.d.mts +33 -0
- package/dist/lib/server/decisioning/response-summary.d.ts +34 -0
- package/dist/lib/server/decisioning/response-summary.d.ts.map +1 -0
- package/dist/lib/server/decisioning/response-summary.js +62 -0
- package/dist/lib/server/decisioning/response-summary.js.map +1 -0
- package/dist/lib/server/decisioning/response-summary.mjs +37 -0
- package/dist/lib/server/decisioning/response-summary.mjs.map +1 -0
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +27 -5
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +27 -5
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/sales.d.mts +7 -1
- package/dist/lib/server/decisioning/specialisms/sales.d.ts +7 -1
- package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -1
- package/dist/lib/server/index.d.mts +1 -1
- package/dist/lib/server/index.d.ts +1 -1
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/server/responses.d.ts.map +1 -1
- package/dist/lib/server/responses.js +9 -1
- package/dist/lib/server/responses.js.map +1 -1
- package/dist/lib/server/responses.mjs +8 -1
- package/dist/lib/server/responses.mjs.map +1 -1
- package/dist/lib/signing/agent-context.d.mts +1 -0
- package/dist/lib/signing/agent-context.d.ts +1 -0
- package/dist/lib/signing/agent-context.d.ts.map +1 -1
- package/dist/lib/signing/agent-context.js +37 -2
- package/dist/lib/signing/agent-context.js.map +1 -1
- package/dist/lib/signing/agent-context.mjs +38 -3
- package/dist/lib/signing/agent-context.mjs.map +1 -1
- package/dist/lib/signing/agent-fetch.d.mts +1 -2
- package/dist/lib/signing/agent-fetch.d.ts +1 -2
- package/dist/lib/signing/agent-fetch.d.ts.map +1 -1
- package/dist/lib/signing/agent-fetch.js +2 -0
- package/dist/lib/signing/agent-fetch.js.map +1 -1
- package/dist/lib/signing/agent-fetch.mjs +2 -0
- package/dist/lib/signing/agent-fetch.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/etld.js.map +1 -1
- package/dist/lib/signing/agent-resolver/etld.mjs.map +1 -1
- package/dist/lib/testing/client.d.mts +6 -0
- package/dist/lib/testing/client.d.ts +6 -0
- package/dist/lib/testing/client.d.ts.map +1 -1
- package/dist/lib/testing/client.js +76 -4
- package/dist/lib/testing/client.js.map +1 -1
- package/dist/lib/testing/client.mjs +75 -4
- package/dist/lib/testing/client.mjs.map +1 -1
- package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
- package/dist/lib/testing/compliance/comply.js +6 -0
- package/dist/lib/testing/compliance/comply.js.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +7 -1
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/storyboard/context.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/context.js +9 -4
- package/dist/lib/testing/storyboard/context.js.map +1 -1
- package/dist/lib/testing/storyboard/context.mjs +9 -4
- package/dist/lib/testing/storyboard/context.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.js +28 -4
- package/dist/lib/testing/storyboard/request-builder.js.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.mjs +28 -4
- package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.d.mts +15 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.d.ts +16 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.js +106 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.js.map +1 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.mjs +82 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.mjs.map +1 -0
- package/dist/lib/testing/storyboard/request-signing/test-kit.d.mts +15 -0
- package/dist/lib/testing/storyboard/request-signing/test-kit.d.ts +15 -0
- package/dist/lib/testing/storyboard/request-signing/test-kit.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/test-kit.js +58 -0
- package/dist/lib/testing/storyboard/request-signing/test-kit.js.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs +58 -0
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.d.mts +2 -0
- package/dist/lib/testing/storyboard/request-signing/vector-loader.d.ts +2 -0
- package/dist/lib/testing/storyboard/request-signing/vector-loader.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.js +7 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.js.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +6 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +31 -7
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +31 -7
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/validations.js +18 -7
- package/dist/lib/testing/storyboard/validations.js.map +1 -1
- package/dist/lib/testing/storyboard/validations.mjs +18 -7
- package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.js +32 -20
- package/dist/lib/testing/storyboard/webhook-receiver.js.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.mjs +32 -20
- package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
- package/dist/lib/testing/types.d.mts +10 -0
- package/dist/lib/testing/types.d.ts +10 -0
- package/dist/lib/testing/types.d.ts.map +1 -1
- package/dist/lib/testing/types.js.map +1 -1
- package/dist/lib/types/comply-test-controller.d.ts +1 -14
- package/dist/lib/types/core.generated.d.mts +1 -1
- package/dist/lib/types/core.generated.d.ts +1 -1
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js.map +1 -1
- package/dist/lib/types/get-products.d.ts +1 -14
- package/dist/lib/types/schemas.generated.d.ts +519 -571
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +2 -2
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +2 -2
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/tools.generated.d.mts +1 -1
- package/dist/lib/types/tools.generated.d.ts +1 -1
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/types/tools.generated.js.map +1 -1
- package/dist/lib/utils/a2a-artifacts.d.ts.map +1 -1
- package/dist/lib/utils/a2a-artifacts.js +2 -2
- package/dist/lib/utils/a2a-artifacts.js.map +1 -1
- package/dist/lib/utils/a2a-artifacts.mjs +2 -2
- package/dist/lib/utils/a2a-artifacts.mjs.map +1 -1
- package/dist/lib/utils/a2a-discovery.d.mts +3 -3
- package/dist/lib/utils/a2a-discovery.d.ts +3 -3
- package/dist/lib/utils/a2a-discovery.js +1 -1
- package/dist/lib/utils/a2a-discovery.js.map +1 -1
- package/dist/lib/utils/a2a-discovery.mjs +1 -1
- package/dist/lib/utils/a2a-discovery.mjs.map +1 -1
- package/dist/lib/utils/tool-request-schemas.d.mts +31 -31
- package/dist/lib/utils/tool-request-schemas.d.ts +31 -31
- package/dist/lib/v2/projection/index.d.mts +2 -0
- package/dist/lib/v2/projection/index.d.ts +2 -0
- package/dist/lib/v2/projection/index.d.ts.map +1 -1
- package/dist/lib/v2/projection/index.js +3 -0
- package/dist/lib/v2/projection/index.js.map +1 -1
- package/dist/lib/v2/projection/index.mjs +2 -0
- package/dist/lib/v2/projection/index.mjs.map +1 -1
- package/dist/lib/v2/projection/legacy-normalization.d.mts +24 -0
- package/dist/lib/v2/projection/legacy-normalization.d.ts +25 -0
- package/dist/lib/v2/projection/legacy-normalization.d.ts.map +1 -0
- package/dist/lib/v2/projection/legacy-normalization.js +32 -0
- package/dist/lib/v2/projection/legacy-normalization.js.map +1 -0
- package/dist/lib/v2/projection/legacy-normalization.mjs +8 -0
- package/dist/lib/v2/projection/legacy-normalization.mjs.map +1 -0
- 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 -3
- package/dist/lib/version.mjs.map +1 -1
- package/docs/guides/BUILD-AN-AGENT.md +42 -6
- package/docs/llms.txt +2 -2
- package/docs/migration-13-to-14.md +17 -0
- package/package.json +44 -41
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/server/responses.ts"],"sourcesContent":["/**\n * Typed response builders for AdCP MCP servers.\n *\n * @deprecated For new code, use `createAdcpServerFromPlatform` from\n * `@adcp/sdk/server` instead — it constructs wire responses internally\n * from your typed `DecisioningPlatform` return values, so adopters don't\n * touch these builders. The functions below remain exported for v5\n * adopters wiring raw MCP tool handlers (mid-migration), and for adopters\n * shaping bespoke tools the platform interface doesn't yet model. For new\n * v6 adopters, ignore this whole module — the framework handles wire\n * shaping.\n *\n * Each function takes typed data (compile-time checked against AdCP schemas)\n * and returns an MCP-compatible tool response with `content` (text summary)\n * + `structuredContent` (typed payload).\n *\n * The input parameter enforces the AdCP schema shape at compile time.\n * The return type is compatible with MCP SDK's CallToolResult.\n *\n * @example\n * ```typescript\n * import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\n * import { legacyCapabilitiesResponse, legacyProductsResponse, adcpError } from '@adcp/sdk/server';\n * import { GetProductsRequestSchema } from '@adcp/sdk/schemas';\n *\n * const server = new McpServer({ name: 'My Agent', version: '1.0.0' });\n *\n * server.registerTool(\n * 'get_adcp_capabilities',\n * { inputSchema: {} },\n * async () => capabilitiesResponse({ supported_protocols: ['media_buy'] })\n * );\n *\n * server.registerTool(\n * 'get_products',\n * { inputSchema: GetProductsRequestSchema.shape },\n * async (params) => legacyProductsResponse({ products: myProducts, cache_scope: 'account' })\n * );\n * ```\n */\n\nimport type { GetAdCPCapabilitiesResponse } from '../types/tools.generated';\nimport type { GetMediaBuyDeliveryResponse } from '../types/tools.generated';\nimport type { RequireCacheScopeWhenProducts, ServerPayload } from '../types/server-payload';\nimport { validActionsForStatus } from './media-buy-helpers';\nimport type { CancelMediaBuyInput } from './media-buy-helpers';\nimport type {\n ListCreativeFormatsResponse,\n GetProductsResponse,\n CreateMediaBuySuccess,\n UpdateMediaBuySuccess,\n GetMediaBuysResponse,\n ProvidePerformanceFeedbackSuccess,\n BuildCreativeSuccess,\n BuildCreativeMultiSuccess,\n PreviewCreativeSingleResponse,\n PreviewCreativeBatchResponse,\n PreviewCreativeVariantResponse,\n GetCreativeDeliveryResponse,\n ListCreativesResponse,\n SyncCreativesError,\n SyncCreativesSuccess,\n GetSignalsResponse,\n ActivateSignalSuccess,\n ListAccountsResponse,\n ListPropertyListsResponse,\n ListCollectionListsResponse,\n ListContentStandardsResponse,\n GetPlanAuditLogsResponse,\n ReportUsageRequest,\n ReportUsageResponse,\n SyncAccountsResponse,\n SyncGovernanceResponse,\n} from '../types/tools.generated';\nimport type {\n AcquireRightsResponse,\n AcquireRightsAcquired,\n AcquireRightsPendingApproval,\n AcquireRightsRejected,\n UpdateRightsResponse,\n UpdateRightsSuccess,\n CreativeApprovalResponse,\n CreativeApproved,\n CreativeRejected,\n CreativePendingReview,\n CreativeApprovalError,\n} from '../types/core.generated';\n\n/**\n * MCP-compatible tool response shape.\n *\n * `structuredContent` is optional because error responses legitimately carry\n * only `content` (the human-readable error text) — forcing every wrapper to\n * fabricate an empty structuredContent obscures the success/error split.\n * All success builders in this file still populate it.\n *\n * Uses Record<string, unknown> for structuredContent to satisfy\n * MCP SDK's CallToolResult index signature requirement.\n */\nexport interface McpToolResponse {\n [key: string]: unknown;\n content: Array<{ type: 'text'; text: string }>;\n structuredContent?: Record<string, unknown>;\n}\n\n// MCP SDK requires structuredContent to have an index signature ({ [x: string]: unknown }).\n// Generated AdCP types are TypeScript interfaces without index signatures. At runtime,\n// JSON objects are always Records — this bridge is safe.\nexport function toStructuredContent(data: object): Record<string, unknown> {\n return data as unknown as Record<string, unknown>;\n}\n\nconst MEDIA_BUY_STATUS_VALUES = new Set([\n 'pending_creatives',\n 'pending_start',\n 'active',\n 'paused',\n 'completed',\n 'rejected',\n 'canceled',\n]);\n\nfunction completedStructuredContent(data: object, opts?: { splitMediaBuyStatus?: boolean }): Record<string, unknown> {\n const structured = { ...toStructuredContent(data) };\n if (\n opts?.splitMediaBuyStatus === true &&\n typeof structured.status === 'string' &&\n MEDIA_BUY_STATUS_VALUES.has(structured.status)\n ) {\n if (structured.media_buy_status === undefined) structured.media_buy_status = structured.status;\n delete structured.status;\n }\n if (structured.status === undefined) structured.status = 'completed';\n return structured;\n}\n\nfunction failedStructuredContent(data: object): Record<string, unknown> {\n const structured = { ...toStructuredContent(data) };\n if (structured.status === undefined) structured.status = 'failed';\n return structured;\n}\n\nfunction stripNotificationConfigSecrets<T extends object>(row: T): T {\n const notificationConfigs = (row as { notification_configs?: unknown }).notification_configs;\n if (!Array.isArray(notificationConfigs)) return row;\n return {\n ...row,\n notification_configs: notificationConfigs.map(config => {\n if (config == null || typeof config !== 'object') return config;\n const authentication = (config as { authentication?: unknown }).authentication;\n if (authentication == null || typeof authentication !== 'object') return config;\n const { credentials: _credentials, ...authenticationWithoutCredentials } = authentication as Record<\n string,\n unknown\n >;\n const stripped = { ...(config as Record<string, unknown>) };\n if (Object.keys(authenticationWithoutCredentials).length > 0) {\n stripped.authentication = authenticationWithoutCredentials;\n } else {\n delete stripped.authentication;\n }\n return stripped;\n }),\n };\n}\n\nfunction stripBusinessEntityBank<T extends object>(row: T, key: 'billing_entity' | 'invoice_recipient'): T {\n const entity = (row as Record<string, unknown>)[key];\n if (entity == null || typeof entity !== 'object') return row;\n if (!('bank' in entity)) return row;\n const { bank: _bank, ...entityWithoutBank } = entity as Record<string, unknown>;\n const stripped = { ...row } as Record<string, unknown>;\n if (Object.keys(entityWithoutBank).length > 0) {\n stripped[key] = entityWithoutBank;\n } else {\n delete stripped[key];\n }\n return stripped as T;\n}\n\nfunction stripAccountWriteOnlyFields<T extends object>(account: T): T {\n return stripBusinessEntityBank(stripNotificationConfigSecrets(account), 'billing_entity');\n}\n\nfunction stripAccountsWriteOnlyFields<T extends { accounts?: unknown }>(data: T): T {\n if (!Array.isArray(data.accounts)) return data;\n return {\n ...data,\n accounts: data.accounts.map(account =>\n account != null && typeof account === 'object' ? stripAccountWriteOnlyFields(account) : account\n ),\n };\n}\n\nfunction stripMediaBuyWriteOnlyFields<T extends object>(buy: T): T {\n let stripped = stripBusinessEntityBank(buy, 'invoice_recipient');\n const account = (stripped as { account?: unknown }).account;\n if (account == null || typeof account !== 'object') return stripped;\n return {\n ...stripped,\n account: stripAccountWriteOnlyFields(account),\n };\n}\n\nfunction stripMediaBuysWriteOnlyFields<T extends { media_buys?: unknown }>(data: T): T {\n if (!Array.isArray(data.media_buys)) return data;\n return {\n ...data,\n media_buys: data.media_buys.map(buy =>\n buy != null && typeof buy === 'object' ? stripMediaBuyWriteOnlyFields(buy) : buy\n ),\n };\n}\n\n// `setup` is only ever nested inside an `Account` (the IO-signing / pending_approval\n// path). A top-level `setup` on a media buy response means the builder read the\n// storyboard's \"setup.url\" shorthand as a top-level field. The strict handler types\n// would catch this, but `DomainHandler` accepts `Record<string, unknown>` for DX,\n// so the error has to move to runtime.\nfunction assertNoTopLevelSetup(data: unknown, builder: string): void {\n if (data != null && typeof data === 'object' && 'setup' in data) {\n throw new Error(\n `${builder}: \\`setup\\` is not a field on the media buy — it belongs inside \\`account.setup\\`. ` +\n `Move \\`{ setup: { url, message } }\\` to \\`{ account: { ..., setup: { url, message } } }\\`. ` +\n `The setup URL is a property of the Account (returned alongside \\`status: 'pending_approval'\\`), not the MediaBuy.`\n );\n }\n}\n\n/**\n * Build a get_adcp_capabilities response.\n *\n * `supported_protocols` lists AdCP domain protocols (media_buy, signals, governance, etc.),\n * NOT transport protocols (mcp, a2a).\n *\n * Stamps the v3 protocol envelope's required `status: \"completed\"` field at\n * the top level of `structuredContent`. Synchronous task responses MUST carry\n * `status` per `protocol-envelope.json` (AdCP #4876); without it the\n * `v3_envelope_integrity/no_legacy_status_fields` conformance step fails.\n * The status is injected here rather than added to `GetAdCPCapabilitiesResponse`\n * because it's an envelope concern, not a payload field — the wire shape and\n * the typed payload model live at different layers.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function capabilitiesResponse(\n data: ServerPayload<GetAdCPCapabilitiesResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [{ type: 'text', text: summary ?? 'Agent capabilities retrieved' }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a get_products response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function productsResponse(\n data: RequireCacheScopeWhenProducts<ServerPayload<GetProductsResponse>>,\n summary?: string\n): McpToolResponse {\n const structured = completedStructuredContent(data);\n const defaultSummary =\n data.unchanged === true ? 'Product feed unchanged' : `Found ${(data.products ?? []).length} products`;\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: structured,\n };\n}\n\n/**\n * Build a successful create_media_buy response.\n *\n * Applies protocol defaults when not explicitly provided:\n * - `revision` defaults to `1` (initial revision for optimistic concurrency)\n * - `confirmed_at` defaults to the current ISO 8601 timestamp\n * - `valid_actions` populated from status via `validActionsForStatus()` when\n * `status` is provided but `valid_actions` is not\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function mediaBuyResponse(data: ServerPayload<CreateMediaBuySuccess>, summary?: string): McpToolResponse {\n assertNoTopLevelSetup(data, 'mediaBuyResponse');\n const withDefaults = { ...stripMediaBuyWriteOnlyFields(data) };\n const legacyStatus = (withDefaults as typeof withDefaults & { status?: unknown }).status;\n if (withDefaults.media_buy_status == null && typeof legacyStatus === 'string') {\n withDefaults.media_buy_status = legacyStatus as NonNullable<typeof withDefaults.media_buy_status>;\n }\n if (withDefaults.revision === undefined) {\n withDefaults.revision = 1;\n }\n if (withDefaults.confirmed_at === undefined) {\n withDefaults.confirmed_at = new Date().toISOString();\n }\n if (withDefaults.valid_actions === undefined && withDefaults.media_buy_status != null) {\n withDefaults.valid_actions = validActionsForStatus(withDefaults.media_buy_status);\n }\n return {\n content: [{ type: 'text', text: summary ?? `Media buy ${withDefaults.media_buy_id} created` }],\n structuredContent: completedStructuredContent(withDefaults, { splitMediaBuyStatus: true }),\n };\n}\n\n/**\n * Build a get_media_buy_delivery response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function deliveryResponse(data: ServerPayload<GetMediaBuyDeliveryResponse>, summary?: string): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text:\n summary ??\n `Delivery data for ${data.media_buy_deliveries.length} media buy${data.media_buy_deliveries.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a list_accounts response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listAccountsResponse(data: ServerPayload<ListAccountsResponse>, summary?: string): McpToolResponse {\n const stripped = stripAccountsWriteOnlyFields(data);\n return {\n content: [{ type: 'text', text: summary ?? `Found ${stripped.accounts.length} accounts` }],\n structuredContent: completedStructuredContent(stripped),\n };\n}\n\n/**\n * Build a list_creative_formats response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listCreativeFormatsResponse(\n data: ServerPayload<ListCreativeFormatsResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [{ type: 'text', text: summary ?? `Found ${data.formats.length} creative formats` }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a successful update_media_buy response.\n *\n * When `media_buy_status` is provided but `valid_actions` is not, auto-populates\n * `valid_actions` from `validActionsForStatus()`.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function updateMediaBuyResponse(data: ServerPayload<UpdateMediaBuySuccess>, summary?: string): McpToolResponse {\n assertNoTopLevelSetup(data, 'updateMediaBuyResponse');\n const withDefaults = { ...stripBusinessEntityBank(data, 'invoice_recipient') };\n const legacyStatus = (withDefaults as typeof withDefaults & { status?: unknown }).status;\n if (withDefaults.media_buy_status == null && typeof legacyStatus === 'string') {\n withDefaults.media_buy_status = legacyStatus as NonNullable<typeof withDefaults.media_buy_status>;\n }\n if (withDefaults.valid_actions === undefined && withDefaults.media_buy_status != null) {\n withDefaults.valid_actions = validActionsForStatus(withDefaults.media_buy_status);\n }\n return {\n content: [{ type: 'text', text: summary ?? `Media buy ${withDefaults.media_buy_id} updated` }],\n structuredContent: completedStructuredContent(withDefaults, { splitMediaBuyStatus: true }),\n };\n}\n\n/**\n * Build a get_media_buys response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function getMediaBuysResponse(data: ServerPayload<GetMediaBuysResponse>, summary?: string): McpToolResponse {\n if (Array.isArray(data.media_buys)) {\n for (const buy of data.media_buys) {\n assertNoTopLevelSetup(buy, 'getMediaBuysResponse');\n }\n }\n const stripped = stripMediaBuysWriteOnlyFields(data);\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Found ${stripped.media_buys.length} media buy${stripped.media_buys.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(stripped),\n };\n}\n\n/**\n * Build a successful provide_performance_feedback response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function performanceFeedbackResponse(\n data: ServerPayload<ProvidePerformanceFeedbackSuccess>,\n summary?: string\n): McpToolResponse {\n return {\n content: [{ type: 'text', text: summary ?? 'Performance feedback accepted' }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a successful build_creative response (single format).\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function buildCreativeResponse(data: ServerPayload<BuildCreativeSuccess>, summary?: string): McpToolResponse {\n // Optional-chain the default summary — handler responses that drop\n // `format_id` still reach the wire-level schema validator (which names\n // the missing field), instead of crashing the dispatcher here with an\n // opaque `Cannot read properties of undefined (reading 'id')`.\n const formatId = data.creative_manifest?.format_id?.id;\n return {\n content: [{ type: 'text', text: summary ?? (formatId ? `Creative built: ${formatId}` : 'Creative built') }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a successful build_creative response (multi-format).\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function buildCreativeMultiResponse(\n data: ServerPayload<BuildCreativeMultiSuccess>,\n summary?: string\n): McpToolResponse {\n const count = data.creative_manifests?.length ?? 0;\n return {\n content: [{ type: 'text', text: summary ?? `Built ${count} creative formats` }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a preview_creative response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function previewCreativeResponse(\n data: PreviewCreativeSingleResponse | PreviewCreativeBatchResponse | PreviewCreativeVariantResponse,\n summary?: string\n): McpToolResponse {\n const defaultSummary =\n data.response_type === 'single'\n ? (() => {\n const n = (data as PreviewCreativeSingleResponse).previews.length;\n return `Preview generated: ${n} variant${n === 1 ? '' : 's'}`;\n })()\n : data.response_type === 'batch'\n ? (() => {\n const n = (data as PreviewCreativeBatchResponse).results.length;\n return `Batch preview: ${n} result${n === 1 ? '' : 's'}`;\n })()\n : `Variant preview generated`;\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a get_creative_delivery response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function creativeDeliveryResponse(\n data: ServerPayload<GetCreativeDeliveryResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [{ type: 'text', text: summary ?? `Creative delivery data for ${data.currency} report` }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a list_creatives response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listCreativesResponse(data: ServerPayload<ListCreativesResponse>, summary?: string): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text:\n summary ?? `Found ${data.query_summary.total_matching} creatives (${data.query_summary.returned} returned)`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a list_property_lists response. The governance property-list catalog\n * is returned under the required `lists` wrapper — use this helper so\n * handlers can't accidentally emit a bare array at the top level (which the\n * storyboard runner flags as shape drift).\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listPropertyListsResponse(\n data: ServerPayload<ListPropertyListsResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Found ${data.lists.length} property list${data.lists.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a list_collection_lists response. Companion to\n * `listPropertyListsResponse` — same `lists` wrapper shape; parallel\n * governance surface for program-level collections.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listCollectionListsResponse(\n data: ServerPayload<ListCollectionListsResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Found ${data.lists.length} collection list${data.lists.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a list_content_standards response. The response type is a union\n * (success branch with `standards` array, error branch with `errors`) —\n * the helper wraps either shape verbatim; schema-level invariants are\n * enforced at wire validation, not here.\n *\n * Discriminates on `'standards' in data` rather than `'errors' in data` so\n * a legitimate success response that happens to carry advisory `errors`\n * still gets a counted summary. The error-only text fires only when\n * `standards` is absent. Mirrors `acquireRightsResponse`'s success-first\n * discrimination pattern a few screens down.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listContentStandardsResponse(\n data: ServerPayload<ListContentStandardsResponse>,\n summary?: string\n): McpToolResponse {\n const defaultSummary =\n 'standards' in data\n ? `Found ${data.standards.length} content standard${data.standards.length === 1 ? '' : 's'}`\n : 'Content standards lookup error';\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a get_plan_audit_logs response. Wraps the audit data array under\n * the required `plans` key — handlers that return a bare array trip the\n * storyboard runner's shape-drift hint.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function getPlanAuditLogsResponse(\n data: ServerPayload<GetPlanAuditLogsResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Audit data for ${data.plans.length} plan${data.plans.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\ntype SyncCreativesResponsePayload = ServerPayload<SyncCreativesSuccess> | ServerPayload<SyncCreativesError>;\n\nfunction isSyncCreativesErrorPayload(data: SyncCreativesResponsePayload): data is ServerPayload<SyncCreativesError> {\n return (\n Array.isArray((data as { errors?: unknown }).errors) && !Array.isArray((data as { creatives?: unknown }).creatives)\n );\n}\n\n/**\n * Build a sync_creatives response. Accepts both row-level success payloads\n * and operation-level error payloads. If a payload includes `creatives`, the\n * builder treats it as success-shaped even when advisory row errors are also\n * present; operation-level errors are the errors-only arm.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function syncCreativesResponse(data: SyncCreativesResponsePayload, summary?: string): McpToolResponse {\n if (isSyncCreativesErrorPayload(data)) {\n const firstError = data.errors[0];\n const defaultSummary = firstError ? `${firstError.code}: ${firstError.message}` : 'Sync creatives failed';\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n isError: true,\n structuredContent: failedStructuredContent(data),\n };\n }\n\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Synced ${data.creatives.length} creative${data.creatives.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a get_signals response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function getSignalsResponse(data: ServerPayload<GetSignalsResponse>, summary?: string): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Found ${(data.signals ?? []).length} signal${(data.signals ?? []).length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a successful activate_signal response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function activateSignalResponse(data: ServerPayload<ActivateSignalSuccess>, summary?: string): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text:\n summary ??\n `Signal activated across ${data.deployments.length} deployment${data.deployments.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a cancel response for update_media_buy with action: 'cancel'.\n *\n * Eliminates the cancellation metadata trap by requiring `canceled_by`\n * and auto-setting `canceled_at`, `status: 'canceled'`, and `valid_actions: []`.\n *\n * Note: `cancellation` is not yet on the `UpdateMediaBuySuccess` generated type\n * (it exists on the full `MediaBuy` entity). This builder constructs the response\n * as a plain object to include it. When the upstream schema adds `cancellation`\n * to the update response, this can be tightened.\n *\n * @example\n * ```typescript\n * server.registerTool(\n * 'update_media_buy',\n * { inputSchema: UpdateMediaBuyRequestSchema.shape },\n * async (params) => {\n * if (params.action === 'cancel') {\n * return cancelMediaBuyResponse({\n * media_buy_id: params.media_buy_id,\n * canceled_by: 'buyer',\n * revision: currentRevision + 1,\n * });\n * }\n * // ... handle other actions\n * }\n * );\n * ```\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function cancelMediaBuyResponse(input: CancelMediaBuyInput, summary?: string): McpToolResponse {\n const cancellation: Record<string, unknown> = {\n canceled_at: input.canceled_at ?? new Date().toISOString(),\n canceled_by: input.canceled_by,\n };\n if (input.reason !== undefined) {\n cancellation.reason = input.reason;\n }\n\n const data: Record<string, unknown> = {\n media_buy_id: input.media_buy_id,\n status: 'canceled',\n valid_actions: [],\n revision: input.revision,\n cancellation,\n };\n if (input.affected_packages !== undefined) {\n data.affected_packages = input.affected_packages;\n }\n if (input.sandbox !== undefined) {\n data.sandbox = input.sandbox;\n }\n\n return {\n content: [{ type: 'text', text: summary ?? `Media buy ${input.media_buy_id} canceled` }],\n structuredContent: completedStructuredContent(data, { splitMediaBuyStatus: true }),\n };\n}\n\n/**\n * Build an `acquire_rights` response. Thin envelope wrapper — enforces the\n * discriminated union on `status` at the type level, wraps the domain object\n * in `content` + `structuredContent`, nothing else. Schema-level constraints\n * (credential length, schemes cardinality, required-field presence) belong\n * in wire-level Zod validation, not here.\n *\n * Enable dev-time enforcement via\n * `createAdcpServer({ validation: { responses: 'strict' } })` until it\n * becomes the default.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function acquireRightsResponse(data: ServerPayload<AcquireRightsResponse>, summary?: string): McpToolResponse {\n const dataAsAny = data as AcquireRightsResponse & { rights_status?: string; rights_id?: string };\n const defaultSummary =\n 'errors' in data\n ? 'Rights acquisition error'\n : dataAsAny.rights_status === 'acquired'\n ? `Rights ${dataAsAny.rights_id} acquired`\n : dataAsAny.rights_status === 'rejected'\n ? `Rights ${dataAsAny.rights_id} rejected`\n : `Rights ${dataAsAny.rights_id} pending approval`;\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Per-variant constructor — builds an `AcquireRightsAcquired` success response\n * and wraps it. Cleaner autocomplete than `acquireRightsResponse({ rights_status: 'acquired', ... })`\n * because a coding agent typing `acquireRightsAcqu…` gets the required-fields\n * shape directly without reading a 4-variant union.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function acquireRightsAcquired(\n data: Omit<AcquireRightsAcquired, 'rights_status'>,\n summary?: string\n): McpToolResponse {\n return acquireRightsResponse({ ...data, rights_status: 'acquired' } as unknown as AcquireRightsResponse, summary);\n}\n\n/** Per-variant constructor for the `pending_approval` branch. */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function acquireRightsPendingApproval(\n data: Omit<AcquireRightsPendingApproval, 'rights_status'>,\n summary?: string\n): McpToolResponse {\n return acquireRightsResponse(\n { ...data, rights_status: 'pending_approval' } as unknown as AcquireRightsResponse,\n summary\n );\n}\n\n/** Per-variant constructor for the `rejected` branch. */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function acquireRightsRejected(\n data: Omit<AcquireRightsRejected, 'rights_status'>,\n summary?: string\n): McpToolResponse {\n return acquireRightsResponse({ ...data, rights_status: 'rejected' } as unknown as AcquireRightsResponse, summary);\n}\n\n/**\n * Build an `update_rights` response. Wraps a `UpdateRightsResponse` (success\n * or error arm — discriminated structurally on `errors` presence) in the\n * standard `content` + `structuredContent` envelope. The framework auto-\n * applies this wrapper for v6 typed-platform handlers; direct callers are\n * v5 raw-handler adopters only.\n *\n * Mirrors `acquireRightsResponse`'s shape conventions (success-first\n * default summary, error pass-through).\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function updateRightsResponse(data: ServerPayload<UpdateRightsResponse>, summary?: string): McpToolResponse {\n const defaultSummary =\n 'errors' in data\n ? 'Rights update error'\n : data.implementation_date == null\n ? `Rights ${data.rights_id} update pending approval`\n : `Rights ${data.rights_id} updated`;\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Per-variant constructor for the success arm. The wire spec doesn't\n * carry a `status` discriminator on `update_rights` (unlike\n * `acquire_rights`); success is identified structurally by absence of\n * `errors`. The narrow constructor is still useful — it gives autocomplete\n * the success-shape fields (`terms`, `generation_credentials`,\n * `rights_constraint`) without crossing the union.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function updateRightsSuccess(data: ServerPayload<UpdateRightsSuccess>, summary?: string): McpToolResponse {\n return updateRightsResponse(data as unknown as UpdateRightsResponse, summary);\n}\n\n/**\n * Build a `creative_approval` webhook response.\n *\n * Unlike the other builders in this module, `creative_approval` is NOT an\n * MCP/A2A tool — the spec models it as an HTTP webhook. The buyer POSTs\n * a `CreativeApprovalRequest` to the `approval_webhook` URL returned in\n * `acquire_rights`; the brand-rights agent reviews and returns one of four\n * arms (Approved / Rejected / PendingReview / Error). Adopters wire this\n * builder into their HTTP server's response path — see the\n * `BrandRightsPlatform.reviewCreativeApproval` Platform method and the\n * skill at `skills/build-brand-rights-agent/SKILL.md` for the receiver\n * pattern.\n *\n * Returns the raw JSON-serializable payload, NOT an `McpToolResponse` —\n * webhooks have no `content` envelope. Adopters serialize this to JSON and\n * write to the HTTP response body.\n */\nexport function creativeApprovalResponse(data: CreativeApprovalResponse): CreativeApprovalResponse {\n return data;\n}\n\n/** Per-variant constructor for the `approved` branch — webhook payload. */\nexport function creativeApprovalApproved(data: Omit<CreativeApproved, 'status'>): CreativeApproved {\n return { ...data, status: 'approved' } as CreativeApproved;\n}\n\n/** Per-variant constructor for the `rejected` branch — webhook payload. */\nexport function creativeApprovalRejected(data: Omit<CreativeRejected, 'status'>): CreativeRejected {\n return { ...data, status: 'rejected' } as CreativeRejected;\n}\n\n/** Per-variant constructor for the `pending_review` branch — webhook payload. */\nexport function creativeApprovalPendingReview(data: Omit<CreativePendingReview, 'status'>): CreativePendingReview {\n return { ...data, status: 'pending_review' } as CreativePendingReview;\n}\n\n/** Per-variant constructor for the multi-error arm — webhook payload. */\nexport function creativeApprovalError(data: CreativeApprovalError): CreativeApprovalError {\n return data;\n}\n\n/**\n * Build a `sync_accounts` response. Thin envelope wrapper accepting the full\n * `SyncAccountsResponse` union; error payloads pass through.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function syncAccountsResponse(data: ServerPayload<SyncAccountsResponse>, summary?: string): McpToolResponse {\n const stripped = 'accounts' in data ? stripAccountsWriteOnlyFields(data) : data;\n const defaultSummary =\n 'errors' in stripped\n ? 'Account sync error'\n : `Synced ${stripped.accounts?.length ?? 0} account${stripped.accounts?.length === 1 ? '' : 's'}`;\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: completedStructuredContent(stripped),\n };\n}\n\n/**\n * Build a sync_governance response. The spec permits two top-level shapes\n * (success / error); the type union enforces discrimination on `status`.\n *\n * Strips `governance_agents[i].authentication` from every row before emit:\n * the spec marks `authentication.credentials` write-only (the buyer sends\n * the bearer; the seller persists it for outbound `check_governance` calls\n * but MUST NOT echo it back). The natural `{ ...entry.governance_agents[i] }`\n * echo idiom would compile silently against the typed return shape and ship\n * credentials over the wire AND into the idempotency replay cache, arming\n * the buyer (and any subsequent caller hitting the same key) to impersonate\n * the seller against the governance agent. Strip is enforced at the wire-\n * emit boundary so both v5 (`opts.accounts.syncGovernance`) and v6\n * (`AccountStore.syncGovernance`) paths are protected.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function syncGovernanceResponse(data: ServerPayload<SyncGovernanceResponse>, summary?: string): McpToolResponse {\n const stripped = stripGovernanceAgentSecrets(data);\n return {\n content: [{ type: 'text', text: summary ?? 'Governance registration synced' }],\n structuredContent: completedStructuredContent(stripped),\n };\n}\n\nfunction stripGovernanceAgentSecrets(\n data: ServerPayload<SyncGovernanceResponse>\n): ServerPayload<SyncGovernanceResponse> {\n if (!('accounts' in data) || !Array.isArray(data.accounts)) return data;\n return {\n ...data,\n accounts: data.accounts.map(row => {\n if (!row.governance_agents) return row;\n return {\n ...row,\n // AdCP 3.1.0-beta.2 narrowed the wire shape to `{ url }` only;\n // `categories` was removed (per-agent category signaling moved\n // out of band) and `authentication` remains write-only. Project\n // explicitly to defeat JS / `as any` smuggling of either field.\n governance_agents: row.governance_agents.map(a => ({ url: a.url })),\n };\n }),\n };\n}\n\n/**\n * Build a `report_usage` response. Thin envelope wrapper. Schema-level\n * `accepted` requiredness is enforced at the type level (via\n * `ReportUsageResponse.accepted: number`) and at wire-level validation;\n * this builder does not re-assert it.\n *\n * @example\n * ```typescript\n * // Explicit:\n * reportUsage: async (params) =>\n * reportUsageResponse({ accepted: 8, errors: [{ usage_index: 2, message: 'invalid' }] })\n *\n * // Ack every usage[] row with optional errors (shortcut):\n * reportUsage: async (params) => reportUsageResponse.acceptAll(params)\n * ```\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function reportUsageResponse(data: ServerPayload<ReportUsageResponse>, summary?: string): McpToolResponse {\n return {\n content: [\n { type: 'text', text: summary ?? `Accepted ${data.accepted} usage record${data.accepted === 1 ? '' : 's'}` },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Shortcut for the common case: accept all rows in the request, optionally\n * minus any `errors[]` the caller computed. Sets\n * `accepted = (request.usage?.length ?? 0) - errors.length`.\n *\n * Use with honest errors — passing no `errors` when rows failed validation\n * is lying to buyers and the audit trail.\n */\nreportUsageResponse.acceptAll = function acceptAll(\n request: ReportUsageRequest,\n opts?: { errors?: ReportUsageResponse['errors']; summary?: string }\n): McpToolResponse {\n const total = request.usage?.length ?? 0;\n const errors = opts?.errors ?? [];\n const accepted = Math.max(0, total - errors.length);\n return reportUsageResponse(\n {\n status: errors.length > 0 ? 'failed' : 'completed',\n accepted,\n ...(errors.length > 0 ? { errors } : {}),\n } as ReportUsageResponse,\n opts?.summary\n );\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/server/responses.ts"],"sourcesContent":["/**\n * Typed response builders for AdCP MCP servers.\n *\n * @deprecated For new code, use `createAdcpServerFromPlatform` from\n * `@adcp/sdk/server` instead — it constructs wire responses internally\n * from your typed `DecisioningPlatform` return values, so adopters don't\n * touch these builders. The functions below remain exported for v5\n * adopters wiring raw MCP tool handlers (mid-migration), and for adopters\n * shaping bespoke tools the platform interface doesn't yet model. For new\n * v6 adopters, ignore this whole module — the framework handles wire\n * shaping.\n *\n * Each function takes typed data (compile-time checked against AdCP schemas)\n * and returns an MCP-compatible tool response with `content` (text summary)\n * + `structuredContent` (typed payload).\n *\n * The input parameter enforces the AdCP schema shape at compile time.\n * The return type is compatible with MCP SDK's CallToolResult.\n *\n * @example\n * ```typescript\n * import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\n * import { legacyCapabilitiesResponse, legacyProductsResponse, adcpError } from '@adcp/sdk/server';\n * import { GetProductsRequestSchema } from '@adcp/sdk/schemas';\n *\n * const server = new McpServer({ name: 'My Agent', version: '1.0.0' });\n *\n * server.registerTool(\n * 'get_adcp_capabilities',\n * { inputSchema: {} },\n * async () => capabilitiesResponse({ supported_protocols: ['media_buy'] })\n * );\n *\n * server.registerTool(\n * 'get_products',\n * { inputSchema: GetProductsRequestSchema.shape },\n * async (params) => legacyProductsResponse({ products: myProducts, cache_scope: 'account' })\n * );\n * ```\n */\n\nimport type { GetAdCPCapabilitiesResponse } from '../types/tools.generated';\nimport type { GetMediaBuyDeliveryResponse } from '../types/tools.generated';\nimport type { RequireCacheScopeWhenProducts, ServerPayload } from '../types/server-payload';\nimport { validActionsForStatus } from './media-buy-helpers';\nimport type { CancelMediaBuyInput } from './media-buy-helpers';\nimport type {\n ListCreativeFormatsResponse,\n GetProductsResponse,\n CreateMediaBuySuccess,\n UpdateMediaBuySuccess,\n GetMediaBuysResponse,\n ProvidePerformanceFeedbackSuccess,\n BuildCreativeSuccess,\n BuildCreativeMultiSuccess,\n PreviewCreativeSingleResponse,\n PreviewCreativeBatchResponse,\n PreviewCreativeVariantResponse,\n GetCreativeDeliveryResponse,\n ListCreativesResponse,\n SyncCreativesError,\n SyncCreativesSuccess,\n GetSignalsResponse,\n ActivateSignalSuccess,\n ListAccountsResponse,\n ListPropertyListsResponse,\n ListCollectionListsResponse,\n ListContentStandardsResponse,\n GetPlanAuditLogsResponse,\n ReportUsageRequest,\n ReportUsageResponse,\n SyncAccountsResponse,\n SyncGovernanceResponse,\n} from '../types/tools.generated';\nimport type {\n AcquireRightsResponse,\n AcquireRightsAcquired,\n AcquireRightsPendingApproval,\n AcquireRightsRejected,\n UpdateRightsResponse,\n UpdateRightsSuccess,\n CreativeApprovalResponse,\n CreativeApproved,\n CreativeRejected,\n CreativePendingReview,\n CreativeApprovalError,\n} from '../types/core.generated';\n\n/**\n * MCP-compatible tool response shape.\n *\n * `structuredContent` is optional because error responses legitimately carry\n * only `content` (the human-readable error text) — forcing every wrapper to\n * fabricate an empty structuredContent obscures the success/error split.\n * All success builders in this file still populate it.\n *\n * Uses Record<string, unknown> for structuredContent to satisfy\n * MCP SDK's CallToolResult index signature requirement.\n */\nexport interface McpToolResponse {\n [key: string]: unknown;\n content: Array<{ type: 'text'; text: string }>;\n structuredContent?: Record<string, unknown>;\n}\n\n// Explicit summaries are framework metadata, not wire data. Keep the marker\n// out-of-band so later framework-owned response rewrites can preserve an\n// adopter disclosure without serializing bookkeeping into structuredContent.\nconst explicitResponseSummaries = new WeakMap<object, string>();\n\n/** @internal */\nexport function _getExplicitResponseSummary(response: McpToolResponse): string | undefined {\n return explicitResponseSummaries.get(response);\n}\n\n// MCP SDK requires structuredContent to have an index signature ({ [x: string]: unknown }).\n// Generated AdCP types are TypeScript interfaces without index signatures. At runtime,\n// JSON objects are always Records — this bridge is safe.\nexport function toStructuredContent(data: object): Record<string, unknown> {\n return data as unknown as Record<string, unknown>;\n}\n\nconst MEDIA_BUY_STATUS_VALUES = new Set([\n 'pending_creatives',\n 'pending_start',\n 'active',\n 'paused',\n 'completed',\n 'rejected',\n 'canceled',\n]);\n\nfunction completedStructuredContent(data: object, opts?: { splitMediaBuyStatus?: boolean }): Record<string, unknown> {\n const structured = { ...toStructuredContent(data) };\n if (\n opts?.splitMediaBuyStatus === true &&\n typeof structured.status === 'string' &&\n MEDIA_BUY_STATUS_VALUES.has(structured.status)\n ) {\n if (structured.media_buy_status === undefined) structured.media_buy_status = structured.status;\n delete structured.status;\n }\n if (structured.status === undefined) structured.status = 'completed';\n return structured;\n}\n\nfunction failedStructuredContent(data: object): Record<string, unknown> {\n const structured = { ...toStructuredContent(data) };\n if (structured.status === undefined) structured.status = 'failed';\n return structured;\n}\n\nfunction stripNotificationConfigSecrets<T extends object>(row: T): T {\n const notificationConfigs = (row as { notification_configs?: unknown }).notification_configs;\n if (!Array.isArray(notificationConfigs)) return row;\n return {\n ...row,\n notification_configs: notificationConfigs.map(config => {\n if (config == null || typeof config !== 'object') return config;\n const authentication = (config as { authentication?: unknown }).authentication;\n if (authentication == null || typeof authentication !== 'object') return config;\n const { credentials: _credentials, ...authenticationWithoutCredentials } = authentication as Record<\n string,\n unknown\n >;\n const stripped = { ...(config as Record<string, unknown>) };\n if (Object.keys(authenticationWithoutCredentials).length > 0) {\n stripped.authentication = authenticationWithoutCredentials;\n } else {\n delete stripped.authentication;\n }\n return stripped;\n }),\n };\n}\n\nfunction stripBusinessEntityBank<T extends object>(row: T, key: 'billing_entity' | 'invoice_recipient'): T {\n const entity = (row as Record<string, unknown>)[key];\n if (entity == null || typeof entity !== 'object') return row;\n if (!('bank' in entity)) return row;\n const { bank: _bank, ...entityWithoutBank } = entity as Record<string, unknown>;\n const stripped = { ...row } as Record<string, unknown>;\n if (Object.keys(entityWithoutBank).length > 0) {\n stripped[key] = entityWithoutBank;\n } else {\n delete stripped[key];\n }\n return stripped as T;\n}\n\nfunction stripAccountWriteOnlyFields<T extends object>(account: T): T {\n return stripBusinessEntityBank(stripNotificationConfigSecrets(account), 'billing_entity');\n}\n\nfunction stripAccountsWriteOnlyFields<T extends { accounts?: unknown }>(data: T): T {\n if (!Array.isArray(data.accounts)) return data;\n return {\n ...data,\n accounts: data.accounts.map(account =>\n account != null && typeof account === 'object' ? stripAccountWriteOnlyFields(account) : account\n ),\n };\n}\n\nfunction stripMediaBuyWriteOnlyFields<T extends object>(buy: T): T {\n let stripped = stripBusinessEntityBank(buy, 'invoice_recipient');\n const account = (stripped as { account?: unknown }).account;\n if (account == null || typeof account !== 'object') return stripped;\n return {\n ...stripped,\n account: stripAccountWriteOnlyFields(account),\n };\n}\n\nfunction stripMediaBuysWriteOnlyFields<T extends { media_buys?: unknown }>(data: T): T {\n if (!Array.isArray(data.media_buys)) return data;\n return {\n ...data,\n media_buys: data.media_buys.map(buy =>\n buy != null && typeof buy === 'object' ? stripMediaBuyWriteOnlyFields(buy) : buy\n ),\n };\n}\n\n// `setup` is only ever nested inside an `Account` (the IO-signing / pending_approval\n// path). A top-level `setup` on a media buy response means the builder read the\n// storyboard's \"setup.url\" shorthand as a top-level field. The strict handler types\n// would catch this, but `DomainHandler` accepts `Record<string, unknown>` for DX,\n// so the error has to move to runtime.\nfunction assertNoTopLevelSetup(data: unknown, builder: string): void {\n if (data != null && typeof data === 'object' && 'setup' in data) {\n throw new Error(\n `${builder}: \\`setup\\` is not a field on the media buy — it belongs inside \\`account.setup\\`. ` +\n `Move \\`{ setup: { url, message } }\\` to \\`{ account: { ..., setup: { url, message } } }\\`. ` +\n `The setup URL is a property of the Account (returned alongside \\`status: 'pending_approval'\\`), not the MediaBuy.`\n );\n }\n}\n\n/**\n * Build a get_adcp_capabilities response.\n *\n * `supported_protocols` lists AdCP domain protocols (media_buy, signals, governance, etc.),\n * NOT transport protocols (mcp, a2a).\n *\n * Stamps the v3 protocol envelope's required `status: \"completed\"` field at\n * the top level of `structuredContent`. Synchronous task responses MUST carry\n * `status` per `protocol-envelope.json` (AdCP #4876); without it the\n * `v3_envelope_integrity/no_legacy_status_fields` conformance step fails.\n * The status is injected here rather than added to `GetAdCPCapabilitiesResponse`\n * because it's an envelope concern, not a payload field — the wire shape and\n * the typed payload model live at different layers.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function capabilitiesResponse(\n data: ServerPayload<GetAdCPCapabilitiesResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [{ type: 'text', text: summary ?? 'Agent capabilities retrieved' }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a get_products response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function productsResponse(\n data: RequireCacheScopeWhenProducts<ServerPayload<GetProductsResponse>>,\n summary?: string\n): McpToolResponse {\n const structured = completedStructuredContent(data);\n const defaultSummary =\n data.unchanged === true ? 'Product feed unchanged' : `Found ${(data.products ?? []).length} products`;\n const response: McpToolResponse = {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: structured,\n };\n if (summary !== undefined) explicitResponseSummaries.set(response, summary);\n return response;\n}\n\n/**\n * Build a successful create_media_buy response.\n *\n * Applies protocol defaults when not explicitly provided:\n * - `revision` defaults to `1` (initial revision for optimistic concurrency)\n * - `confirmed_at` defaults to the current ISO 8601 timestamp\n * - `valid_actions` populated from status via `validActionsForStatus()` when\n * `status` is provided but `valid_actions` is not\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function mediaBuyResponse(data: ServerPayload<CreateMediaBuySuccess>, summary?: string): McpToolResponse {\n assertNoTopLevelSetup(data, 'mediaBuyResponse');\n const withDefaults = { ...stripMediaBuyWriteOnlyFields(data) };\n const legacyStatus = (withDefaults as typeof withDefaults & { status?: unknown }).status;\n if (withDefaults.media_buy_status == null && typeof legacyStatus === 'string') {\n withDefaults.media_buy_status = legacyStatus as NonNullable<typeof withDefaults.media_buy_status>;\n }\n if (withDefaults.revision === undefined) {\n withDefaults.revision = 1;\n }\n if (withDefaults.confirmed_at === undefined) {\n withDefaults.confirmed_at = new Date().toISOString();\n }\n if (withDefaults.valid_actions === undefined && withDefaults.media_buy_status != null) {\n withDefaults.valid_actions = validActionsForStatus(withDefaults.media_buy_status);\n }\n return {\n content: [{ type: 'text', text: summary ?? `Media buy ${withDefaults.media_buy_id} created` }],\n structuredContent: completedStructuredContent(withDefaults, { splitMediaBuyStatus: true }),\n };\n}\n\n/**\n * Build a get_media_buy_delivery response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function deliveryResponse(data: ServerPayload<GetMediaBuyDeliveryResponse>, summary?: string): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text:\n summary ??\n `Delivery data for ${data.media_buy_deliveries.length} media buy${data.media_buy_deliveries.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a list_accounts response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listAccountsResponse(data: ServerPayload<ListAccountsResponse>, summary?: string): McpToolResponse {\n const stripped = stripAccountsWriteOnlyFields(data);\n return {\n content: [{ type: 'text', text: summary ?? `Found ${stripped.accounts.length} accounts` }],\n structuredContent: completedStructuredContent(stripped),\n };\n}\n\n/**\n * Build a list_creative_formats response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listCreativeFormatsResponse(\n data: ServerPayload<ListCreativeFormatsResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [{ type: 'text', text: summary ?? `Found ${data.formats.length} creative formats` }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a successful update_media_buy response.\n *\n * When `media_buy_status` is provided but `valid_actions` is not, auto-populates\n * `valid_actions` from `validActionsForStatus()`.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function updateMediaBuyResponse(data: ServerPayload<UpdateMediaBuySuccess>, summary?: string): McpToolResponse {\n assertNoTopLevelSetup(data, 'updateMediaBuyResponse');\n const withDefaults = { ...stripBusinessEntityBank(data, 'invoice_recipient') };\n const legacyStatus = (withDefaults as typeof withDefaults & { status?: unknown }).status;\n if (withDefaults.media_buy_status == null && typeof legacyStatus === 'string') {\n withDefaults.media_buy_status = legacyStatus as NonNullable<typeof withDefaults.media_buy_status>;\n }\n if (withDefaults.valid_actions === undefined && withDefaults.media_buy_status != null) {\n withDefaults.valid_actions = validActionsForStatus(withDefaults.media_buy_status);\n }\n return {\n content: [{ type: 'text', text: summary ?? `Media buy ${withDefaults.media_buy_id} updated` }],\n structuredContent: completedStructuredContent(withDefaults, { splitMediaBuyStatus: true }),\n };\n}\n\n/**\n * Build a get_media_buys response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function getMediaBuysResponse(data: ServerPayload<GetMediaBuysResponse>, summary?: string): McpToolResponse {\n if (Array.isArray(data.media_buys)) {\n for (const buy of data.media_buys) {\n assertNoTopLevelSetup(buy, 'getMediaBuysResponse');\n }\n }\n const stripped = stripMediaBuysWriteOnlyFields(data);\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Found ${stripped.media_buys.length} media buy${stripped.media_buys.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(stripped),\n };\n}\n\n/**\n * Build a successful provide_performance_feedback response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function performanceFeedbackResponse(\n data: ServerPayload<ProvidePerformanceFeedbackSuccess>,\n summary?: string\n): McpToolResponse {\n return {\n content: [{ type: 'text', text: summary ?? 'Performance feedback accepted' }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a successful build_creative response (single format).\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function buildCreativeResponse(data: ServerPayload<BuildCreativeSuccess>, summary?: string): McpToolResponse {\n // Optional-chain the default summary — handler responses that drop\n // `format_id` still reach the wire-level schema validator (which names\n // the missing field), instead of crashing the dispatcher here with an\n // opaque `Cannot read properties of undefined (reading 'id')`.\n const formatId = data.creative_manifest?.format_id?.id;\n return {\n content: [{ type: 'text', text: summary ?? (formatId ? `Creative built: ${formatId}` : 'Creative built') }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a successful build_creative response (multi-format).\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function buildCreativeMultiResponse(\n data: ServerPayload<BuildCreativeMultiSuccess>,\n summary?: string\n): McpToolResponse {\n const count = data.creative_manifests?.length ?? 0;\n return {\n content: [{ type: 'text', text: summary ?? `Built ${count} creative formats` }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a preview_creative response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function previewCreativeResponse(\n data: PreviewCreativeSingleResponse | PreviewCreativeBatchResponse | PreviewCreativeVariantResponse,\n summary?: string\n): McpToolResponse {\n const defaultSummary =\n data.response_type === 'single'\n ? (() => {\n const n = (data as PreviewCreativeSingleResponse).previews.length;\n return `Preview generated: ${n} variant${n === 1 ? '' : 's'}`;\n })()\n : data.response_type === 'batch'\n ? (() => {\n const n = (data as PreviewCreativeBatchResponse).results.length;\n return `Batch preview: ${n} result${n === 1 ? '' : 's'}`;\n })()\n : `Variant preview generated`;\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a get_creative_delivery response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function creativeDeliveryResponse(\n data: ServerPayload<GetCreativeDeliveryResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [{ type: 'text', text: summary ?? `Creative delivery data for ${data.currency} report` }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a list_creatives response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listCreativesResponse(data: ServerPayload<ListCreativesResponse>, summary?: string): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text:\n summary ?? `Found ${data.query_summary.total_matching} creatives (${data.query_summary.returned} returned)`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a list_property_lists response. The governance property-list catalog\n * is returned under the required `lists` wrapper — use this helper so\n * handlers can't accidentally emit a bare array at the top level (which the\n * storyboard runner flags as shape drift).\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listPropertyListsResponse(\n data: ServerPayload<ListPropertyListsResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Found ${data.lists.length} property list${data.lists.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a list_collection_lists response. Companion to\n * `listPropertyListsResponse` — same `lists` wrapper shape; parallel\n * governance surface for program-level collections.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listCollectionListsResponse(\n data: ServerPayload<ListCollectionListsResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Found ${data.lists.length} collection list${data.lists.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a list_content_standards response. The response type is a union\n * (success branch with `standards` array, error branch with `errors`) —\n * the helper wraps either shape verbatim; schema-level invariants are\n * enforced at wire validation, not here.\n *\n * Discriminates on `'standards' in data` rather than `'errors' in data` so\n * a legitimate success response that happens to carry advisory `errors`\n * still gets a counted summary. The error-only text fires only when\n * `standards` is absent. Mirrors `acquireRightsResponse`'s success-first\n * discrimination pattern a few screens down.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function listContentStandardsResponse(\n data: ServerPayload<ListContentStandardsResponse>,\n summary?: string\n): McpToolResponse {\n const defaultSummary =\n 'standards' in data\n ? `Found ${data.standards.length} content standard${data.standards.length === 1 ? '' : 's'}`\n : 'Content standards lookup error';\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a get_plan_audit_logs response. Wraps the audit data array under\n * the required `plans` key — handlers that return a bare array trip the\n * storyboard runner's shape-drift hint.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function getPlanAuditLogsResponse(\n data: ServerPayload<GetPlanAuditLogsResponse>,\n summary?: string\n): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Audit data for ${data.plans.length} plan${data.plans.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\ntype SyncCreativesResponsePayload = ServerPayload<SyncCreativesSuccess> | ServerPayload<SyncCreativesError>;\n\nfunction isSyncCreativesErrorPayload(data: SyncCreativesResponsePayload): data is ServerPayload<SyncCreativesError> {\n return (\n Array.isArray((data as { errors?: unknown }).errors) && !Array.isArray((data as { creatives?: unknown }).creatives)\n );\n}\n\n/**\n * Build a sync_creatives response. Accepts both row-level success payloads\n * and operation-level error payloads. If a payload includes `creatives`, the\n * builder treats it as success-shaped even when advisory row errors are also\n * present; operation-level errors are the errors-only arm.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function syncCreativesResponse(data: SyncCreativesResponsePayload, summary?: string): McpToolResponse {\n if (isSyncCreativesErrorPayload(data)) {\n const firstError = data.errors[0];\n const defaultSummary = firstError ? `${firstError.code}: ${firstError.message}` : 'Sync creatives failed';\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n isError: true,\n structuredContent: failedStructuredContent(data),\n };\n }\n\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Synced ${data.creatives.length} creative${data.creatives.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a get_signals response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function getSignalsResponse(data: ServerPayload<GetSignalsResponse>, summary?: string): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text: summary ?? `Found ${(data.signals ?? []).length} signal${(data.signals ?? []).length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a successful activate_signal response.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function activateSignalResponse(data: ServerPayload<ActivateSignalSuccess>, summary?: string): McpToolResponse {\n return {\n content: [\n {\n type: 'text',\n text:\n summary ??\n `Signal activated across ${data.deployments.length} deployment${data.deployments.length === 1 ? '' : 's'}`,\n },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Build a cancel response for update_media_buy with action: 'cancel'.\n *\n * Eliminates the cancellation metadata trap by requiring `canceled_by`\n * and auto-setting `canceled_at`, `status: 'canceled'`, and `valid_actions: []`.\n *\n * Note: `cancellation` is not yet on the `UpdateMediaBuySuccess` generated type\n * (it exists on the full `MediaBuy` entity). This builder constructs the response\n * as a plain object to include it. When the upstream schema adds `cancellation`\n * to the update response, this can be tightened.\n *\n * @example\n * ```typescript\n * server.registerTool(\n * 'update_media_buy',\n * { inputSchema: UpdateMediaBuyRequestSchema.shape },\n * async (params) => {\n * if (params.action === 'cancel') {\n * return cancelMediaBuyResponse({\n * media_buy_id: params.media_buy_id,\n * canceled_by: 'buyer',\n * revision: currentRevision + 1,\n * });\n * }\n * // ... handle other actions\n * }\n * );\n * ```\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function cancelMediaBuyResponse(input: CancelMediaBuyInput, summary?: string): McpToolResponse {\n const cancellation: Record<string, unknown> = {\n canceled_at: input.canceled_at ?? new Date().toISOString(),\n canceled_by: input.canceled_by,\n };\n if (input.reason !== undefined) {\n cancellation.reason = input.reason;\n }\n\n const data: Record<string, unknown> = {\n media_buy_id: input.media_buy_id,\n status: 'canceled',\n valid_actions: [],\n revision: input.revision,\n cancellation,\n };\n if (input.affected_packages !== undefined) {\n data.affected_packages = input.affected_packages;\n }\n if (input.sandbox !== undefined) {\n data.sandbox = input.sandbox;\n }\n\n return {\n content: [{ type: 'text', text: summary ?? `Media buy ${input.media_buy_id} canceled` }],\n structuredContent: completedStructuredContent(data, { splitMediaBuyStatus: true }),\n };\n}\n\n/**\n * Build an `acquire_rights` response. Thin envelope wrapper — enforces the\n * discriminated union on `status` at the type level, wraps the domain object\n * in `content` + `structuredContent`, nothing else. Schema-level constraints\n * (credential length, schemes cardinality, required-field presence) belong\n * in wire-level Zod validation, not here.\n *\n * Enable dev-time enforcement via\n * `createAdcpServer({ validation: { responses: 'strict' } })` until it\n * becomes the default.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function acquireRightsResponse(data: ServerPayload<AcquireRightsResponse>, summary?: string): McpToolResponse {\n const dataAsAny = data as AcquireRightsResponse & { rights_status?: string; rights_id?: string };\n const defaultSummary =\n 'errors' in data\n ? 'Rights acquisition error'\n : dataAsAny.rights_status === 'acquired'\n ? `Rights ${dataAsAny.rights_id} acquired`\n : dataAsAny.rights_status === 'rejected'\n ? `Rights ${dataAsAny.rights_id} rejected`\n : `Rights ${dataAsAny.rights_id} pending approval`;\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Per-variant constructor — builds an `AcquireRightsAcquired` success response\n * and wraps it. Cleaner autocomplete than `acquireRightsResponse({ rights_status: 'acquired', ... })`\n * because a coding agent typing `acquireRightsAcqu…` gets the required-fields\n * shape directly without reading a 4-variant union.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function acquireRightsAcquired(\n data: Omit<AcquireRightsAcquired, 'rights_status'>,\n summary?: string\n): McpToolResponse {\n return acquireRightsResponse({ ...data, rights_status: 'acquired' } as unknown as AcquireRightsResponse, summary);\n}\n\n/** Per-variant constructor for the `pending_approval` branch. */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function acquireRightsPendingApproval(\n data: Omit<AcquireRightsPendingApproval, 'rights_status'>,\n summary?: string\n): McpToolResponse {\n return acquireRightsResponse(\n { ...data, rights_status: 'pending_approval' } as unknown as AcquireRightsResponse,\n summary\n );\n}\n\n/** Per-variant constructor for the `rejected` branch. */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function acquireRightsRejected(\n data: Omit<AcquireRightsRejected, 'rights_status'>,\n summary?: string\n): McpToolResponse {\n return acquireRightsResponse({ ...data, rights_status: 'rejected' } as unknown as AcquireRightsResponse, summary);\n}\n\n/**\n * Build an `update_rights` response. Wraps a `UpdateRightsResponse` (success\n * or error arm — discriminated structurally on `errors` presence) in the\n * standard `content` + `structuredContent` envelope. The framework auto-\n * applies this wrapper for v6 typed-platform handlers; direct callers are\n * v5 raw-handler adopters only.\n *\n * Mirrors `acquireRightsResponse`'s shape conventions (success-first\n * default summary, error pass-through).\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function updateRightsResponse(data: ServerPayload<UpdateRightsResponse>, summary?: string): McpToolResponse {\n const defaultSummary =\n 'errors' in data\n ? 'Rights update error'\n : data.implementation_date == null\n ? `Rights ${data.rights_id} update pending approval`\n : `Rights ${data.rights_id} updated`;\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Per-variant constructor for the success arm. The wire spec doesn't\n * carry a `status` discriminator on `update_rights` (unlike\n * `acquire_rights`); success is identified structurally by absence of\n * `errors`. The narrow constructor is still useful — it gives autocomplete\n * the success-shape fields (`terms`, `generation_credentials`,\n * `rights_constraint`) without crossing the union.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function updateRightsSuccess(data: ServerPayload<UpdateRightsSuccess>, summary?: string): McpToolResponse {\n return updateRightsResponse(data as unknown as UpdateRightsResponse, summary);\n}\n\n/**\n * Build a `creative_approval` webhook response.\n *\n * Unlike the other builders in this module, `creative_approval` is NOT an\n * MCP/A2A tool — the spec models it as an HTTP webhook. The buyer POSTs\n * a `CreativeApprovalRequest` to the `approval_webhook` URL returned in\n * `acquire_rights`; the brand-rights agent reviews and returns one of four\n * arms (Approved / Rejected / PendingReview / Error). Adopters wire this\n * builder into their HTTP server's response path — see the\n * `BrandRightsPlatform.reviewCreativeApproval` Platform method and the\n * skill at `skills/build-brand-rights-agent/SKILL.md` for the receiver\n * pattern.\n *\n * Returns the raw JSON-serializable payload, NOT an `McpToolResponse` —\n * webhooks have no `content` envelope. Adopters serialize this to JSON and\n * write to the HTTP response body.\n */\nexport function creativeApprovalResponse(data: CreativeApprovalResponse): CreativeApprovalResponse {\n return data;\n}\n\n/** Per-variant constructor for the `approved` branch — webhook payload. */\nexport function creativeApprovalApproved(data: Omit<CreativeApproved, 'status'>): CreativeApproved {\n return { ...data, status: 'approved' } as CreativeApproved;\n}\n\n/** Per-variant constructor for the `rejected` branch — webhook payload. */\nexport function creativeApprovalRejected(data: Omit<CreativeRejected, 'status'>): CreativeRejected {\n return { ...data, status: 'rejected' } as CreativeRejected;\n}\n\n/** Per-variant constructor for the `pending_review` branch — webhook payload. */\nexport function creativeApprovalPendingReview(data: Omit<CreativePendingReview, 'status'>): CreativePendingReview {\n return { ...data, status: 'pending_review' } as CreativePendingReview;\n}\n\n/** Per-variant constructor for the multi-error arm — webhook payload. */\nexport function creativeApprovalError(data: CreativeApprovalError): CreativeApprovalError {\n return data;\n}\n\n/**\n * Build a `sync_accounts` response. Thin envelope wrapper accepting the full\n * `SyncAccountsResponse` union; error payloads pass through.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function syncAccountsResponse(data: ServerPayload<SyncAccountsResponse>, summary?: string): McpToolResponse {\n const stripped = 'accounts' in data ? stripAccountsWriteOnlyFields(data) : data;\n const defaultSummary =\n 'errors' in stripped\n ? 'Account sync error'\n : `Synced ${stripped.accounts?.length ?? 0} account${stripped.accounts?.length === 1 ? '' : 's'}`;\n return {\n content: [{ type: 'text', text: summary ?? defaultSummary }],\n structuredContent: completedStructuredContent(stripped),\n };\n}\n\n/**\n * Build a sync_governance response. The spec permits two top-level shapes\n * (success / error); the type union enforces discrimination on `status`.\n *\n * Strips `governance_agents[i].authentication` from every row before emit:\n * the spec marks `authentication.credentials` write-only (the buyer sends\n * the bearer; the seller persists it for outbound `check_governance` calls\n * but MUST NOT echo it back). The natural `{ ...entry.governance_agents[i] }`\n * echo idiom would compile silently against the typed return shape and ship\n * credentials over the wire AND into the idempotency replay cache, arming\n * the buyer (and any subsequent caller hitting the same key) to impersonate\n * the seller against the governance agent. Strip is enforced at the wire-\n * emit boundary so both v5 (`opts.accounts.syncGovernance`) and v6\n * (`AccountStore.syncGovernance`) paths are protected.\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function syncGovernanceResponse(data: ServerPayload<SyncGovernanceResponse>, summary?: string): McpToolResponse {\n const stripped = stripGovernanceAgentSecrets(data);\n return {\n content: [{ type: 'text', text: summary ?? 'Governance registration synced' }],\n structuredContent: completedStructuredContent(stripped),\n };\n}\n\nfunction stripGovernanceAgentSecrets(\n data: ServerPayload<SyncGovernanceResponse>\n): ServerPayload<SyncGovernanceResponse> {\n if (!('accounts' in data) || !Array.isArray(data.accounts)) return data;\n return {\n ...data,\n accounts: data.accounts.map(row => {\n if (!row.governance_agents) return row;\n return {\n ...row,\n // AdCP 3.1.0-beta.2 narrowed the wire shape to `{ url }` only;\n // `categories` was removed (per-agent category signaling moved\n // out of band) and `authentication` remains write-only. Project\n // explicitly to defeat JS / `as any` smuggling of either field.\n governance_agents: row.governance_agents.map(a => ({ url: a.url })),\n };\n }),\n };\n}\n\n/**\n * Build a `report_usage` response. Thin envelope wrapper. Schema-level\n * `accepted` requiredness is enforced at the type level (via\n * `ReportUsageResponse.accepted: number`) and at wire-level validation;\n * this builder does not re-assert it.\n *\n * @example\n * ```typescript\n * // Explicit:\n * reportUsage: async (params) =>\n * reportUsageResponse({ accepted: 8, errors: [{ usage_index: 2, message: 'invalid' }] })\n *\n * // Ack every usage[] row with optional errors (shortcut):\n * reportUsage: async (params) => reportUsageResponse.acceptAll(params)\n * ```\n */\n/** @deprecated v6: `createAdcpServerFromPlatform` constructs wire responses from typed platform returns. Direct use is for v5 raw-handler adopters mid-migration only. */\nexport function reportUsageResponse(data: ServerPayload<ReportUsageResponse>, summary?: string): McpToolResponse {\n return {\n content: [\n { type: 'text', text: summary ?? `Accepted ${data.accepted} usage record${data.accepted === 1 ? '' : 's'}` },\n ],\n structuredContent: completedStructuredContent(data),\n };\n}\n\n/**\n * Shortcut for the common case: accept all rows in the request, optionally\n * minus any `errors[]` the caller computed. Sets\n * `accepted = (request.usage?.length ?? 0) - errors.length`.\n *\n * Use with honest errors — passing no `errors` when rows failed validation\n * is lying to buyers and the audit trail.\n */\nreportUsageResponse.acceptAll = function acceptAll(\n request: ReportUsageRequest,\n opts?: { errors?: ReportUsageResponse['errors']; summary?: string }\n): McpToolResponse {\n const total = request.usage?.length ?? 0;\n const errors = opts?.errors ?? [];\n const accepted = Math.max(0, total - errors.length);\n return reportUsageResponse(\n {\n status: errors.length > 0 ? 'failed' : 'completed',\n accepted,\n ...(errors.length > 0 ? { errors } : {}),\n } as ReportUsageResponse,\n opts?.summary\n );\n};\n"],"mappings":"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","names":[]}
|
|
@@ -13,6 +13,7 @@ import type { AdcpSignAlg } from './types.mjs';
|
|
|
13
13
|
export interface AgentSigningIdentitySnapshot {
|
|
14
14
|
keyid: string;
|
|
15
15
|
algorithm: AdcpSignAlg;
|
|
16
|
+
adcpUse?: string;
|
|
16
17
|
/** Defensively hashed disambiguator — see {@link buildAgentSigningContext}. */
|
|
17
18
|
fingerprint: string;
|
|
18
19
|
}
|
|
@@ -13,6 +13,7 @@ import type { AdcpSignAlg } from './types';
|
|
|
13
13
|
export interface AgentSigningIdentitySnapshot {
|
|
14
14
|
keyid: string;
|
|
15
15
|
algorithm: AdcpSignAlg;
|
|
16
|
+
adcpUse?: string;
|
|
16
17
|
/** Defensively hashed disambiguator — see {@link buildAgentSigningContext}. */
|
|
17
18
|
fingerprint: string;
|
|
18
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-context.d.ts","sourceRoot":"","sources":["../../../src/lib/signing/agent-context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAEL,eAAe,EAEf,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-context.d.ts","sourceRoot":"","sources":["../../../src/lib/signing/agent-context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAEL,eAAe,EAEf,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAK3C;;;;;;;GAOG;AACH,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,WAAW,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC,8DAA8D;IAC9D,OAAO,EAAE,yBAAyB,CAAC;IACnC,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,EAAE,4BAA4B,CAAC;IACvC,gIAAgI;IAChI,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,aAAa,EAAE,MAAM,gBAAgB,GAAG,SAAS,CAAC;IAClD,yEAAyE;IACzE,KAAK,EAAE,eAAe,CAAC;IACvB,iEAAiE;IACjE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gFAAgF;IAChF,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,UAAU,IAAI,IAAI,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,0EAA6E,CAAC;AAEhH;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,eAAe,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9D,mBAAmB,GAAG,SAAS,CAmCjC"}
|
|
@@ -26,6 +26,7 @@ var import_node_crypto = require("node:crypto");
|
|
|
26
26
|
var import_global_async_local_storage = require('../utils/global-async-local-storage.js');
|
|
27
27
|
var import_capability_cache = require('./capability-cache.js');
|
|
28
28
|
var import_version = require('../version.js');
|
|
29
|
+
const CAPABILITY_SCOPE_SALT = (0, import_node_crypto.randomBytes)(32);
|
|
29
30
|
const signingContextStorage = (0, import_global_async_local_storage.globalAsyncLocalStorage)("signingContext");
|
|
30
31
|
function buildAgentSigningContext(agent, options = {}) {
|
|
31
32
|
const signing = agent.request_signing;
|
|
@@ -34,7 +35,12 @@ function buildAgentSigningContext(agent, options = {}) {
|
|
|
34
35
|
const identity = snapshotIdentity(signing);
|
|
35
36
|
const cacheFingerprint = deriveCacheFingerprint(identity);
|
|
36
37
|
const adcpVersion = options.adcpVersion ?? import_version.ADCP_VERSION;
|
|
37
|
-
const capabilityCacheKey = (0, import_capability_cache.buildCapabilityCacheKey)(
|
|
38
|
+
const capabilityCacheKey = (0, import_capability_cache.buildCapabilityCacheKey)(
|
|
39
|
+
agent.agent_uri,
|
|
40
|
+
capabilityPrincipalScope(agent),
|
|
41
|
+
cacheFingerprint,
|
|
42
|
+
adcpVersion
|
|
43
|
+
);
|
|
38
44
|
const cacheKey = `sig=${cacheFingerprint};adcp=${adcpVersion}`;
|
|
39
45
|
const provider = signing.kind === "provider" ? signing.provider : void 0;
|
|
40
46
|
return {
|
|
@@ -49,23 +55,52 @@ function buildAgentSigningContext(agent, options = {}) {
|
|
|
49
55
|
invalidate: () => cache.invalidate(capabilityCacheKey)
|
|
50
56
|
};
|
|
51
57
|
}
|
|
58
|
+
function capabilityPrincipalScope(agent) {
|
|
59
|
+
const credentials = agent.oauth_client_credentials;
|
|
60
|
+
const headers = agent.headers ? Object.fromEntries(
|
|
61
|
+
Object.entries(agent.headers).map(([name, value]) => [name.toLowerCase(), value]).sort(([a], [b]) => a.localeCompare(b))
|
|
62
|
+
) : void 0;
|
|
63
|
+
const scope = {
|
|
64
|
+
protocol: agent.protocol,
|
|
65
|
+
authToken: agent.auth_token,
|
|
66
|
+
oauthAccessToken: agent.oauth_tokens?.access_token,
|
|
67
|
+
oauthClientId: agent.oauth_client?.client_id,
|
|
68
|
+
oauthResource: agent.oauth_resource,
|
|
69
|
+
oauthClientCredentials: credentials ? {
|
|
70
|
+
tokenEndpoint: credentials.token_endpoint,
|
|
71
|
+
clientId: credentials.client_id,
|
|
72
|
+
scope: credentials.scope,
|
|
73
|
+
resource: credentials.resource,
|
|
74
|
+
audience: credentials.audience
|
|
75
|
+
} : void 0,
|
|
76
|
+
headers
|
|
77
|
+
};
|
|
78
|
+
return capabilityScopeDisambiguator(JSON.stringify(scope));
|
|
79
|
+
}
|
|
80
|
+
function capabilityScopeDisambiguator(value) {
|
|
81
|
+
return Buffer.from((0, import_node_crypto.hkdfSync)("sha256", value, CAPABILITY_SCOPE_SALT, "adcp-signing-capability-cache", 32)).toString(
|
|
82
|
+
"hex"
|
|
83
|
+
);
|
|
84
|
+
}
|
|
52
85
|
function snapshotIdentity(signing) {
|
|
53
86
|
if (signing.kind === "provider") {
|
|
54
87
|
const provider = signing.provider;
|
|
55
88
|
return {
|
|
56
89
|
keyid: provider.keyid,
|
|
57
90
|
algorithm: provider.algorithm,
|
|
91
|
+
...provider.adcpUse !== void 0 && { adcpUse: provider.adcpUse },
|
|
58
92
|
fingerprint: provider.fingerprint
|
|
59
93
|
};
|
|
60
94
|
}
|
|
61
95
|
return {
|
|
62
96
|
keyid: signing.kid,
|
|
63
97
|
algorithm: signing.alg,
|
|
98
|
+
...typeof signing.private_key.adcp_use === "string" && { adcpUse: signing.private_key.adcp_use },
|
|
64
99
|
fingerprint: inlineFingerprint(signing.kid, signing.private_key.d)
|
|
65
100
|
};
|
|
66
101
|
}
|
|
67
102
|
function deriveCacheFingerprint(identity) {
|
|
68
|
-
return (0, import_node_crypto.createHash)("sha256").update(identity.algorithm).update("\0").update(identity.keyid).update("\0").update(identity.fingerprint).digest("hex").slice(0, 16);
|
|
103
|
+
return (0, import_node_crypto.createHash)("sha256").update(identity.algorithm).update("\0").update(identity.keyid).update("\0").update(identity.adcpUse ?? "").update("\0").update(identity.fingerprint).digest("hex").slice(0, 16);
|
|
69
104
|
}
|
|
70
105
|
function inlineFingerprint(kid, d) {
|
|
71
106
|
if (!d) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/signing/agent-context.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { globalAsyncLocalStorage } from '../utils/global-async-local-storage';\nimport type { AgentConfig, AgentRequestSigningConfig } from '../types/adcp';\nimport {\n buildCapabilityCacheKey,\n CapabilityCache,\n defaultCapabilityCache,\n type CachedCapability,\n} from './capability-cache';\nimport type { SigningProvider } from './provider';\nimport type { AdcpSignAlg } from './types';\nimport { ADCP_VERSION } from '../version';\n\n/**\n * Snapshot of the signing identity captured at context-build time. The\n * transport layer reads from this snapshot rather than from `provider.*`\n * directly so a provider object whose fields drift between context build\n * and outbound request can't desynchronize the on-wire `keyid` from the\n * cache key the connection was bound to. TypeScript's `readonly` modifier\n * is compile-time only; the snapshot is the runtime defense.\n */\nexport interface AgentSigningIdentitySnapshot {\n keyid: string;\n algorithm: AdcpSignAlg;\n /** Defensively hashed disambiguator — see {@link buildAgentSigningContext}. */\n fingerprint: string;\n}\n\n/**\n * Per-call signing context passed down to the MCP/A2A transport layer. Built\n * at `ProtocolClient.callTool` and consumed by the signing fetch wrapper\n * attached to the transport. Opaque to the transport helpers — they only\n * use `cacheKey` (to disambiguate connection-cache entries per signing\n * identity), `getCapability` (to read the cached seller advertisement on\n * each outbound request), and `signing` (to produce the signer key or\n * provider).\n */\nexport interface AgentSigningContext {\n /** Signing config copied from AgentConfig.request_signing. */\n signing: AgentRequestSigningConfig;\n /** Provider when `signing.kind === 'provider'`; undefined for inline keys. */\n provider?: SigningProvider;\n /** Snapshot of identity fields read from the provider at build time. */\n identity: AgentSigningIdentitySnapshot;\n /** Suffix to append to transport connection-cache keys so agents with different signing identities don't share a connection. */\n cacheKey: string;\n /** Lazy accessor for the currently cached capability for this agent. */\n getCapability: () => CachedCapability | undefined;\n /** Capability cache backing this context (for external invalidation). */\n cache: CapabilityCache;\n /** Stable cache key used against the capability cache itself. */\n capabilityCacheKey: string;\n /** Trusted SDK/endpoint pin used to select the request-signing wire profile. */\n adcpVersion: string;\n /**\n * Evict this context's capability entry so the next outbound call\n * re-primes `get_adcp_capabilities`. Use after a seller-side rotation\n * signal — or on a 401 / protocol-signature error — without having to\n * rebuild the cache key from the agent's identifying fields.\n */\n invalidate(): void;\n}\n\n/**\n * AsyncLocalStorage carrying the signing context across the transport layer.\n * Top-level protocol entries (`callMCPTool`, `callA2ATool`, etc.) push a\n * context onto this storage for the duration of the call; internal helpers\n * (`withCachedConnection`, `connectMCPWithFallback`, `buildFetchImpl`) read\n * it when building cache keys and signing-fetch wrappers, avoiding the need\n * to thread `signingContext` through every intermediate signature.\n *\n * The top-level entries always call `run()` — including with `undefined` —\n * so a non-signing call cannot inherit a stale context from an enclosing\n * scope.\n */\nexport const signingContextStorage = globalAsyncLocalStorage<AgentSigningContext | undefined>('signingContext');\n\n/**\n * Build an `AgentSigningContext` from an `AgentConfig` when signing is\n * configured. Returns `undefined` when the agent has no `request_signing`\n * block — callers use this to branch into the no-op fast path.\n */\nexport function buildAgentSigningContext(\n agent: AgentConfig,\n options: { cache?: CapabilityCache; adcpVersion?: string } = {}\n): AgentSigningContext | undefined {\n const signing = agent.request_signing;\n if (!signing) return undefined;\n\n const cache = options.cache ?? defaultCapabilityCache;\n const identity = snapshotIdentity(signing);\n const cacheFingerprint = deriveCacheFingerprint(identity);\n const adcpVersion = options.adcpVersion ?? ADCP_VERSION;\n const capabilityCacheKey = buildCapabilityCacheKey(agent.agent_uri, agent.auth_token, cacheFingerprint, adcpVersion);\n // Transport-connection cache-key suffix binds to the defensively hashed\n // identity, not just the advertised `kid`. Two tenants that misconfigure\n // the same `kid` string but hold distinct keys must not collide on a\n // shared cached transport — that would sign one tenant's outbound\n // requests with the other tenant's key (same `kid`, different material),\n // an impersonation. The hash includes `algorithm` so an Ed25519/P-256\n // swap on the same `kid+fingerprint` doesn't alias either.\n const cacheKey = `sig=${cacheFingerprint};adcp=${adcpVersion}`;\n const provider = signing.kind === 'provider' ? signing.provider : undefined;\n\n return {\n signing,\n provider,\n identity,\n cacheKey,\n cache,\n capabilityCacheKey,\n adcpVersion,\n getCapability: () => cache.get(capabilityCacheKey),\n invalidate: () => cache.invalidate(capabilityCacheKey),\n };\n}\n\n/**\n * Snapshot the signing identity at context-build time. For provider configs,\n * reads `keyid` / `algorithm` / `fingerprint` once and freezes them. For\n * inline configs, derives a fingerprint from the private scalar — same\n * 64-bit cache disambiguator the SDK has always used.\n */\nfunction snapshotIdentity(signing: AgentRequestSigningConfig): AgentSigningIdentitySnapshot {\n if (signing.kind === 'provider') {\n const provider = signing.provider;\n return {\n keyid: provider.keyid,\n algorithm: provider.algorithm,\n fingerprint: provider.fingerprint,\n };\n }\n return {\n keyid: signing.kid,\n algorithm: signing.alg,\n fingerprint: inlineFingerprint(signing.kid, signing.private_key.d),\n };\n}\n\n/**\n * Defensively hash the snapshot before composing cache keys. A\n * provider-supplied `fingerprint` is treated as untrusted input — a\n * confused integrator could return a constant, an empty string, or a\n * tenant-controlled value, any of which would re-enable cross-tenant\n * collisions on the same `kid`. Including `algorithm` in the digest\n * prevents an Ed25519/P-256 swap on identical `kid+fingerprint` from\n * aliasing.\n *\n * Truncated to 16 hex chars — a 64-bit collision-resistance budget against\n * random keys is plenty for a cache disambiguator, and we never rely on\n * this value as a security boundary.\n */\nfunction deriveCacheFingerprint(identity: AgentSigningIdentitySnapshot): string {\n return createHash('sha256')\n .update(identity.algorithm)\n .update('\\0')\n .update(identity.keyid)\n .update('\\0')\n .update(identity.fingerprint)\n .digest('hex')\n .slice(0, 16);\n}\n\nfunction inlineFingerprint(kid: string, d: string | undefined): string {\n if (!d) {\n throw new TypeError(\n `AgentRequestSigningConfig (kind: 'inline', kid='${kid}') is missing 'private_key.d' — JWK must include the private scalar.`\n );\n }\n return createHash('sha256').update(kid).update('\\0').update(d).digest('hex').slice(0, 16);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAA2B;AAC3B,wCAAwC;AAExC,8BAKO;AAGP,qBAA6B;AAgEtB,MAAM,4BAAwB,2DAAyD,gBAAgB;AAOvG,SAAS,yBACd,OACA,UAA6D,CAAC,GAC7B;AACjC,QAAM,UAAU,MAAM;AACtB,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,WAAW,iBAAiB,OAAO;AACzC,QAAM,mBAAmB,uBAAuB,QAAQ;AACxD,QAAM,cAAc,QAAQ,eAAe;AAC3C,QAAM,yBAAqB,iDAAwB,MAAM,WAAW,MAAM,YAAY,kBAAkB,WAAW;AAQnH,QAAM,WAAW,OAAO,gBAAgB,SAAS,WAAW;AAC5D,QAAM,WAAW,QAAQ,SAAS,aAAa,QAAQ,WAAW;AAElE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,MAAM,MAAM,IAAI,kBAAkB;AAAA,IACjD,YAAY,MAAM,MAAM,WAAW,kBAAkB;AAAA,EACvD;AACF;AAQA,SAAS,iBAAiB,SAAkE;AAC1F,MAAI,QAAQ,SAAS,YAAY;AAC/B,UAAM,WAAW,QAAQ;AACzB,WAAO;AAAA,MACL,OAAO,SAAS;AAAA,MAChB,WAAW,SAAS;AAAA,MACpB,aAAa,SAAS;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,WAAW,QAAQ;AAAA,IACnB,aAAa,kBAAkB,QAAQ,KAAK,QAAQ,YAAY,CAAC;AAAA,EACnE;AACF;AAeA,SAAS,uBAAuB,UAAgD;AAC9E,aAAO,+BAAW,QAAQ,EACvB,OAAO,SAAS,SAAS,EACzB,OAAO,IAAI,EACX,OAAO,SAAS,KAAK,EACrB,OAAO,IAAI,EACX,OAAO,SAAS,WAAW,EAC3B,OAAO,KAAK,EACZ,MAAM,GAAG,EAAE;AAChB;AAEA,SAAS,kBAAkB,KAAa,GAA+B;AACrE,MAAI,CAAC,GAAG;AACN,UAAM,IAAI;AAAA,MACR,mDAAmD,GAAG;AAAA,IACxD;AAAA,EACF;AACA,aAAO,+BAAW,QAAQ,EAAE,OAAO,GAAG,EAAE,OAAO,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC1F;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/signing/agent-context.ts"],"sourcesContent":["import { createHash, hkdfSync, randomBytes } from 'node:crypto';\nimport { globalAsyncLocalStorage } from '../utils/global-async-local-storage';\nimport type { AgentConfig, AgentRequestSigningConfig } from '../types/adcp';\nimport {\n buildCapabilityCacheKey,\n CapabilityCache,\n defaultCapabilityCache,\n type CachedCapability,\n} from './capability-cache';\nimport type { SigningProvider } from './provider';\nimport type { AdcpSignAlg } from './types';\nimport { ADCP_VERSION } from '../version';\n\nconst CAPABILITY_SCOPE_SALT = randomBytes(32);\n\n/**\n * Snapshot of the signing identity captured at context-build time. The\n * transport layer reads from this snapshot rather than from `provider.*`\n * directly so a provider object whose fields drift between context build\n * and outbound request can't desynchronize the on-wire `keyid` from the\n * cache key the connection was bound to. TypeScript's `readonly` modifier\n * is compile-time only; the snapshot is the runtime defense.\n */\nexport interface AgentSigningIdentitySnapshot {\n keyid: string;\n algorithm: AdcpSignAlg;\n adcpUse?: string;\n /** Defensively hashed disambiguator — see {@link buildAgentSigningContext}. */\n fingerprint: string;\n}\n\n/**\n * Per-call signing context passed down to the MCP/A2A transport layer. Built\n * at `ProtocolClient.callTool` and consumed by the signing fetch wrapper\n * attached to the transport. Opaque to the transport helpers — they only\n * use `cacheKey` (to disambiguate connection-cache entries per signing\n * identity), `getCapability` (to read the cached seller advertisement on\n * each outbound request), and `signing` (to produce the signer key or\n * provider).\n */\nexport interface AgentSigningContext {\n /** Signing config copied from AgentConfig.request_signing. */\n signing: AgentRequestSigningConfig;\n /** Provider when `signing.kind === 'provider'`; undefined for inline keys. */\n provider?: SigningProvider;\n /** Snapshot of identity fields read from the provider at build time. */\n identity: AgentSigningIdentitySnapshot;\n /** Suffix to append to transport connection-cache keys so agents with different signing identities don't share a connection. */\n cacheKey: string;\n /** Lazy accessor for the currently cached capability for this agent. */\n getCapability: () => CachedCapability | undefined;\n /** Capability cache backing this context (for external invalidation). */\n cache: CapabilityCache;\n /** Stable cache key used against the capability cache itself. */\n capabilityCacheKey: string;\n /** Trusted SDK/endpoint pin used to select the request-signing wire profile. */\n adcpVersion: string;\n /**\n * Evict this context's capability entry so the next outbound call\n * re-primes `get_adcp_capabilities`. Use after a seller-side rotation\n * signal — or on a 401 / protocol-signature error — without having to\n * rebuild the cache key from the agent's identifying fields.\n */\n invalidate(): void;\n}\n\n/**\n * AsyncLocalStorage carrying the signing context across the transport layer.\n * Top-level protocol entries (`callMCPTool`, `callA2ATool`, etc.) push a\n * context onto this storage for the duration of the call; internal helpers\n * (`withCachedConnection`, `connectMCPWithFallback`, `buildFetchImpl`) read\n * it when building cache keys and signing-fetch wrappers, avoiding the need\n * to thread `signingContext` through every intermediate signature.\n *\n * The top-level entries always call `run()` — including with `undefined` —\n * so a non-signing call cannot inherit a stale context from an enclosing\n * scope.\n */\nexport const signingContextStorage = globalAsyncLocalStorage<AgentSigningContext | undefined>('signingContext');\n\n/**\n * Build an `AgentSigningContext` from an `AgentConfig` when signing is\n * configured. Returns `undefined` when the agent has no `request_signing`\n * block — callers use this to branch into the no-op fast path.\n */\nexport function buildAgentSigningContext(\n agent: AgentConfig,\n options: { cache?: CapabilityCache; adcpVersion?: string } = {}\n): AgentSigningContext | undefined {\n const signing = agent.request_signing;\n if (!signing) return undefined;\n\n const cache = options.cache ?? defaultCapabilityCache;\n const identity = snapshotIdentity(signing);\n const cacheFingerprint = deriveCacheFingerprint(identity);\n const adcpVersion = options.adcpVersion ?? ADCP_VERSION;\n const capabilityCacheKey = buildCapabilityCacheKey(\n agent.agent_uri,\n capabilityPrincipalScope(agent),\n cacheFingerprint,\n adcpVersion\n );\n // Transport-connection cache-key suffix binds to the defensively hashed\n // identity, not just the advertised `kid`. Two tenants that misconfigure\n // the same `kid` string but hold distinct keys must not collide on a\n // shared cached transport — that would sign one tenant's outbound\n // requests with the other tenant's key (same `kid`, different material),\n // an impersonation. The hash includes `algorithm` so an Ed25519/P-256\n // swap on the same `kid+fingerprint` doesn't alias either.\n const cacheKey = `sig=${cacheFingerprint};adcp=${adcpVersion}`;\n const provider = signing.kind === 'provider' ? signing.provider : undefined;\n\n return {\n signing,\n provider,\n identity,\n cacheKey,\n cache,\n capabilityCacheKey,\n adcpVersion,\n getCapability: () => cache.get(capabilityCacheKey),\n invalidate: () => cache.invalidate(capabilityCacheKey),\n };\n}\n\n/**\n * Bind capability advertisements to the effective authenticated/routed\n * principal. Basic and routing credentials live in headers, while OAuth\n * credentials live outside `auth_token`; hashing the complete scope prevents\n * one principal from reusing another principal's signing policy.\n */\nfunction capabilityPrincipalScope(agent: AgentConfig): string | undefined {\n const credentials = agent.oauth_client_credentials;\n const headers = agent.headers\n ? Object.fromEntries(\n Object.entries(agent.headers)\n .map(([name, value]) => [name.toLowerCase(), value] as const)\n .sort(([a], [b]) => a.localeCompare(b))\n )\n : undefined;\n const scope = {\n protocol: agent.protocol,\n authToken: agent.auth_token,\n oauthAccessToken: agent.oauth_tokens?.access_token,\n oauthClientId: agent.oauth_client?.client_id,\n oauthResource: agent.oauth_resource,\n oauthClientCredentials: credentials\n ? {\n tokenEndpoint: credentials.token_endpoint,\n clientId: credentials.client_id,\n scope: credentials.scope,\n resource: credentials.resource,\n audience: credentials.audience,\n }\n : undefined,\n headers,\n };\n return capabilityScopeDisambiguator(JSON.stringify(scope));\n}\n\nfunction capabilityScopeDisambiguator(value: string): string {\n return Buffer.from(hkdfSync('sha256', value, CAPABILITY_SCOPE_SALT, 'adcp-signing-capability-cache', 32)).toString(\n 'hex'\n );\n}\n\n/**\n * Snapshot the signing identity at context-build time. For provider configs,\n * reads `keyid` / `algorithm` / `fingerprint` once and freezes them. For\n * inline configs, derives a fingerprint from the private scalar — same\n * 64-bit cache disambiguator the SDK has always used.\n */\nfunction snapshotIdentity(signing: AgentRequestSigningConfig): AgentSigningIdentitySnapshot {\n if (signing.kind === 'provider') {\n const provider = signing.provider;\n return {\n keyid: provider.keyid,\n algorithm: provider.algorithm,\n ...(provider.adcpUse !== undefined && { adcpUse: provider.adcpUse }),\n fingerprint: provider.fingerprint,\n };\n }\n return {\n keyid: signing.kid,\n algorithm: signing.alg,\n ...(typeof signing.private_key.adcp_use === 'string' && { adcpUse: signing.private_key.adcp_use }),\n fingerprint: inlineFingerprint(signing.kid, signing.private_key.d),\n };\n}\n\n/**\n * Defensively hash the snapshot before composing cache keys. A\n * provider-supplied `fingerprint` is treated as untrusted input — a\n * confused integrator could return a constant, an empty string, or a\n * tenant-controlled value, any of which would re-enable cross-tenant\n * collisions on the same `kid`. Including `algorithm` in the digest\n * prevents an Ed25519/P-256 swap on identical `kid+fingerprint` from\n * aliasing.\n *\n * Truncated to 16 hex chars — a 64-bit collision-resistance budget against\n * random keys is plenty for a cache disambiguator, and we never rely on\n * this value as a security boundary.\n */\nfunction deriveCacheFingerprint(identity: AgentSigningIdentitySnapshot): string {\n return createHash('sha256')\n .update(identity.algorithm)\n .update('\\0')\n .update(identity.keyid)\n .update('\\0')\n .update(identity.adcpUse ?? '')\n .update('\\0')\n .update(identity.fingerprint)\n .digest('hex')\n .slice(0, 16);\n}\n\nfunction inlineFingerprint(kid: string, d: string | undefined): string {\n if (!d) {\n throw new TypeError(\n `AgentRequestSigningConfig (kind: 'inline', kid='${kid}') is missing 'private_key.d' — JWK must include the private scalar.`\n );\n }\n return createHash('sha256').update(kid).update('\\0').update(d).digest('hex').slice(0, 16);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
1
|
+
import { createHash, hkdfSync, randomBytes } from "node:crypto";
|
|
2
2
|
import { globalAsyncLocalStorage } from "../utils/global-async-local-storage.mjs";
|
|
3
3
|
import {
|
|
4
4
|
buildCapabilityCacheKey,
|
|
5
5
|
defaultCapabilityCache
|
|
6
6
|
} from "./capability-cache.mjs";
|
|
7
7
|
import { ADCP_VERSION } from "../version.mjs";
|
|
8
|
+
const CAPABILITY_SCOPE_SALT = randomBytes(32);
|
|
8
9
|
const signingContextStorage = globalAsyncLocalStorage("signingContext");
|
|
9
10
|
function buildAgentSigningContext(agent, options = {}) {
|
|
10
11
|
const signing = agent.request_signing;
|
|
@@ -13,7 +14,12 @@ function buildAgentSigningContext(agent, options = {}) {
|
|
|
13
14
|
const identity = snapshotIdentity(signing);
|
|
14
15
|
const cacheFingerprint = deriveCacheFingerprint(identity);
|
|
15
16
|
const adcpVersion = options.adcpVersion ?? ADCP_VERSION;
|
|
16
|
-
const capabilityCacheKey = buildCapabilityCacheKey(
|
|
17
|
+
const capabilityCacheKey = buildCapabilityCacheKey(
|
|
18
|
+
agent.agent_uri,
|
|
19
|
+
capabilityPrincipalScope(agent),
|
|
20
|
+
cacheFingerprint,
|
|
21
|
+
adcpVersion
|
|
22
|
+
);
|
|
17
23
|
const cacheKey = `sig=${cacheFingerprint};adcp=${adcpVersion}`;
|
|
18
24
|
const provider = signing.kind === "provider" ? signing.provider : void 0;
|
|
19
25
|
return {
|
|
@@ -28,23 +34,52 @@ function buildAgentSigningContext(agent, options = {}) {
|
|
|
28
34
|
invalidate: () => cache.invalidate(capabilityCacheKey)
|
|
29
35
|
};
|
|
30
36
|
}
|
|
37
|
+
function capabilityPrincipalScope(agent) {
|
|
38
|
+
const credentials = agent.oauth_client_credentials;
|
|
39
|
+
const headers = agent.headers ? Object.fromEntries(
|
|
40
|
+
Object.entries(agent.headers).map(([name, value]) => [name.toLowerCase(), value]).sort(([a], [b]) => a.localeCompare(b))
|
|
41
|
+
) : void 0;
|
|
42
|
+
const scope = {
|
|
43
|
+
protocol: agent.protocol,
|
|
44
|
+
authToken: agent.auth_token,
|
|
45
|
+
oauthAccessToken: agent.oauth_tokens?.access_token,
|
|
46
|
+
oauthClientId: agent.oauth_client?.client_id,
|
|
47
|
+
oauthResource: agent.oauth_resource,
|
|
48
|
+
oauthClientCredentials: credentials ? {
|
|
49
|
+
tokenEndpoint: credentials.token_endpoint,
|
|
50
|
+
clientId: credentials.client_id,
|
|
51
|
+
scope: credentials.scope,
|
|
52
|
+
resource: credentials.resource,
|
|
53
|
+
audience: credentials.audience
|
|
54
|
+
} : void 0,
|
|
55
|
+
headers
|
|
56
|
+
};
|
|
57
|
+
return capabilityScopeDisambiguator(JSON.stringify(scope));
|
|
58
|
+
}
|
|
59
|
+
function capabilityScopeDisambiguator(value) {
|
|
60
|
+
return Buffer.from(hkdfSync("sha256", value, CAPABILITY_SCOPE_SALT, "adcp-signing-capability-cache", 32)).toString(
|
|
61
|
+
"hex"
|
|
62
|
+
);
|
|
63
|
+
}
|
|
31
64
|
function snapshotIdentity(signing) {
|
|
32
65
|
if (signing.kind === "provider") {
|
|
33
66
|
const provider = signing.provider;
|
|
34
67
|
return {
|
|
35
68
|
keyid: provider.keyid,
|
|
36
69
|
algorithm: provider.algorithm,
|
|
70
|
+
...provider.adcpUse !== void 0 && { adcpUse: provider.adcpUse },
|
|
37
71
|
fingerprint: provider.fingerprint
|
|
38
72
|
};
|
|
39
73
|
}
|
|
40
74
|
return {
|
|
41
75
|
keyid: signing.kid,
|
|
42
76
|
algorithm: signing.alg,
|
|
77
|
+
...typeof signing.private_key.adcp_use === "string" && { adcpUse: signing.private_key.adcp_use },
|
|
43
78
|
fingerprint: inlineFingerprint(signing.kid, signing.private_key.d)
|
|
44
79
|
};
|
|
45
80
|
}
|
|
46
81
|
function deriveCacheFingerprint(identity) {
|
|
47
|
-
return createHash("sha256").update(identity.algorithm).update("\0").update(identity.keyid).update("\0").update(identity.fingerprint).digest("hex").slice(0, 16);
|
|
82
|
+
return createHash("sha256").update(identity.algorithm).update("\0").update(identity.keyid).update("\0").update(identity.adcpUse ?? "").update("\0").update(identity.fingerprint).digest("hex").slice(0, 16);
|
|
48
83
|
}
|
|
49
84
|
function inlineFingerprint(kid, d) {
|
|
50
85
|
if (!d) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/signing/agent-context.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { globalAsyncLocalStorage } from '../utils/global-async-local-storage';\nimport type { AgentConfig, AgentRequestSigningConfig } from '../types/adcp';\nimport {\n buildCapabilityCacheKey,\n CapabilityCache,\n defaultCapabilityCache,\n type CachedCapability,\n} from './capability-cache';\nimport type { SigningProvider } from './provider';\nimport type { AdcpSignAlg } from './types';\nimport { ADCP_VERSION } from '../version';\n\n/**\n * Snapshot of the signing identity captured at context-build time. The\n * transport layer reads from this snapshot rather than from `provider.*`\n * directly so a provider object whose fields drift between context build\n * and outbound request can't desynchronize the on-wire `keyid` from the\n * cache key the connection was bound to. TypeScript's `readonly` modifier\n * is compile-time only; the snapshot is the runtime defense.\n */\nexport interface AgentSigningIdentitySnapshot {\n keyid: string;\n algorithm: AdcpSignAlg;\n /** Defensively hashed disambiguator — see {@link buildAgentSigningContext}. */\n fingerprint: string;\n}\n\n/**\n * Per-call signing context passed down to the MCP/A2A transport layer. Built\n * at `ProtocolClient.callTool` and consumed by the signing fetch wrapper\n * attached to the transport. Opaque to the transport helpers — they only\n * use `cacheKey` (to disambiguate connection-cache entries per signing\n * identity), `getCapability` (to read the cached seller advertisement on\n * each outbound request), and `signing` (to produce the signer key or\n * provider).\n */\nexport interface AgentSigningContext {\n /** Signing config copied from AgentConfig.request_signing. */\n signing: AgentRequestSigningConfig;\n /** Provider when `signing.kind === 'provider'`; undefined for inline keys. */\n provider?: SigningProvider;\n /** Snapshot of identity fields read from the provider at build time. */\n identity: AgentSigningIdentitySnapshot;\n /** Suffix to append to transport connection-cache keys so agents with different signing identities don't share a connection. */\n cacheKey: string;\n /** Lazy accessor for the currently cached capability for this agent. */\n getCapability: () => CachedCapability | undefined;\n /** Capability cache backing this context (for external invalidation). */\n cache: CapabilityCache;\n /** Stable cache key used against the capability cache itself. */\n capabilityCacheKey: string;\n /** Trusted SDK/endpoint pin used to select the request-signing wire profile. */\n adcpVersion: string;\n /**\n * Evict this context's capability entry so the next outbound call\n * re-primes `get_adcp_capabilities`. Use after a seller-side rotation\n * signal — or on a 401 / protocol-signature error — without having to\n * rebuild the cache key from the agent's identifying fields.\n */\n invalidate(): void;\n}\n\n/**\n * AsyncLocalStorage carrying the signing context across the transport layer.\n * Top-level protocol entries (`callMCPTool`, `callA2ATool`, etc.) push a\n * context onto this storage for the duration of the call; internal helpers\n * (`withCachedConnection`, `connectMCPWithFallback`, `buildFetchImpl`) read\n * it when building cache keys and signing-fetch wrappers, avoiding the need\n * to thread `signingContext` through every intermediate signature.\n *\n * The top-level entries always call `run()` — including with `undefined` —\n * so a non-signing call cannot inherit a stale context from an enclosing\n * scope.\n */\nexport const signingContextStorage = globalAsyncLocalStorage<AgentSigningContext | undefined>('signingContext');\n\n/**\n * Build an `AgentSigningContext` from an `AgentConfig` when signing is\n * configured. Returns `undefined` when the agent has no `request_signing`\n * block — callers use this to branch into the no-op fast path.\n */\nexport function buildAgentSigningContext(\n agent: AgentConfig,\n options: { cache?: CapabilityCache; adcpVersion?: string } = {}\n): AgentSigningContext | undefined {\n const signing = agent.request_signing;\n if (!signing) return undefined;\n\n const cache = options.cache ?? defaultCapabilityCache;\n const identity = snapshotIdentity(signing);\n const cacheFingerprint = deriveCacheFingerprint(identity);\n const adcpVersion = options.adcpVersion ?? ADCP_VERSION;\n const capabilityCacheKey = buildCapabilityCacheKey(agent.agent_uri, agent.auth_token, cacheFingerprint, adcpVersion);\n // Transport-connection cache-key suffix binds to the defensively hashed\n // identity, not just the advertised `kid`. Two tenants that misconfigure\n // the same `kid` string but hold distinct keys must not collide on a\n // shared cached transport — that would sign one tenant's outbound\n // requests with the other tenant's key (same `kid`, different material),\n // an impersonation. The hash includes `algorithm` so an Ed25519/P-256\n // swap on the same `kid+fingerprint` doesn't alias either.\n const cacheKey = `sig=${cacheFingerprint};adcp=${adcpVersion}`;\n const provider = signing.kind === 'provider' ? signing.provider : undefined;\n\n return {\n signing,\n provider,\n identity,\n cacheKey,\n cache,\n capabilityCacheKey,\n adcpVersion,\n getCapability: () => cache.get(capabilityCacheKey),\n invalidate: () => cache.invalidate(capabilityCacheKey),\n };\n}\n\n/**\n * Snapshot the signing identity at context-build time. For provider configs,\n * reads `keyid` / `algorithm` / `fingerprint` once and freezes them. For\n * inline configs, derives a fingerprint from the private scalar — same\n * 64-bit cache disambiguator the SDK has always used.\n */\nfunction snapshotIdentity(signing: AgentRequestSigningConfig): AgentSigningIdentitySnapshot {\n if (signing.kind === 'provider') {\n const provider = signing.provider;\n return {\n keyid: provider.keyid,\n algorithm: provider.algorithm,\n fingerprint: provider.fingerprint,\n };\n }\n return {\n keyid: signing.kid,\n algorithm: signing.alg,\n fingerprint: inlineFingerprint(signing.kid, signing.private_key.d),\n };\n}\n\n/**\n * Defensively hash the snapshot before composing cache keys. A\n * provider-supplied `fingerprint` is treated as untrusted input — a\n * confused integrator could return a constant, an empty string, or a\n * tenant-controlled value, any of which would re-enable cross-tenant\n * collisions on the same `kid`. Including `algorithm` in the digest\n * prevents an Ed25519/P-256 swap on identical `kid+fingerprint` from\n * aliasing.\n *\n * Truncated to 16 hex chars — a 64-bit collision-resistance budget against\n * random keys is plenty for a cache disambiguator, and we never rely on\n * this value as a security boundary.\n */\nfunction deriveCacheFingerprint(identity: AgentSigningIdentitySnapshot): string {\n return createHash('sha256')\n .update(identity.algorithm)\n .update('\\0')\n .update(identity.keyid)\n .update('\\0')\n .update(identity.fingerprint)\n .digest('hex')\n .slice(0, 16);\n}\n\nfunction inlineFingerprint(kid: string, d: string | undefined): string {\n if (!d) {\n throw new TypeError(\n `AgentRequestSigningConfig (kind: 'inline', kid='${kid}') is missing 'private_key.d' — JWK must include the private scalar.`\n );\n }\n return createHash('sha256').update(kid).update('\\0').update(d).digest('hex').slice(0, 16);\n}\n"],"mappings":"AAAA,SAAS,kBAAkB;AAC3B,SAAS,+BAA+B;AAExC;AAAA,EACE;AAAA,EAEA;AAAA,OAEK;AAGP,SAAS,oBAAoB;AAgEtB,MAAM,wBAAwB,wBAAyD,gBAAgB;AAOvG,SAAS,yBACd,OACA,UAA6D,CAAC,GAC7B;AACjC,QAAM,UAAU,MAAM;AACtB,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,WAAW,iBAAiB,OAAO;AACzC,QAAM,mBAAmB,uBAAuB,QAAQ;AACxD,QAAM,cAAc,QAAQ,eAAe;AAC3C,QAAM,qBAAqB,wBAAwB,MAAM,WAAW,MAAM,YAAY,kBAAkB,WAAW;AAQnH,QAAM,WAAW,OAAO,gBAAgB,SAAS,WAAW;AAC5D,QAAM,WAAW,QAAQ,SAAS,aAAa,QAAQ,WAAW;AAElE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,MAAM,MAAM,IAAI,kBAAkB;AAAA,IACjD,YAAY,MAAM,MAAM,WAAW,kBAAkB;AAAA,EACvD;AACF;AAQA,SAAS,iBAAiB,SAAkE;AAC1F,MAAI,QAAQ,SAAS,YAAY;AAC/B,UAAM,WAAW,QAAQ;AACzB,WAAO;AAAA,MACL,OAAO,SAAS;AAAA,MAChB,WAAW,SAAS;AAAA,MACpB,aAAa,SAAS;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,WAAW,QAAQ;AAAA,IACnB,aAAa,kBAAkB,QAAQ,KAAK,QAAQ,YAAY,CAAC;AAAA,EACnE;AACF;AAeA,SAAS,uBAAuB,UAAgD;AAC9E,SAAO,WAAW,QAAQ,EACvB,OAAO,SAAS,SAAS,EACzB,OAAO,IAAI,EACX,OAAO,SAAS,KAAK,EACrB,OAAO,IAAI,EACX,OAAO,SAAS,WAAW,EAC3B,OAAO,KAAK,EACZ,MAAM,GAAG,EAAE;AAChB;AAEA,SAAS,kBAAkB,KAAa,GAA+B;AACrE,MAAI,CAAC,GAAG;AACN,UAAM,IAAI;AAAA,MACR,mDAAmD,GAAG;AAAA,IACxD;AAAA,EACF;AACA,SAAO,WAAW,QAAQ,EAAE,OAAO,GAAG,EAAE,OAAO,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC1F;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/signing/agent-context.ts"],"sourcesContent":["import { createHash, hkdfSync, randomBytes } from 'node:crypto';\nimport { globalAsyncLocalStorage } from '../utils/global-async-local-storage';\nimport type { AgentConfig, AgentRequestSigningConfig } from '../types/adcp';\nimport {\n buildCapabilityCacheKey,\n CapabilityCache,\n defaultCapabilityCache,\n type CachedCapability,\n} from './capability-cache';\nimport type { SigningProvider } from './provider';\nimport type { AdcpSignAlg } from './types';\nimport { ADCP_VERSION } from '../version';\n\nconst CAPABILITY_SCOPE_SALT = randomBytes(32);\n\n/**\n * Snapshot of the signing identity captured at context-build time. The\n * transport layer reads from this snapshot rather than from `provider.*`\n * directly so a provider object whose fields drift between context build\n * and outbound request can't desynchronize the on-wire `keyid` from the\n * cache key the connection was bound to. TypeScript's `readonly` modifier\n * is compile-time only; the snapshot is the runtime defense.\n */\nexport interface AgentSigningIdentitySnapshot {\n keyid: string;\n algorithm: AdcpSignAlg;\n adcpUse?: string;\n /** Defensively hashed disambiguator — see {@link buildAgentSigningContext}. */\n fingerprint: string;\n}\n\n/**\n * Per-call signing context passed down to the MCP/A2A transport layer. Built\n * at `ProtocolClient.callTool` and consumed by the signing fetch wrapper\n * attached to the transport. Opaque to the transport helpers — they only\n * use `cacheKey` (to disambiguate connection-cache entries per signing\n * identity), `getCapability` (to read the cached seller advertisement on\n * each outbound request), and `signing` (to produce the signer key or\n * provider).\n */\nexport interface AgentSigningContext {\n /** Signing config copied from AgentConfig.request_signing. */\n signing: AgentRequestSigningConfig;\n /** Provider when `signing.kind === 'provider'`; undefined for inline keys. */\n provider?: SigningProvider;\n /** Snapshot of identity fields read from the provider at build time. */\n identity: AgentSigningIdentitySnapshot;\n /** Suffix to append to transport connection-cache keys so agents with different signing identities don't share a connection. */\n cacheKey: string;\n /** Lazy accessor for the currently cached capability for this agent. */\n getCapability: () => CachedCapability | undefined;\n /** Capability cache backing this context (for external invalidation). */\n cache: CapabilityCache;\n /** Stable cache key used against the capability cache itself. */\n capabilityCacheKey: string;\n /** Trusted SDK/endpoint pin used to select the request-signing wire profile. */\n adcpVersion: string;\n /**\n * Evict this context's capability entry so the next outbound call\n * re-primes `get_adcp_capabilities`. Use after a seller-side rotation\n * signal — or on a 401 / protocol-signature error — without having to\n * rebuild the cache key from the agent's identifying fields.\n */\n invalidate(): void;\n}\n\n/**\n * AsyncLocalStorage carrying the signing context across the transport layer.\n * Top-level protocol entries (`callMCPTool`, `callA2ATool`, etc.) push a\n * context onto this storage for the duration of the call; internal helpers\n * (`withCachedConnection`, `connectMCPWithFallback`, `buildFetchImpl`) read\n * it when building cache keys and signing-fetch wrappers, avoiding the need\n * to thread `signingContext` through every intermediate signature.\n *\n * The top-level entries always call `run()` — including with `undefined` —\n * so a non-signing call cannot inherit a stale context from an enclosing\n * scope.\n */\nexport const signingContextStorage = globalAsyncLocalStorage<AgentSigningContext | undefined>('signingContext');\n\n/**\n * Build an `AgentSigningContext` from an `AgentConfig` when signing is\n * configured. Returns `undefined` when the agent has no `request_signing`\n * block — callers use this to branch into the no-op fast path.\n */\nexport function buildAgentSigningContext(\n agent: AgentConfig,\n options: { cache?: CapabilityCache; adcpVersion?: string } = {}\n): AgentSigningContext | undefined {\n const signing = agent.request_signing;\n if (!signing) return undefined;\n\n const cache = options.cache ?? defaultCapabilityCache;\n const identity = snapshotIdentity(signing);\n const cacheFingerprint = deriveCacheFingerprint(identity);\n const adcpVersion = options.adcpVersion ?? ADCP_VERSION;\n const capabilityCacheKey = buildCapabilityCacheKey(\n agent.agent_uri,\n capabilityPrincipalScope(agent),\n cacheFingerprint,\n adcpVersion\n );\n // Transport-connection cache-key suffix binds to the defensively hashed\n // identity, not just the advertised `kid`. Two tenants that misconfigure\n // the same `kid` string but hold distinct keys must not collide on a\n // shared cached transport — that would sign one tenant's outbound\n // requests with the other tenant's key (same `kid`, different material),\n // an impersonation. The hash includes `algorithm` so an Ed25519/P-256\n // swap on the same `kid+fingerprint` doesn't alias either.\n const cacheKey = `sig=${cacheFingerprint};adcp=${adcpVersion}`;\n const provider = signing.kind === 'provider' ? signing.provider : undefined;\n\n return {\n signing,\n provider,\n identity,\n cacheKey,\n cache,\n capabilityCacheKey,\n adcpVersion,\n getCapability: () => cache.get(capabilityCacheKey),\n invalidate: () => cache.invalidate(capabilityCacheKey),\n };\n}\n\n/**\n * Bind capability advertisements to the effective authenticated/routed\n * principal. Basic and routing credentials live in headers, while OAuth\n * credentials live outside `auth_token`; hashing the complete scope prevents\n * one principal from reusing another principal's signing policy.\n */\nfunction capabilityPrincipalScope(agent: AgentConfig): string | undefined {\n const credentials = agent.oauth_client_credentials;\n const headers = agent.headers\n ? Object.fromEntries(\n Object.entries(agent.headers)\n .map(([name, value]) => [name.toLowerCase(), value] as const)\n .sort(([a], [b]) => a.localeCompare(b))\n )\n : undefined;\n const scope = {\n protocol: agent.protocol,\n authToken: agent.auth_token,\n oauthAccessToken: agent.oauth_tokens?.access_token,\n oauthClientId: agent.oauth_client?.client_id,\n oauthResource: agent.oauth_resource,\n oauthClientCredentials: credentials\n ? {\n tokenEndpoint: credentials.token_endpoint,\n clientId: credentials.client_id,\n scope: credentials.scope,\n resource: credentials.resource,\n audience: credentials.audience,\n }\n : undefined,\n headers,\n };\n return capabilityScopeDisambiguator(JSON.stringify(scope));\n}\n\nfunction capabilityScopeDisambiguator(value: string): string {\n return Buffer.from(hkdfSync('sha256', value, CAPABILITY_SCOPE_SALT, 'adcp-signing-capability-cache', 32)).toString(\n 'hex'\n );\n}\n\n/**\n * Snapshot the signing identity at context-build time. For provider configs,\n * reads `keyid` / `algorithm` / `fingerprint` once and freezes them. For\n * inline configs, derives a fingerprint from the private scalar — same\n * 64-bit cache disambiguator the SDK has always used.\n */\nfunction snapshotIdentity(signing: AgentRequestSigningConfig): AgentSigningIdentitySnapshot {\n if (signing.kind === 'provider') {\n const provider = signing.provider;\n return {\n keyid: provider.keyid,\n algorithm: provider.algorithm,\n ...(provider.adcpUse !== undefined && { adcpUse: provider.adcpUse }),\n fingerprint: provider.fingerprint,\n };\n }\n return {\n keyid: signing.kid,\n algorithm: signing.alg,\n ...(typeof signing.private_key.adcp_use === 'string' && { adcpUse: signing.private_key.adcp_use }),\n fingerprint: inlineFingerprint(signing.kid, signing.private_key.d),\n };\n}\n\n/**\n * Defensively hash the snapshot before composing cache keys. A\n * provider-supplied `fingerprint` is treated as untrusted input — a\n * confused integrator could return a constant, an empty string, or a\n * tenant-controlled value, any of which would re-enable cross-tenant\n * collisions on the same `kid`. Including `algorithm` in the digest\n * prevents an Ed25519/P-256 swap on identical `kid+fingerprint` from\n * aliasing.\n *\n * Truncated to 16 hex chars — a 64-bit collision-resistance budget against\n * random keys is plenty for a cache disambiguator, and we never rely on\n * this value as a security boundary.\n */\nfunction deriveCacheFingerprint(identity: AgentSigningIdentitySnapshot): string {\n return createHash('sha256')\n .update(identity.algorithm)\n .update('\\0')\n .update(identity.keyid)\n .update('\\0')\n .update(identity.adcpUse ?? '')\n .update('\\0')\n .update(identity.fingerprint)\n .digest('hex')\n .slice(0, 16);\n}\n\nfunction inlineFingerprint(kid: string, d: string | undefined): string {\n if (!d) {\n throw new TypeError(\n `AgentRequestSigningConfig (kind: 'inline', kid='${kid}') is missing 'private_key.d' — JWK must include the private scalar.`\n );\n }\n return createHash('sha256').update(kid).update('\\0').update(d).digest('hex').slice(0, 16);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -35,8 +35,7 @@ export declare function extractAdcpOperation(body: unknown): string | undefined;
|
|
|
35
35
|
* `sign_supported: true` (defaults off).
|
|
36
36
|
*
|
|
37
37
|
* Returns false when the capability is unknown (cold cache) except for ops
|
|
38
|
-
* in `always_sign
|
|
39
|
-
* never signed.
|
|
38
|
+
* in `always_sign`.
|
|
40
39
|
*/
|
|
41
40
|
export declare function shouldSignOperation(operation: string | undefined, capability: VerifierCapability | undefined, config: AgentRequestSigningConfig): boolean;
|
|
42
41
|
/**
|
|
@@ -35,8 +35,7 @@ export declare function extractAdcpOperation(body: unknown): string | undefined;
|
|
|
35
35
|
* `sign_supported: true` (defaults off).
|
|
36
36
|
*
|
|
37
37
|
* Returns false when the capability is unknown (cold cache) except for ops
|
|
38
|
-
* in `always_sign
|
|
39
|
-
* never signed.
|
|
38
|
+
* in `always_sign`.
|
|
40
39
|
*/
|
|
41
40
|
export declare function shouldSignOperation(operation: string | undefined, capability: VerifierCapability | undefined, config: AgentRequestSigningConfig): boolean;
|
|
42
41
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-fetch.d.ts","sourceRoot":"","sources":["../../../src/lib/signing/agent-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,+BAA+B,EAC/B,iCAAiC,EAClC,MAAM,eAAe,CAAC;AAGvB,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAI1C,OAAO,EAAE,gCAAgC,EAAE,MAAM,kBAAkB,CAAC;AAEpE,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AA4C1F;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAgCtE;AAsBD
|
|
1
|
+
{"version":3,"file":"agent-fetch.d.ts","sourceRoot":"","sources":["../../../src/lib/signing/agent-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,+BAA+B,EAC/B,iCAAiC,EAClC,MAAM,eAAe,CAAC;AAGvB,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAI1C,OAAO,EAAE,gCAAgC,EAAE,MAAM,kBAAkB,CAAC;AAEpE,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AA4C1F;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAgCtE;AAsBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,UAAU,EAAE,kBAAkB,GAAG,SAAS,EAC1C,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAQT;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,GAAG,OAAO,CAG1F;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,+BAA+B,GAAG,SAAS,CAM9E;AAED,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM,IAAI,+BAA+B,CAElH;AAED,+CAA+C;AAC/C,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,yBAAyB,GAChC,MAAM,IAAI,iCAAiC,CAE7C;AAED,MAAM,WAAW,6BAA6B;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,yBAAyB,CAAC;IACnC,+EAA+E;IAC/E,aAAa,EAAE,MAAM,gBAAgB,GAAG,SAAS,CAAC;IAClD,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,6BAA6B,GAAG,SAAS,CAmCxF;AAgBD,MAAM,WAAW,6BAA6B;IAC5C,iFAAiF;IACjF,OAAO,EAAE,yBAAyB,CAAC;IACnC,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;OASG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,6BAA6B,GAAG,SAAS,CAUxF"}
|
|
@@ -155,10 +155,12 @@ function buildAgentSigningFetch(options) {
|
|
|
155
155
|
function freezeProviderIdentity(provider) {
|
|
156
156
|
const keyid = provider.keyid;
|
|
157
157
|
const algorithm = provider.algorithm;
|
|
158
|
+
const adcpUse = provider.adcpUse;
|
|
158
159
|
const fingerprint = provider.fingerprint;
|
|
159
160
|
return {
|
|
160
161
|
keyid,
|
|
161
162
|
algorithm,
|
|
163
|
+
adcpUse,
|
|
162
164
|
fingerprint,
|
|
163
165
|
sign: (payload) => provider.sign(payload)
|
|
164
166
|
};
|