@adcp/sdk 13.0.4 → 13.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adcp-grade.js +4 -3
- package/bin/adcp.js +18 -0
- package/dist/lib/conformance/invariants/uniformError.d.ts.map +1 -1
- package/dist/lib/conformance/invariants/uniformError.js +21 -0
- package/dist/lib/conformance/invariants/uniformError.js.map +1 -1
- package/dist/lib/conformance/invariants/uniformError.mjs +22 -1
- package/dist/lib/conformance/invariants/uniformError.mjs.map +1 -1
- package/dist/lib/core/AgentClient.d.mts +1 -1
- package/dist/lib/core/AgentClient.d.ts +1 -1
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/AgentClient.js +1 -1
- package/dist/lib/core/AgentClient.js.map +1 -1
- package/dist/lib/core/AgentClient.mjs +1 -1
- package/dist/lib/core/AgentClient.mjs.map +1 -1
- package/dist/lib/core/SingleAgentClient.d.mts +1 -1
- package/dist/lib/core/SingleAgentClient.d.ts +1 -1
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +88 -48
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +88 -48
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
- package/dist/lib/core/TaskExecutor.js +8 -4
- package/dist/lib/core/TaskExecutor.js.map +1 -1
- package/dist/lib/core/TaskExecutor.mjs +8 -4
- package/dist/lib/core/TaskExecutor.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/net/agent-transport-fetch.d.mts +15 -0
- package/dist/lib/net/agent-transport-fetch.d.ts +15 -0
- package/dist/lib/net/agent-transport-fetch.d.ts.map +1 -1
- package/dist/lib/net/agent-transport-fetch.js +37 -2
- package/dist/lib/net/agent-transport-fetch.js.map +1 -1
- package/dist/lib/net/agent-transport-fetch.mjs +37 -2
- package/dist/lib/net/agent-transport-fetch.mjs.map +1 -1
- package/dist/lib/net/credential-headers.d.mts +1 -0
- package/dist/lib/net/credential-headers.d.ts +2 -0
- package/dist/lib/net/credential-headers.d.ts.map +1 -0
- package/dist/lib/net/credential-headers.js +34 -0
- package/dist/lib/net/credential-headers.js.map +1 -0
- package/dist/lib/net/credential-headers.mjs +10 -0
- package/dist/lib/net/credential-headers.mjs.map +1 -0
- package/dist/lib/protocols/a2a-native-v1.d.mts +18 -0
- package/dist/lib/protocols/a2a-native-v1.d.ts +19 -0
- package/dist/lib/protocols/a2a-native-v1.d.ts.map +1 -0
- package/dist/lib/protocols/a2a-native-v1.js +183 -0
- package/dist/lib/protocols/a2a-native-v1.js.map +1 -0
- package/dist/lib/protocols/a2a-native-v1.mjs +167 -0
- package/dist/lib/protocols/a2a-native-v1.mjs.map +1 -0
- package/dist/lib/protocols/a2a-push-notification.d.mts +13 -0
- package/dist/lib/protocols/a2a-push-notification.d.ts +14 -0
- package/dist/lib/protocols/a2a-push-notification.d.ts.map +1 -0
- package/dist/lib/protocols/a2a-push-notification.js +42 -0
- package/dist/lib/protocols/a2a-push-notification.js.map +1 -0
- package/dist/lib/protocols/a2a-push-notification.mjs +23 -0
- package/dist/lib/protocols/a2a-push-notification.mjs.map +1 -0
- package/dist/lib/protocols/a2a.d.mts +15 -5
- package/dist/lib/protocols/a2a.d.ts +15 -5
- package/dist/lib/protocols/a2a.d.ts.map +1 -1
- package/dist/lib/protocols/a2a.js +102 -13
- package/dist/lib/protocols/a2a.js.map +1 -1
- package/dist/lib/protocols/a2a.mjs +90 -12
- package/dist/lib/protocols/a2a.mjs.map +1 -1
- package/dist/lib/protocols/index.d.mts +3 -0
- package/dist/lib/protocols/index.d.ts +3 -0
- package/dist/lib/protocols/index.d.ts.map +1 -1
- package/dist/lib/protocols/index.js +18 -6
- package/dist/lib/protocols/index.js.map +1 -1
- package/dist/lib/protocols/index.mjs +18 -6
- package/dist/lib/protocols/index.mjs.map +1 -1
- package/dist/lib/protocols/mcp-modern.d.ts.map +1 -1
- package/dist/lib/protocols/mcp-modern.js +3 -1
- package/dist/lib/protocols/mcp-modern.js.map +1 -1
- package/dist/lib/protocols/mcp-modern.mjs +3 -1
- package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
- package/dist/lib/protocols/mcp-tasks.d.ts.map +1 -1
- package/dist/lib/protocols/mcp-tasks.js +2 -1
- package/dist/lib/protocols/mcp-tasks.js.map +1 -1
- package/dist/lib/protocols/mcp-tasks.mjs +2 -1
- package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
- package/dist/lib/protocols/mcp.d.mts +8 -5
- package/dist/lib/protocols/mcp.d.ts +8 -5
- package/dist/lib/protocols/mcp.d.ts.map +1 -1
- package/dist/lib/protocols/mcp.js +12 -4
- package/dist/lib/protocols/mcp.js.map +1 -1
- package/dist/lib/protocols/mcp.mjs +12 -4
- package/dist/lib/protocols/mcp.mjs.map +1 -1
- package/dist/lib/protocols/rawResponseCapture.d.mts +9 -1
- package/dist/lib/protocols/rawResponseCapture.d.ts +9 -1
- package/dist/lib/protocols/rawResponseCapture.d.ts.map +1 -1
- package/dist/lib/protocols/rawResponseCapture.js +153 -10
- package/dist/lib/protocols/rawResponseCapture.js.map +1 -1
- package/dist/lib/protocols/rawResponseCapture.mjs +153 -10
- package/dist/lib/protocols/rawResponseCapture.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/signing/agent-fetch.d.mts +3 -1
- package/dist/lib/signing/agent-fetch.d.ts +3 -1
- package/dist/lib/signing/agent-fetch.d.ts.map +1 -1
- package/dist/lib/signing/agent-fetch.js +4 -2
- package/dist/lib/signing/agent-fetch.js.map +1 -1
- package/dist/lib/signing/agent-fetch.mjs +4 -2
- package/dist/lib/signing/agent-fetch.mjs.map +1 -1
- package/dist/lib/signing/protocol-methods.d.mts +24 -0
- package/dist/lib/signing/protocol-methods.d.ts +25 -0
- package/dist/lib/signing/protocol-methods.d.ts.map +1 -0
- package/dist/lib/signing/protocol-methods.js +51 -0
- package/dist/lib/signing/protocol-methods.js.map +1 -0
- package/dist/lib/signing/protocol-methods.mjs +25 -0
- package/dist/lib/signing/protocol-methods.mjs.map +1 -0
- package/dist/lib/signing/types.d.mts +2 -0
- package/dist/lib/signing/types.d.ts +2 -0
- package/dist/lib/signing/types.d.ts.map +1 -1
- package/dist/lib/signing/types.js.map +1 -1
- package/dist/lib/signing/types.mjs.map +1 -1
- package/dist/lib/signing/verifier.d.ts.map +1 -1
- package/dist/lib/signing/verifier.js +6 -2
- package/dist/lib/signing/verifier.js.map +1 -1
- package/dist/lib/signing/verifier.mjs +6 -2
- package/dist/lib/signing/verifier.mjs.map +1 -1
- package/dist/lib/testing/client.d.ts.map +1 -1
- package/dist/lib/testing/client.js +4 -1
- package/dist/lib/testing/client.js.map +1 -1
- package/dist/lib/testing/client.mjs +4 -1
- 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 +3 -0
- package/dist/lib/testing/compliance/comply.js.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +3 -0
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/storyboard/agent-routing.d.mts +3 -1
- package/dist/lib/testing/storyboard/agent-routing.d.ts +3 -1
- package/dist/lib/testing/storyboard/agent-routing.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/agent-routing.js +5 -2
- package/dist/lib/testing/storyboard/agent-routing.js.map +1 -1
- package/dist/lib/testing/storyboard/agent-routing.mjs +4 -2
- package/dist/lib/testing/storyboard/agent-routing.mjs.map +1 -1
- package/dist/lib/testing/storyboard/compliance.d.mts +1 -1
- package/dist/lib/testing/storyboard/compliance.d.ts +1 -1
- package/dist/lib/testing/storyboard/compliance.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/compliance.js +4 -1
- package/dist/lib/testing/storyboard/compliance.js.map +1 -1
- package/dist/lib/testing/storyboard/compliance.mjs +4 -1
- package/dist/lib/testing/storyboard/compliance.mjs.map +1 -1
- package/dist/lib/testing/storyboard/native-a2a-compliance.d.mts +7 -0
- package/dist/lib/testing/storyboard/native-a2a-compliance.d.ts +8 -0
- package/dist/lib/testing/storyboard/native-a2a-compliance.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/native-a2a-compliance.js +45 -0
- package/dist/lib/testing/storyboard/native-a2a-compliance.js.map +1 -0
- package/dist/lib/testing/storyboard/native-a2a-compliance.mjs +21 -0
- package/dist/lib/testing/storyboard/native-a2a-compliance.mjs.map +1 -0
- package/dist/lib/testing/storyboard/probes.d.mts +2 -0
- package/dist/lib/testing/storyboard/probes.d.ts +2 -0
- package/dist/lib/testing/storyboard/probes.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/probes.js +3 -2
- package/dist/lib/testing/storyboard/probes.js.map +1 -1
- package/dist/lib/testing/storyboard/probes.mjs +3 -2
- package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.mts +31 -0
- package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.ts +32 -0
- package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.js +279 -0
- package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.js.map +1 -0
- package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.mjs +244 -0
- package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.mjs.map +1 -0
- package/dist/lib/testing/storyboard/request-signing/builder.d.mts +4 -1
- package/dist/lib/testing/storyboard/request-signing/builder.d.ts +4 -1
- package/dist/lib/testing/storyboard/request-signing/builder.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/builder.js +19 -0
- package/dist/lib/testing/storyboard/request-signing/builder.js.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +19 -0
- package/dist/lib/testing/storyboard/request-signing/builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/grader.d.mts +5 -6
- package/dist/lib/testing/storyboard/request-signing/grader.d.ts +5 -6
- package/dist/lib/testing/storyboard/request-signing/grader.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/grader.js +82 -13
- package/dist/lib/testing/storyboard/request-signing/grader.js.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/grader.mjs +86 -13
- package/dist/lib/testing/storyboard/request-signing/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/index.d.mts +1 -0
- package/dist/lib/testing/storyboard/request-signing/index.d.ts +1 -0
- package/dist/lib/testing/storyboard/request-signing/index.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/index.js +7 -0
- package/dist/lib/testing/storyboard/request-signing/index.js.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/index.mjs +8 -0
- package/dist/lib/testing/storyboard/request-signing/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.mts +2 -2
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.ts +2 -2
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.js +6 -5
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.js.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +6 -5
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/types.d.mts +1 -0
- package/dist/lib/testing/storyboard/request-signing/types.d.ts +1 -0
- package/dist/lib/testing/storyboard/request-signing/types.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/types.js.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.js +1 -0
- package/dist/lib/testing/storyboard/request-signing/vector-loader.js.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +1 -0
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.mts +28 -1
- package/dist/lib/testing/storyboard/runner.d.ts +28 -1
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +251 -55
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +255 -60
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/types.d.mts +4 -2
- package/dist/lib/testing/storyboard/types.d.ts +4 -2
- package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/types.js +1 -0
- package/dist/lib/testing/storyboard/types.js.map +1 -1
- package/dist/lib/testing/storyboard/types.mjs +1 -0
- package/dist/lib/testing/storyboard/types.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 +97 -22
- package/dist/lib/testing/storyboard/validations.js.map +1 -1
- package/dist/lib/testing/storyboard/validations.mjs +98 -22
- package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/version.mjs.map +1 -1
- package/docs/guides/BUILD-AN-AGENT.md +1 -1
- package/docs/llms.txt +5 -3
- package/package.json +2 -1
|
@@ -198,6 +198,7 @@ function passthrough(vector, options) {
|
|
|
198
198
|
};
|
|
199
199
|
}
|
|
200
200
|
function protocolMethodPassthrough(vector, options) {
|
|
201
|
+
if (options.transport === "a2a") return passthrough(vector, options);
|
|
201
202
|
const url = options.baseUrl ?? vector.request.url;
|
|
202
203
|
const headers = { ...vector.request.headers };
|
|
203
204
|
if (options.transport === "mcp") {
|
|
@@ -252,6 +253,17 @@ function retargetUrl(vectorUrl, baseUrl) {
|
|
|
252
253
|
}
|
|
253
254
|
function applyTransport(vector, options) {
|
|
254
255
|
const headers = { ...vector.request.headers };
|
|
256
|
+
if (options.transport === "a2a") {
|
|
257
|
+
if (!options.a2aRequest) {
|
|
258
|
+
throw new Error("transport: 'a2a' requires a request captured from the official @a2a-js/sdk client");
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
method: options.a2aRequest.method,
|
|
262
|
+
url: options.a2aRequest.url,
|
|
263
|
+
headers: mergeHeadersCaseInsensitively(options.a2aRequest.headers, headers),
|
|
264
|
+
body: options.a2aRequest.body
|
|
265
|
+
};
|
|
266
|
+
}
|
|
255
267
|
if (options.transport === "mcp") {
|
|
256
268
|
if (!options.baseUrl) {
|
|
257
269
|
throw new Error(`transport: 'mcp' requires a baseUrl (the MCP endpoint, e.g. http://agent/mcp)`);
|
|
@@ -273,6 +285,13 @@ function applyTransport(vector, options) {
|
|
|
273
285
|
body: vector.request.body
|
|
274
286
|
};
|
|
275
287
|
}
|
|
288
|
+
function mergeHeadersCaseInsensitively(base, overrides) {
|
|
289
|
+
const overridden = new Set(Object.keys(overrides).map((name) => name.toLowerCase()));
|
|
290
|
+
return {
|
|
291
|
+
...Object.fromEntries(Object.entries(base).filter(([name]) => !overridden.has(name.toLowerCase()))),
|
|
292
|
+
...overrides
|
|
293
|
+
};
|
|
294
|
+
}
|
|
276
295
|
const OPERATION_NAME_SAFE = /^[a-z][a-z0-9_]*$/;
|
|
277
296
|
function extractOperationFromVectorUrl(vectorUrl) {
|
|
278
297
|
const parsed = new URL(vectorUrl);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/builder.ts"],"sourcesContent":["import { createPrivateKey, randomBytes, randomUUID, sign as nodeSign, type JsonWebKey } from 'crypto';\nimport {\n buildSignatureBase,\n finalizeRequestSignature,\n formatSignatureParams,\n prepareRequestSignature,\n REQUEST_SIGNING_TAG,\n type AdcpJsonWebKey,\n type RequestLike,\n type SignatureParams,\n type SignerKey,\n} from '../../../signing';\nimport { findKey } from './vector-loader';\nimport type { NegativeVector, PositiveVector, TestKeyset, TestKeypair } from './types';\n\nexport interface BuildOptions {\n /** Override the signer clock (unix seconds). Defaults to `Date.now()/1000`. */\n now?: number;\n /** Override the nonce. Defaults to freshly-generated. */\n nonce?: string;\n /** Override the `expires - created` window (seconds). Defaults to 300. */\n windowSeconds?: number;\n /**\n * Agent base URL. When set, the vector's request URL has its origin replaced\n * with this base before signing — the vectors point at `seller.example.com`\n * but real agents live elsewhere. The path and query are preserved so the\n * operation intent (e.g., `/adcp/create_media_buy`) is unchanged.\n *\n * Canonicalization-edge vectors (005 default-port, 006 dot-segment path,\n * 007 query preservation, 008 percent-encoded path) bake their edge case\n * into the vector URL; replacing the origin keeps that edge intact in the\n * path/query, but vectors sensitive to the port or scheme will no longer\n * exercise the edge against a mismatched agent base.\n */\n baseUrl?: string;\n /**\n * Transport-layer framing. `'raw'` (default) sends the vector body to the\n * retargeted vector URL verbatim — matches the conformance vectors' intent\n * of testing a per-operation HTTP endpoint. `'mcp'` wraps the vector body\n * in a JSON-RPC `tools/call` envelope and posts to `baseUrl` as-is (no\n * path join); operation name comes from the vector URL's last segment.\n *\n * MCP mode trades the canonicalization-edge coverage for reach: vectors\n * 005–008 fold into plain POSTs against the MCP endpoint, but the grader\n * works against any MCP agent that wires a verifier at the HTTP layer.\n */\n transport?: 'raw' | 'mcp';\n /**\n * JSON-RPC `id` for the MCP envelope. Defaults to `crypto.randomUUID()`\n * so concurrent runs never collide. Override for tests that need a stable\n * id — JSON-RPC 2.0 permits number, string, or null.\n */\n mcpJsonRpcId?: number | string;\n}\n\nexport interface SignedHttpRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\nexport function buildPositiveRequest(\n vector: PositiveVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, {\n coverContentDigest: vector.verifier_capability.covers_content_digest === 'required',\n ...options,\n });\n}\n\n/**\n * Apply the adversarial mutation documented for a negative vector.\n *\n * Black-box grader: the positive/001 signature bytes sitting in most negative\n * fixtures are placeholders; we re-sign dynamically, then mutate. Covers all\n * 20 current negative vectors. Stateful contract vectors (016 replay, 017\n * revoked, 020 rate abuse) produce a single well-formed request; the\n * storyboard runner orchestrates the repeat/flood/revoked-keyid behavior\n * around that request per the signed-requests-runner test-kit.\n */\nexport function buildNegativeRequest(\n vector: NegativeVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const mutation = MUTATIONS[vector.id];\n if (!mutation) {\n throw new Error(`No adversarial builder registered for negative vector \"${vector.id}\"`);\n }\n return mutation(vector, keys, options);\n}\n\nexport function listSupportedNegativeVectors(): string[] {\n return Object.keys(MUTATIONS);\n}\n\ntype Mutator = (vector: NegativeVector, keys: TestKeyset, options: BuildOptions) => SignedHttpRequest;\n\nconst MUTATIONS: Record<string, Mutator> = {\n '001-no-signature-header': (vector, _keys, options) => {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: stripSignatureHeaders(shaped.headers),\n body: shaped.body,\n };\n },\n\n '002-wrong-tag': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { tag: 'example-org/signing/v1' });\n },\n\n '003-expired-signature': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const now = nowSeconds(options);\n return sign(key, vector, { ...options, now: now - 600, windowSeconds: 300 });\n },\n\n '004-window-too-long': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, {\n expiresDelta: 301,\n });\n },\n\n '005-alg-not-allowed': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { alg: 'rsa-pss-sha512' });\n },\n\n '006-missing-covered-component': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithComponents(key, vector, options, ['@method', '@target-uri', 'content-type']);\n },\n\n '007-missing-content-digest': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: false });\n },\n\n '008-unknown-keyid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { keyid: 'unknown-key-9999' });\n },\n\n '009-key-ops-missing-verify': (vector, keys, options) => {\n // Vector 009 pins `jwks_ref: [\"test-gov-2026\"]` (adcp_use:\n // governance-signing, not request-signing) — use it directly instead of\n // inferring. Honors the vector's intent if future keysets add a second\n // non-request-signing keypair.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '010-content-digest-mismatch': (vector, keys, options) => {\n // Vector 010 tests \"signer committed a wrong Content-Digest value\" — the\n // signature IS valid over the base that includes that wrong value, so the\n // verifier passes the signature check (step 10) and then fails the\n // digest-vs-body recompute (step 11). Do NOT mutate the body post-sign —\n // that tests a different bug (body-tampered-in-transit) and a verifier\n // that recomputes digest from sent body would not catch the \"lying\n // signer\" path this vector exercises.\n const key = signerKeyFor(vector, keys);\n // Zero-byte digest: guaranteed not to match the actual body.\n const zeroDigest = 'sha-256=:' + Buffer.alloc(32).toString('base64') + ':';\n const headersWithBadDigest = { ...vector.request.headers, 'Content-Digest': zeroDigest };\n const vectorWithBadDigest = {\n ...vector,\n request: { ...vector.request, headers: headersWithBadDigest },\n };\n // Sign the request WITH content-digest in covered components, without\n // letting `signRequest` recompute the digest over the real body.\n return signWithComponents(key, vectorWithBadDigest, options, [\n '@method',\n '@target-uri',\n '@authority',\n 'content-type',\n 'content-digest',\n ]);\n },\n\n '011-malformed-header': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n return {\n ...signed,\n headers: {\n ...signed.headers,\n 'Signature-Input': 'sig1=not a valid structured-field value!!!',\n },\n };\n },\n\n '012-missing-expires-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitExpires: true });\n },\n\n '013-expires-le-created': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { expiresDelta: 0 });\n },\n\n '014-missing-nonce-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitNonce: true });\n },\n\n '015-signature-invalid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const zeroSig = Buffer.alloc(64).toString('base64url');\n return {\n ...signed,\n headers: {\n ...signed.headers,\n Signature: `sig1=:${zeroSig}:`,\n },\n };\n },\n\n '016-replayed-nonce': (vector, keys, options) => {\n // Black-box runner sends the request twice; first accepted, second rejected.\n // Builder produces the single well-formed request used for both submissions.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '017-key-revoked': (vector, keys, options) => {\n // Use the dedicated revoked key (`test-revoked-2026`) declared by the\n // signed-requests-runner test-kit. For current pre-#2353 caches, vector 017\n // still references test-ed25519-2026; fall back to whatever the vector says.\n const kid = vector.jwks_ref?.[0];\n if (!kid) throw new Error(`${vector.id}: jwks_ref missing`);\n const key = keyFor(keys, kid);\n return sign(key, vector, options);\n },\n\n '018-digest-covered-when-forbidden': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: true });\n },\n\n '019-signature-without-signature-input': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const { 'Signature-Input': _drop, ...rest } = signed.headers;\n return { ...signed, headers: rest };\n },\n\n '020-rate-abuse': (vector, keys, options) => {\n // Runner floods the agent with distinct-nonce requests from the same keyid.\n // Builder produces a single well-formed request; the runner generates N\n // distinct nonces by calling this builder repeatedly with `options.nonce`.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n // Vectors 021-026 ship their exact malformed headers in the fixture — the\n // adversarial shape (duplicate sig-input label, multi-valued content-type\n // / content-digest, unquoted string param, malformed JWK, non-ASCII host)\n // lives in the vector itself, not in a programmatic mutation. Builder just\n // preserves the fixture's headers verbatim after applying transport.\n '021-duplicate-signature-input-label': (vector, _keys, options) => passthrough(vector, options),\n '022-multi-valued-content-type': (vector, _keys, options) => passthrough(vector, options),\n '023-multi-valued-content-digest': (vector, _keys, options) => passthrough(vector, options),\n '024-unquoted-string-param': (vector, _keys, options) => passthrough(vector, options),\n '025-jwk-alg-crv-mismatch': (vector, _keys, options) => passthrough(vector, options),\n '026-non-ascii-host': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 027 tests the \"webhook authentication MUST trigger signing\" rule:\n // the fixture is a plain bearer-auth request with zero signature headers,\n // and the adversarial shape is precisely that absence. Passthrough preserves\n // the fixture bytes; retargeting still works via applyTransport.\n '027-webhook-registration-authentication-unsigned': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 028 grades the `protocol_methods_required_for` namespace\n // (adcp#4326). The fixture body is already a JSON-RPC envelope with\n // `method: \"tasks/cancel\"` — NOT a `tools/call` envelope — so the standard\n // MCP-mode `applyTransport` (which would wrap the body in `tools/call`)\n // is wrong here. Use `protocolMethodPassthrough` which keeps the body\n // verbatim and targets `baseUrl` directly when set, matching how an\n // agent's MCP endpoint routes JSON-RPC `tasks/*` methods.\n '028-unsigned-protocol-method-required': (vector, _keys, options) => protocolMethodPassthrough(vector, options),\n};\n\nfunction passthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n}\n\n/**\n * Passthrough for vectors whose body is already a JSON-RPC envelope with a\n * non-`tools/call` `method` (e.g., `tasks/cancel`). MCP-mode `applyTransport`\n * would wrap the body in `tools/call`, which is wrong: the protocol_methods\n * namespace matches against the JSON-RPC envelope's `method` field, so\n * wrapping in `tools/call` would route the request to MCP tool dispatch\n * (looking up a tool literally named \"tasks/cancel\"; 404) instead of the\n * SDK's auto-registered `tasks/cancel` JSON-RPC handler.\n *\n * Targets `options.baseUrl` directly when set (the MCP endpoint URL), or\n * the vector's URL verbatim otherwise.\n */\nfunction protocolMethodPassthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n const url = options.baseUrl ?? vector.request.url;\n const headers = { ...vector.request.headers };\n // MCP Streamable HTTP requires this Accept negotiation header on JSON-RPC\n // probes — match the wrapping path's behavior.\n if (options.transport === 'mcp') {\n headers['Accept'] = 'application/json, text/event-stream';\n }\n return {\n method: vector.request.method,\n url,\n headers,\n body: vector.request.body,\n };\n}\n\n// ── Primitives ────────────────────────────────────────────────\n\ninterface SignArgs extends BuildOptions {\n coverContentDigest?: boolean;\n}\n\nfunction sign(key: SignerKey, vector: PositiveVector | NegativeVector, args: SignArgs): SignedHttpRequest {\n const shaped = applyTransport(vector, args);\n const request: RequestLike = {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n // Negative-vector 009 deliberately signs with a wrong-purpose key\n // (`adcp_use: 'governance-signing'`) to exercise the verifier's step-8\n // purpose check. The signer-side `signRequest` gate refuses wrong-purpose\n // keys to prevent the more common operator footgun; bypass it here by\n // composing `prepareRequestSignature` (which takes `SignatureIdentity`\n // and runs no gate) with this file's local `produceSignature` helper.\n // The bypass is intentional and confined to test-vector authoring.\n const prepared = prepareRequestSignature(\n request,\n { keyid: key.keyid, alg: key.alg },\n {\n coverContentDigest: args.coverContentDigest === true,\n now: args.now !== undefined ? () => args.now! : undefined,\n nonce: args.nonce,\n windowSeconds: args.windowSeconds,\n }\n );\n const signature = produceSignature(key, Buffer.from(prepared.base, 'utf8'));\n const signed = finalizeRequestSignature(prepared, signature);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: mergeHeaders(shaped.headers, signed.headers),\n body: shaped.body,\n };\n}\n\nfunction retargetUrl(vectorUrl: string, baseUrl: string | undefined): string {\n if (!baseUrl) return vectorUrl;\n const v = new URL(vectorUrl);\n const b = new URL(baseUrl);\n v.protocol = b.protocol;\n v.host = b.host;\n // Prefix the agent's mount path (from baseUrl) ahead of the vector's path\n // so agents mounted at e.g. `/v1/adcp/*` receive requests at\n // `/v1/adcp/create_media_buy` rather than the bare `/adcp/create_media_buy`\n // the vector carries. When baseUrl has no path (or just `/`), this is a\n // no-op. Canonicalization-edge vectors (005–008) bake their edge into the\n // vector's path/query; we preserve those bytes by joining, not replacing.\n if (b.pathname && b.pathname !== '/') {\n const mount = b.pathname.replace(/\\/+$/, '');\n const vectorPath = v.pathname.startsWith('/') ? v.pathname : `/${v.pathname}`;\n v.pathname = `${mount}${vectorPath}`;\n }\n return v.toString();\n}\n\ninterface TransportShapedRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\n/**\n * Apply the transport transform to a vector's request shape. In `'raw'` mode\n * (default) this is just origin-swap path-merge. In `'mcp'` mode:\n * - URL becomes `baseUrl` exactly (no path join — MCP agents expose a single\n * JSON-RPC endpoint; the operation is named in the body).\n * - Body is wrapped in a JSON-RPC `tools/call` envelope; the operation name\n * comes from the vector's last URL segment.\n * - `Accept: application/json, text/event-stream` added so MCP Streamable\n * HTTP servers don't 406 on the probe.\n *\n * Shared call site for `sign`, `signWithParamOverride`, `signWithComponents`\n * so every mutation path produces MCP-shaped requests when requested.\n */\nfunction applyTransport(vector: PositiveVector | NegativeVector, options: BuildOptions): TransportShapedRequest {\n const headers = { ...vector.request.headers };\n if (options.transport === 'mcp') {\n if (!options.baseUrl) {\n throw new Error(`transport: 'mcp' requires a baseUrl (the MCP endpoint, e.g. http://agent/mcp)`);\n }\n const operation = extractOperationFromVectorUrl(vector.request.url);\n const envelope = wrapMcpEnvelope(operation, vector.request.body, options.mcpJsonRpcId);\n // Accept header added for MCP Streamable HTTP negotiation. Not in the\n // signed components list (MANDATORY_COMPONENTS doesn't include `accept`),\n // so adding it after the vector's headers doesn't affect the signature.\n headers['Accept'] = 'application/json, text/event-stream';\n return {\n method: vector.request.method,\n url: options.baseUrl,\n headers,\n body: envelope,\n };\n }\n return {\n method: vector.request.method,\n url: retargetUrl(vector.request.url, options.baseUrl),\n headers,\n body: vector.request.body,\n };\n}\n\n// AdCP operation names are spec-defined identifiers (lowercase alnum +\n// underscore — `create_media_buy`, `sync_creatives`, `si_send_message`,\n// etc.; verified against every `task:` value shipped in\n// `compliance/cache/{version}/protocols/**/*.yaml`). Constrain the extractor\n// output to that shape so a compromised compliance cache can't smuggle\n// arbitrary bytes into `params.name` via a weird vector URL.\nconst OPERATION_NAME_SAFE = /^[a-z][a-z0-9_]*$/;\n\nfunction extractOperationFromVectorUrl(vectorUrl: string): string {\n const parsed = new URL(vectorUrl);\n const segments = parsed.pathname.split('/').filter(Boolean);\n const last = segments[segments.length - 1];\n if (!last) throw new Error(`Cannot extract operation from vector URL: ${vectorUrl}`);\n if (!OPERATION_NAME_SAFE.test(last)) {\n throw new Error(\n `Operation name \"${last}\" extracted from ${vectorUrl} fails identifier check. ` +\n `AdCP operations are lowercase_snake_case; this is likely a corrupted compliance cache.`\n );\n }\n return last;\n}\n\nfunction wrapMcpEnvelope(\n operation: string,\n rawBody: string | undefined,\n idOverride: number | string | undefined\n): string {\n const id = idOverride ?? randomUUID();\n // Conformance vectors' bodies are spec-typed as JSON. A parse failure is\n // a vector drift, not a runtime input-validation case — let it surface.\n const args = rawBody && rawBody.length > 0 ? JSON.parse(rawBody) : {};\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n method: 'tools/call',\n params: { name: operation, arguments: args },\n });\n}\n\ninterface ParamOverride {\n tag?: string;\n alg?: string;\n keyid?: string;\n expiresDelta?: number;\n omitExpires?: boolean;\n omitNonce?: boolean;\n}\n\n/**\n * Build a signature base with overridden params, sign it directly, and emit\n * the headers. Needed when the mutation lives in `@signature-params` itself\n * (tag, alg, keyid, expires, nonce) — signRequest won't emit those exact\n * malformations.\n */\nfunction signWithParamOverride(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n override: ParamOverride\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const hasBody = (request.body ?? '').length > 0;\n const components = hasBody\n ? ['@method', '@target-uri', '@authority', 'content-type']\n : ['@method', '@target-uri', '@authority'];\n\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + (override.expiresDelta ?? windowSeconds),\n nonce: options.nonce ?? randomNonce(),\n keyid: override.keyid ?? key.keyid,\n alg: override.alg ?? key.alg,\n tag: override.tag ?? REQUEST_SIGNING_TAG,\n };\n\n const paramsString = formatParamsWithOmissions(components, params, override);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction signWithComponents(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n components: string[]\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + windowSeconds,\n nonce: options.nonce ?? randomNonce(),\n keyid: key.keyid,\n alg: key.alg,\n tag: REQUEST_SIGNING_TAG,\n };\n const paramsString = formatSignatureParams(components, params);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction formatParamsWithOmissions(\n components: ReadonlyArray<string>,\n params: SignatureParams,\n override: ParamOverride\n): string {\n const componentList = components.map(c => `\"${c}\"`).join(' ');\n const pairs: string[] = [];\n pairs.push(`created=${params.created}`);\n if (!override.omitExpires) pairs.push(`expires=${params.expires}`);\n if (!override.omitNonce) pairs.push(`nonce=\"${params.nonce}\"`);\n pairs.push(`keyid=\"${params.keyid}\"`);\n pairs.push(`alg=\"${params.alg}\"`);\n pairs.push(`tag=\"${params.tag}\"`);\n return `(${componentList});${pairs.join(';')}`;\n}\n\nfunction produceSignature(key: SignerKey, data: Buffer): Uint8Array {\n const privateKey = createPrivateKey({ key: key.privateKey as JsonWebKey, format: 'jwk' });\n if (key.alg === 'ed25519') {\n return new Uint8Array(nodeSign(null, data, privateKey));\n }\n return new Uint8Array(nodeSign('sha256', data, { key: privateKey, dsaEncoding: 'ieee-p1363' }));\n}\n\n// ── Helpers ───────────────────────────────────────────────────\n\nfunction signerKeyFor(vector: PositiveVector | NegativeVector, keys: TestKeyset): SignerKey {\n const kid = vector.jwks_ref?.[0];\n if (!kid) {\n throw new Error(\n `${vector.id}: jwks_ref missing — vectors signed dynamically by the builder must declare a keys.json kid. ` +\n `Vectors shipping an inline jwks_override must use a passthrough mutator (no re-signing).`\n );\n }\n return keyFor(keys, kid);\n}\n\nfunction keyFor(keys: TestKeyset, kid: string): SignerKey {\n const keypair = findKey(keys, kid);\n return toSignerKey(keypair);\n}\n\nfunction toSignerKey(keypair: TestKeypair): SignerKey {\n const alg: SignerKey['alg'] = keypair.crv === 'Ed25519' ? 'ed25519' : 'ecdsa-p256-sha256';\n const privateKey: AdcpJsonWebKey = {\n kid: keypair.kid,\n kty: keypair.kty,\n crv: keypair.crv,\n alg: keypair.alg,\n use: keypair.use,\n key_ops: ['sign'],\n adcp_use: keypair.adcp_use,\n x: keypair.x,\n y: keypair.y,\n d: keypair.private_d,\n };\n return { keyid: keypair.kid, alg, privateKey };\n}\n\nfunction stripSignatureHeaders(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n const lower = k.toLowerCase();\n if (lower === 'signature' || lower === 'signature-input' || lower === 'content-digest') continue;\n out[k] = v;\n }\n return out;\n}\n\nfunction mergeHeaders(from: Record<string, string>, signed: Record<string, string>): Record<string, string> {\n // Drop original Signature/Signature-Input/Content-Digest before overlaying fresh ones.\n const base = stripSignatureHeaders(from);\n return { ...base, ...signed };\n}\n\nfunction nowSeconds(options: BuildOptions): number {\n return options.now ?? Math.floor(Date.now() / 1000);\n}\n\nfunction randomNonce(): string {\n return randomBytes(16).toString('base64url');\n}\n"],"mappings":"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","names":["nodeSign"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/builder.ts"],"sourcesContent":["import { createPrivateKey, randomBytes, randomUUID, sign as nodeSign, type JsonWebKey } from 'crypto';\nimport {\n buildSignatureBase,\n finalizeRequestSignature,\n formatSignatureParams,\n prepareRequestSignature,\n REQUEST_SIGNING_TAG,\n type AdcpJsonWebKey,\n type RequestLike,\n type SignatureParams,\n type SignerKey,\n} from '../../../signing';\nimport { findKey } from './vector-loader';\nimport type { NegativeVector, PositiveVector, TestKeyset, TestKeypair } from './types';\nimport type { CapturedA2aRequest } from './a2a-dispatch';\n\nexport interface BuildOptions {\n /** Override the signer clock (unix seconds). Defaults to `Date.now()/1000`. */\n now?: number;\n /** Override the nonce. Defaults to freshly-generated. */\n nonce?: string;\n /** Override the `expires - created` window (seconds). Defaults to 300. */\n windowSeconds?: number;\n /**\n * Agent base URL. When set, the vector's request URL has its origin replaced\n * with this base before signing — the vectors point at `seller.example.com`\n * but real agents live elsewhere. The path and query are preserved so the\n * operation intent (e.g., `/adcp/create_media_buy`) is unchanged.\n *\n * Canonicalization-edge vectors (005 default-port, 006 dot-segment path,\n * 007 query preservation, 008 percent-encoded path) bake their edge case\n * into the vector URL; replacing the origin keeps that edge intact in the\n * path/query, but vectors sensitive to the port or scheme will no longer\n * exercise the edge against a mismatched agent base.\n */\n baseUrl?: string;\n /**\n * Transport-layer framing. `'raw'` (default) sends the vector body to the\n * retargeted vector URL verbatim — matches the conformance vectors' intent\n * of testing a per-operation HTTP endpoint. `'mcp'` wraps the vector body\n * in a JSON-RPC `tools/call` envelope and posts to `baseUrl` as-is (no\n * path join); operation name comes from the vector URL's last segment.\n *\n * MCP mode trades the canonicalization-edge coverage for reach: vectors\n * 005–008 fold into plain POSTs against the MCP endpoint, but the grader\n * works against any MCP agent that wires a verifier at the HTTP layer.\n */\n transport?: 'raw' | 'mcp' | 'a2a';\n /** Request emitted by the official A2A SDK; required for A2A transport. */\n a2aRequest?: CapturedA2aRequest;\n /**\n * JSON-RPC `id` for the MCP envelope. Defaults to `crypto.randomUUID()`\n * so concurrent runs never collide. Override for tests that need a stable\n * id — JSON-RPC 2.0 permits number, string, or null.\n */\n mcpJsonRpcId?: number | string;\n}\n\nexport interface SignedHttpRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\nexport function buildPositiveRequest(\n vector: PositiveVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, {\n coverContentDigest: vector.verifier_capability.covers_content_digest === 'required',\n ...options,\n });\n}\n\n/**\n * Apply the adversarial mutation documented for a negative vector.\n *\n * Black-box grader: the positive/001 signature bytes sitting in most negative\n * fixtures are placeholders; we re-sign dynamically, then mutate. Covers all\n * 20 current negative vectors. Stateful contract vectors (016 replay, 017\n * revoked, 020 rate abuse) produce a single well-formed request; the\n * storyboard runner orchestrates the repeat/flood/revoked-keyid behavior\n * around that request per the signed-requests-runner test-kit.\n */\nexport function buildNegativeRequest(\n vector: NegativeVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const mutation = MUTATIONS[vector.id];\n if (!mutation) {\n throw new Error(`No adversarial builder registered for negative vector \"${vector.id}\"`);\n }\n return mutation(vector, keys, options);\n}\n\nexport function listSupportedNegativeVectors(): string[] {\n return Object.keys(MUTATIONS);\n}\n\ntype Mutator = (vector: NegativeVector, keys: TestKeyset, options: BuildOptions) => SignedHttpRequest;\n\nconst MUTATIONS: Record<string, Mutator> = {\n '001-no-signature-header': (vector, _keys, options) => {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: stripSignatureHeaders(shaped.headers),\n body: shaped.body,\n };\n },\n\n '002-wrong-tag': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { tag: 'example-org/signing/v1' });\n },\n\n '003-expired-signature': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const now = nowSeconds(options);\n return sign(key, vector, { ...options, now: now - 600, windowSeconds: 300 });\n },\n\n '004-window-too-long': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, {\n expiresDelta: 301,\n });\n },\n\n '005-alg-not-allowed': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { alg: 'rsa-pss-sha512' });\n },\n\n '006-missing-covered-component': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithComponents(key, vector, options, ['@method', '@target-uri', 'content-type']);\n },\n\n '007-missing-content-digest': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: false });\n },\n\n '008-unknown-keyid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { keyid: 'unknown-key-9999' });\n },\n\n '009-key-ops-missing-verify': (vector, keys, options) => {\n // Vector 009 pins `jwks_ref: [\"test-gov-2026\"]` (adcp_use:\n // governance-signing, not request-signing) — use it directly instead of\n // inferring. Honors the vector's intent if future keysets add a second\n // non-request-signing keypair.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '010-content-digest-mismatch': (vector, keys, options) => {\n // Vector 010 tests \"signer committed a wrong Content-Digest value\" — the\n // signature IS valid over the base that includes that wrong value, so the\n // verifier passes the signature check (step 10) and then fails the\n // digest-vs-body recompute (step 11). Do NOT mutate the body post-sign —\n // that tests a different bug (body-tampered-in-transit) and a verifier\n // that recomputes digest from sent body would not catch the \"lying\n // signer\" path this vector exercises.\n const key = signerKeyFor(vector, keys);\n // Zero-byte digest: guaranteed not to match the actual body.\n const zeroDigest = 'sha-256=:' + Buffer.alloc(32).toString('base64') + ':';\n const headersWithBadDigest = { ...vector.request.headers, 'Content-Digest': zeroDigest };\n const vectorWithBadDigest = {\n ...vector,\n request: { ...vector.request, headers: headersWithBadDigest },\n };\n // Sign the request WITH content-digest in covered components, without\n // letting `signRequest` recompute the digest over the real body.\n return signWithComponents(key, vectorWithBadDigest, options, [\n '@method',\n '@target-uri',\n '@authority',\n 'content-type',\n 'content-digest',\n ]);\n },\n\n '011-malformed-header': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n return {\n ...signed,\n headers: {\n ...signed.headers,\n 'Signature-Input': 'sig1=not a valid structured-field value!!!',\n },\n };\n },\n\n '012-missing-expires-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitExpires: true });\n },\n\n '013-expires-le-created': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { expiresDelta: 0 });\n },\n\n '014-missing-nonce-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitNonce: true });\n },\n\n '015-signature-invalid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const zeroSig = Buffer.alloc(64).toString('base64url');\n return {\n ...signed,\n headers: {\n ...signed.headers,\n Signature: `sig1=:${zeroSig}:`,\n },\n };\n },\n\n '016-replayed-nonce': (vector, keys, options) => {\n // Black-box runner sends the request twice; first accepted, second rejected.\n // Builder produces the single well-formed request used for both submissions.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '017-key-revoked': (vector, keys, options) => {\n // Use the dedicated revoked key (`test-revoked-2026`) declared by the\n // signed-requests-runner test-kit. For current pre-#2353 caches, vector 017\n // still references test-ed25519-2026; fall back to whatever the vector says.\n const kid = vector.jwks_ref?.[0];\n if (!kid) throw new Error(`${vector.id}: jwks_ref missing`);\n const key = keyFor(keys, kid);\n return sign(key, vector, options);\n },\n\n '018-digest-covered-when-forbidden': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: true });\n },\n\n '019-signature-without-signature-input': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const { 'Signature-Input': _drop, ...rest } = signed.headers;\n return { ...signed, headers: rest };\n },\n\n '020-rate-abuse': (vector, keys, options) => {\n // Runner floods the agent with distinct-nonce requests from the same keyid.\n // Builder produces a single well-formed request; the runner generates N\n // distinct nonces by calling this builder repeatedly with `options.nonce`.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n // Vectors 021-026 ship their exact malformed headers in the fixture — the\n // adversarial shape (duplicate sig-input label, multi-valued content-type\n // / content-digest, unquoted string param, malformed JWK, non-ASCII host)\n // lives in the vector itself, not in a programmatic mutation. Builder just\n // preserves the fixture's headers verbatim after applying transport.\n '021-duplicate-signature-input-label': (vector, _keys, options) => passthrough(vector, options),\n '022-multi-valued-content-type': (vector, _keys, options) => passthrough(vector, options),\n '023-multi-valued-content-digest': (vector, _keys, options) => passthrough(vector, options),\n '024-unquoted-string-param': (vector, _keys, options) => passthrough(vector, options),\n '025-jwk-alg-crv-mismatch': (vector, _keys, options) => passthrough(vector, options),\n '026-non-ascii-host': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 027 tests the \"webhook authentication MUST trigger signing\" rule:\n // the fixture is a plain bearer-auth request with zero signature headers,\n // and the adversarial shape is precisely that absence. Passthrough preserves\n // the fixture bytes; retargeting still works via applyTransport.\n '027-webhook-registration-authentication-unsigned': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 028 grades the `protocol_methods_required_for` namespace\n // (adcp#4326). The fixture body is already a JSON-RPC envelope with\n // `method: \"tasks/cancel\"` — NOT a `tools/call` envelope — so the standard\n // MCP-mode `applyTransport` (which would wrap the body in `tools/call`)\n // is wrong here. Use `protocolMethodPassthrough` which keeps the body\n // verbatim and targets `baseUrl` directly when set, matching how an\n // agent's MCP endpoint routes JSON-RPC `tasks/*` methods.\n '028-unsigned-protocol-method-required': (vector, _keys, options) => protocolMethodPassthrough(vector, options),\n};\n\nfunction passthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n}\n\n/**\n * Passthrough for vectors whose body is already a JSON-RPC envelope with a\n * non-`tools/call` `method` (e.g., `tasks/cancel`). MCP-mode `applyTransport`\n * would wrap the body in `tools/call`, which is wrong: the protocol_methods\n * namespace matches against the JSON-RPC envelope's `method` field, so\n * wrapping in `tools/call` would route the request to MCP tool dispatch\n * (looking up a tool literally named \"tasks/cancel\"; 404) instead of the\n * SDK's auto-registered `tasks/cancel` JSON-RPC handler.\n *\n * Targets `options.baseUrl` directly when set (the MCP endpoint URL), or\n * the vector's URL verbatim otherwise.\n */\nfunction protocolMethodPassthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n if (options.transport === 'a2a') return passthrough(vector, options);\n const url = options.baseUrl ?? vector.request.url;\n const headers = { ...vector.request.headers };\n // MCP Streamable HTTP requires this Accept negotiation header on JSON-RPC\n // probes — match the wrapping path's behavior.\n if (options.transport === 'mcp') {\n headers['Accept'] = 'application/json, text/event-stream';\n }\n return {\n method: vector.request.method,\n url,\n headers,\n body: vector.request.body,\n };\n}\n\n// ── Primitives ────────────────────────────────────────────────\n\ninterface SignArgs extends BuildOptions {\n coverContentDigest?: boolean;\n}\n\nfunction sign(key: SignerKey, vector: PositiveVector | NegativeVector, args: SignArgs): SignedHttpRequest {\n const shaped = applyTransport(vector, args);\n const request: RequestLike = {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n // Negative-vector 009 deliberately signs with a wrong-purpose key\n // (`adcp_use: 'governance-signing'`) to exercise the verifier's step-8\n // purpose check. The signer-side `signRequest` gate refuses wrong-purpose\n // keys to prevent the more common operator footgun; bypass it here by\n // composing `prepareRequestSignature` (which takes `SignatureIdentity`\n // and runs no gate) with this file's local `produceSignature` helper.\n // The bypass is intentional and confined to test-vector authoring.\n const prepared = prepareRequestSignature(\n request,\n { keyid: key.keyid, alg: key.alg },\n {\n coverContentDigest: args.coverContentDigest === true,\n now: args.now !== undefined ? () => args.now! : undefined,\n nonce: args.nonce,\n windowSeconds: args.windowSeconds,\n }\n );\n const signature = produceSignature(key, Buffer.from(prepared.base, 'utf8'));\n const signed = finalizeRequestSignature(prepared, signature);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: mergeHeaders(shaped.headers, signed.headers),\n body: shaped.body,\n };\n}\n\nfunction retargetUrl(vectorUrl: string, baseUrl: string | undefined): string {\n if (!baseUrl) return vectorUrl;\n const v = new URL(vectorUrl);\n const b = new URL(baseUrl);\n v.protocol = b.protocol;\n v.host = b.host;\n // Prefix the agent's mount path (from baseUrl) ahead of the vector's path\n // so agents mounted at e.g. `/v1/adcp/*` receive requests at\n // `/v1/adcp/create_media_buy` rather than the bare `/adcp/create_media_buy`\n // the vector carries. When baseUrl has no path (or just `/`), this is a\n // no-op. Canonicalization-edge vectors (005–008) bake their edge into the\n // vector's path/query; we preserve those bytes by joining, not replacing.\n if (b.pathname && b.pathname !== '/') {\n const mount = b.pathname.replace(/\\/+$/, '');\n const vectorPath = v.pathname.startsWith('/') ? v.pathname : `/${v.pathname}`;\n v.pathname = `${mount}${vectorPath}`;\n }\n return v.toString();\n}\n\ninterface TransportShapedRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\n/**\n * Apply the transport transform to a vector's request shape. In `'raw'` mode\n * (default) this is just origin-swap path-merge. In `'mcp'` mode:\n * - URL becomes `baseUrl` exactly (no path join — MCP agents expose a single\n * JSON-RPC endpoint; the operation is named in the body).\n * - Body is wrapped in a JSON-RPC `tools/call` envelope; the operation name\n * comes from the vector's last URL segment.\n * - `Accept: application/json, text/event-stream` added so MCP Streamable\n * HTTP servers don't 406 on the probe.\n *\n * Shared call site for `sign`, `signWithParamOverride`, `signWithComponents`\n * so every mutation path produces MCP-shaped requests when requested.\n */\nfunction applyTransport(vector: PositiveVector | NegativeVector, options: BuildOptions): TransportShapedRequest {\n const headers = { ...vector.request.headers };\n if (options.transport === 'a2a') {\n if (!options.a2aRequest) {\n throw new Error(\"transport: 'a2a' requires a request captured from the official @a2a-js/sdk client\");\n }\n return {\n method: options.a2aRequest.method,\n url: options.a2aRequest.url,\n headers: mergeHeadersCaseInsensitively(options.a2aRequest.headers, headers),\n body: options.a2aRequest.body,\n };\n }\n if (options.transport === 'mcp') {\n if (!options.baseUrl) {\n throw new Error(`transport: 'mcp' requires a baseUrl (the MCP endpoint, e.g. http://agent/mcp)`);\n }\n const operation = extractOperationFromVectorUrl(vector.request.url);\n const envelope = wrapMcpEnvelope(operation, vector.request.body, options.mcpJsonRpcId);\n // Accept header added for MCP Streamable HTTP negotiation. Not in the\n // signed components list (MANDATORY_COMPONENTS doesn't include `accept`),\n // so adding it after the vector's headers doesn't affect the signature.\n headers['Accept'] = 'application/json, text/event-stream';\n return {\n method: vector.request.method,\n url: options.baseUrl,\n headers,\n body: envelope,\n };\n }\n return {\n method: vector.request.method,\n url: retargetUrl(vector.request.url, options.baseUrl),\n headers,\n body: vector.request.body,\n };\n}\n\nfunction mergeHeadersCaseInsensitively(\n base: Record<string, string>,\n overrides: Record<string, string>\n): Record<string, string> {\n const overridden = new Set(Object.keys(overrides).map(name => name.toLowerCase()));\n return {\n ...Object.fromEntries(Object.entries(base).filter(([name]) => !overridden.has(name.toLowerCase()))),\n ...overrides,\n };\n}\n\n// AdCP operation names are spec-defined identifiers (lowercase alnum +\n// underscore — `create_media_buy`, `sync_creatives`, `si_send_message`,\n// etc.; verified against every `task:` value shipped in\n// `compliance/cache/{version}/protocols/**/*.yaml`). Constrain the extractor\n// output to that shape so a compromised compliance cache can't smuggle\n// arbitrary bytes into `params.name` via a weird vector URL.\nconst OPERATION_NAME_SAFE = /^[a-z][a-z0-9_]*$/;\n\nfunction extractOperationFromVectorUrl(vectorUrl: string): string {\n const parsed = new URL(vectorUrl);\n const segments = parsed.pathname.split('/').filter(Boolean);\n const last = segments[segments.length - 1];\n if (!last) throw new Error(`Cannot extract operation from vector URL: ${vectorUrl}`);\n if (!OPERATION_NAME_SAFE.test(last)) {\n throw new Error(\n `Operation name \"${last}\" extracted from ${vectorUrl} fails identifier check. ` +\n `AdCP operations are lowercase_snake_case; this is likely a corrupted compliance cache.`\n );\n }\n return last;\n}\n\nfunction wrapMcpEnvelope(\n operation: string,\n rawBody: string | undefined,\n idOverride: number | string | undefined\n): string {\n const id = idOverride ?? randomUUID();\n // Conformance vectors' bodies are spec-typed as JSON. A parse failure is\n // a vector drift, not a runtime input-validation case — let it surface.\n const args = rawBody && rawBody.length > 0 ? JSON.parse(rawBody) : {};\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n method: 'tools/call',\n params: { name: operation, arguments: args },\n });\n}\n\ninterface ParamOverride {\n tag?: string;\n alg?: string;\n keyid?: string;\n expiresDelta?: number;\n omitExpires?: boolean;\n omitNonce?: boolean;\n}\n\n/**\n * Build a signature base with overridden params, sign it directly, and emit\n * the headers. Needed when the mutation lives in `@signature-params` itself\n * (tag, alg, keyid, expires, nonce) — signRequest won't emit those exact\n * malformations.\n */\nfunction signWithParamOverride(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n override: ParamOverride\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const hasBody = (request.body ?? '').length > 0;\n const components = hasBody\n ? ['@method', '@target-uri', '@authority', 'content-type']\n : ['@method', '@target-uri', '@authority'];\n\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + (override.expiresDelta ?? windowSeconds),\n nonce: options.nonce ?? randomNonce(),\n keyid: override.keyid ?? key.keyid,\n alg: override.alg ?? key.alg,\n tag: override.tag ?? REQUEST_SIGNING_TAG,\n };\n\n const paramsString = formatParamsWithOmissions(components, params, override);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction signWithComponents(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n components: string[]\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + windowSeconds,\n nonce: options.nonce ?? randomNonce(),\n keyid: key.keyid,\n alg: key.alg,\n tag: REQUEST_SIGNING_TAG,\n };\n const paramsString = formatSignatureParams(components, params);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction formatParamsWithOmissions(\n components: ReadonlyArray<string>,\n params: SignatureParams,\n override: ParamOverride\n): string {\n const componentList = components.map(c => `\"${c}\"`).join(' ');\n const pairs: string[] = [];\n pairs.push(`created=${params.created}`);\n if (!override.omitExpires) pairs.push(`expires=${params.expires}`);\n if (!override.omitNonce) pairs.push(`nonce=\"${params.nonce}\"`);\n pairs.push(`keyid=\"${params.keyid}\"`);\n pairs.push(`alg=\"${params.alg}\"`);\n pairs.push(`tag=\"${params.tag}\"`);\n return `(${componentList});${pairs.join(';')}`;\n}\n\nfunction produceSignature(key: SignerKey, data: Buffer): Uint8Array {\n const privateKey = createPrivateKey({ key: key.privateKey as JsonWebKey, format: 'jwk' });\n if (key.alg === 'ed25519') {\n return new Uint8Array(nodeSign(null, data, privateKey));\n }\n return new Uint8Array(nodeSign('sha256', data, { key: privateKey, dsaEncoding: 'ieee-p1363' }));\n}\n\n// ── Helpers ───────────────────────────────────────────────────\n\nfunction signerKeyFor(vector: PositiveVector | NegativeVector, keys: TestKeyset): SignerKey {\n const kid = vector.jwks_ref?.[0];\n if (!kid) {\n throw new Error(\n `${vector.id}: jwks_ref missing — vectors signed dynamically by the builder must declare a keys.json kid. ` +\n `Vectors shipping an inline jwks_override must use a passthrough mutator (no re-signing).`\n );\n }\n return keyFor(keys, kid);\n}\n\nfunction keyFor(keys: TestKeyset, kid: string): SignerKey {\n const keypair = findKey(keys, kid);\n return toSignerKey(keypair);\n}\n\nfunction toSignerKey(keypair: TestKeypair): SignerKey {\n const alg: SignerKey['alg'] = keypair.crv === 'Ed25519' ? 'ed25519' : 'ecdsa-p256-sha256';\n const privateKey: AdcpJsonWebKey = {\n kid: keypair.kid,\n kty: keypair.kty,\n crv: keypair.crv,\n alg: keypair.alg,\n use: keypair.use,\n key_ops: ['sign'],\n adcp_use: keypair.adcp_use,\n x: keypair.x,\n y: keypair.y,\n d: keypair.private_d,\n };\n return { keyid: keypair.kid, alg, privateKey };\n}\n\nfunction stripSignatureHeaders(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n const lower = k.toLowerCase();\n if (lower === 'signature' || lower === 'signature-input' || lower === 'content-digest') continue;\n out[k] = v;\n }\n return out;\n}\n\nfunction mergeHeaders(from: Record<string, string>, signed: Record<string, string>): Record<string, string> {\n // Drop original Signature/Signature-Input/Content-Digest before overlaying fresh ones.\n const base = stripSignatureHeaders(from);\n return { ...base, ...signed };\n}\n\nfunction nowSeconds(options: BuildOptions): number {\n return options.now ?? Math.floor(Date.now() / 1000);\n}\n\nfunction randomNonce(): string {\n return randomBytes(16).toString('base64url');\n}\n"],"mappings":"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","names":["nodeSign"]}
|
|
@@ -179,6 +179,7 @@ function passthrough(vector, options) {
|
|
|
179
179
|
};
|
|
180
180
|
}
|
|
181
181
|
function protocolMethodPassthrough(vector, options) {
|
|
182
|
+
if (options.transport === "a2a") return passthrough(vector, options);
|
|
182
183
|
const url = options.baseUrl ?? vector.request.url;
|
|
183
184
|
const headers = { ...vector.request.headers };
|
|
184
185
|
if (options.transport === "mcp") {
|
|
@@ -233,6 +234,17 @@ function retargetUrl(vectorUrl, baseUrl) {
|
|
|
233
234
|
}
|
|
234
235
|
function applyTransport(vector, options) {
|
|
235
236
|
const headers = { ...vector.request.headers };
|
|
237
|
+
if (options.transport === "a2a") {
|
|
238
|
+
if (!options.a2aRequest) {
|
|
239
|
+
throw new Error("transport: 'a2a' requires a request captured from the official @a2a-js/sdk client");
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
method: options.a2aRequest.method,
|
|
243
|
+
url: options.a2aRequest.url,
|
|
244
|
+
headers: mergeHeadersCaseInsensitively(options.a2aRequest.headers, headers),
|
|
245
|
+
body: options.a2aRequest.body
|
|
246
|
+
};
|
|
247
|
+
}
|
|
236
248
|
if (options.transport === "mcp") {
|
|
237
249
|
if (!options.baseUrl) {
|
|
238
250
|
throw new Error(`transport: 'mcp' requires a baseUrl (the MCP endpoint, e.g. http://agent/mcp)`);
|
|
@@ -254,6 +266,13 @@ function applyTransport(vector, options) {
|
|
|
254
266
|
body: vector.request.body
|
|
255
267
|
};
|
|
256
268
|
}
|
|
269
|
+
function mergeHeadersCaseInsensitively(base, overrides) {
|
|
270
|
+
const overridden = new Set(Object.keys(overrides).map((name) => name.toLowerCase()));
|
|
271
|
+
return {
|
|
272
|
+
...Object.fromEntries(Object.entries(base).filter(([name]) => !overridden.has(name.toLowerCase()))),
|
|
273
|
+
...overrides
|
|
274
|
+
};
|
|
275
|
+
}
|
|
257
276
|
const OPERATION_NAME_SAFE = /^[a-z][a-z0-9_]*$/;
|
|
258
277
|
function extractOperationFromVectorUrl(vectorUrl) {
|
|
259
278
|
const parsed = new URL(vectorUrl);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/builder.ts"],"sourcesContent":["import { createPrivateKey, randomBytes, randomUUID, sign as nodeSign, type JsonWebKey } from 'crypto';\nimport {\n buildSignatureBase,\n finalizeRequestSignature,\n formatSignatureParams,\n prepareRequestSignature,\n REQUEST_SIGNING_TAG,\n type AdcpJsonWebKey,\n type RequestLike,\n type SignatureParams,\n type SignerKey,\n} from '../../../signing';\nimport { findKey } from './vector-loader';\nimport type { NegativeVector, PositiveVector, TestKeyset, TestKeypair } from './types';\n\nexport interface BuildOptions {\n /** Override the signer clock (unix seconds). Defaults to `Date.now()/1000`. */\n now?: number;\n /** Override the nonce. Defaults to freshly-generated. */\n nonce?: string;\n /** Override the `expires - created` window (seconds). Defaults to 300. */\n windowSeconds?: number;\n /**\n * Agent base URL. When set, the vector's request URL has its origin replaced\n * with this base before signing — the vectors point at `seller.example.com`\n * but real agents live elsewhere. The path and query are preserved so the\n * operation intent (e.g., `/adcp/create_media_buy`) is unchanged.\n *\n * Canonicalization-edge vectors (005 default-port, 006 dot-segment path,\n * 007 query preservation, 008 percent-encoded path) bake their edge case\n * into the vector URL; replacing the origin keeps that edge intact in the\n * path/query, but vectors sensitive to the port or scheme will no longer\n * exercise the edge against a mismatched agent base.\n */\n baseUrl?: string;\n /**\n * Transport-layer framing. `'raw'` (default) sends the vector body to the\n * retargeted vector URL verbatim — matches the conformance vectors' intent\n * of testing a per-operation HTTP endpoint. `'mcp'` wraps the vector body\n * in a JSON-RPC `tools/call` envelope and posts to `baseUrl` as-is (no\n * path join); operation name comes from the vector URL's last segment.\n *\n * MCP mode trades the canonicalization-edge coverage for reach: vectors\n * 005–008 fold into plain POSTs against the MCP endpoint, but the grader\n * works against any MCP agent that wires a verifier at the HTTP layer.\n */\n transport?: 'raw' | 'mcp';\n /**\n * JSON-RPC `id` for the MCP envelope. Defaults to `crypto.randomUUID()`\n * so concurrent runs never collide. Override for tests that need a stable\n * id — JSON-RPC 2.0 permits number, string, or null.\n */\n mcpJsonRpcId?: number | string;\n}\n\nexport interface SignedHttpRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\nexport function buildPositiveRequest(\n vector: PositiveVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, {\n coverContentDigest: vector.verifier_capability.covers_content_digest === 'required',\n ...options,\n });\n}\n\n/**\n * Apply the adversarial mutation documented for a negative vector.\n *\n * Black-box grader: the positive/001 signature bytes sitting in most negative\n * fixtures are placeholders; we re-sign dynamically, then mutate. Covers all\n * 20 current negative vectors. Stateful contract vectors (016 replay, 017\n * revoked, 020 rate abuse) produce a single well-formed request; the\n * storyboard runner orchestrates the repeat/flood/revoked-keyid behavior\n * around that request per the signed-requests-runner test-kit.\n */\nexport function buildNegativeRequest(\n vector: NegativeVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const mutation = MUTATIONS[vector.id];\n if (!mutation) {\n throw new Error(`No adversarial builder registered for negative vector \"${vector.id}\"`);\n }\n return mutation(vector, keys, options);\n}\n\nexport function listSupportedNegativeVectors(): string[] {\n return Object.keys(MUTATIONS);\n}\n\ntype Mutator = (vector: NegativeVector, keys: TestKeyset, options: BuildOptions) => SignedHttpRequest;\n\nconst MUTATIONS: Record<string, Mutator> = {\n '001-no-signature-header': (vector, _keys, options) => {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: stripSignatureHeaders(shaped.headers),\n body: shaped.body,\n };\n },\n\n '002-wrong-tag': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { tag: 'example-org/signing/v1' });\n },\n\n '003-expired-signature': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const now = nowSeconds(options);\n return sign(key, vector, { ...options, now: now - 600, windowSeconds: 300 });\n },\n\n '004-window-too-long': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, {\n expiresDelta: 301,\n });\n },\n\n '005-alg-not-allowed': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { alg: 'rsa-pss-sha512' });\n },\n\n '006-missing-covered-component': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithComponents(key, vector, options, ['@method', '@target-uri', 'content-type']);\n },\n\n '007-missing-content-digest': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: false });\n },\n\n '008-unknown-keyid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { keyid: 'unknown-key-9999' });\n },\n\n '009-key-ops-missing-verify': (vector, keys, options) => {\n // Vector 009 pins `jwks_ref: [\"test-gov-2026\"]` (adcp_use:\n // governance-signing, not request-signing) — use it directly instead of\n // inferring. Honors the vector's intent if future keysets add a second\n // non-request-signing keypair.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '010-content-digest-mismatch': (vector, keys, options) => {\n // Vector 010 tests \"signer committed a wrong Content-Digest value\" — the\n // signature IS valid over the base that includes that wrong value, so the\n // verifier passes the signature check (step 10) and then fails the\n // digest-vs-body recompute (step 11). Do NOT mutate the body post-sign —\n // that tests a different bug (body-tampered-in-transit) and a verifier\n // that recomputes digest from sent body would not catch the \"lying\n // signer\" path this vector exercises.\n const key = signerKeyFor(vector, keys);\n // Zero-byte digest: guaranteed not to match the actual body.\n const zeroDigest = 'sha-256=:' + Buffer.alloc(32).toString('base64') + ':';\n const headersWithBadDigest = { ...vector.request.headers, 'Content-Digest': zeroDigest };\n const vectorWithBadDigest = {\n ...vector,\n request: { ...vector.request, headers: headersWithBadDigest },\n };\n // Sign the request WITH content-digest in covered components, without\n // letting `signRequest` recompute the digest over the real body.\n return signWithComponents(key, vectorWithBadDigest, options, [\n '@method',\n '@target-uri',\n '@authority',\n 'content-type',\n 'content-digest',\n ]);\n },\n\n '011-malformed-header': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n return {\n ...signed,\n headers: {\n ...signed.headers,\n 'Signature-Input': 'sig1=not a valid structured-field value!!!',\n },\n };\n },\n\n '012-missing-expires-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitExpires: true });\n },\n\n '013-expires-le-created': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { expiresDelta: 0 });\n },\n\n '014-missing-nonce-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitNonce: true });\n },\n\n '015-signature-invalid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const zeroSig = Buffer.alloc(64).toString('base64url');\n return {\n ...signed,\n headers: {\n ...signed.headers,\n Signature: `sig1=:${zeroSig}:`,\n },\n };\n },\n\n '016-replayed-nonce': (vector, keys, options) => {\n // Black-box runner sends the request twice; first accepted, second rejected.\n // Builder produces the single well-formed request used for both submissions.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '017-key-revoked': (vector, keys, options) => {\n // Use the dedicated revoked key (`test-revoked-2026`) declared by the\n // signed-requests-runner test-kit. For current pre-#2353 caches, vector 017\n // still references test-ed25519-2026; fall back to whatever the vector says.\n const kid = vector.jwks_ref?.[0];\n if (!kid) throw new Error(`${vector.id}: jwks_ref missing`);\n const key = keyFor(keys, kid);\n return sign(key, vector, options);\n },\n\n '018-digest-covered-when-forbidden': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: true });\n },\n\n '019-signature-without-signature-input': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const { 'Signature-Input': _drop, ...rest } = signed.headers;\n return { ...signed, headers: rest };\n },\n\n '020-rate-abuse': (vector, keys, options) => {\n // Runner floods the agent with distinct-nonce requests from the same keyid.\n // Builder produces a single well-formed request; the runner generates N\n // distinct nonces by calling this builder repeatedly with `options.nonce`.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n // Vectors 021-026 ship their exact malformed headers in the fixture — the\n // adversarial shape (duplicate sig-input label, multi-valued content-type\n // / content-digest, unquoted string param, malformed JWK, non-ASCII host)\n // lives in the vector itself, not in a programmatic mutation. Builder just\n // preserves the fixture's headers verbatim after applying transport.\n '021-duplicate-signature-input-label': (vector, _keys, options) => passthrough(vector, options),\n '022-multi-valued-content-type': (vector, _keys, options) => passthrough(vector, options),\n '023-multi-valued-content-digest': (vector, _keys, options) => passthrough(vector, options),\n '024-unquoted-string-param': (vector, _keys, options) => passthrough(vector, options),\n '025-jwk-alg-crv-mismatch': (vector, _keys, options) => passthrough(vector, options),\n '026-non-ascii-host': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 027 tests the \"webhook authentication MUST trigger signing\" rule:\n // the fixture is a plain bearer-auth request with zero signature headers,\n // and the adversarial shape is precisely that absence. Passthrough preserves\n // the fixture bytes; retargeting still works via applyTransport.\n '027-webhook-registration-authentication-unsigned': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 028 grades the `protocol_methods_required_for` namespace\n // (adcp#4326). The fixture body is already a JSON-RPC envelope with\n // `method: \"tasks/cancel\"` — NOT a `tools/call` envelope — so the standard\n // MCP-mode `applyTransport` (which would wrap the body in `tools/call`)\n // is wrong here. Use `protocolMethodPassthrough` which keeps the body\n // verbatim and targets `baseUrl` directly when set, matching how an\n // agent's MCP endpoint routes JSON-RPC `tasks/*` methods.\n '028-unsigned-protocol-method-required': (vector, _keys, options) => protocolMethodPassthrough(vector, options),\n};\n\nfunction passthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n}\n\n/**\n * Passthrough for vectors whose body is already a JSON-RPC envelope with a\n * non-`tools/call` `method` (e.g., `tasks/cancel`). MCP-mode `applyTransport`\n * would wrap the body in `tools/call`, which is wrong: the protocol_methods\n * namespace matches against the JSON-RPC envelope's `method` field, so\n * wrapping in `tools/call` would route the request to MCP tool dispatch\n * (looking up a tool literally named \"tasks/cancel\"; 404) instead of the\n * SDK's auto-registered `tasks/cancel` JSON-RPC handler.\n *\n * Targets `options.baseUrl` directly when set (the MCP endpoint URL), or\n * the vector's URL verbatim otherwise.\n */\nfunction protocolMethodPassthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n const url = options.baseUrl ?? vector.request.url;\n const headers = { ...vector.request.headers };\n // MCP Streamable HTTP requires this Accept negotiation header on JSON-RPC\n // probes — match the wrapping path's behavior.\n if (options.transport === 'mcp') {\n headers['Accept'] = 'application/json, text/event-stream';\n }\n return {\n method: vector.request.method,\n url,\n headers,\n body: vector.request.body,\n };\n}\n\n// ── Primitives ────────────────────────────────────────────────\n\ninterface SignArgs extends BuildOptions {\n coverContentDigest?: boolean;\n}\n\nfunction sign(key: SignerKey, vector: PositiveVector | NegativeVector, args: SignArgs): SignedHttpRequest {\n const shaped = applyTransport(vector, args);\n const request: RequestLike = {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n // Negative-vector 009 deliberately signs with a wrong-purpose key\n // (`adcp_use: 'governance-signing'`) to exercise the verifier's step-8\n // purpose check. The signer-side `signRequest` gate refuses wrong-purpose\n // keys to prevent the more common operator footgun; bypass it here by\n // composing `prepareRequestSignature` (which takes `SignatureIdentity`\n // and runs no gate) with this file's local `produceSignature` helper.\n // The bypass is intentional and confined to test-vector authoring.\n const prepared = prepareRequestSignature(\n request,\n { keyid: key.keyid, alg: key.alg },\n {\n coverContentDigest: args.coverContentDigest === true,\n now: args.now !== undefined ? () => args.now! : undefined,\n nonce: args.nonce,\n windowSeconds: args.windowSeconds,\n }\n );\n const signature = produceSignature(key, Buffer.from(prepared.base, 'utf8'));\n const signed = finalizeRequestSignature(prepared, signature);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: mergeHeaders(shaped.headers, signed.headers),\n body: shaped.body,\n };\n}\n\nfunction retargetUrl(vectorUrl: string, baseUrl: string | undefined): string {\n if (!baseUrl) return vectorUrl;\n const v = new URL(vectorUrl);\n const b = new URL(baseUrl);\n v.protocol = b.protocol;\n v.host = b.host;\n // Prefix the agent's mount path (from baseUrl) ahead of the vector's path\n // so agents mounted at e.g. `/v1/adcp/*` receive requests at\n // `/v1/adcp/create_media_buy` rather than the bare `/adcp/create_media_buy`\n // the vector carries. When baseUrl has no path (or just `/`), this is a\n // no-op. Canonicalization-edge vectors (005–008) bake their edge into the\n // vector's path/query; we preserve those bytes by joining, not replacing.\n if (b.pathname && b.pathname !== '/') {\n const mount = b.pathname.replace(/\\/+$/, '');\n const vectorPath = v.pathname.startsWith('/') ? v.pathname : `/${v.pathname}`;\n v.pathname = `${mount}${vectorPath}`;\n }\n return v.toString();\n}\n\ninterface TransportShapedRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\n/**\n * Apply the transport transform to a vector's request shape. In `'raw'` mode\n * (default) this is just origin-swap path-merge. In `'mcp'` mode:\n * - URL becomes `baseUrl` exactly (no path join — MCP agents expose a single\n * JSON-RPC endpoint; the operation is named in the body).\n * - Body is wrapped in a JSON-RPC `tools/call` envelope; the operation name\n * comes from the vector's last URL segment.\n * - `Accept: application/json, text/event-stream` added so MCP Streamable\n * HTTP servers don't 406 on the probe.\n *\n * Shared call site for `sign`, `signWithParamOverride`, `signWithComponents`\n * so every mutation path produces MCP-shaped requests when requested.\n */\nfunction applyTransport(vector: PositiveVector | NegativeVector, options: BuildOptions): TransportShapedRequest {\n const headers = { ...vector.request.headers };\n if (options.transport === 'mcp') {\n if (!options.baseUrl) {\n throw new Error(`transport: 'mcp' requires a baseUrl (the MCP endpoint, e.g. http://agent/mcp)`);\n }\n const operation = extractOperationFromVectorUrl(vector.request.url);\n const envelope = wrapMcpEnvelope(operation, vector.request.body, options.mcpJsonRpcId);\n // Accept header added for MCP Streamable HTTP negotiation. Not in the\n // signed components list (MANDATORY_COMPONENTS doesn't include `accept`),\n // so adding it after the vector's headers doesn't affect the signature.\n headers['Accept'] = 'application/json, text/event-stream';\n return {\n method: vector.request.method,\n url: options.baseUrl,\n headers,\n body: envelope,\n };\n }\n return {\n method: vector.request.method,\n url: retargetUrl(vector.request.url, options.baseUrl),\n headers,\n body: vector.request.body,\n };\n}\n\n// AdCP operation names are spec-defined identifiers (lowercase alnum +\n// underscore — `create_media_buy`, `sync_creatives`, `si_send_message`,\n// etc.; verified against every `task:` value shipped in\n// `compliance/cache/{version}/protocols/**/*.yaml`). Constrain the extractor\n// output to that shape so a compromised compliance cache can't smuggle\n// arbitrary bytes into `params.name` via a weird vector URL.\nconst OPERATION_NAME_SAFE = /^[a-z][a-z0-9_]*$/;\n\nfunction extractOperationFromVectorUrl(vectorUrl: string): string {\n const parsed = new URL(vectorUrl);\n const segments = parsed.pathname.split('/').filter(Boolean);\n const last = segments[segments.length - 1];\n if (!last) throw new Error(`Cannot extract operation from vector URL: ${vectorUrl}`);\n if (!OPERATION_NAME_SAFE.test(last)) {\n throw new Error(\n `Operation name \"${last}\" extracted from ${vectorUrl} fails identifier check. ` +\n `AdCP operations are lowercase_snake_case; this is likely a corrupted compliance cache.`\n );\n }\n return last;\n}\n\nfunction wrapMcpEnvelope(\n operation: string,\n rawBody: string | undefined,\n idOverride: number | string | undefined\n): string {\n const id = idOverride ?? randomUUID();\n // Conformance vectors' bodies are spec-typed as JSON. A parse failure is\n // a vector drift, not a runtime input-validation case — let it surface.\n const args = rawBody && rawBody.length > 0 ? JSON.parse(rawBody) : {};\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n method: 'tools/call',\n params: { name: operation, arguments: args },\n });\n}\n\ninterface ParamOverride {\n tag?: string;\n alg?: string;\n keyid?: string;\n expiresDelta?: number;\n omitExpires?: boolean;\n omitNonce?: boolean;\n}\n\n/**\n * Build a signature base with overridden params, sign it directly, and emit\n * the headers. Needed when the mutation lives in `@signature-params` itself\n * (tag, alg, keyid, expires, nonce) — signRequest won't emit those exact\n * malformations.\n */\nfunction signWithParamOverride(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n override: ParamOverride\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const hasBody = (request.body ?? '').length > 0;\n const components = hasBody\n ? ['@method', '@target-uri', '@authority', 'content-type']\n : ['@method', '@target-uri', '@authority'];\n\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + (override.expiresDelta ?? windowSeconds),\n nonce: options.nonce ?? randomNonce(),\n keyid: override.keyid ?? key.keyid,\n alg: override.alg ?? key.alg,\n tag: override.tag ?? REQUEST_SIGNING_TAG,\n };\n\n const paramsString = formatParamsWithOmissions(components, params, override);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction signWithComponents(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n components: string[]\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + windowSeconds,\n nonce: options.nonce ?? randomNonce(),\n keyid: key.keyid,\n alg: key.alg,\n tag: REQUEST_SIGNING_TAG,\n };\n const paramsString = formatSignatureParams(components, params);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction formatParamsWithOmissions(\n components: ReadonlyArray<string>,\n params: SignatureParams,\n override: ParamOverride\n): string {\n const componentList = components.map(c => `\"${c}\"`).join(' ');\n const pairs: string[] = [];\n pairs.push(`created=${params.created}`);\n if (!override.omitExpires) pairs.push(`expires=${params.expires}`);\n if (!override.omitNonce) pairs.push(`nonce=\"${params.nonce}\"`);\n pairs.push(`keyid=\"${params.keyid}\"`);\n pairs.push(`alg=\"${params.alg}\"`);\n pairs.push(`tag=\"${params.tag}\"`);\n return `(${componentList});${pairs.join(';')}`;\n}\n\nfunction produceSignature(key: SignerKey, data: Buffer): Uint8Array {\n const privateKey = createPrivateKey({ key: key.privateKey as JsonWebKey, format: 'jwk' });\n if (key.alg === 'ed25519') {\n return new Uint8Array(nodeSign(null, data, privateKey));\n }\n return new Uint8Array(nodeSign('sha256', data, { key: privateKey, dsaEncoding: 'ieee-p1363' }));\n}\n\n// ── Helpers ───────────────────────────────────────────────────\n\nfunction signerKeyFor(vector: PositiveVector | NegativeVector, keys: TestKeyset): SignerKey {\n const kid = vector.jwks_ref?.[0];\n if (!kid) {\n throw new Error(\n `${vector.id}: jwks_ref missing — vectors signed dynamically by the builder must declare a keys.json kid. ` +\n `Vectors shipping an inline jwks_override must use a passthrough mutator (no re-signing).`\n );\n }\n return keyFor(keys, kid);\n}\n\nfunction keyFor(keys: TestKeyset, kid: string): SignerKey {\n const keypair = findKey(keys, kid);\n return toSignerKey(keypair);\n}\n\nfunction toSignerKey(keypair: TestKeypair): SignerKey {\n const alg: SignerKey['alg'] = keypair.crv === 'Ed25519' ? 'ed25519' : 'ecdsa-p256-sha256';\n const privateKey: AdcpJsonWebKey = {\n kid: keypair.kid,\n kty: keypair.kty,\n crv: keypair.crv,\n alg: keypair.alg,\n use: keypair.use,\n key_ops: ['sign'],\n adcp_use: keypair.adcp_use,\n x: keypair.x,\n y: keypair.y,\n d: keypair.private_d,\n };\n return { keyid: keypair.kid, alg, privateKey };\n}\n\nfunction stripSignatureHeaders(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n const lower = k.toLowerCase();\n if (lower === 'signature' || lower === 'signature-input' || lower === 'content-digest') continue;\n out[k] = v;\n }\n return out;\n}\n\nfunction mergeHeaders(from: Record<string, string>, signed: Record<string, string>): Record<string, string> {\n // Drop original Signature/Signature-Input/Content-Digest before overlaying fresh ones.\n const base = stripSignatureHeaders(from);\n return { ...base, ...signed };\n}\n\nfunction nowSeconds(options: BuildOptions): number {\n return options.now ?? Math.floor(Date.now() / 1000);\n}\n\nfunction randomNonce(): string {\n return randomBytes(16).toString('base64url');\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/lib/testing/storyboard/request-signing/builder.ts"],"sourcesContent":["import { createPrivateKey, randomBytes, randomUUID, sign as nodeSign, type JsonWebKey } from 'crypto';\nimport {\n buildSignatureBase,\n finalizeRequestSignature,\n formatSignatureParams,\n prepareRequestSignature,\n REQUEST_SIGNING_TAG,\n type AdcpJsonWebKey,\n type RequestLike,\n type SignatureParams,\n type SignerKey,\n} from '../../../signing';\nimport { findKey } from './vector-loader';\nimport type { NegativeVector, PositiveVector, TestKeyset, TestKeypair } from './types';\nimport type { CapturedA2aRequest } from './a2a-dispatch';\n\nexport interface BuildOptions {\n /** Override the signer clock (unix seconds). Defaults to `Date.now()/1000`. */\n now?: number;\n /** Override the nonce. Defaults to freshly-generated. */\n nonce?: string;\n /** Override the `expires - created` window (seconds). Defaults to 300. */\n windowSeconds?: number;\n /**\n * Agent base URL. When set, the vector's request URL has its origin replaced\n * with this base before signing — the vectors point at `seller.example.com`\n * but real agents live elsewhere. The path and query are preserved so the\n * operation intent (e.g., `/adcp/create_media_buy`) is unchanged.\n *\n * Canonicalization-edge vectors (005 default-port, 006 dot-segment path,\n * 007 query preservation, 008 percent-encoded path) bake their edge case\n * into the vector URL; replacing the origin keeps that edge intact in the\n * path/query, but vectors sensitive to the port or scheme will no longer\n * exercise the edge against a mismatched agent base.\n */\n baseUrl?: string;\n /**\n * Transport-layer framing. `'raw'` (default) sends the vector body to the\n * retargeted vector URL verbatim — matches the conformance vectors' intent\n * of testing a per-operation HTTP endpoint. `'mcp'` wraps the vector body\n * in a JSON-RPC `tools/call` envelope and posts to `baseUrl` as-is (no\n * path join); operation name comes from the vector URL's last segment.\n *\n * MCP mode trades the canonicalization-edge coverage for reach: vectors\n * 005–008 fold into plain POSTs against the MCP endpoint, but the grader\n * works against any MCP agent that wires a verifier at the HTTP layer.\n */\n transport?: 'raw' | 'mcp' | 'a2a';\n /** Request emitted by the official A2A SDK; required for A2A transport. */\n a2aRequest?: CapturedA2aRequest;\n /**\n * JSON-RPC `id` for the MCP envelope. Defaults to `crypto.randomUUID()`\n * so concurrent runs never collide. Override for tests that need a stable\n * id — JSON-RPC 2.0 permits number, string, or null.\n */\n mcpJsonRpcId?: number | string;\n}\n\nexport interface SignedHttpRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\nexport function buildPositiveRequest(\n vector: PositiveVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, {\n coverContentDigest: vector.verifier_capability.covers_content_digest === 'required',\n ...options,\n });\n}\n\n/**\n * Apply the adversarial mutation documented for a negative vector.\n *\n * Black-box grader: the positive/001 signature bytes sitting in most negative\n * fixtures are placeholders; we re-sign dynamically, then mutate. Covers all\n * 20 current negative vectors. Stateful contract vectors (016 replay, 017\n * revoked, 020 rate abuse) produce a single well-formed request; the\n * storyboard runner orchestrates the repeat/flood/revoked-keyid behavior\n * around that request per the signed-requests-runner test-kit.\n */\nexport function buildNegativeRequest(\n vector: NegativeVector,\n keys: TestKeyset,\n options: BuildOptions = {}\n): SignedHttpRequest {\n const mutation = MUTATIONS[vector.id];\n if (!mutation) {\n throw new Error(`No adversarial builder registered for negative vector \"${vector.id}\"`);\n }\n return mutation(vector, keys, options);\n}\n\nexport function listSupportedNegativeVectors(): string[] {\n return Object.keys(MUTATIONS);\n}\n\ntype Mutator = (vector: NegativeVector, keys: TestKeyset, options: BuildOptions) => SignedHttpRequest;\n\nconst MUTATIONS: Record<string, Mutator> = {\n '001-no-signature-header': (vector, _keys, options) => {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: stripSignatureHeaders(shaped.headers),\n body: shaped.body,\n };\n },\n\n '002-wrong-tag': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { tag: 'example-org/signing/v1' });\n },\n\n '003-expired-signature': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const now = nowSeconds(options);\n return sign(key, vector, { ...options, now: now - 600, windowSeconds: 300 });\n },\n\n '004-window-too-long': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, {\n expiresDelta: 301,\n });\n },\n\n '005-alg-not-allowed': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { alg: 'rsa-pss-sha512' });\n },\n\n '006-missing-covered-component': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithComponents(key, vector, options, ['@method', '@target-uri', 'content-type']);\n },\n\n '007-missing-content-digest': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: false });\n },\n\n '008-unknown-keyid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { keyid: 'unknown-key-9999' });\n },\n\n '009-key-ops-missing-verify': (vector, keys, options) => {\n // Vector 009 pins `jwks_ref: [\"test-gov-2026\"]` (adcp_use:\n // governance-signing, not request-signing) — use it directly instead of\n // inferring. Honors the vector's intent if future keysets add a second\n // non-request-signing keypair.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '010-content-digest-mismatch': (vector, keys, options) => {\n // Vector 010 tests \"signer committed a wrong Content-Digest value\" — the\n // signature IS valid over the base that includes that wrong value, so the\n // verifier passes the signature check (step 10) and then fails the\n // digest-vs-body recompute (step 11). Do NOT mutate the body post-sign —\n // that tests a different bug (body-tampered-in-transit) and a verifier\n // that recomputes digest from sent body would not catch the \"lying\n // signer\" path this vector exercises.\n const key = signerKeyFor(vector, keys);\n // Zero-byte digest: guaranteed not to match the actual body.\n const zeroDigest = 'sha-256=:' + Buffer.alloc(32).toString('base64') + ':';\n const headersWithBadDigest = { ...vector.request.headers, 'Content-Digest': zeroDigest };\n const vectorWithBadDigest = {\n ...vector,\n request: { ...vector.request, headers: headersWithBadDigest },\n };\n // Sign the request WITH content-digest in covered components, without\n // letting `signRequest` recompute the digest over the real body.\n return signWithComponents(key, vectorWithBadDigest, options, [\n '@method',\n '@target-uri',\n '@authority',\n 'content-type',\n 'content-digest',\n ]);\n },\n\n '011-malformed-header': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n return {\n ...signed,\n headers: {\n ...signed.headers,\n 'Signature-Input': 'sig1=not a valid structured-field value!!!',\n },\n };\n },\n\n '012-missing-expires-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitExpires: true });\n },\n\n '013-expires-le-created': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { expiresDelta: 0 });\n },\n\n '014-missing-nonce-param': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return signWithParamOverride(key, vector, options, { omitNonce: true });\n },\n\n '015-signature-invalid': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const zeroSig = Buffer.alloc(64).toString('base64url');\n return {\n ...signed,\n headers: {\n ...signed.headers,\n Signature: `sig1=:${zeroSig}:`,\n },\n };\n },\n\n '016-replayed-nonce': (vector, keys, options) => {\n // Black-box runner sends the request twice; first accepted, second rejected.\n // Builder produces the single well-formed request used for both submissions.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n '017-key-revoked': (vector, keys, options) => {\n // Use the dedicated revoked key (`test-revoked-2026`) declared by the\n // signed-requests-runner test-kit. For current pre-#2353 caches, vector 017\n // still references test-ed25519-2026; fall back to whatever the vector says.\n const kid = vector.jwks_ref?.[0];\n if (!kid) throw new Error(`${vector.id}: jwks_ref missing`);\n const key = keyFor(keys, kid);\n return sign(key, vector, options);\n },\n\n '018-digest-covered-when-forbidden': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, { ...options, coverContentDigest: true });\n },\n\n '019-signature-without-signature-input': (vector, keys, options) => {\n const key = signerKeyFor(vector, keys);\n const signed = sign(key, vector, options);\n const { 'Signature-Input': _drop, ...rest } = signed.headers;\n return { ...signed, headers: rest };\n },\n\n '020-rate-abuse': (vector, keys, options) => {\n // Runner floods the agent with distinct-nonce requests from the same keyid.\n // Builder produces a single well-formed request; the runner generates N\n // distinct nonces by calling this builder repeatedly with `options.nonce`.\n const key = signerKeyFor(vector, keys);\n return sign(key, vector, options);\n },\n\n // Vectors 021-026 ship their exact malformed headers in the fixture — the\n // adversarial shape (duplicate sig-input label, multi-valued content-type\n // / content-digest, unquoted string param, malformed JWK, non-ASCII host)\n // lives in the vector itself, not in a programmatic mutation. Builder just\n // preserves the fixture's headers verbatim after applying transport.\n '021-duplicate-signature-input-label': (vector, _keys, options) => passthrough(vector, options),\n '022-multi-valued-content-type': (vector, _keys, options) => passthrough(vector, options),\n '023-multi-valued-content-digest': (vector, _keys, options) => passthrough(vector, options),\n '024-unquoted-string-param': (vector, _keys, options) => passthrough(vector, options),\n '025-jwk-alg-crv-mismatch': (vector, _keys, options) => passthrough(vector, options),\n '026-non-ascii-host': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 027 tests the \"webhook authentication MUST trigger signing\" rule:\n // the fixture is a plain bearer-auth request with zero signature headers,\n // and the adversarial shape is precisely that absence. Passthrough preserves\n // the fixture bytes; retargeting still works via applyTransport.\n '027-webhook-registration-authentication-unsigned': (vector, _keys, options) => passthrough(vector, options),\n\n // Vector 028 grades the `protocol_methods_required_for` namespace\n // (adcp#4326). The fixture body is already a JSON-RPC envelope with\n // `method: \"tasks/cancel\"` — NOT a `tools/call` envelope — so the standard\n // MCP-mode `applyTransport` (which would wrap the body in `tools/call`)\n // is wrong here. Use `protocolMethodPassthrough` which keeps the body\n // verbatim and targets `baseUrl` directly when set, matching how an\n // agent's MCP endpoint routes JSON-RPC `tasks/*` methods.\n '028-unsigned-protocol-method-required': (vector, _keys, options) => protocolMethodPassthrough(vector, options),\n};\n\nfunction passthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n}\n\n/**\n * Passthrough for vectors whose body is already a JSON-RPC envelope with a\n * non-`tools/call` `method` (e.g., `tasks/cancel`). MCP-mode `applyTransport`\n * would wrap the body in `tools/call`, which is wrong: the protocol_methods\n * namespace matches against the JSON-RPC envelope's `method` field, so\n * wrapping in `tools/call` would route the request to MCP tool dispatch\n * (looking up a tool literally named \"tasks/cancel\"; 404) instead of the\n * SDK's auto-registered `tasks/cancel` JSON-RPC handler.\n *\n * Targets `options.baseUrl` directly when set (the MCP endpoint URL), or\n * the vector's URL verbatim otherwise.\n */\nfunction protocolMethodPassthrough(vector: NegativeVector, options: BuildOptions): SignedHttpRequest {\n if (options.transport === 'a2a') return passthrough(vector, options);\n const url = options.baseUrl ?? vector.request.url;\n const headers = { ...vector.request.headers };\n // MCP Streamable HTTP requires this Accept negotiation header on JSON-RPC\n // probes — match the wrapping path's behavior.\n if (options.transport === 'mcp') {\n headers['Accept'] = 'application/json, text/event-stream';\n }\n return {\n method: vector.request.method,\n url,\n headers,\n body: vector.request.body,\n };\n}\n\n// ── Primitives ────────────────────────────────────────────────\n\ninterface SignArgs extends BuildOptions {\n coverContentDigest?: boolean;\n}\n\nfunction sign(key: SignerKey, vector: PositiveVector | NegativeVector, args: SignArgs): SignedHttpRequest {\n const shaped = applyTransport(vector, args);\n const request: RequestLike = {\n method: shaped.method,\n url: shaped.url,\n headers: shaped.headers,\n body: shaped.body,\n };\n // Negative-vector 009 deliberately signs with a wrong-purpose key\n // (`adcp_use: 'governance-signing'`) to exercise the verifier's step-8\n // purpose check. The signer-side `signRequest` gate refuses wrong-purpose\n // keys to prevent the more common operator footgun; bypass it here by\n // composing `prepareRequestSignature` (which takes `SignatureIdentity`\n // and runs no gate) with this file's local `produceSignature` helper.\n // The bypass is intentional and confined to test-vector authoring.\n const prepared = prepareRequestSignature(\n request,\n { keyid: key.keyid, alg: key.alg },\n {\n coverContentDigest: args.coverContentDigest === true,\n now: args.now !== undefined ? () => args.now! : undefined,\n nonce: args.nonce,\n windowSeconds: args.windowSeconds,\n }\n );\n const signature = produceSignature(key, Buffer.from(prepared.base, 'utf8'));\n const signed = finalizeRequestSignature(prepared, signature);\n return {\n method: shaped.method,\n url: shaped.url,\n headers: mergeHeaders(shaped.headers, signed.headers),\n body: shaped.body,\n };\n}\n\nfunction retargetUrl(vectorUrl: string, baseUrl: string | undefined): string {\n if (!baseUrl) return vectorUrl;\n const v = new URL(vectorUrl);\n const b = new URL(baseUrl);\n v.protocol = b.protocol;\n v.host = b.host;\n // Prefix the agent's mount path (from baseUrl) ahead of the vector's path\n // so agents mounted at e.g. `/v1/adcp/*` receive requests at\n // `/v1/adcp/create_media_buy` rather than the bare `/adcp/create_media_buy`\n // the vector carries. When baseUrl has no path (or just `/`), this is a\n // no-op. Canonicalization-edge vectors (005–008) bake their edge into the\n // vector's path/query; we preserve those bytes by joining, not replacing.\n if (b.pathname && b.pathname !== '/') {\n const mount = b.pathname.replace(/\\/+$/, '');\n const vectorPath = v.pathname.startsWith('/') ? v.pathname : `/${v.pathname}`;\n v.pathname = `${mount}${vectorPath}`;\n }\n return v.toString();\n}\n\ninterface TransportShapedRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: string;\n}\n\n/**\n * Apply the transport transform to a vector's request shape. In `'raw'` mode\n * (default) this is just origin-swap path-merge. In `'mcp'` mode:\n * - URL becomes `baseUrl` exactly (no path join — MCP agents expose a single\n * JSON-RPC endpoint; the operation is named in the body).\n * - Body is wrapped in a JSON-RPC `tools/call` envelope; the operation name\n * comes from the vector's last URL segment.\n * - `Accept: application/json, text/event-stream` added so MCP Streamable\n * HTTP servers don't 406 on the probe.\n *\n * Shared call site for `sign`, `signWithParamOverride`, `signWithComponents`\n * so every mutation path produces MCP-shaped requests when requested.\n */\nfunction applyTransport(vector: PositiveVector | NegativeVector, options: BuildOptions): TransportShapedRequest {\n const headers = { ...vector.request.headers };\n if (options.transport === 'a2a') {\n if (!options.a2aRequest) {\n throw new Error(\"transport: 'a2a' requires a request captured from the official @a2a-js/sdk client\");\n }\n return {\n method: options.a2aRequest.method,\n url: options.a2aRequest.url,\n headers: mergeHeadersCaseInsensitively(options.a2aRequest.headers, headers),\n body: options.a2aRequest.body,\n };\n }\n if (options.transport === 'mcp') {\n if (!options.baseUrl) {\n throw new Error(`transport: 'mcp' requires a baseUrl (the MCP endpoint, e.g. http://agent/mcp)`);\n }\n const operation = extractOperationFromVectorUrl(vector.request.url);\n const envelope = wrapMcpEnvelope(operation, vector.request.body, options.mcpJsonRpcId);\n // Accept header added for MCP Streamable HTTP negotiation. Not in the\n // signed components list (MANDATORY_COMPONENTS doesn't include `accept`),\n // so adding it after the vector's headers doesn't affect the signature.\n headers['Accept'] = 'application/json, text/event-stream';\n return {\n method: vector.request.method,\n url: options.baseUrl,\n headers,\n body: envelope,\n };\n }\n return {\n method: vector.request.method,\n url: retargetUrl(vector.request.url, options.baseUrl),\n headers,\n body: vector.request.body,\n };\n}\n\nfunction mergeHeadersCaseInsensitively(\n base: Record<string, string>,\n overrides: Record<string, string>\n): Record<string, string> {\n const overridden = new Set(Object.keys(overrides).map(name => name.toLowerCase()));\n return {\n ...Object.fromEntries(Object.entries(base).filter(([name]) => !overridden.has(name.toLowerCase()))),\n ...overrides,\n };\n}\n\n// AdCP operation names are spec-defined identifiers (lowercase alnum +\n// underscore — `create_media_buy`, `sync_creatives`, `si_send_message`,\n// etc.; verified against every `task:` value shipped in\n// `compliance/cache/{version}/protocols/**/*.yaml`). Constrain the extractor\n// output to that shape so a compromised compliance cache can't smuggle\n// arbitrary bytes into `params.name` via a weird vector URL.\nconst OPERATION_NAME_SAFE = /^[a-z][a-z0-9_]*$/;\n\nfunction extractOperationFromVectorUrl(vectorUrl: string): string {\n const parsed = new URL(vectorUrl);\n const segments = parsed.pathname.split('/').filter(Boolean);\n const last = segments[segments.length - 1];\n if (!last) throw new Error(`Cannot extract operation from vector URL: ${vectorUrl}`);\n if (!OPERATION_NAME_SAFE.test(last)) {\n throw new Error(\n `Operation name \"${last}\" extracted from ${vectorUrl} fails identifier check. ` +\n `AdCP operations are lowercase_snake_case; this is likely a corrupted compliance cache.`\n );\n }\n return last;\n}\n\nfunction wrapMcpEnvelope(\n operation: string,\n rawBody: string | undefined,\n idOverride: number | string | undefined\n): string {\n const id = idOverride ?? randomUUID();\n // Conformance vectors' bodies are spec-typed as JSON. A parse failure is\n // a vector drift, not a runtime input-validation case — let it surface.\n const args = rawBody && rawBody.length > 0 ? JSON.parse(rawBody) : {};\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n method: 'tools/call',\n params: { name: operation, arguments: args },\n });\n}\n\ninterface ParamOverride {\n tag?: string;\n alg?: string;\n keyid?: string;\n expiresDelta?: number;\n omitExpires?: boolean;\n omitNonce?: boolean;\n}\n\n/**\n * Build a signature base with overridden params, sign it directly, and emit\n * the headers. Needed when the mutation lives in `@signature-params` itself\n * (tag, alg, keyid, expires, nonce) — signRequest won't emit those exact\n * malformations.\n */\nfunction signWithParamOverride(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n override: ParamOverride\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const hasBody = (request.body ?? '').length > 0;\n const components = hasBody\n ? ['@method', '@target-uri', '@authority', 'content-type']\n : ['@method', '@target-uri', '@authority'];\n\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + (override.expiresDelta ?? windowSeconds),\n nonce: options.nonce ?? randomNonce(),\n keyid: override.keyid ?? key.keyid,\n alg: override.alg ?? key.alg,\n tag: override.tag ?? REQUEST_SIGNING_TAG,\n };\n\n const paramsString = formatParamsWithOmissions(components, params, override);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction signWithComponents(\n key: SignerKey,\n vector: PositiveVector | NegativeVector,\n options: BuildOptions,\n components: string[]\n): SignedHttpRequest {\n const shaped = applyTransport(vector, options);\n const url = shaped.url;\n const request: RequestLike = {\n method: shaped.method,\n url,\n headers: shaped.headers,\n body: shaped.body,\n };\n const now = nowSeconds(options);\n const windowSeconds = options.windowSeconds ?? 300;\n const params: SignatureParams = {\n created: now,\n expires: now + windowSeconds,\n nonce: options.nonce ?? randomNonce(),\n keyid: key.keyid,\n alg: key.alg,\n tag: REQUEST_SIGNING_TAG,\n };\n const paramsString = formatSignatureParams(components, params);\n const base = buildSignatureBase(components, request, params, paramsString);\n const signature = produceSignature(key, Buffer.from(base, 'utf8'));\n return {\n method: shaped.method,\n url,\n headers: {\n ...shaped.headers,\n 'Signature-Input': `sig1=${paramsString}`,\n Signature: `sig1=:${Buffer.from(signature).toString('base64url')}:`,\n },\n body: shaped.body,\n };\n}\n\nfunction formatParamsWithOmissions(\n components: ReadonlyArray<string>,\n params: SignatureParams,\n override: ParamOverride\n): string {\n const componentList = components.map(c => `\"${c}\"`).join(' ');\n const pairs: string[] = [];\n pairs.push(`created=${params.created}`);\n if (!override.omitExpires) pairs.push(`expires=${params.expires}`);\n if (!override.omitNonce) pairs.push(`nonce=\"${params.nonce}\"`);\n pairs.push(`keyid=\"${params.keyid}\"`);\n pairs.push(`alg=\"${params.alg}\"`);\n pairs.push(`tag=\"${params.tag}\"`);\n return `(${componentList});${pairs.join(';')}`;\n}\n\nfunction produceSignature(key: SignerKey, data: Buffer): Uint8Array {\n const privateKey = createPrivateKey({ key: key.privateKey as JsonWebKey, format: 'jwk' });\n if (key.alg === 'ed25519') {\n return new Uint8Array(nodeSign(null, data, privateKey));\n }\n return new Uint8Array(nodeSign('sha256', data, { key: privateKey, dsaEncoding: 'ieee-p1363' }));\n}\n\n// ── Helpers ───────────────────────────────────────────────────\n\nfunction signerKeyFor(vector: PositiveVector | NegativeVector, keys: TestKeyset): SignerKey {\n const kid = vector.jwks_ref?.[0];\n if (!kid) {\n throw new Error(\n `${vector.id}: jwks_ref missing — vectors signed dynamically by the builder must declare a keys.json kid. ` +\n `Vectors shipping an inline jwks_override must use a passthrough mutator (no re-signing).`\n );\n }\n return keyFor(keys, kid);\n}\n\nfunction keyFor(keys: TestKeyset, kid: string): SignerKey {\n const keypair = findKey(keys, kid);\n return toSignerKey(keypair);\n}\n\nfunction toSignerKey(keypair: TestKeypair): SignerKey {\n const alg: SignerKey['alg'] = keypair.crv === 'Ed25519' ? 'ed25519' : 'ecdsa-p256-sha256';\n const privateKey: AdcpJsonWebKey = {\n kid: keypair.kid,\n kty: keypair.kty,\n crv: keypair.crv,\n alg: keypair.alg,\n use: keypair.use,\n key_ops: ['sign'],\n adcp_use: keypair.adcp_use,\n x: keypair.x,\n y: keypair.y,\n d: keypair.private_d,\n };\n return { keyid: keypair.kid, alg, privateKey };\n}\n\nfunction stripSignatureHeaders(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n const lower = k.toLowerCase();\n if (lower === 'signature' || lower === 'signature-input' || lower === 'content-digest') continue;\n out[k] = v;\n }\n return out;\n}\n\nfunction mergeHeaders(from: Record<string, string>, signed: Record<string, string>): Record<string, string> {\n // Drop original Signature/Signature-Input/Content-Digest before overlaying fresh ones.\n const base = stripSignatureHeaders(from);\n return { ...base, ...signed };\n}\n\nfunction nowSeconds(options: BuildOptions): number {\n return options.now ?? Math.floor(Date.now() / 1000);\n}\n\nfunction randomNonce(): string {\n return randomBytes(16).toString('base64url');\n}\n"],"mappings":"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","names":[]}
|
|
@@ -92,7 +92,9 @@ export interface GradeOptions extends LoadVectorsOptions {
|
|
|
92
92
|
*
|
|
93
93
|
* See adcontextprotocol/adcp-client#612 for the MCP-mode rationale.
|
|
94
94
|
*/
|
|
95
|
-
transport?: 'raw' | 'mcp';
|
|
95
|
+
transport?: 'raw' | 'mcp' | 'a2a';
|
|
96
|
+
/** Trusted Agent Card fetch seam for A2A tests and custom runtimes. */
|
|
97
|
+
cardFetch?: typeof fetch;
|
|
96
98
|
/**
|
|
97
99
|
* MCP session ID to attach as `Mcp-Session-Id` on every probe after
|
|
98
100
|
* signing. When `transport` is `'mcp'` and this field is `undefined`,
|
|
@@ -148,6 +150,8 @@ export interface VectorGradeResult {
|
|
|
148
150
|
/** For negatives: the error code the spec says we should see. */
|
|
149
151
|
expected_error_code?: string;
|
|
150
152
|
http_status: number;
|
|
153
|
+
/** Actual card-selected A2A endpoint, when applicable. */
|
|
154
|
+
probe_url?: string;
|
|
151
155
|
diagnostic?: string;
|
|
152
156
|
probe_duration_ms: number;
|
|
153
157
|
/**
|
|
@@ -195,9 +199,4 @@ export interface GradeReport {
|
|
|
195
199
|
* copy fires.
|
|
196
200
|
*/
|
|
197
201
|
export declare function gradeRequestSigning(agentUrl: string, options?: GradeOptions): Promise<GradeReport>;
|
|
198
|
-
/**
|
|
199
|
-
* Grade a single vector. Loads the vectors+keys+contract on every call; for
|
|
200
|
-
* the storyboard-runner dispatch path where the caller runs many vectors in
|
|
201
|
-
* sequence, prefer `gradeRequestSigning` which loads once.
|
|
202
|
-
*/
|
|
203
202
|
export declare function gradeOneVector(vectorId: string, kind: 'positive' | 'negative', agentUrl: string, options?: GradeOptions): Promise<VectorGradeResult>;
|
|
@@ -92,7 +92,9 @@ export interface GradeOptions extends LoadVectorsOptions {
|
|
|
92
92
|
*
|
|
93
93
|
* See adcontextprotocol/adcp-client#612 for the MCP-mode rationale.
|
|
94
94
|
*/
|
|
95
|
-
transport?: 'raw' | 'mcp';
|
|
95
|
+
transport?: 'raw' | 'mcp' | 'a2a';
|
|
96
|
+
/** Trusted Agent Card fetch seam for A2A tests and custom runtimes. */
|
|
97
|
+
cardFetch?: typeof fetch;
|
|
96
98
|
/**
|
|
97
99
|
* MCP session ID to attach as `Mcp-Session-Id` on every probe after
|
|
98
100
|
* signing. When `transport` is `'mcp'` and this field is `undefined`,
|
|
@@ -148,6 +150,8 @@ export interface VectorGradeResult {
|
|
|
148
150
|
/** For negatives: the error code the spec says we should see. */
|
|
149
151
|
expected_error_code?: string;
|
|
150
152
|
http_status: number;
|
|
153
|
+
/** Actual card-selected A2A endpoint, when applicable. */
|
|
154
|
+
probe_url?: string;
|
|
151
155
|
diagnostic?: string;
|
|
152
156
|
probe_duration_ms: number;
|
|
153
157
|
/**
|
|
@@ -195,10 +199,5 @@ export interface GradeReport {
|
|
|
195
199
|
* copy fires.
|
|
196
200
|
*/
|
|
197
201
|
export declare function gradeRequestSigning(agentUrl: string, options?: GradeOptions): Promise<GradeReport>;
|
|
198
|
-
/**
|
|
199
|
-
* Grade a single vector. Loads the vectors+keys+contract on every call; for
|
|
200
|
-
* the storyboard-runner dispatch path where the caller runs many vectors in
|
|
201
|
-
* sequence, prefer `gradeRequestSigning` which loads once.
|
|
202
|
-
*/
|
|
203
202
|
export declare function gradeOneVector(vectorId: string, kind: 'positive' | 'negative', agentUrl: string, options?: GradeOptions): Promise<VectorGradeResult>;
|
|
204
203
|
//# sourceMappingURL=grader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grader.d.ts","sourceRoot":"","sources":["../../../../../src/lib/testing/storyboard/request-signing/grader.ts"],"names":[],"mappings":"AAGA,OAAO,EAA6B,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"grader.d.ts","sourceRoot":"","sources":["../../../../../src/lib/testing/storyboard/request-signing/grader.ts"],"names":[],"mappings":"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"}
|