@adcp/sdk 15.0.0 → 15.2.0

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.
Files changed (142) hide show
  1. package/bin/adcp-grade.js +46 -2
  2. package/bin/adcp.js +7 -2
  3. package/dist/lib/canonical-references/index.d.mts +19 -1
  4. package/dist/lib/canonical-references/index.d.ts +19 -1
  5. package/dist/lib/canonical-references/index.js +81 -9
  6. package/dist/lib/canonical-references/index.mjs +80 -9
  7. package/dist/lib/client/core.d.mts +1 -0
  8. package/dist/lib/client/core.d.ts +1 -0
  9. package/dist/lib/core/AgentClient.d.mts +9 -1
  10. package/dist/lib/core/AgentClient.d.ts +9 -1
  11. package/dist/lib/core/AgentClient.js +10 -0
  12. package/dist/lib/core/AgentClient.mjs +10 -0
  13. package/dist/lib/core/SingleAgentClient.d.mts +13 -2
  14. package/dist/lib/core/SingleAgentClient.d.ts +13 -2
  15. package/dist/lib/core/SingleAgentClient.js +23 -5
  16. package/dist/lib/core/SingleAgentClient.mjs +23 -5
  17. package/dist/lib/index.d.mts +1 -1
  18. package/dist/lib/index.d.ts +1 -1
  19. package/dist/lib/reporting/gcs/adapter.d.mts +31 -0
  20. package/dist/lib/reporting/gcs/adapter.d.ts +31 -0
  21. package/dist/lib/reporting/gcs/adapter.js +342 -0
  22. package/dist/lib/reporting/gcs/adapter.mjs +325 -0
  23. package/dist/lib/reporting/gcs/bucket-policy.d.mts +3 -0
  24. package/dist/lib/reporting/gcs/bucket-policy.d.ts +3 -0
  25. package/dist/lib/reporting/gcs/bucket-policy.js +31 -0
  26. package/dist/lib/reporting/gcs/bucket-policy.mjs +7 -0
  27. package/dist/lib/reporting/gcs/errors.d.mts +5 -0
  28. package/dist/lib/reporting/gcs/errors.d.ts +5 -0
  29. package/dist/lib/reporting/gcs/errors.js +41 -0
  30. package/dist/lib/reporting/gcs/errors.mjs +16 -0
  31. package/dist/lib/reporting/gcs/fence.d.mts +36 -0
  32. package/dist/lib/reporting/gcs/fence.d.ts +36 -0
  33. package/dist/lib/reporting/gcs/fence.js +250 -0
  34. package/dist/lib/reporting/gcs/fence.mjs +230 -0
  35. package/dist/lib/reporting/gcs/index.d.mts +7 -0
  36. package/dist/lib/reporting/gcs/index.d.ts +7 -0
  37. package/dist/lib/reporting/gcs/index.js +41 -0
  38. package/dist/lib/reporting/gcs/index.mjs +12 -0
  39. package/dist/lib/reporting/gcs/io.d.mts +7 -0
  40. package/dist/lib/reporting/gcs/io.d.ts +7 -0
  41. package/dist/lib/reporting/gcs/io.js +95 -0
  42. package/dist/lib/reporting/gcs/io.mjs +69 -0
  43. package/dist/lib/reporting/gcs/reader.d.mts +43 -0
  44. package/dist/lib/reporting/gcs/reader.d.ts +43 -0
  45. package/dist/lib/reporting/gcs/reader.js +193 -0
  46. package/dist/lib/reporting/gcs/reader.mjs +169 -0
  47. package/dist/lib/reporting/gcs/validation.d.mts +5 -0
  48. package/dist/lib/reporting/gcs/validation.d.ts +5 -0
  49. package/dist/lib/reporting/gcs/validation.js +49 -0
  50. package/dist/lib/reporting/gcs/validation.mjs +25 -0
  51. package/dist/lib/reporting/ledger/handler.d.mts +1 -0
  52. package/dist/lib/reporting/ledger/handler.d.ts +1 -0
  53. package/dist/lib/reporting/ledger/index.d.mts +1 -0
  54. package/dist/lib/reporting/ledger/index.d.ts +1 -0
  55. package/dist/lib/reporting/ledger/index.js +2 -0
  56. package/dist/lib/reporting/ledger/index.mjs +1 -0
  57. package/dist/lib/reporting/ledger/managed-postgres.d.mts +16 -1
  58. package/dist/lib/reporting/ledger/managed-postgres.d.ts +16 -1
  59. package/dist/lib/reporting/ledger/managed-postgres.js +243 -2
  60. package/dist/lib/reporting/ledger/managed-postgres.mjs +248 -2
  61. package/dist/lib/reporting/ledger/object-writes.d.mts +69 -0
  62. package/dist/lib/reporting/ledger/object-writes.d.ts +69 -0
  63. package/dist/lib/reporting/ledger/object-writes.js +147 -0
  64. package/dist/lib/reporting/ledger/object-writes.mjs +114 -0
  65. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  66. package/dist/lib/server/a2a-adapter.d.mts +50 -1
  67. package/dist/lib/server/a2a-adapter.d.ts +50 -1
  68. package/dist/lib/server/a2a-adapter.js +230 -7
  69. package/dist/lib/server/a2a-adapter.mjs +237 -7
  70. package/dist/lib/server/auth-signature.d.mts +84 -46
  71. package/dist/lib/server/auth-signature.d.ts +84 -46
  72. package/dist/lib/server/auth-signature.js +48 -14
  73. package/dist/lib/server/auth-signature.mjs +58 -15
  74. package/dist/lib/server/create-adcp-server.js +5 -16
  75. package/dist/lib/server/create-adcp-server.mjs +5 -16
  76. package/dist/lib/server/index.d.mts +1 -1
  77. package/dist/lib/server/index.d.ts +1 -1
  78. package/dist/lib/server/index.js +2 -0
  79. package/dist/lib/server/index.mjs +3 -1
  80. package/dist/lib/signing/agent-fetch.js +3 -33
  81. package/dist/lib/signing/agent-fetch.mjs +3 -33
  82. package/dist/lib/signing/middleware.d.mts +9 -1
  83. package/dist/lib/signing/middleware.d.ts +9 -1
  84. package/dist/lib/signing/operation-resolution.d.mts +37 -0
  85. package/dist/lib/signing/operation-resolution.d.ts +37 -0
  86. package/dist/lib/signing/operation-resolution.js +154 -0
  87. package/dist/lib/signing/operation-resolution.mjs +125 -0
  88. package/dist/lib/signing/postgres-replay-store.d.mts +1 -1
  89. package/dist/lib/signing/postgres-replay-store.d.ts +1 -1
  90. package/dist/lib/signing/redis-replay-store.d.mts +1 -1
  91. package/dist/lib/signing/redis-replay-store.d.ts +1 -1
  92. package/dist/lib/signing/server.d.mts +1 -0
  93. package/dist/lib/signing/server.d.ts +1 -0
  94. package/dist/lib/signing/server.js +7 -0
  95. package/dist/lib/signing/server.mjs +8 -0
  96. package/dist/lib/signing/verifier.d.mts +36 -1
  97. package/dist/lib/signing/verifier.d.ts +36 -1
  98. package/dist/lib/signing/verifier.js +66 -34
  99. package/dist/lib/signing/verifier.mjs +61 -34
  100. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.mts +12 -0
  101. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.ts +12 -0
  102. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.js +29 -2
  103. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.mjs +27 -1
  104. package/dist/lib/testing/storyboard/request-signing/a2a-operation-resolution.d.mts +61 -0
  105. package/dist/lib/testing/storyboard/request-signing/a2a-operation-resolution.d.ts +61 -0
  106. package/dist/lib/testing/storyboard/request-signing/a2a-operation-resolution.js +298 -0
  107. package/dist/lib/testing/storyboard/request-signing/a2a-operation-resolution.mjs +276 -0
  108. package/dist/lib/testing/storyboard/request-signing/grader.d.mts +31 -1
  109. package/dist/lib/testing/storyboard/request-signing/grader.d.ts +31 -1
  110. package/dist/lib/testing/storyboard/request-signing/grader.js +11 -0
  111. package/dist/lib/testing/storyboard/request-signing/grader.mjs +11 -0
  112. package/dist/lib/testing/storyboard/request-signing/index.d.mts +5 -4
  113. package/dist/lib/testing/storyboard/request-signing/index.d.ts +5 -4
  114. package/dist/lib/testing/storyboard/request-signing/index.js +13 -0
  115. package/dist/lib/testing/storyboard/request-signing/index.mjs +18 -2
  116. package/dist/lib/testing/storyboard/request-signing/types.d.mts +43 -0
  117. package/dist/lib/testing/storyboard/request-signing/types.d.ts +43 -0
  118. package/dist/lib/testing/storyboard/request-signing/types.js +3 -0
  119. package/dist/lib/testing/storyboard/request-signing/types.mjs +2 -0
  120. package/dist/lib/testing/storyboard/request-signing/vector-loader.d.mts +42 -1
  121. package/dist/lib/testing/storyboard/request-signing/vector-loader.d.ts +42 -1
  122. package/dist/lib/testing/storyboard/request-signing/vector-loader.js +100 -1
  123. package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +104 -3
  124. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  125. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  126. package/dist/lib/version.d.mts +3 -3
  127. package/dist/lib/version.d.ts +3 -3
  128. package/dist/lib/version.js +3 -3
  129. package/dist/lib/version.mjs +3 -3
  130. package/docs/TYPE-SUMMARY.md +2 -2
  131. package/docs/guides/BUILD-AN-AGENT.md +9 -4
  132. package/docs/guides/CREATIVE-DELIVERY.md +34 -0
  133. package/docs/guides/REPORTING-GCS-FENCE.md +52 -0
  134. package/docs/guides/REPORTING-GCS-MANAGED.md +56 -0
  135. package/docs/guides/REPORTING-OPERATIONS.md +4 -0
  136. package/docs/guides/SIGNING-GUIDE.md +20 -6
  137. package/docs/guides/VALIDATE-YOUR-AGENT.md +4 -0
  138. package/docs/llms.txt +2 -2
  139. package/docs/migration-14.x-rc-worksheet.md +5 -4
  140. package/docs/migration-buyer-agent-registry.md +1 -1
  141. package/package.json +19 -1
  142. package/skills/build-seller-agent/specialisms/signed-requests.md +2 -0
@@ -116,3 +116,15 @@ export declare function operationFromVectorUrl(vectorUrl: string): string;
116
116
  export declare function resolveA2aDispatchTarget(agentUrl: string, options?: A2aDispatchOptions): Promise<{
117
117
  endpoint: string;
118
118
  }>;
119
+ /**
120
+ * The A2A HTTP+JSON binding base URL the agent card declares, if any.
121
+ *
122
+ * Reads the raw card (not the SDK's normalization, which exposes only the
123
+ * interfaces its own transports drive) and accepts both card dialects:
124
+ * `supportedInterfaces[]` with `protocolBinding` (1.0) and `url` /
125
+ * `preferredTransport` / `additionalInterfaces[]` with `transport` (0.3).
126
+ * Returns `undefined` when the card does not resolve or declares no
127
+ * HTTP+JSON interface; the caller treats that as "this binding is not served"
128
+ * rather than guessing a path.
129
+ */
130
+ export declare function resolveA2aHttpJsonEndpoint(agentUrl: string, options?: A2aDispatchOptions): Promise<string | undefined>;
@@ -116,3 +116,15 @@ export declare function operationFromVectorUrl(vectorUrl: string): string;
116
116
  export declare function resolveA2aDispatchTarget(agentUrl: string, options?: A2aDispatchOptions): Promise<{
117
117
  endpoint: string;
118
118
  }>;
119
+ /**
120
+ * The A2A HTTP+JSON binding base URL the agent card declares, if any.
121
+ *
122
+ * Reads the raw card (not the SDK's normalization, which exposes only the
123
+ * interfaces its own transports drive) and accepts both card dialects:
124
+ * `supportedInterfaces[]` with `protocolBinding` (1.0) and `url` /
125
+ * `preferredTransport` / `additionalInterfaces[]` with `transport` (0.3).
126
+ * Returns `undefined` when the card does not resolve or declares no
127
+ * HTTP+JSON interface; the caller treats that as "this binding is not served"
128
+ * rather than guessing a path.
129
+ */
130
+ export declare function resolveA2aHttpJsonEndpoint(agentUrl: string, options?: A2aDispatchOptions): Promise<string | undefined>;
@@ -30,7 +30,8 @@ var a2a_dispatch_exports = {};
30
30
  __export(a2a_dispatch_exports, {
31
31
  captureA2aRequest: () => captureA2aRequest,
32
32
  operationFromVectorUrl: () => operationFromVectorUrl,
33
- resolveA2aDispatchTarget: () => resolveA2aDispatchTarget
33
+ resolveA2aDispatchTarget: () => resolveA2aDispatchTarget,
34
+ resolveA2aHttpJsonEndpoint: () => resolveA2aHttpJsonEndpoint
34
35
  });
35
36
  module.exports = __toCommonJS(a2a_dispatch_exports);
36
37
  var import_agent_transport_fetch = require('../../../net/agent-transport-fetch.js');
@@ -172,9 +173,35 @@ async function resolveA2aDispatchTarget(agentUrl, options = {}) {
172
173
  }
173
174
  throw new Error("the A2A client returned without issuing a dispatch probe; no endpoint was resolved");
174
175
  }
176
+ async function resolveA2aHttpJsonEndpoint(agentUrl, options = {}) {
177
+ const cardFetch = buildGuardedCardFetch(agentUrl, options);
178
+ const isHttpJson = (value) => typeof value === "string" && value.replace(/\s+/g, "").toUpperCase() === "HTTP+JSON";
179
+ for (const cardUrl of (0, import_a2a_discovery.buildCardUrls)(agentUrl)) {
180
+ let card;
181
+ try {
182
+ const res = await cardFetch(cardUrl, { headers: { accept: "application/json" }, redirect: "manual" });
183
+ if (!res.ok) continue;
184
+ card = await res.json();
185
+ } catch {
186
+ continue;
187
+ }
188
+ const interfaces = [];
189
+ for (const key of ["supportedInterfaces", "additionalInterfaces"]) {
190
+ const list = card[key];
191
+ if (Array.isArray(list)) interfaces.push(...list.filter((i) => !!i));
192
+ }
193
+ if (typeof card.url === "string") interfaces.push({ url: card.url, transport: card.preferredTransport });
194
+ const match = interfaces.find(
195
+ (i) => typeof i.url === "string" && (isHttpJson(i.protocolBinding) || isHttpJson(i.transport))
196
+ );
197
+ if (match) return match.url;
198
+ }
199
+ return void 0;
200
+ }
175
201
  // Annotate the CommonJS export names for ESM import in node:
176
202
  0 && (module.exports = {
177
203
  captureA2aRequest,
178
204
  operationFromVectorUrl,
179
- resolveA2aDispatchTarget
205
+ resolveA2aDispatchTarget,
206
+ resolveA2aHttpJsonEndpoint
180
207
  });
@@ -137,8 +137,34 @@ async function resolveA2aDispatchTarget(agentUrl, options = {}) {
137
137
  }
138
138
  throw new Error("the A2A client returned without issuing a dispatch probe; no endpoint was resolved");
139
139
  }
140
+ async function resolveA2aHttpJsonEndpoint(agentUrl, options = {}) {
141
+ const cardFetch = buildGuardedCardFetch(agentUrl, options);
142
+ const isHttpJson = (value) => typeof value === "string" && value.replace(/\s+/g, "").toUpperCase() === "HTTP+JSON";
143
+ for (const cardUrl of buildCardUrls(agentUrl)) {
144
+ let card;
145
+ try {
146
+ const res = await cardFetch(cardUrl, { headers: { accept: "application/json" }, redirect: "manual" });
147
+ if (!res.ok) continue;
148
+ card = await res.json();
149
+ } catch {
150
+ continue;
151
+ }
152
+ const interfaces = [];
153
+ for (const key of ["supportedInterfaces", "additionalInterfaces"]) {
154
+ const list = card[key];
155
+ if (Array.isArray(list)) interfaces.push(...list.filter((i) => !!i));
156
+ }
157
+ if (typeof card.url === "string") interfaces.push({ url: card.url, transport: card.preferredTransport });
158
+ const match = interfaces.find(
159
+ (i) => typeof i.url === "string" && (isHttpJson(i.protocolBinding) || isHttpJson(i.transport))
160
+ );
161
+ if (match) return match.url;
162
+ }
163
+ return void 0;
164
+ }
140
165
  export {
141
166
  captureA2aRequest,
142
167
  operationFromVectorUrl,
143
- resolveA2aDispatchTarget
168
+ resolveA2aDispatchTarget,
169
+ resolveA2aHttpJsonEndpoint
144
170
  };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Grading of the A2A operation-resolution vectors (adcp#7945, GHSA-frxv-c96c-4vqw).
3
+ *
4
+ * `request_signing.required_for` matches the AdCP operation a verifier resolves
5
+ * from the request. Over A2A that operation is the `skill` of the Message's sole
6
+ * DataPart, not the JSON-RPC method (`SendMessage`, `message/send`, ...). A
7
+ * verifier that matched only `tools/call` waved unsigned `create_media_buy`
8
+ * through. These vectors grade that rule black-box, against a live agent.
9
+ *
10
+ * ## Why this is not routed through the official-client capture
11
+ *
12
+ * The root vectors are framed by `@a2a-js/sdk` (`a2a-dispatch.ts`) because the
13
+ * request must be one a real buyer emits. These vectors are the opposite: the
14
+ * defect under test lives IN the bytes (a duplicate DataPart, a case-variant
15
+ * method, a batch array, a lone `Signature` header), and a well-behaved client
16
+ * refuses to emit most of them. So each vector's body and headers go out
17
+ * verbatim. Only the destination changes: the vector's URL is a placeholder, so
18
+ * the request is retargeted at the agent's real JSON-RPC endpoint, discovered
19
+ * from the agent card the same way the official-client path does. The four
20
+ * signed vectors are re-signed against that real URL with the shared test key
21
+ * (their recorded signatures are bound to the placeholder URL and cannot be
22
+ * replayed).
23
+ */
24
+ import { type A2aVectorSource } from './vector-loader.mjs';
25
+ import type { SignedRequestsRunnerContract } from './test-kit.mjs';
26
+ import type { GradeOptions, VectorGradeResult } from './grader.mjs';
27
+ import type { A2aVectorTier, TestKeyset } from './types.mjs';
28
+ /** Id of the synthetic skipped row reported when no A2A vectors are available. */
29
+ export declare const A2A_UNAVAILABLE_ROW_ID = "a2a/operation-resolution-vectors";
30
+ export interface A2aTierSummary {
31
+ passed: number;
32
+ failed: number;
33
+ skipped: number;
34
+ /** Ids of failed vectors in this tier. */
35
+ failed_vectors: string[];
36
+ }
37
+ export interface A2aOperationResolutionSummary {
38
+ /** `false` when the compliance bundle (and any override) carried no A2A vectors. */
39
+ vectors_available: boolean;
40
+ source: A2aVectorSource;
41
+ source_dir?: string;
42
+ /** Set when `vectors_available` is `false`: why nothing was graded. */
43
+ message?: string;
44
+ /**
45
+ * Per-tier counts. `contradiction-resolution` is MUST for a 3.2 verifier;
46
+ * `hardening` is SHOULD in 3.2.x and MUST from 3.3. Both count toward the
47
+ * report's pass/fail; the split tells an operator which one failed.
48
+ */
49
+ tiers: Record<A2aVectorTier, A2aTierSummary>;
50
+ }
51
+ export interface A2aGradeOutcome {
52
+ positive: VectorGradeResult[];
53
+ negative: VectorGradeResult[];
54
+ summary: A2aOperationResolutionSummary;
55
+ }
56
+ /**
57
+ * Grade every A2A operation-resolution vector against *agentUrl*. Returns
58
+ * `undefined` when the caller restricted the run (`onlyVectors`) to ids outside
59
+ * this corpus, so a single-vector regression run is not buried in skip rows.
60
+ */
61
+ export declare function gradeA2aOperationResolution(agentUrl: string, keys: TestKeyset, contract: SignedRequestsRunnerContract | undefined, options: GradeOptions): Promise<A2aGradeOutcome | undefined>;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Grading of the A2A operation-resolution vectors (adcp#7945, GHSA-frxv-c96c-4vqw).
3
+ *
4
+ * `request_signing.required_for` matches the AdCP operation a verifier resolves
5
+ * from the request. Over A2A that operation is the `skill` of the Message's sole
6
+ * DataPart, not the JSON-RPC method (`SendMessage`, `message/send`, ...). A
7
+ * verifier that matched only `tools/call` waved unsigned `create_media_buy`
8
+ * through. These vectors grade that rule black-box, against a live agent.
9
+ *
10
+ * ## Why this is not routed through the official-client capture
11
+ *
12
+ * The root vectors are framed by `@a2a-js/sdk` (`a2a-dispatch.ts`) because the
13
+ * request must be one a real buyer emits. These vectors are the opposite: the
14
+ * defect under test lives IN the bytes (a duplicate DataPart, a case-variant
15
+ * method, a batch array, a lone `Signature` header), and a well-behaved client
16
+ * refuses to emit most of them. So each vector's body and headers go out
17
+ * verbatim. Only the destination changes: the vector's URL is a placeholder, so
18
+ * the request is retargeted at the agent's real JSON-RPC endpoint, discovered
19
+ * from the agent card the same way the official-client path does. The four
20
+ * signed vectors are re-signed against that real URL with the shared test key
21
+ * (their recorded signatures are bound to the placeholder URL and cannot be
22
+ * replayed).
23
+ */
24
+ import { type A2aVectorSource } from './vector-loader';
25
+ import type { SignedRequestsRunnerContract } from './test-kit';
26
+ import type { GradeOptions, VectorGradeResult } from './grader';
27
+ import type { A2aVectorTier, TestKeyset } from './types';
28
+ /** Id of the synthetic skipped row reported when no A2A vectors are available. */
29
+ export declare const A2A_UNAVAILABLE_ROW_ID = "a2a/operation-resolution-vectors";
30
+ export interface A2aTierSummary {
31
+ passed: number;
32
+ failed: number;
33
+ skipped: number;
34
+ /** Ids of failed vectors in this tier. */
35
+ failed_vectors: string[];
36
+ }
37
+ export interface A2aOperationResolutionSummary {
38
+ /** `false` when the compliance bundle (and any override) carried no A2A vectors. */
39
+ vectors_available: boolean;
40
+ source: A2aVectorSource;
41
+ source_dir?: string;
42
+ /** Set when `vectors_available` is `false`: why nothing was graded. */
43
+ message?: string;
44
+ /**
45
+ * Per-tier counts. `contradiction-resolution` is MUST for a 3.2 verifier;
46
+ * `hardening` is SHOULD in 3.2.x and MUST from 3.3. Both count toward the
47
+ * report's pass/fail; the split tells an operator which one failed.
48
+ */
49
+ tiers: Record<A2aVectorTier, A2aTierSummary>;
50
+ }
51
+ export interface A2aGradeOutcome {
52
+ positive: VectorGradeResult[];
53
+ negative: VectorGradeResult[];
54
+ summary: A2aOperationResolutionSummary;
55
+ }
56
+ /**
57
+ * Grade every A2A operation-resolution vector against *agentUrl*. Returns
58
+ * `undefined` when the caller restricted the run (`onlyVectors`) to ids outside
59
+ * this corpus, so a single-vector regression run is not buried in skip rows.
60
+ */
61
+ export declare function gradeA2aOperationResolution(agentUrl: string, keys: TestKeyset, contract: SignedRequestsRunnerContract | undefined, options: GradeOptions): Promise<A2aGradeOutcome | undefined>;
@@ -0,0 +1,298 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var a2a_operation_resolution_exports = {};
20
+ __export(a2a_operation_resolution_exports, {
21
+ A2A_UNAVAILABLE_ROW_ID: () => A2A_UNAVAILABLE_ROW_ID,
22
+ gradeA2aOperationResolution: () => gradeA2aOperationResolution
23
+ });
24
+ module.exports = __toCommonJS(a2a_operation_resolution_exports);
25
+ var import_builder = require('./builder.js');
26
+ var import_probe = require('./probe.js');
27
+ var import_a2a_dispatch = require('./a2a-dispatch.js');
28
+ var import_vector_loader = require('./vector-loader.js');
29
+ const A2A_UNAVAILABLE_ROW_ID = "a2a/operation-resolution-vectors";
30
+ const ALTERNATE_ACCEPTED_CODES = {
31
+ "a2a/negative/023-batch-body": ["request_signature_required"]
32
+ };
33
+ function emptyTiers() {
34
+ return {
35
+ "contradiction-resolution": { passed: 0, failed: 0, skipped: 0, failed_vectors: [] },
36
+ hardening: { passed: 0, failed: 0, skipped: 0, failed_vectors: [] }
37
+ };
38
+ }
39
+ async function gradeA2aOperationResolution(agentUrl, keys, contract, options) {
40
+ if (options.onlyVectors && !options.onlyVectors.some((id) => id.startsWith("a2a/"))) return void 0;
41
+ const loaded = (0, import_vector_loader.loadA2aOperationResolutionVectors)(options);
42
+ const tiers = emptyTiers();
43
+ if (loaded.source === "none") {
44
+ return {
45
+ positive: [],
46
+ negative: [
47
+ {
48
+ vector_id: A2A_UNAVAILABLE_ROW_ID,
49
+ kind: "negative",
50
+ passed: true,
51
+ skipped: true,
52
+ skip_reason: "a2a_vectors_unavailable",
53
+ diagnostic: import_vector_loader.A2A_VECTORS_UNAVAILABLE_MESSAGE,
54
+ http_status: 0,
55
+ probe_duration_ms: 0
56
+ }
57
+ ],
58
+ summary: {
59
+ vectors_available: false,
60
+ source: "none",
61
+ message: import_vector_loader.A2A_VECTORS_UNAVAILABLE_MESSAGE,
62
+ tiers
63
+ }
64
+ };
65
+ }
66
+ const dispatchOptions = {
67
+ allowPrivateIp: options.allowPrivateIp === true,
68
+ ...options.timeoutMs !== void 0 ? { timeoutMs: options.timeoutMs } : {},
69
+ ...options.cardFetch ? { cardFetch: options.cardFetch } : {}
70
+ };
71
+ const probeOptions = {
72
+ allowPrivateIp: options.allowPrivateIp === true,
73
+ timeoutMs: options.timeoutMs
74
+ };
75
+ let jsonRpcEndpoint;
76
+ const jsonRpc = () => jsonRpcEndpoint ??= (0, import_a2a_dispatch.resolveA2aDispatchTarget)(agentUrl, dispatchOptions).then((target) => target.endpoint);
77
+ let httpJsonEndpoint;
78
+ const httpJson = () => httpJsonEndpoint ??= (0, import_a2a_dispatch.resolveA2aHttpJsonEndpoint)(agentUrl, dispatchOptions);
79
+ const requiredFor = options.agentCapability?.required_for ?? options.agentRequiredFor;
80
+ const protocolMethodsRequiredFor = options.agentCapability !== void 0 ? options.agentCapability.protocol_methods_required_for ?? [] : options.agentProtocolMethodsRequiredFor;
81
+ const contentDigestPolicy = options.agentCapability?.covers_content_digest ?? options.agentContentDigestPolicy;
82
+ const results = [];
83
+ const grade = async (vector) => {
84
+ const skip = preflightSkip(vector, {
85
+ options,
86
+ contract,
87
+ requiredFor,
88
+ protocolMethodsRequiredFor,
89
+ contentDigestPolicy
90
+ });
91
+ if (skip) return skip;
92
+ let url;
93
+ if (isHttpJsonBinding(vector)) {
94
+ const base = await httpJson();
95
+ if (!base) {
96
+ return skipped(
97
+ vector,
98
+ "transport_ungradable",
99
+ `Vector ${vector.id} grades the A2A HTTP+JSON binding (POST \u2026/message:send), but the agent card declares no HTTP+JSON interface. An agent that does not serve that binding cannot be bypassed through it.`
100
+ );
101
+ }
102
+ url = `${base.replace(/\/+$/, "")}/${lastPathSegment(vector.request.url)}`;
103
+ } else {
104
+ url = await jsonRpc();
105
+ }
106
+ const request = buildRequest(vector, url, keys);
107
+ const probe = await (0, import_probe.probeSignedRequest)(request, probeOptions);
108
+ return vector.kind === "positive" ? gradePositive(vector, probe) : gradeNegative(vector, probe);
109
+ };
110
+ for (const vector of [...loaded.positive, ...loaded.negative]) {
111
+ const result = await grade(vector);
112
+ results.push(result);
113
+ const tier = tiers[vector.tier];
114
+ if (result.skipped) tier.skipped++;
115
+ else if (result.passed) tier.passed++;
116
+ else {
117
+ tier.failed++;
118
+ tier.failed_vectors.push(vector.id);
119
+ }
120
+ }
121
+ return {
122
+ positive: results.filter((r) => r.kind === "positive"),
123
+ negative: results.filter((r) => r.kind === "negative"),
124
+ summary: {
125
+ vectors_available: true,
126
+ source: loaded.source,
127
+ ...loaded.sourceDir ? { source_dir: loaded.sourceDir } : {},
128
+ tiers
129
+ }
130
+ };
131
+ }
132
+ function skipped(vector, skip_reason, diagnostic) {
133
+ return {
134
+ vector_id: vector.id,
135
+ kind: vector.kind,
136
+ tier: vector.tier,
137
+ passed: true,
138
+ // skipped is not failed; overall pass/fail excludes skipped
139
+ skipped: true,
140
+ skip_reason,
141
+ ...vector.kind === "negative" && vector.expected_outcome.error_code ? { expected_error_code: vector.expected_outcome.error_code } : {},
142
+ ...diagnostic ? { diagnostic } : {},
143
+ http_status: 0,
144
+ probe_duration_ms: 0
145
+ };
146
+ }
147
+ function preflightSkip(vector, ctx) {
148
+ const { options } = ctx;
149
+ if (options.onlyVectors && !options.onlyVectors.includes(vector.id)) {
150
+ return skipped(vector, "not_in_only_vectors");
151
+ }
152
+ if (options.skipVectors?.includes(vector.id)) return skipped(vector, "operator_skip");
153
+ const mismatch = capabilityMismatch(vector, ctx.requiredFor, ctx.protocolMethodsRequiredFor);
154
+ if (mismatch) return skipped(vector, "capability_profile_mismatch", mismatch);
155
+ if (vector.kind === "positive" && isSigned(vector) && ctx.contentDigestPolicy === "forbidden") {
156
+ return skipped(
157
+ vector,
158
+ "capability_profile_mismatch",
159
+ `Vector ${vector.id} is signed with content-digest covered, but the agent declares covers_content_digest='forbidden'.`
160
+ );
161
+ }
162
+ if (vector.kind === "positive" && vector.expected_outcome.status === "verified" && !options.allowLiveSideEffects && ctx.contract?.endpoint_scope !== "sandbox") {
163
+ return skipped(
164
+ vector,
165
+ "live_side_effect_opt_in_required",
166
+ `Vector ${vector.id} sends a validly signed ${vector.expected_outcome.resolved_operation ?? "operation"} request the agent will accept and run. Pass allowLiveSideEffects: true (or point the grader at an endpoint whose signed-requests-runner contract declares endpoint_scope: sandbox) to run it.`
167
+ );
168
+ }
169
+ return void 0;
170
+ }
171
+ function capabilityMismatch(vector, requiredFor, protocolMethodsRequiredFor) {
172
+ if (vector.kind === "negative") {
173
+ if (vector.expected_outcome.error_code !== "request_signature_required") return void 0;
174
+ const methods = vector.verifier_capability.protocol_methods_required_for ?? [];
175
+ if (methods.length > 0) {
176
+ if (!protocolMethodsRequiredFor) return void 0;
177
+ const missing = methods.filter((m) => !protocolMethodsRequiredFor.includes(m));
178
+ return missing.length === 0 ? void 0 : `Vector asserts protocol_methods_required_for includes [${missing.join(", ")}] but the agent declares [${protocolMethodsRequiredFor.join(", ")}]. Add the method to request_signing.protocol_methods_required_for to grade it.`;
179
+ }
180
+ const operation2 = vector.expected_outcome.resolved_operation;
181
+ if (!requiredFor || typeof operation2 !== "string" || requiredFor.includes(operation2)) return void 0;
182
+ return `Vector asserts ${operation2} is in required_for but the agent declares required_for [${requiredFor.join(", ")}]. The vector tests a rejection path the agent has not opted into; add the operation to request_signing.required_for to grade it.`;
183
+ }
184
+ if (vector.expected_outcome.status !== "unsigned") return void 0;
185
+ const operation = vector.expected_outcome.resolved_operation;
186
+ if (requiredFor && typeof operation === "string" && requiredFor.includes(operation)) {
187
+ return `Vector asserts ${operation} needs no signature, but the agent declares it in required_for.`;
188
+ }
189
+ const method = jsonRpcMethodOf(vector.request.body);
190
+ if (protocolMethodsRequiredFor && method !== void 0 && protocolMethodsRequiredFor.includes(method)) {
191
+ return `Vector asserts an unsigned ${method} is accepted, but the agent declares ${method} in protocol_methods_required_for.`;
192
+ }
193
+ return void 0;
194
+ }
195
+ function hasHeader(headers, name) {
196
+ return Object.keys(headers).some((key) => key.toLowerCase() === name);
197
+ }
198
+ function isSigned(vector) {
199
+ return hasHeader(vector.request.headers, "signature-input");
200
+ }
201
+ function isHttpJsonBinding(vector) {
202
+ try {
203
+ return /(?:^|\/)message:(?:send|stream)$/.test(new URL(vector.request.url).pathname);
204
+ } catch {
205
+ return false;
206
+ }
207
+ }
208
+ function lastPathSegment(url) {
209
+ return new URL(url).pathname.split("/").filter(Boolean).pop() ?? "";
210
+ }
211
+ function jsonRpcMethodOf(body) {
212
+ if (!body) return void 0;
213
+ try {
214
+ const parsed = JSON.parse(body);
215
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
216
+ const method = parsed.method;
217
+ return typeof method === "string" ? method : void 0;
218
+ }
219
+ } catch {
220
+ }
221
+ return void 0;
222
+ }
223
+ function buildRequest(vector, url, keys) {
224
+ const request = { ...vector.request, url, headers: { ...vector.request.headers } };
225
+ if (!isSigned(vector)) return request;
226
+ const asPositive = {
227
+ kind: "positive",
228
+ id: vector.id,
229
+ name: vector.name,
230
+ signing_profile_version: vector.signing_profile_version,
231
+ reference_now: vector.reference_now,
232
+ request,
233
+ verifier_capability: vector.verifier_capability,
234
+ jwks_ref: vector.jwks_ref
235
+ };
236
+ return (0, import_builder.buildPositiveRequest)(asPositive, keys, { transport: "raw" });
237
+ }
238
+ function isSignatureChallenge(probe) {
239
+ if (probe.status !== 401) return false;
240
+ if (probe.wwwAuthenticateErrorCode !== void 0) return true;
241
+ return /(?:^|,)\s*Signature\b/i.test(probe.headers["www-authenticate"] ?? "");
242
+ }
243
+ function gradePositive(vector, probe) {
244
+ const rejected = isSignatureChallenge(probe);
245
+ const passed = !probe.error && !rejected;
246
+ let diagnostic;
247
+ if (probe.error) diagnostic = `probe error: ${probe.error}`;
248
+ else if (rejected) {
249
+ const code = probe.wwwAuthenticateErrorCode ?? "(none)";
250
+ diagnostic = vector.expected_outcome.status === "verified" ? `expected the signed request to be accepted past the signature layer, got 401 with error="${code}". Check the grader test key is registered with the agent. Vector: ${vector.name}` : `expected no signature rejection (the resolved operation does not require one), got 401 with error="${code}". Vector: ${vector.name}`;
251
+ }
252
+ return {
253
+ vector_id: vector.id,
254
+ kind: "positive",
255
+ tier: vector.tier,
256
+ passed,
257
+ http_status: probe.status,
258
+ probe_url: probe.url,
259
+ ...probe.wwwAuthenticateErrorCode ? { actual_error_code: probe.wwwAuthenticateErrorCode } : {},
260
+ ...diagnostic ? { diagnostic } : {},
261
+ ...probe.error !== void 0 && { transport_error: true },
262
+ probe_duration_ms: probe.duration_ms
263
+ };
264
+ }
265
+ function gradeNegative(vector, probe) {
266
+ const expected = vector.expected_error_code;
267
+ const accepted = [expected, ...ALTERNATE_ACCEPTED_CODES[vector.id] ?? []];
268
+ const actual = probe.wwwAuthenticateErrorCode;
269
+ const passed = !probe.error && probe.status === 401 && actual !== void 0 && accepted.includes(actual);
270
+ let diagnostic;
271
+ if (!passed) {
272
+ const wanted = accepted.map((code) => `"${code}"`).join(" or ");
273
+ if (probe.error) diagnostic = `probe error: ${probe.error}`;
274
+ else if (probe.status !== 401) {
275
+ diagnostic = `expected 401 with error=${wanted}, got ${probe.status}. The request reached the agent's dispatcher: the verifier did not resolve the operation from the A2A DataPart skill (GHSA-frxv-c96c-4vqw). Vector: ${vector.name}`;
276
+ } else {
277
+ diagnostic = `expected error=${wanted}, got error="${actual ?? "(none)"}". Vector: ${vector.name}`;
278
+ }
279
+ }
280
+ return {
281
+ vector_id: vector.id,
282
+ kind: "negative",
283
+ tier: vector.tier,
284
+ passed,
285
+ http_status: probe.status,
286
+ probe_url: probe.url,
287
+ expected_error_code: expected,
288
+ ...actual ? { actual_error_code: actual } : {},
289
+ ...diagnostic ? { diagnostic } : {},
290
+ ...probe.error !== void 0 && { transport_error: true },
291
+ probe_duration_ms: probe.duration_ms
292
+ };
293
+ }
294
+ // Annotate the CommonJS export names for ESM import in node:
295
+ 0 && (module.exports = {
296
+ A2A_UNAVAILABLE_ROW_ID,
297
+ gradeA2aOperationResolution
298
+ });