@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
@@ -0,0 +1,69 @@
1
+ export declare class ReportingObjectWriteConflictError extends Error {
2
+ constructor();
3
+ }
4
+ /** Symbol branding preserves errors when CJS stores are paired with ESM fences. */
5
+ export declare function isReportingObjectWriteConflictError(error: unknown): boolean;
6
+ export declare class ReportingObjectWriteNotRevokedError extends Error {
7
+ constructor();
8
+ }
9
+ export declare function isReportingObjectWriteNotRevokedError(error: unknown): boolean;
10
+ /** Non-secret destination identity, scoped to the store's isolated tenant database. */
11
+ export interface ReportingObjectWriteScopeV1 {
12
+ account_id: string;
13
+ destination_ref: string;
14
+ generation: number;
15
+ }
16
+ export interface ReportingObjectWriteV1 {
17
+ bucket: string;
18
+ object_name: string;
19
+ sha256: string;
20
+ size_bytes: number;
21
+ }
22
+ export interface ReportingObjectWriteBindingV1 {
23
+ bucket: string;
24
+ /** SHA-256 of a host-owned deployment namespace; immutable per authorization generation. */
25
+ namespace_key: string;
26
+ }
27
+ export interface ReportingObjectWriteContextV1 {
28
+ signal?: AbortSignal;
29
+ }
30
+ export declare function reportingObjectWriteScopeKey(scope: ReportingObjectWriteScopeV1): string;
31
+ export declare function reportingObjectWriteName(scope: ReportingObjectWriteScopeV1, binding: ReportingObjectWriteBindingV1, planId: string, index: number): string;
32
+ export interface ReportingObjectWritePlanV1 extends ReportingObjectWriteScopeV1 {
33
+ provider: ReportingObjectWriteBindingV1;
34
+ /** Stable opaque identity for the same logical delivery across retries. */
35
+ plan_id: string;
36
+ objects: readonly ReportingObjectWriteV1[];
37
+ }
38
+ export interface ReportingObjectWriteCursorV1 {
39
+ plan_id: string;
40
+ object_index: number;
41
+ }
42
+ export interface ReportingObjectWriteStoreV1 {
43
+ /** Registration and destination revocation MUST share one authority/lock boundary. */
44
+ registerObjectWritePlan(plan: ReportingObjectWritePlanV1, context?: ReportingObjectWriteContextV1): Promise<'registered' | 'unchanged' | 'revoked'>;
45
+ /** Authoritative cleanup routing, available only for a closed generation. */
46
+ getObjectWriteBinding(scope: ReportingObjectWriteScopeV1, context?: ReportingObjectWriteContextV1): Promise<ReportingObjectWriteBindingV1 | null>;
47
+ /** Only reads closed (revoked) generations; inventory never prunes automatically. */
48
+ listRevokedObjectWrites(scope: ReportingObjectWriteScopeV1, options?: {
49
+ after?: ReportingObjectWriteCursorV1;
50
+ limit?: number;
51
+ }, context?: ReportingObjectWriteContextV1): Promise<Array<ReportingObjectWriteV1 & ReportingObjectWriteCursorV1>>;
52
+ /** Trusted provider code calls this only after verifying a persistent tombstone. */
53
+ markObjectWriteFenced(input: ReportingObjectWriteScopeV1 & ReportingObjectWriteCursorV1 & {
54
+ tombstone_generation: string;
55
+ }, context?: ReportingObjectWriteContextV1): Promise<void>;
56
+ }
57
+ /** Apply after REPORTING_MANAGED_DELIVERY_MIGRATION. Additive and independently opt-in. */
58
+ export declare const REPORTING_OBJECT_WRITE_MIGRATION = "\nCREATE TABLE IF NOT EXISTS adcp_reporting_object_write_bindings (\n account_id TEXT NOT NULL,\n destination_ref TEXT NOT NULL,\n generation BIGINT NOT NULL,\n bucket TEXT NOT NULL,\n namespace_key TEXT NOT NULL CHECK (namespace_key ~ '^[a-f0-9]{64}$'),\n PRIMARY KEY (account_id, destination_ref, generation),\n FOREIGN KEY (account_id, destination_ref, generation)\n REFERENCES adcp_reporting_destination_authorizations(account_id, destination_ref, generation)\n);\nCREATE TABLE IF NOT EXISTS adcp_reporting_object_write_plans (\n account_id TEXT NOT NULL,\n destination_ref TEXT NOT NULL,\n generation BIGINT NOT NULL,\n plan_id TEXT NOT NULL CHECK (plan_id ~ '^[a-f0-9]{64}$'),\n fingerprint TEXT NOT NULL,\n PRIMARY KEY (account_id, destination_ref, generation, plan_id),\n FOREIGN KEY (account_id, destination_ref, generation)\n REFERENCES adcp_reporting_destination_authorizations(account_id, destination_ref, generation)\n);\nCREATE TABLE IF NOT EXISTS adcp_reporting_object_writes (\n account_id TEXT NOT NULL,\n destination_ref TEXT NOT NULL,\n generation BIGINT NOT NULL,\n plan_id TEXT NOT NULL,\n object_index INTEGER NOT NULL CHECK (object_index >= 0 AND object_index < 128),\n bucket TEXT NOT NULL,\n object_name TEXT NOT NULL,\n sha256 TEXT NOT NULL CHECK (sha256 ~ '^[a-f0-9]{64}$'),\n size_bytes BIGINT NOT NULL CHECK (size_bytes >= 0 AND size_bytes <= 67108864),\n fenced_at TIMESTAMPTZ,\n tombstone_generation TEXT,\n PRIMARY KEY (account_id, destination_ref, generation, plan_id, object_index),\n UNIQUE (bucket, object_name),\n FOREIGN KEY (account_id, destination_ref, generation, plan_id)\n REFERENCES adcp_reporting_object_write_plans(account_id, destination_ref, generation, plan_id)\n);\n";
59
+ export declare function assertReportingObjectWriteScope(scope: ReportingObjectWriteScopeV1): void;
60
+ export declare function reportingObjectWritePlanFingerprint(plan: ReportingObjectWritePlanV1): string;
61
+ /** Opt-in authority for complete provider adapters; the original primitive store port is unchanged. */
62
+ export interface ReportingObjectWriteAuthorityStoreV1 extends ReportingObjectWriteStoreV1 {
63
+ probeObjectWriteAuthority(context?: ReportingObjectWriteContextV1): Promise<boolean>;
64
+ getObjectWriteAuthorityId(context?: ReportingObjectWriteContextV1): Promise<string>;
65
+ getAuthorizedObjectWriteBinding(scope: ReportingObjectWriteScopeV1, context?: ReportingObjectWriteContextV1): Promise<ReportingObjectWriteBindingV1 | null>;
66
+ getObjectWritePlan(scope: ReportingObjectWriteScopeV1, planId: string, context?: ReportingObjectWriteContextV1): Promise<ReportingObjectWritePlanV1 | null>;
67
+ }
68
+ /** PostgreSQL 13+; apply after REPORTING_OBJECT_WRITE_MIGRATION. Identity survives replica/worker restart. */
69
+ export declare const REPORTING_OBJECT_WRITE_AUTHORITY_MIGRATION = "\nCREATE TABLE IF NOT EXISTS adcp_reporting_object_write_authority (\n singleton BOOLEAN PRIMARY KEY DEFAULT TRUE CHECK (singleton),\n installation_id UUID NOT NULL DEFAULT gen_random_uuid(),\n schema_version INTEGER NOT NULL DEFAULT 1 CHECK (schema_version = 1)\n);\nINSERT INTO adcp_reporting_object_write_authority (singleton) VALUES (TRUE) ON CONFLICT DO NOTHING;\n";
@@ -0,0 +1,69 @@
1
+ export declare class ReportingObjectWriteConflictError extends Error {
2
+ constructor();
3
+ }
4
+ /** Symbol branding preserves errors when CJS stores are paired with ESM fences. */
5
+ export declare function isReportingObjectWriteConflictError(error: unknown): boolean;
6
+ export declare class ReportingObjectWriteNotRevokedError extends Error {
7
+ constructor();
8
+ }
9
+ export declare function isReportingObjectWriteNotRevokedError(error: unknown): boolean;
10
+ /** Non-secret destination identity, scoped to the store's isolated tenant database. */
11
+ export interface ReportingObjectWriteScopeV1 {
12
+ account_id: string;
13
+ destination_ref: string;
14
+ generation: number;
15
+ }
16
+ export interface ReportingObjectWriteV1 {
17
+ bucket: string;
18
+ object_name: string;
19
+ sha256: string;
20
+ size_bytes: number;
21
+ }
22
+ export interface ReportingObjectWriteBindingV1 {
23
+ bucket: string;
24
+ /** SHA-256 of a host-owned deployment namespace; immutable per authorization generation. */
25
+ namespace_key: string;
26
+ }
27
+ export interface ReportingObjectWriteContextV1 {
28
+ signal?: AbortSignal;
29
+ }
30
+ export declare function reportingObjectWriteScopeKey(scope: ReportingObjectWriteScopeV1): string;
31
+ export declare function reportingObjectWriteName(scope: ReportingObjectWriteScopeV1, binding: ReportingObjectWriteBindingV1, planId: string, index: number): string;
32
+ export interface ReportingObjectWritePlanV1 extends ReportingObjectWriteScopeV1 {
33
+ provider: ReportingObjectWriteBindingV1;
34
+ /** Stable opaque identity for the same logical delivery across retries. */
35
+ plan_id: string;
36
+ objects: readonly ReportingObjectWriteV1[];
37
+ }
38
+ export interface ReportingObjectWriteCursorV1 {
39
+ plan_id: string;
40
+ object_index: number;
41
+ }
42
+ export interface ReportingObjectWriteStoreV1 {
43
+ /** Registration and destination revocation MUST share one authority/lock boundary. */
44
+ registerObjectWritePlan(plan: ReportingObjectWritePlanV1, context?: ReportingObjectWriteContextV1): Promise<'registered' | 'unchanged' | 'revoked'>;
45
+ /** Authoritative cleanup routing, available only for a closed generation. */
46
+ getObjectWriteBinding(scope: ReportingObjectWriteScopeV1, context?: ReportingObjectWriteContextV1): Promise<ReportingObjectWriteBindingV1 | null>;
47
+ /** Only reads closed (revoked) generations; inventory never prunes automatically. */
48
+ listRevokedObjectWrites(scope: ReportingObjectWriteScopeV1, options?: {
49
+ after?: ReportingObjectWriteCursorV1;
50
+ limit?: number;
51
+ }, context?: ReportingObjectWriteContextV1): Promise<Array<ReportingObjectWriteV1 & ReportingObjectWriteCursorV1>>;
52
+ /** Trusted provider code calls this only after verifying a persistent tombstone. */
53
+ markObjectWriteFenced(input: ReportingObjectWriteScopeV1 & ReportingObjectWriteCursorV1 & {
54
+ tombstone_generation: string;
55
+ }, context?: ReportingObjectWriteContextV1): Promise<void>;
56
+ }
57
+ /** Apply after REPORTING_MANAGED_DELIVERY_MIGRATION. Additive and independently opt-in. */
58
+ export declare const REPORTING_OBJECT_WRITE_MIGRATION = "\nCREATE TABLE IF NOT EXISTS adcp_reporting_object_write_bindings (\n account_id TEXT NOT NULL,\n destination_ref TEXT NOT NULL,\n generation BIGINT NOT NULL,\n bucket TEXT NOT NULL,\n namespace_key TEXT NOT NULL CHECK (namespace_key ~ '^[a-f0-9]{64}$'),\n PRIMARY KEY (account_id, destination_ref, generation),\n FOREIGN KEY (account_id, destination_ref, generation)\n REFERENCES adcp_reporting_destination_authorizations(account_id, destination_ref, generation)\n);\nCREATE TABLE IF NOT EXISTS adcp_reporting_object_write_plans (\n account_id TEXT NOT NULL,\n destination_ref TEXT NOT NULL,\n generation BIGINT NOT NULL,\n plan_id TEXT NOT NULL CHECK (plan_id ~ '^[a-f0-9]{64}$'),\n fingerprint TEXT NOT NULL,\n PRIMARY KEY (account_id, destination_ref, generation, plan_id),\n FOREIGN KEY (account_id, destination_ref, generation)\n REFERENCES adcp_reporting_destination_authorizations(account_id, destination_ref, generation)\n);\nCREATE TABLE IF NOT EXISTS adcp_reporting_object_writes (\n account_id TEXT NOT NULL,\n destination_ref TEXT NOT NULL,\n generation BIGINT NOT NULL,\n plan_id TEXT NOT NULL,\n object_index INTEGER NOT NULL CHECK (object_index >= 0 AND object_index < 128),\n bucket TEXT NOT NULL,\n object_name TEXT NOT NULL,\n sha256 TEXT NOT NULL CHECK (sha256 ~ '^[a-f0-9]{64}$'),\n size_bytes BIGINT NOT NULL CHECK (size_bytes >= 0 AND size_bytes <= 67108864),\n fenced_at TIMESTAMPTZ,\n tombstone_generation TEXT,\n PRIMARY KEY (account_id, destination_ref, generation, plan_id, object_index),\n UNIQUE (bucket, object_name),\n FOREIGN KEY (account_id, destination_ref, generation, plan_id)\n REFERENCES adcp_reporting_object_write_plans(account_id, destination_ref, generation, plan_id)\n);\n";
59
+ export declare function assertReportingObjectWriteScope(scope: ReportingObjectWriteScopeV1): void;
60
+ export declare function reportingObjectWritePlanFingerprint(plan: ReportingObjectWritePlanV1): string;
61
+ /** Opt-in authority for complete provider adapters; the original primitive store port is unchanged. */
62
+ export interface ReportingObjectWriteAuthorityStoreV1 extends ReportingObjectWriteStoreV1 {
63
+ probeObjectWriteAuthority(context?: ReportingObjectWriteContextV1): Promise<boolean>;
64
+ getObjectWriteAuthorityId(context?: ReportingObjectWriteContextV1): Promise<string>;
65
+ getAuthorizedObjectWriteBinding(scope: ReportingObjectWriteScopeV1, context?: ReportingObjectWriteContextV1): Promise<ReportingObjectWriteBindingV1 | null>;
66
+ getObjectWritePlan(scope: ReportingObjectWriteScopeV1, planId: string, context?: ReportingObjectWriteContextV1): Promise<ReportingObjectWritePlanV1 | null>;
67
+ }
68
+ /** PostgreSQL 13+; apply after REPORTING_OBJECT_WRITE_MIGRATION. Identity survives replica/worker restart. */
69
+ export declare const REPORTING_OBJECT_WRITE_AUTHORITY_MIGRATION = "\nCREATE TABLE IF NOT EXISTS adcp_reporting_object_write_authority (\n singleton BOOLEAN PRIMARY KEY DEFAULT TRUE CHECK (singleton),\n installation_id UUID NOT NULL DEFAULT gen_random_uuid(),\n schema_version INTEGER NOT NULL DEFAULT 1 CHECK (schema_version = 1)\n);\nINSERT INTO adcp_reporting_object_write_authority (singleton) VALUES (TRUE) ON CONFLICT DO NOTHING;\n";
@@ -0,0 +1,147 @@
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 object_writes_exports = {};
20
+ __export(object_writes_exports, {
21
+ REPORTING_OBJECT_WRITE_AUTHORITY_MIGRATION: () => REPORTING_OBJECT_WRITE_AUTHORITY_MIGRATION,
22
+ REPORTING_OBJECT_WRITE_MIGRATION: () => REPORTING_OBJECT_WRITE_MIGRATION,
23
+ ReportingObjectWriteConflictError: () => ReportingObjectWriteConflictError,
24
+ ReportingObjectWriteNotRevokedError: () => ReportingObjectWriteNotRevokedError,
25
+ assertReportingObjectWriteScope: () => assertReportingObjectWriteScope,
26
+ isReportingObjectWriteConflictError: () => isReportingObjectWriteConflictError,
27
+ isReportingObjectWriteNotRevokedError: () => isReportingObjectWriteNotRevokedError,
28
+ reportingObjectWriteName: () => reportingObjectWriteName,
29
+ reportingObjectWritePlanFingerprint: () => reportingObjectWritePlanFingerprint,
30
+ reportingObjectWriteScopeKey: () => reportingObjectWriteScopeKey
31
+ });
32
+ module.exports = __toCommonJS(object_writes_exports);
33
+ var import_node_crypto = require("node:crypto");
34
+ var import_jcs = require('../../utils/jcs.js');
35
+ class ReportingObjectWriteConflictError extends Error {
36
+ constructor() {
37
+ super("Reporting object-write plan conflict");
38
+ this.name = "ReportingObjectWriteConflictError";
39
+ Object.defineProperty(this, /* @__PURE__ */ Symbol.for("adcp.reporting.objectWriteConflict"), { value: true });
40
+ }
41
+ }
42
+ function isReportingObjectWriteConflictError(error) {
43
+ return !!error && typeof error === "object" && error[/* @__PURE__ */ Symbol.for("adcp.reporting.objectWriteConflict")] === true;
44
+ }
45
+ class ReportingObjectWriteNotRevokedError extends Error {
46
+ constructor() {
47
+ super("Reporting object-write generation is not revoked");
48
+ this.name = "ReportingObjectWriteNotRevokedError";
49
+ Object.defineProperty(this, /* @__PURE__ */ Symbol.for("adcp.reporting.objectWriteNotRevoked"), { value: true });
50
+ }
51
+ }
52
+ function isReportingObjectWriteNotRevokedError(error) {
53
+ return !!error && typeof error === "object" && error[/* @__PURE__ */ Symbol.for("adcp.reporting.objectWriteNotRevoked")] === true;
54
+ }
55
+ function reportingObjectWriteScopeKey(scope) {
56
+ assertReportingObjectWriteScope(scope);
57
+ return (0, import_node_crypto.createHash)("sha256").update(JSON.stringify([scope.account_id, scope.destination_ref, scope.generation])).digest("hex");
58
+ }
59
+ function reportingObjectWriteName(scope, binding, planId, index) {
60
+ return `adcp-reporting/${binding.namespace_key}/${reportingObjectWriteScopeKey(scope)}/${planId}/${index}`;
61
+ }
62
+ const REPORTING_OBJECT_WRITE_MIGRATION = `
63
+ CREATE TABLE IF NOT EXISTS adcp_reporting_object_write_bindings (
64
+ account_id TEXT NOT NULL,
65
+ destination_ref TEXT NOT NULL,
66
+ generation BIGINT NOT NULL,
67
+ bucket TEXT NOT NULL,
68
+ namespace_key TEXT NOT NULL CHECK (namespace_key ~ '^[a-f0-9]{64}$'),
69
+ PRIMARY KEY (account_id, destination_ref, generation),
70
+ FOREIGN KEY (account_id, destination_ref, generation)
71
+ REFERENCES adcp_reporting_destination_authorizations(account_id, destination_ref, generation)
72
+ );
73
+ CREATE TABLE IF NOT EXISTS adcp_reporting_object_write_plans (
74
+ account_id TEXT NOT NULL,
75
+ destination_ref TEXT NOT NULL,
76
+ generation BIGINT NOT NULL,
77
+ plan_id TEXT NOT NULL CHECK (plan_id ~ '^[a-f0-9]{64}$'),
78
+ fingerprint TEXT NOT NULL,
79
+ PRIMARY KEY (account_id, destination_ref, generation, plan_id),
80
+ FOREIGN KEY (account_id, destination_ref, generation)
81
+ REFERENCES adcp_reporting_destination_authorizations(account_id, destination_ref, generation)
82
+ );
83
+ CREATE TABLE IF NOT EXISTS adcp_reporting_object_writes (
84
+ account_id TEXT NOT NULL,
85
+ destination_ref TEXT NOT NULL,
86
+ generation BIGINT NOT NULL,
87
+ plan_id TEXT NOT NULL,
88
+ object_index INTEGER NOT NULL CHECK (object_index >= 0 AND object_index < 128),
89
+ bucket TEXT NOT NULL,
90
+ object_name TEXT NOT NULL,
91
+ sha256 TEXT NOT NULL CHECK (sha256 ~ '^[a-f0-9]{64}$'),
92
+ size_bytes BIGINT NOT NULL CHECK (size_bytes >= 0 AND size_bytes <= 67108864),
93
+ fenced_at TIMESTAMPTZ,
94
+ tombstone_generation TEXT,
95
+ PRIMARY KEY (account_id, destination_ref, generation, plan_id, object_index),
96
+ UNIQUE (bucket, object_name),
97
+ FOREIGN KEY (account_id, destination_ref, generation, plan_id)
98
+ REFERENCES adcp_reporting_object_write_plans(account_id, destination_ref, generation, plan_id)
99
+ );
100
+ `;
101
+ function assertReportingObjectWriteScope(scope) {
102
+ if (!scope || ![scope.account_id, scope.destination_ref].every((v) => typeof v === "string" && v.length > 0 && v.length <= 255) || !Number.isSafeInteger(scope.generation) || scope.generation < 1)
103
+ throw new Error("Invalid reporting object-write scope");
104
+ }
105
+ function reportingObjectWritePlanFingerprint(plan) {
106
+ assertReportingObjectWriteScope(plan);
107
+ if (!plan.provider || typeof plan.provider.bucket !== "string" || !/^[a-z0-9][a-z0-9.-]{1,220}[a-z0-9]$/.test(plan.provider.bucket) || typeof plan.provider.namespace_key !== "string" || !/^[a-f0-9]{64}$/.test(plan.provider.namespace_key) || typeof plan.plan_id !== "string" || !/^[a-f0-9]{64}$/.test(plan.plan_id) || !Array.isArray(plan.objects) || plan.objects.length < 1 || plan.objects.length > 128 || plan.objects.some(
108
+ (o, i) => !o || typeof o.bucket !== "string" || !/^[a-z0-9][a-z0-9.-]{1,220}[a-z0-9]$/.test(o.bucket) || o.bucket !== plan.provider.bucket || o.object_name !== reportingObjectWriteName(plan, plan.provider, plan.plan_id, i) || typeof o.object_name !== "string" || !/^[A-Za-z0-9/_-]{1,1024}$/.test(o.object_name) || typeof o.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(o.sha256) || !Number.isSafeInteger(o.size_bytes) || o.size_bytes < 0 || o.size_bytes > 64 * 1024 * 1024
109
+ ) || plan.objects.reduce((total, o) => total + o.size_bytes, 0) > 64 * 1024 * 1024 || new Set(plan.objects.map((o) => JSON.stringify([o.bucket, o.object_name]))).size !== plan.objects.length)
110
+ throw new Error("Invalid reporting object-write plan");
111
+ return (0, import_node_crypto.createHash)("sha256").update(
112
+ (0, import_jcs.canonicalize)({
113
+ account_id: plan.account_id,
114
+ destination_ref: plan.destination_ref,
115
+ generation: plan.generation,
116
+ plan_id: plan.plan_id,
117
+ provider: { bucket: plan.provider.bucket, namespace_key: plan.provider.namespace_key },
118
+ objects: plan.objects.map(({ bucket, object_name, sha256, size_bytes }) => ({
119
+ bucket,
120
+ object_name,
121
+ sha256,
122
+ size_bytes
123
+ }))
124
+ })
125
+ ).digest("hex");
126
+ }
127
+ const REPORTING_OBJECT_WRITE_AUTHORITY_MIGRATION = `
128
+ CREATE TABLE IF NOT EXISTS adcp_reporting_object_write_authority (
129
+ singleton BOOLEAN PRIMARY KEY DEFAULT TRUE CHECK (singleton),
130
+ installation_id UUID NOT NULL DEFAULT gen_random_uuid(),
131
+ schema_version INTEGER NOT NULL DEFAULT 1 CHECK (schema_version = 1)
132
+ );
133
+ INSERT INTO adcp_reporting_object_write_authority (singleton) VALUES (TRUE) ON CONFLICT DO NOTHING;
134
+ `;
135
+ // Annotate the CommonJS export names for ESM import in node:
136
+ 0 && (module.exports = {
137
+ REPORTING_OBJECT_WRITE_AUTHORITY_MIGRATION,
138
+ REPORTING_OBJECT_WRITE_MIGRATION,
139
+ ReportingObjectWriteConflictError,
140
+ ReportingObjectWriteNotRevokedError,
141
+ assertReportingObjectWriteScope,
142
+ isReportingObjectWriteConflictError,
143
+ isReportingObjectWriteNotRevokedError,
144
+ reportingObjectWriteName,
145
+ reportingObjectWritePlanFingerprint,
146
+ reportingObjectWriteScopeKey
147
+ });
@@ -0,0 +1,114 @@
1
+ import { createHash } from "node:crypto";
2
+ import { canonicalize } from "../../utils/jcs.mjs";
3
+ class ReportingObjectWriteConflictError extends Error {
4
+ constructor() {
5
+ super("Reporting object-write plan conflict");
6
+ this.name = "ReportingObjectWriteConflictError";
7
+ Object.defineProperty(this, /* @__PURE__ */ Symbol.for("adcp.reporting.objectWriteConflict"), { value: true });
8
+ }
9
+ }
10
+ function isReportingObjectWriteConflictError(error) {
11
+ return !!error && typeof error === "object" && error[/* @__PURE__ */ Symbol.for("adcp.reporting.objectWriteConflict")] === true;
12
+ }
13
+ class ReportingObjectWriteNotRevokedError extends Error {
14
+ constructor() {
15
+ super("Reporting object-write generation is not revoked");
16
+ this.name = "ReportingObjectWriteNotRevokedError";
17
+ Object.defineProperty(this, /* @__PURE__ */ Symbol.for("adcp.reporting.objectWriteNotRevoked"), { value: true });
18
+ }
19
+ }
20
+ function isReportingObjectWriteNotRevokedError(error) {
21
+ return !!error && typeof error === "object" && error[/* @__PURE__ */ Symbol.for("adcp.reporting.objectWriteNotRevoked")] === true;
22
+ }
23
+ function reportingObjectWriteScopeKey(scope) {
24
+ assertReportingObjectWriteScope(scope);
25
+ return createHash("sha256").update(JSON.stringify([scope.account_id, scope.destination_ref, scope.generation])).digest("hex");
26
+ }
27
+ function reportingObjectWriteName(scope, binding, planId, index) {
28
+ return `adcp-reporting/${binding.namespace_key}/${reportingObjectWriteScopeKey(scope)}/${planId}/${index}`;
29
+ }
30
+ const REPORTING_OBJECT_WRITE_MIGRATION = `
31
+ CREATE TABLE IF NOT EXISTS adcp_reporting_object_write_bindings (
32
+ account_id TEXT NOT NULL,
33
+ destination_ref TEXT NOT NULL,
34
+ generation BIGINT NOT NULL,
35
+ bucket TEXT NOT NULL,
36
+ namespace_key TEXT NOT NULL CHECK (namespace_key ~ '^[a-f0-9]{64}$'),
37
+ PRIMARY KEY (account_id, destination_ref, generation),
38
+ FOREIGN KEY (account_id, destination_ref, generation)
39
+ REFERENCES adcp_reporting_destination_authorizations(account_id, destination_ref, generation)
40
+ );
41
+ CREATE TABLE IF NOT EXISTS adcp_reporting_object_write_plans (
42
+ account_id TEXT NOT NULL,
43
+ destination_ref TEXT NOT NULL,
44
+ generation BIGINT NOT NULL,
45
+ plan_id TEXT NOT NULL CHECK (plan_id ~ '^[a-f0-9]{64}$'),
46
+ fingerprint TEXT NOT NULL,
47
+ PRIMARY KEY (account_id, destination_ref, generation, plan_id),
48
+ FOREIGN KEY (account_id, destination_ref, generation)
49
+ REFERENCES adcp_reporting_destination_authorizations(account_id, destination_ref, generation)
50
+ );
51
+ CREATE TABLE IF NOT EXISTS adcp_reporting_object_writes (
52
+ account_id TEXT NOT NULL,
53
+ destination_ref TEXT NOT NULL,
54
+ generation BIGINT NOT NULL,
55
+ plan_id TEXT NOT NULL,
56
+ object_index INTEGER NOT NULL CHECK (object_index >= 0 AND object_index < 128),
57
+ bucket TEXT NOT NULL,
58
+ object_name TEXT NOT NULL,
59
+ sha256 TEXT NOT NULL CHECK (sha256 ~ '^[a-f0-9]{64}$'),
60
+ size_bytes BIGINT NOT NULL CHECK (size_bytes >= 0 AND size_bytes <= 67108864),
61
+ fenced_at TIMESTAMPTZ,
62
+ tombstone_generation TEXT,
63
+ PRIMARY KEY (account_id, destination_ref, generation, plan_id, object_index),
64
+ UNIQUE (bucket, object_name),
65
+ FOREIGN KEY (account_id, destination_ref, generation, plan_id)
66
+ REFERENCES adcp_reporting_object_write_plans(account_id, destination_ref, generation, plan_id)
67
+ );
68
+ `;
69
+ function assertReportingObjectWriteScope(scope) {
70
+ if (!scope || ![scope.account_id, scope.destination_ref].every((v) => typeof v === "string" && v.length > 0 && v.length <= 255) || !Number.isSafeInteger(scope.generation) || scope.generation < 1)
71
+ throw new Error("Invalid reporting object-write scope");
72
+ }
73
+ function reportingObjectWritePlanFingerprint(plan) {
74
+ assertReportingObjectWriteScope(plan);
75
+ if (!plan.provider || typeof plan.provider.bucket !== "string" || !/^[a-z0-9][a-z0-9.-]{1,220}[a-z0-9]$/.test(plan.provider.bucket) || typeof plan.provider.namespace_key !== "string" || !/^[a-f0-9]{64}$/.test(plan.provider.namespace_key) || typeof plan.plan_id !== "string" || !/^[a-f0-9]{64}$/.test(plan.plan_id) || !Array.isArray(plan.objects) || plan.objects.length < 1 || plan.objects.length > 128 || plan.objects.some(
76
+ (o, i) => !o || typeof o.bucket !== "string" || !/^[a-z0-9][a-z0-9.-]{1,220}[a-z0-9]$/.test(o.bucket) || o.bucket !== plan.provider.bucket || o.object_name !== reportingObjectWriteName(plan, plan.provider, plan.plan_id, i) || typeof o.object_name !== "string" || !/^[A-Za-z0-9/_-]{1,1024}$/.test(o.object_name) || typeof o.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(o.sha256) || !Number.isSafeInteger(o.size_bytes) || o.size_bytes < 0 || o.size_bytes > 64 * 1024 * 1024
77
+ ) || plan.objects.reduce((total, o) => total + o.size_bytes, 0) > 64 * 1024 * 1024 || new Set(plan.objects.map((o) => JSON.stringify([o.bucket, o.object_name]))).size !== plan.objects.length)
78
+ throw new Error("Invalid reporting object-write plan");
79
+ return createHash("sha256").update(
80
+ canonicalize({
81
+ account_id: plan.account_id,
82
+ destination_ref: plan.destination_ref,
83
+ generation: plan.generation,
84
+ plan_id: plan.plan_id,
85
+ provider: { bucket: plan.provider.bucket, namespace_key: plan.provider.namespace_key },
86
+ objects: plan.objects.map(({ bucket, object_name, sha256, size_bytes }) => ({
87
+ bucket,
88
+ object_name,
89
+ sha256,
90
+ size_bytes
91
+ }))
92
+ })
93
+ ).digest("hex");
94
+ }
95
+ const REPORTING_OBJECT_WRITE_AUTHORITY_MIGRATION = `
96
+ CREATE TABLE IF NOT EXISTS adcp_reporting_object_write_authority (
97
+ singleton BOOLEAN PRIMARY KEY DEFAULT TRUE CHECK (singleton),
98
+ installation_id UUID NOT NULL DEFAULT gen_random_uuid(),
99
+ schema_version INTEGER NOT NULL DEFAULT 1 CHECK (schema_version = 1)
100
+ );
101
+ INSERT INTO adcp_reporting_object_write_authority (singleton) VALUES (TRUE) ON CONFLICT DO NOTHING;
102
+ `;
103
+ export {
104
+ REPORTING_OBJECT_WRITE_AUTHORITY_MIGRATION,
105
+ REPORTING_OBJECT_WRITE_MIGRATION,
106
+ ReportingObjectWriteConflictError,
107
+ ReportingObjectWriteNotRevokedError,
108
+ assertReportingObjectWriteScope,
109
+ isReportingObjectWriteConflictError,
110
+ isReportingObjectWriteNotRevokedError,
111
+ reportingObjectWriteName,
112
+ reportingObjectWritePlanFingerprint,
113
+ reportingObjectWriteScopeKey
114
+ };
@@ -4,5 +4,5 @@
4
4
  "source_sha": "4e553ad955f83b49c7d221ab5c3ff78237ad02e3",
5
5
  "source_tarball_sha256": "580656d6466ef9f0d1119985e6726c2efea718dc671e2ad30957fcb2fd54af0f",
6
6
  "upstream_adcp_version": "2.5.3",
7
- "synced_at": "2026-10-07T00:14:46.446Z"
7
+ "synced_at": "2026-10-07T16:17:49.392Z"
8
8
  }
@@ -53,8 +53,9 @@ import { type TaskStore } from '@a2a-js/sdk/server';
53
53
  import { AgentCard } from '@a2a-js/sdk';
54
54
  import type { AgentCapabilities, AgentProvider, AgentSkill, SecurityScheme } from '@a2a-js/sdk';
55
55
  import type { Request, RequestHandler } from 'express';
56
+ import type { IncomingMessage } from 'node:http';
56
57
  import { type AdcpAuthInfo, type AdcpServer } from './adcp-server.mjs';
57
- import type { AdcpLogger } from './create-adcp-server.mjs';
58
+ import { type AdcpLogger, type AdcpPreTransport } from './create-adcp-server.mjs';
58
59
  import type { A2ALegacyCompatOptions } from '../protocols/a2a.mjs';
59
60
  /**
60
61
  * Agent-card identity fields the adapter can't derive automatically.
@@ -185,6 +186,48 @@ export interface A2AAdapterOptions {
185
186
  * Set `enabled: false` to expose only the native A2A 1.0 path.
186
187
  */
187
188
  legacyCompat?: A2ALegacyCompatOptions;
189
+ /**
190
+ * RFC 9421 request-signature gate for the JSON-RPC endpoint. Defaults to the
191
+ * verifier that `createAdcpServer({ signedRequests })` attaches to `server`,
192
+ * so a seller that configures `signedRequests` enforces `required_for`,
193
+ * `protocol_methods_required_for` and the webhook-authentication rule over
194
+ * A2A exactly as it does over MCP. Pass it explicitly when you wired the
195
+ * verifier by hand (`serve({ preTransport })`).
196
+ *
197
+ * The gate runs on every `POST` to the JSON-RPC endpoint, before
198
+ * {@link A2AAdapterOptions.authenticate}. The adapter buffers the request
199
+ * body itself so the gate sees the exact signed bytes, resolves the AdCP
200
+ * operation from the Message's sole DataPart (`skill`), and rejects a body
201
+ * that does not resolve to exactly one operation with `request_body_malformed`
202
+ * before any handler runs. The dispatcher then runs only that operation.
203
+ * Unlike `authenticate`, a gate rejection is an HTTP 401 carrying
204
+ * `WWW-Authenticate: Signature error="<code>"`.
205
+ *
206
+ * A verified signature is surfaced to handlers as `ctx.authInfo`
207
+ * (`clientId: signing:<keyid>`). When `authenticate` is also set, its result
208
+ * stays authoritative and must carry the same `clientId`.
209
+ *
210
+ * Body capture: do not mount a body parser ahead of the adapter unless it
211
+ * records the raw bytes (`express.json({ verify: adapter.rawBodyVerify })`);
212
+ * a request whose raw body is unavailable is rejected.
213
+ */
214
+ preTransport?: AdcpPreTransport;
215
+ /**
216
+ * Canonical URL a client signed for this request (the signature's
217
+ * `@target-uri`). Defaults to the origin of `agentCard.url` plus the request's
218
+ * original path and query. Override when a path-rewriting proxy changes the
219
+ * path between the client and this process. Never derive it from a
220
+ * client-controlled `Host` / `X-Forwarded-*` header.
221
+ */
222
+ signedRequestsUrl?: (req: Request) => string;
223
+ /**
224
+ * Acknowledge that a seller advertising `signed-requests` / `request_signing`
225
+ * is not verifying signatures on this adapter (for example, an authenticating
226
+ * gateway in front of it does). Without this, `createA2AAdapter` refuses to
227
+ * construct when `server` advertises request signing but no gate is wired,
228
+ * because the advertisement would be false for A2A.
229
+ */
230
+ allowUnenforcedSignedRequests?: boolean;
188
231
  }
189
232
  /** Minimal Express app surface the adapter's `mount()` helper needs. */
190
233
  export interface ExpressAppLike {
@@ -227,6 +270,12 @@ export interface A2AAdapter {
227
270
  agentCardHandler: RequestHandler;
228
271
  /** Returns the merged, validated agent card. */
229
272
  getAgentCard(): Promise<AgentCard>;
273
+ /**
274
+ * `verify` hook for `express.json({ verify })` that records the exact request
275
+ * bytes on `req.rawBody`. Use it when a body parser must run ahead of the
276
+ * adapter on a signed-requests deployment.
277
+ */
278
+ rawBodyVerify: (req: IncomingMessage, res: unknown, buf: Buffer) => void;
230
279
  /**
231
280
  * Wire all A2A routes onto an Express-compatible app in one call.
232
281
  * Eliminates the "card mounted at only one location" footgun: the
@@ -53,8 +53,9 @@ import { type TaskStore } from '@a2a-js/sdk/server';
53
53
  import { AgentCard } from '@a2a-js/sdk';
54
54
  import type { AgentCapabilities, AgentProvider, AgentSkill, SecurityScheme } from '@a2a-js/sdk';
55
55
  import type { Request, RequestHandler } from 'express';
56
+ import type { IncomingMessage } from 'node:http';
56
57
  import { type AdcpAuthInfo, type AdcpServer } from './adcp-server';
57
- import type { AdcpLogger } from './create-adcp-server';
58
+ import { type AdcpLogger, type AdcpPreTransport } from './create-adcp-server';
58
59
  import type { A2ALegacyCompatOptions } from '../protocols/a2a';
59
60
  /**
60
61
  * Agent-card identity fields the adapter can't derive automatically.
@@ -185,6 +186,48 @@ export interface A2AAdapterOptions {
185
186
  * Set `enabled: false` to expose only the native A2A 1.0 path.
186
187
  */
187
188
  legacyCompat?: A2ALegacyCompatOptions;
189
+ /**
190
+ * RFC 9421 request-signature gate for the JSON-RPC endpoint. Defaults to the
191
+ * verifier that `createAdcpServer({ signedRequests })` attaches to `server`,
192
+ * so a seller that configures `signedRequests` enforces `required_for`,
193
+ * `protocol_methods_required_for` and the webhook-authentication rule over
194
+ * A2A exactly as it does over MCP. Pass it explicitly when you wired the
195
+ * verifier by hand (`serve({ preTransport })`).
196
+ *
197
+ * The gate runs on every `POST` to the JSON-RPC endpoint, before
198
+ * {@link A2AAdapterOptions.authenticate}. The adapter buffers the request
199
+ * body itself so the gate sees the exact signed bytes, resolves the AdCP
200
+ * operation from the Message's sole DataPart (`skill`), and rejects a body
201
+ * that does not resolve to exactly one operation with `request_body_malformed`
202
+ * before any handler runs. The dispatcher then runs only that operation.
203
+ * Unlike `authenticate`, a gate rejection is an HTTP 401 carrying
204
+ * `WWW-Authenticate: Signature error="<code>"`.
205
+ *
206
+ * A verified signature is surfaced to handlers as `ctx.authInfo`
207
+ * (`clientId: signing:<keyid>`). When `authenticate` is also set, its result
208
+ * stays authoritative and must carry the same `clientId`.
209
+ *
210
+ * Body capture: do not mount a body parser ahead of the adapter unless it
211
+ * records the raw bytes (`express.json({ verify: adapter.rawBodyVerify })`);
212
+ * a request whose raw body is unavailable is rejected.
213
+ */
214
+ preTransport?: AdcpPreTransport;
215
+ /**
216
+ * Canonical URL a client signed for this request (the signature's
217
+ * `@target-uri`). Defaults to the origin of `agentCard.url` plus the request's
218
+ * original path and query. Override when a path-rewriting proxy changes the
219
+ * path between the client and this process. Never derive it from a
220
+ * client-controlled `Host` / `X-Forwarded-*` header.
221
+ */
222
+ signedRequestsUrl?: (req: Request) => string;
223
+ /**
224
+ * Acknowledge that a seller advertising `signed-requests` / `request_signing`
225
+ * is not verifying signatures on this adapter (for example, an authenticating
226
+ * gateway in front of it does). Without this, `createA2AAdapter` refuses to
227
+ * construct when `server` advertises request signing but no gate is wired,
228
+ * because the advertisement would be false for A2A.
229
+ */
230
+ allowUnenforcedSignedRequests?: boolean;
188
231
  }
189
232
  /** Minimal Express app surface the adapter's `mount()` helper needs. */
190
233
  export interface ExpressAppLike {
@@ -227,6 +270,12 @@ export interface A2AAdapter {
227
270
  agentCardHandler: RequestHandler;
228
271
  /** Returns the merged, validated agent card. */
229
272
  getAgentCard(): Promise<AgentCard>;
273
+ /**
274
+ * `verify` hook for `express.json({ verify })` that records the exact request
275
+ * bytes on `req.rawBody`. Use it when a body parser must run ahead of the
276
+ * adapter on a signed-requests deployment.
277
+ */
278
+ rawBodyVerify: (req: IncomingMessage, res: unknown, buf: Buffer) => void;
230
279
  /**
231
280
  * Wire all A2A routes onto an Express-compatible app in one call.
232
281
  * Eliminates the "card mounted at only one location" footgun: the