@adcp/sdk 16.0.0-beta.1 → 16.0.0-beta.3

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 (155) hide show
  1. package/README.md +54 -0
  2. package/dist/lib/core/ConversationTypes.d.mts +8 -3
  3. package/dist/lib/core/ConversationTypes.d.ts +8 -3
  4. package/dist/lib/core/SingleAgentClient.d.mts +15 -4
  5. package/dist/lib/core/SingleAgentClient.d.ts +15 -4
  6. package/dist/lib/core/SingleAgentClient.js +29 -8
  7. package/dist/lib/core/SingleAgentClient.mjs +29 -8
  8. package/dist/lib/core/TaskExecutor.js +5 -1
  9. package/dist/lib/core/TaskExecutor.mjs +5 -1
  10. package/dist/lib/errors/index.d.mts +9 -4
  11. package/dist/lib/errors/index.d.ts +9 -4
  12. package/dist/lib/identity-3.3/generated-compat.d.mts +34 -0
  13. package/dist/lib/identity-3.3/generated-compat.d.ts +34 -0
  14. package/dist/lib/identity-3.3/generated-compat.js +16 -0
  15. package/dist/lib/identity-3.3/generated-compat.mjs +0 -0
  16. package/dist/lib/identity-3.3/index.d.mts +2 -2
  17. package/dist/lib/identity-3.3/index.d.ts +2 -2
  18. package/dist/lib/identity-3.3/index.js +4 -0
  19. package/dist/lib/identity-3.3/index.mjs +5 -1
  20. package/dist/lib/identity-3.3/lifecycle.d.mts +17 -5
  21. package/dist/lib/identity-3.3/lifecycle.d.ts +17 -5
  22. package/dist/lib/identity-3.3/lifecycle.js +32 -5
  23. package/dist/lib/identity-3.3/lifecycle.mjs +38 -6
  24. package/dist/lib/identity-3.3/revocation.d.mts +39 -3
  25. package/dist/lib/identity-3.3/revocation.d.ts +39 -3
  26. package/dist/lib/identity-3.3/revocation.js +88 -18
  27. package/dist/lib/identity-3.3/revocation.mjs +89 -19
  28. package/dist/lib/identity-3.3/server.d.mts +12 -0
  29. package/dist/lib/identity-3.3/server.d.ts +12 -0
  30. package/dist/lib/identity-3.3/server.js +103 -43
  31. package/dist/lib/identity-3.3/server.mjs +111 -45
  32. package/dist/lib/identity-3.3/trust.d.mts +62 -1
  33. package/dist/lib/identity-3.3/trust.d.ts +62 -1
  34. package/dist/lib/identity-3.3/trust.js +126 -21
  35. package/dist/lib/identity-3.3/trust.mjs +124 -21
  36. package/dist/lib/identity-3.3/types.d.mts +39 -11
  37. package/dist/lib/identity-3.3/types.d.ts +39 -11
  38. package/dist/lib/index.d.mts +3 -3
  39. package/dist/lib/index.d.ts +3 -3
  40. package/dist/lib/index.js +8 -0
  41. package/dist/lib/index.mjs +9 -1
  42. package/dist/lib/negotiation/types.d.mts +20 -39
  43. package/dist/lib/negotiation/types.d.ts +20 -39
  44. package/dist/lib/protocols/index.d.mts +61 -25
  45. package/dist/lib/protocols/index.d.ts +61 -25
  46. package/dist/lib/protocols/index.js +11 -6
  47. package/dist/lib/protocols/index.mjs +5 -2
  48. package/dist/lib/protocols/mcp-modern.js +1 -0
  49. package/dist/lib/protocols/mcp-modern.mjs +2 -1
  50. package/dist/lib/protocols/mcp.js +1 -0
  51. package/dist/lib/protocols/mcp.mjs +2 -1
  52. package/dist/lib/protocols/responseSizeLimit.d.mts +91 -5
  53. package/dist/lib/protocols/responseSizeLimit.d.ts +91 -5
  54. package/dist/lib/protocols/responseSizeLimit.js +195 -31
  55. package/dist/lib/protocols/responseSizeLimit.mjs +192 -31
  56. package/dist/lib/reporting/bigquery/index.js +8 -0
  57. package/dist/lib/reporting/bigquery/index.mjs +8 -0
  58. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  59. package/dist/lib/server/auth-signature.d.mts +6 -1
  60. package/dist/lib/server/auth-signature.d.ts +6 -1
  61. package/dist/lib/server/auth-signature.js +24 -13
  62. package/dist/lib/server/auth-signature.mjs +29 -13
  63. package/dist/lib/server/auth.d.mts +2 -2
  64. package/dist/lib/server/auth.d.ts +2 -2
  65. package/dist/lib/server/create-adcp-server.js +31 -10
  66. package/dist/lib/server/create-adcp-server.mjs +37 -11
  67. package/dist/lib/signing/crypto.d.mts +15 -0
  68. package/dist/lib/signing/crypto.d.ts +15 -0
  69. package/dist/lib/signing/crypto.js +83 -3
  70. package/dist/lib/signing/crypto.mjs +86 -3
  71. package/dist/lib/signing/fetch-async.js +1 -1
  72. package/dist/lib/signing/fetch-async.mjs +1 -1
  73. package/dist/lib/signing/fetch.js +1 -1
  74. package/dist/lib/signing/fetch.mjs +1 -1
  75. package/dist/lib/signing/middleware.js +9 -0
  76. package/dist/lib/signing/middleware.mjs +14 -0
  77. package/dist/lib/signing/parser.d.mts +8 -5
  78. package/dist/lib/signing/parser.d.ts +8 -5
  79. package/dist/lib/signing/parser.js +77 -61
  80. package/dist/lib/signing/parser.mjs +77 -61
  81. package/dist/lib/signing/revocation.js +3 -0
  82. package/dist/lib/signing/revocation.mjs +3 -0
  83. package/dist/lib/signing/server.d.mts +1 -1
  84. package/dist/lib/signing/server.d.ts +1 -1
  85. package/dist/lib/signing/server.js +2 -0
  86. package/dist/lib/signing/server.mjs +2 -1
  87. package/dist/lib/signing/signer.js +2 -8
  88. package/dist/lib/signing/signer.mjs +3 -9
  89. package/dist/lib/signing/testing.js +2 -6
  90. package/dist/lib/signing/testing.mjs +3 -7
  91. package/dist/lib/signing/verifier.js +3 -3
  92. package/dist/lib/signing/verifier.mjs +4 -4
  93. package/dist/lib/signing/web-bot-auth.d.mts +84 -10
  94. package/dist/lib/signing/web-bot-auth.d.ts +84 -10
  95. package/dist/lib/signing/web-bot-auth.js +278 -88
  96. package/dist/lib/signing/web-bot-auth.mjs +279 -94
  97. package/dist/lib/signing/webhook-verifier.js +3 -3
  98. package/dist/lib/signing/webhook-verifier.mjs +4 -4
  99. package/dist/lib/substitution/compile.js +2 -1
  100. package/dist/lib/substitution/compile.mjs +2 -1
  101. package/dist/lib/substitution/consent-macros.d.mts +4 -0
  102. package/dist/lib/substitution/consent-macros.d.ts +4 -0
  103. package/dist/lib/substitution/consent-macros.js +45 -0
  104. package/dist/lib/substitution/consent-macros.mjs +20 -0
  105. package/dist/lib/substitution/index.d.mts +1 -1
  106. package/dist/lib/substitution/index.d.ts +1 -1
  107. package/dist/lib/substitution/index.js +2 -0
  108. package/dist/lib/substitution/index.mjs +2 -1
  109. package/dist/lib/substitution/translate.d.mts +15 -2
  110. package/dist/lib/substitution/translate.d.ts +15 -2
  111. package/dist/lib/substitution/translate.js +148 -26
  112. package/dist/lib/substitution/translate.mjs +147 -26
  113. package/dist/lib/testing/client.js +2 -1
  114. package/dist/lib/testing/client.mjs +2 -1
  115. package/dist/lib/testing/scenarios/capabilities.js +1 -1
  116. package/dist/lib/testing/scenarios/capabilities.mjs +1 -1
  117. package/dist/lib/testing/storyboard/request-signing/builder.js +2 -5
  118. package/dist/lib/testing/storyboard/request-signing/builder.mjs +3 -6
  119. package/dist/lib/testing/storyboard/signer-grader/grader.js +2 -7
  120. package/dist/lib/testing/storyboard/signer-grader/grader.mjs +2 -7
  121. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  122. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  123. package/dist/lib/types/enums.generated.d.mts +3 -0
  124. package/dist/lib/types/enums.generated.d.ts +3 -0
  125. package/dist/lib/types/enums.generated.js +9 -0
  126. package/dist/lib/types/enums.generated.mjs +6 -0
  127. package/dist/lib/v2/projection/catalog-snapshot.js +3 -1
  128. package/dist/lib/v2/projection/catalog-snapshot.mjs +3 -1
  129. package/dist/lib/v2/projection/creative-delivery.d.mts +31 -9
  130. package/dist/lib/v2/projection/creative-delivery.d.ts +31 -9
  131. package/dist/lib/v2/projection/index.d.mts +1 -1
  132. package/dist/lib/v2/projection/index.d.ts +1 -1
  133. package/dist/lib/v2/projection/index.js +2 -0
  134. package/dist/lib/v2/projection/index.mjs +2 -0
  135. package/dist/lib/v2/projection/legacy-routes.d.mts +10 -0
  136. package/dist/lib/v2/projection/legacy-routes.d.ts +10 -0
  137. package/dist/lib/v2/projection/legacy-routes.js +7 -0
  138. package/dist/lib/v2/projection/legacy-routes.mjs +6 -0
  139. package/dist/lib/validation/schema-loader.js +25 -0
  140. package/dist/lib/validation/schema-loader.mjs +24 -0
  141. package/dist/lib/version.d.mts +3 -3
  142. package/dist/lib/version.d.ts +3 -3
  143. package/dist/lib/version.js +3 -3
  144. package/dist/lib/version.mjs +3 -3
  145. package/docs/TYPE-SUMMARY.md +7 -2
  146. package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +3 -2
  147. package/docs/guides/REPORTING-LEDGER.md +15 -5
  148. package/docs/guides/REPORTING-OPERATIONS.md +17 -11
  149. package/docs/guides/UNIVERSAL-MACRO-COMPILATION.md +38 -0
  150. package/docs/guides/VALIDATE-YOUR-AGENT.md +12 -0
  151. package/docs/llms.txt +2 -2
  152. package/docs/migration-12-to-13.md +8 -0
  153. package/docs/migration-14.x-rc-worksheet.md +4 -4
  154. package/docs/migration-agent-identity-3.3.md +150 -11
  155. package/package.json +4 -1
@@ -67,7 +67,7 @@ function bodyToString(body) {
67
67
  }
68
68
  function decodeUtf8Strict(bytes) {
69
69
  try {
70
- return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
70
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
71
71
  } catch {
72
72
  throw new TypeError(
73
73
  "createSigningFetch received a Uint8Array/ArrayBuffer body that is not valid UTF-8. Pass a string body, ensure the bytes are UTF-8, or sign the request manually with `signRequest` against the exact wire bytes you intend to send."
@@ -30,6 +30,15 @@ function createExpressVerifier(options) {
30
30
  const replayStore = options.replayStore ?? new import_replay.InMemoryReplayStore();
31
31
  const revocationStore = options.revocationStore ?? new import_revocation.InMemoryRevocationStore();
32
32
  return async function requestSignatureMiddleware(req, res, next) {
33
+ const { selectSignatureProfile, WebBotAuthError } = require('./web-bot-auth.js');
34
+ if (selectSignatureProfile({ headers: req.headers }) === "web-bot-auth") {
35
+ const refused = new WebBotAuthError(403, "profile_disabled");
36
+ res.status(refused.status).set("Cache-Control", "no-store").json({
37
+ ...refused.body,
38
+ message: "Web Bot Auth is not configured on this endpoint; use createAdcpServer signedRequests.webBotAuth or verifySignatureAsAuthenticator({ webBotAuth })"
39
+ });
40
+ return;
41
+ }
33
42
  try {
34
43
  const url = options.getUrl ? options.getUrl(req) : defaultUrl(req);
35
44
  const body = resolveRawBody(req);
@@ -1,3 +1,8 @@
1
+ import { fileURLToPath as __adcpFileURLToPath } from "node:url";
2
+ import { dirname as __adcpDirname } from "node:path";
3
+ import { createRequire as __adcpCreateRequire } from "node:module";
4
+ const __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));
5
+ const require2 = __adcpCreateRequire(import.meta.url);
1
6
  import { getHeaderValue } from "./canonicalize.mjs";
2
7
  import { RequestSignatureError } from "./errors.mjs";
3
8
  import { InMemoryReplayStore } from "./replay.mjs";
@@ -7,6 +12,15 @@ function createExpressVerifier(options) {
7
12
  const replayStore = options.replayStore ?? new InMemoryReplayStore();
8
13
  const revocationStore = options.revocationStore ?? new InMemoryRevocationStore();
9
14
  return async function requestSignatureMiddleware(req, res, next) {
15
+ const { selectSignatureProfile, WebBotAuthError } = require2("./web-bot-auth");
16
+ if (selectSignatureProfile({ headers: req.headers }) === "web-bot-auth") {
17
+ const refused = new WebBotAuthError(403, "profile_disabled");
18
+ res.status(refused.status).set("Cache-Control", "no-store").json({
19
+ ...refused.body,
20
+ message: "Web Bot Auth is not configured on this endpoint; use createAdcpServer signedRequests.webBotAuth or verifySignatureAsAuthenticator({ webBotAuth })"
21
+ });
22
+ return;
23
+ }
10
24
  try {
11
25
  const url = options.getUrl ? options.getUrl(req) : defaultUrl(req);
12
26
  const body = resolveRawBody(req);
@@ -26,10 +26,13 @@ export interface ParsedSignature {
26
26
  export declare function parseSignatureInput(headerValue: string, expectedLabel?: string): ParsedSignatureInput;
27
27
  export declare function parseSignature(headerValue: string, expectedLabel: string, encoding?: SfBinaryEncoding): ParsedSignature;
28
28
  /**
29
- * RFC 8941 §3.2 parsers deduplicate by keeping the last value. The AdCP
30
- * profile (step 1) overrides that: duplicate keys are a downgrade vector —
31
- * a proxy could smuggle a weaker component set past a verifier that reads
32
- * the first. Detect duplicates at the raw-header level before the library
33
- * silently drops them.
29
+ * RFC 8941 / RFC 9651 parsers deduplicate dictionary keys and parameter keys
30
+ * by keeping the last value. The AdCP profile (step 1) overrides that:
31
+ * duplicates are a cross-implementation differential and a downgrade vector
32
+ * (a proxy could smuggle a weaker component set or a different `created`,
33
+ * `keyid` or `tag` past a verifier that reads the first). Detect them at the
34
+ * raw-header level before the library silently drops them: top-level
35
+ * dictionary keys, parameters on members and inner lists, and parameters on
36
+ * each inner-list item.
34
37
  */
35
38
  export declare function rejectDuplicateDictionaryKeys(headerValue: string, headerName: string): void;
@@ -26,10 +26,13 @@ export interface ParsedSignature {
26
26
  export declare function parseSignatureInput(headerValue: string, expectedLabel?: string): ParsedSignatureInput;
27
27
  export declare function parseSignature(headerValue: string, expectedLabel: string, encoding?: SfBinaryEncoding): ParsedSignature;
28
28
  /**
29
- * RFC 8941 §3.2 parsers deduplicate by keeping the last value. The AdCP
30
- * profile (step 1) overrides that: duplicate keys are a downgrade vector —
31
- * a proxy could smuggle a weaker component set past a verifier that reads
32
- * the first. Detect duplicates at the raw-header level before the library
33
- * silently drops them.
29
+ * RFC 8941 / RFC 9651 parsers deduplicate dictionary keys and parameter keys
30
+ * by keeping the last value. The AdCP profile (step 1) overrides that:
31
+ * duplicates are a cross-implementation differential and a downgrade vector
32
+ * (a proxy could smuggle a weaker component set or a different `created`,
33
+ * `keyid` or `tag` past a verifier that reads the first). Detect them at the
34
+ * raw-header level before the library silently drops them: top-level
35
+ * dictionary keys, parameters on members and inner lists, and parameters on
36
+ * each inner-list item.
34
37
  */
35
38
  export declare function rejectDuplicateDictionaryKeys(headerValue: string, headerName: string): void;
@@ -111,85 +111,101 @@ function isInnerList(entry) {
111
111
  return Array.isArray(entry) && Array.isArray(entry[0]);
112
112
  }
113
113
  function rejectDuplicateDictionaryKeys(headerValue, headerName) {
114
- const keys = extractTopLevelDictKeys(headerValue);
115
- const seen = /* @__PURE__ */ new Set();
116
- for (const key of keys) {
117
- if (seen.has(key)) {
118
- malformed(`${headerName} header declares key "${key}" more than once`);
119
- }
120
- seen.add(key);
121
- }
114
+ const duplicate = findDuplicateStructuredKey(headerValue);
115
+ if (duplicate?.kind === "member") malformed(`${headerName} header declares key "${duplicate.key}" more than once`);
116
+ if (duplicate) malformed(`${headerName} header declares parameter "${duplicate.key}" more than once`);
122
117
  }
123
- function extractTopLevelDictKeys(input) {
124
- const keys = [];
118
+ function findDuplicateStructuredKey(input) {
125
119
  let i = 0;
126
- const len = input.length;
127
- let atEntryStart = true;
128
- while (i < len) {
129
- if (atEntryStart) {
130
- while (i < len && (input[i] === " " || input[i] === " ")) i++;
131
- const keyStart = i;
132
- while (i < len && /[A-Za-z0-9_*-]/.test(input[i])) i++;
133
- if (i > keyStart) keys.push(input.slice(keyStart, i).toLowerCase());
134
- atEntryStart = false;
135
- continue;
120
+ const n = input.length;
121
+ const ows = () => {
122
+ while (i < n && (input[i] === " " || input[i] === " ")) i++;
123
+ };
124
+ const key = () => {
125
+ const start = i;
126
+ while (i < n && /[A-Za-z0-9_.*-]/.test(input[i])) i++;
127
+ return input.slice(start, i).toLowerCase();
128
+ };
129
+ const bareItem = () => {
130
+ if (input[i] === "%" && input[i + 1] === '"') {
131
+ i += 2;
132
+ while (i < n && input[i] !== '"') i++;
133
+ i++;
134
+ return;
136
135
  }
137
- const ch = input[i];
138
- if (ch === '"') {
136
+ if (input[i] === '"') {
139
137
  i++;
140
- while (i < len) {
141
- if (input[i] === "\\" && i + 1 < len) {
138
+ while (i < n) {
139
+ if (input[i] === "\\") {
142
140
  i += 2;
143
141
  continue;
144
142
  }
145
- if (input[i] === '"') {
146
- i++;
147
- break;
148
- }
149
- i++;
143
+ if (input[i++] === '"') return;
150
144
  }
151
- continue;
145
+ return;
152
146
  }
153
- if (ch === ":") {
147
+ if (input[i] === ":") {
154
148
  i++;
155
- while (i < len && input[i] !== ":") i++;
156
- if (i < len) i++;
157
- continue;
149
+ while (i < n && input[i] !== ":") i++;
150
+ i++;
151
+ return;
158
152
  }
159
- if (ch === "(") {
153
+ while (i < n && !/[;,()\s"]/.test(input[i])) i++;
154
+ };
155
+ const parameters = () => {
156
+ const seen = /* @__PURE__ */ new Set();
157
+ while (i < n && input[i] === ";") {
160
158
  i++;
161
- let depth = 1;
162
- while (i < len && depth > 0) {
163
- const c = input[i];
164
- if (c === '"') {
165
- i++;
166
- while (i < len) {
167
- if (input[i] === "\\" && i + 1 < len) {
168
- i += 2;
169
- continue;
170
- }
171
- if (input[i] === '"') {
172
- i++;
173
- break;
174
- }
175
- i++;
176
- }
177
- continue;
178
- }
179
- if (c === "(") depth++;
180
- else if (c === ")") depth--;
159
+ ows();
160
+ const k = key();
161
+ if (!k) return void 0;
162
+ if (seen.has(k)) return k;
163
+ seen.add(k);
164
+ if (input[i] === "=") {
181
165
  i++;
166
+ bareItem();
182
167
  }
183
- continue;
184
168
  }
185
- if (ch === ",") {
186
- atEntryStart = true;
169
+ return void 0;
170
+ };
171
+ const members = /* @__PURE__ */ new Set();
172
+ while (i < n) {
173
+ ows();
174
+ const k = key();
175
+ if (!k) return void 0;
176
+ if (members.has(k)) return { kind: "member", key: k };
177
+ members.add(k);
178
+ let duplicate;
179
+ if (input[i] === "=") {
187
180
  i++;
188
- continue;
189
- }
181
+ if (input[i] === "(") {
182
+ i++;
183
+ for (; ; ) {
184
+ while (i < n && input[i] === " ") i++;
185
+ if (i >= n) return void 0;
186
+ if (input[i] === ")") {
187
+ i++;
188
+ break;
189
+ }
190
+ const before = i;
191
+ bareItem();
192
+ duplicate = parameters();
193
+ if (duplicate) return { kind: "parameter", key: `${k}: ${duplicate}` };
194
+ if (i === before) return void 0;
195
+ }
196
+ duplicate = parameters();
197
+ } else {
198
+ bareItem();
199
+ duplicate = parameters();
200
+ }
201
+ } else duplicate = parameters();
202
+ if (duplicate) return { kind: "parameter", key: `${k}: ${duplicate}` };
203
+ ows();
204
+ if (i >= n) return void 0;
205
+ if (input[i] !== ",") return void 0;
190
206
  i++;
191
207
  }
192
- return keys;
208
+ return void 0;
193
209
  }
194
210
  function normalizeByteSequenceBase64(input) {
195
211
  let out = "";
@@ -86,85 +86,101 @@ function isInnerList(entry) {
86
86
  return Array.isArray(entry) && Array.isArray(entry[0]);
87
87
  }
88
88
  function rejectDuplicateDictionaryKeys(headerValue, headerName) {
89
- const keys = extractTopLevelDictKeys(headerValue);
90
- const seen = /* @__PURE__ */ new Set();
91
- for (const key of keys) {
92
- if (seen.has(key)) {
93
- malformed(`${headerName} header declares key "${key}" more than once`);
94
- }
95
- seen.add(key);
96
- }
89
+ const duplicate = findDuplicateStructuredKey(headerValue);
90
+ if (duplicate?.kind === "member") malformed(`${headerName} header declares key "${duplicate.key}" more than once`);
91
+ if (duplicate) malformed(`${headerName} header declares parameter "${duplicate.key}" more than once`);
97
92
  }
98
- function extractTopLevelDictKeys(input) {
99
- const keys = [];
93
+ function findDuplicateStructuredKey(input) {
100
94
  let i = 0;
101
- const len = input.length;
102
- let atEntryStart = true;
103
- while (i < len) {
104
- if (atEntryStart) {
105
- while (i < len && (input[i] === " " || input[i] === " ")) i++;
106
- const keyStart = i;
107
- while (i < len && /[A-Za-z0-9_*-]/.test(input[i])) i++;
108
- if (i > keyStart) keys.push(input.slice(keyStart, i).toLowerCase());
109
- atEntryStart = false;
110
- continue;
95
+ const n = input.length;
96
+ const ows = () => {
97
+ while (i < n && (input[i] === " " || input[i] === " ")) i++;
98
+ };
99
+ const key = () => {
100
+ const start = i;
101
+ while (i < n && /[A-Za-z0-9_.*-]/.test(input[i])) i++;
102
+ return input.slice(start, i).toLowerCase();
103
+ };
104
+ const bareItem = () => {
105
+ if (input[i] === "%" && input[i + 1] === '"') {
106
+ i += 2;
107
+ while (i < n && input[i] !== '"') i++;
108
+ i++;
109
+ return;
111
110
  }
112
- const ch = input[i];
113
- if (ch === '"') {
111
+ if (input[i] === '"') {
114
112
  i++;
115
- while (i < len) {
116
- if (input[i] === "\\" && i + 1 < len) {
113
+ while (i < n) {
114
+ if (input[i] === "\\") {
117
115
  i += 2;
118
116
  continue;
119
117
  }
120
- if (input[i] === '"') {
121
- i++;
122
- break;
123
- }
124
- i++;
118
+ if (input[i++] === '"') return;
125
119
  }
126
- continue;
120
+ return;
127
121
  }
128
- if (ch === ":") {
122
+ if (input[i] === ":") {
129
123
  i++;
130
- while (i < len && input[i] !== ":") i++;
131
- if (i < len) i++;
132
- continue;
124
+ while (i < n && input[i] !== ":") i++;
125
+ i++;
126
+ return;
133
127
  }
134
- if (ch === "(") {
128
+ while (i < n && !/[;,()\s"]/.test(input[i])) i++;
129
+ };
130
+ const parameters = () => {
131
+ const seen = /* @__PURE__ */ new Set();
132
+ while (i < n && input[i] === ";") {
135
133
  i++;
136
- let depth = 1;
137
- while (i < len && depth > 0) {
138
- const c = input[i];
139
- if (c === '"') {
140
- i++;
141
- while (i < len) {
142
- if (input[i] === "\\" && i + 1 < len) {
143
- i += 2;
144
- continue;
145
- }
146
- if (input[i] === '"') {
147
- i++;
148
- break;
149
- }
150
- i++;
151
- }
152
- continue;
153
- }
154
- if (c === "(") depth++;
155
- else if (c === ")") depth--;
134
+ ows();
135
+ const k = key();
136
+ if (!k) return void 0;
137
+ if (seen.has(k)) return k;
138
+ seen.add(k);
139
+ if (input[i] === "=") {
156
140
  i++;
141
+ bareItem();
157
142
  }
158
- continue;
159
143
  }
160
- if (ch === ",") {
161
- atEntryStart = true;
144
+ return void 0;
145
+ };
146
+ const members = /* @__PURE__ */ new Set();
147
+ while (i < n) {
148
+ ows();
149
+ const k = key();
150
+ if (!k) return void 0;
151
+ if (members.has(k)) return { kind: "member", key: k };
152
+ members.add(k);
153
+ let duplicate;
154
+ if (input[i] === "=") {
162
155
  i++;
163
- continue;
164
- }
156
+ if (input[i] === "(") {
157
+ i++;
158
+ for (; ; ) {
159
+ while (i < n && input[i] === " ") i++;
160
+ if (i >= n) return void 0;
161
+ if (input[i] === ")") {
162
+ i++;
163
+ break;
164
+ }
165
+ const before = i;
166
+ bareItem();
167
+ duplicate = parameters();
168
+ if (duplicate) return { kind: "parameter", key: `${k}: ${duplicate}` };
169
+ if (i === before) return void 0;
170
+ }
171
+ duplicate = parameters();
172
+ } else {
173
+ bareItem();
174
+ duplicate = parameters();
175
+ }
176
+ } else duplicate = parameters();
177
+ if (duplicate) return { kind: "parameter", key: `${k}: ${duplicate}` };
178
+ ows();
179
+ if (i >= n) return void 0;
180
+ if (input[i] !== ",") return void 0;
165
181
  i++;
166
182
  }
167
- return keys;
183
+ return void 0;
168
184
  }
169
185
  function normalizeByteSequenceBase64(input) {
170
186
  let out = "";
@@ -59,6 +59,9 @@ const REASONS = [
59
59
  ];
60
60
  function mergeRevocationDetails(prior, detail) {
61
61
  const reason = REASONS.indexOf(detail.reason ?? "unspecified") > REASONS.indexOf(prior?.reason ?? "unspecified") ? detail.reason : prior?.reason ?? detail.reason;
62
+ const hasValidDate = (entry) => !!entry?.invalidity_date && Number.isFinite(Date.parse(entry.invalidity_date));
63
+ if (reason === "keyCompromise" && [prior, detail].some((entry) => entry?.reason === "keyCompromise" && !hasValidDate(entry)))
64
+ return { reason };
62
65
  const dates = [prior?.invalidity_date, detail.invalidity_date].filter((s) => !!s && Number.isFinite(Date.parse(s))).sort((a, b) => Date.parse(a) - Date.parse(b));
63
66
  return { ...reason ? { reason } : {}, ...dates[0] ? { invalidity_date: dates[0] } : {} };
64
67
  }
@@ -35,6 +35,9 @@ const REASONS = [
35
35
  ];
36
36
  function mergeRevocationDetails(prior, detail) {
37
37
  const reason = REASONS.indexOf(detail.reason ?? "unspecified") > REASONS.indexOf(prior?.reason ?? "unspecified") ? detail.reason : prior?.reason ?? detail.reason;
38
+ const hasValidDate = (entry) => !!entry?.invalidity_date && Number.isFinite(Date.parse(entry.invalidity_date));
39
+ if (reason === "keyCompromise" && [prior, detail].some((entry) => entry?.reason === "keyCompromise" && !hasValidDate(entry)))
40
+ return { reason };
38
41
  const dates = [prior?.invalidity_date, detail.invalidity_date].filter((s) => !!s && Number.isFinite(Date.parse(s))).sort((a, b) => Date.parse(a) - Date.parse(b));
39
42
  return { ...reason ? { reason } : {}, ...dates[0] ? { invalidity_date: dates[0] } : {} };
40
43
  }
@@ -12,7 +12,7 @@ export type { SsrfDnsLookup } from '../net/index.mjs';
12
12
  export { buildResponseSignatureBase, buildSignatureBase, canonicalAuthority, canonicalMethod, canonicalTargetUri, formatSignatureParams, getHeaderValue, type RequestLike, type RequestCanonicalizationProfile, type ResponseLike, type SignatureParams, } from './canonicalize.mjs';
13
13
  export { computeContentDigest, contentDigestMatches, parseContentDigest } from './content-digest.mjs';
14
14
  export { requestContextFromExpress, requestContextFromFetch, requestContextFromLambda, type ExpressRequestLike, type FetchRequestLike, type LambdaRequestEvent, type RequestContextFromExpressOptions, type RequestContextFromLambdaOptions, } from './request-context.mjs';
15
- export { jwkToPublicKey, verifySignature } from './crypto.mjs';
15
+ export { jwkToPublicKey, verifySignature, verifySignatureAsync } from './crypto.mjs';
16
16
  export { RequestSignatureError, RequestSigningErrorCodeMetadata, type RequestSignatureErrorCode, ResponseSignatureError, type ResponseSignatureErrorCode, WebhookSignatureError, type WebhookSignatureErrorCode, } from './errors.mjs';
17
17
  export { StaticJwksResolver, type JwksResolution, type JwksResolver } from './jwks.mjs';
18
18
  export { HttpsJwksResolver, type HttpsJwksResolverOptions } from './jwks-https.mjs';
@@ -12,7 +12,7 @@ export type { SsrfDnsLookup } from '../net';
12
12
  export { buildResponseSignatureBase, buildSignatureBase, canonicalAuthority, canonicalMethod, canonicalTargetUri, formatSignatureParams, getHeaderValue, type RequestLike, type RequestCanonicalizationProfile, type ResponseLike, type SignatureParams, } from './canonicalize';
13
13
  export { computeContentDigest, contentDigestMatches, parseContentDigest } from './content-digest';
14
14
  export { requestContextFromExpress, requestContextFromFetch, requestContextFromLambda, type ExpressRequestLike, type FetchRequestLike, type LambdaRequestEvent, type RequestContextFromExpressOptions, type RequestContextFromLambdaOptions, } from './request-context';
15
- export { jwkToPublicKey, verifySignature } from './crypto';
15
+ export { jwkToPublicKey, verifySignature, verifySignatureAsync } from './crypto';
16
16
  export { RequestSignatureError, RequestSigningErrorCodeMetadata, type RequestSignatureErrorCode, ResponseSignatureError, type ResponseSignatureErrorCode, WebhookSignatureError, type WebhookSignatureErrorCode, } from './errors';
17
17
  export { StaticJwksResolver, type JwksResolution, type JwksResolver } from './jwks';
18
18
  export { HttpsJwksResolver, type HttpsJwksResolverOptions } from './jwks-https';
@@ -83,6 +83,7 @@ __export(server_exports, {
83
83
  sweepExpiredReplays: () => import_postgres_replay_store.sweepExpiredReplays,
84
84
  verifyRequestSignature: () => import_verifier.verifyRequestSignature,
85
85
  verifySignature: () => import_crypto.verifySignature,
86
+ verifySignatureAsync: () => import_crypto.verifySignatureAsync,
86
87
  verifyWebhookSignature: () => import_webhook_verifier.verifyWebhookSignature
87
88
  });
88
89
  module.exports = __toCommonJS(server_exports);
@@ -175,5 +176,6 @@ var import_agent_resolver = require('./agent-resolver/index.js');
175
176
  sweepExpiredReplays,
176
177
  verifyRequestSignature,
177
178
  verifySignature,
179
+ verifySignatureAsync,
178
180
  verifyWebhookSignature
179
181
  });
@@ -13,7 +13,7 @@ import {
13
13
  requestContextFromFetch,
14
14
  requestContextFromLambda
15
15
  } from "./request-context.mjs";
16
- import { jwkToPublicKey, verifySignature } from "./crypto.mjs";
16
+ import { jwkToPublicKey, verifySignature, verifySignatureAsync } from "./crypto.mjs";
17
17
  import {
18
18
  RequestSignatureError,
19
19
  RequestSigningErrorCodeMetadata,
@@ -150,5 +150,6 @@ export {
150
150
  sweepExpiredReplays,
151
151
  verifyRequestSignature,
152
152
  verifySignature,
153
+ verifySignatureAsync,
153
154
  verifyWebhookSignature
154
155
  };
@@ -32,6 +32,7 @@ __export(signer_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(signer_exports);
34
34
  var import_crypto = require("crypto");
35
+ var import_crypto2 = require('./crypto.js');
35
36
  var import_canonicalize = require('./canonicalize.js');
36
37
  var import_content_digest = require('./content-digest.js');
37
38
  var import_errors = require('./errors.js');
@@ -203,14 +204,7 @@ function signResponse(response, key, options = {}) {
203
204
  return finalizeResponseSignature(prepared, signature);
204
205
  }
205
206
  function produceSignature(key, data) {
206
- const privateKey = (0, import_crypto.createPrivateKey)({
207
- key: key.privateKey,
208
- format: "jwk"
209
- });
210
- if (key.alg === "ed25519") {
211
- return new Uint8Array((0, import_crypto.sign)(null, data, privateKey));
212
- }
213
- return new Uint8Array((0, import_crypto.sign)("sha256", data, { key: privateKey, dsaEncoding: "ieee-p1363" }));
207
+ return (0, import_crypto2.signWithPrivateJwk)(key.alg, key.privateKey, data);
214
208
  }
215
209
  function flattenHeaders(headers) {
216
210
  const out = {};
@@ -1,4 +1,5 @@
1
- import { createPrivateKey, randomBytes, sign as nodeSign } from "crypto";
1
+ import { randomBytes } from "crypto";
2
+ import { signWithPrivateJwk } from "./crypto.mjs";
2
3
  import {
3
4
  buildResponseSignatureBase,
4
5
  buildSignatureBase,
@@ -180,14 +181,7 @@ function signResponse(response, key, options = {}) {
180
181
  return finalizeResponseSignature(prepared, signature);
181
182
  }
182
183
  function produceSignature(key, data) {
183
- const privateKey = createPrivateKey({
184
- key: key.privateKey,
185
- format: "jwk"
186
- });
187
- if (key.alg === "ed25519") {
188
- return new Uint8Array(nodeSign(null, data, privateKey));
189
- }
190
- return new Uint8Array(nodeSign("sha256", data, { key: privateKey, dsaEncoding: "ieee-p1363" }));
184
+ return signWithPrivateJwk(key.alg, key.privateKey, data);
191
185
  }
192
186
  function flattenHeaders(headers) {
193
187
  const out = {};
@@ -35,6 +35,7 @@ __export(testing_exports, {
35
35
  });
36
36
  module.exports = __toCommonJS(testing_exports);
37
37
  var import_node_crypto = require("node:crypto");
38
+ var import_crypto = require('./crypto.js');
38
39
  var import_jwks_helpers = require('./jwks-helpers.js');
39
40
  const ALLOW_IN_MEMORY_SIGNER_ENV = "ADCP_ALLOW_IN_MEMORY_SIGNER";
40
41
  class InMemorySigningProvider {
@@ -61,12 +62,7 @@ class InMemorySigningProvider {
61
62
  this.fingerprint = (0, import_node_crypto.createHash)("sha256").update(options.keyid).update("\0").update(options.privateKey.d).digest("hex").slice(0, 16);
62
63
  }
63
64
  async sign(payload) {
64
- const privateKey = (0, import_node_crypto.createPrivateKey)({ key: this.privateKey, format: "jwk" });
65
- const data = Buffer.from(payload);
66
- if (this.algorithm === "ed25519") {
67
- return new Uint8Array((0, import_node_crypto.sign)(null, data, privateKey));
68
- }
69
- return new Uint8Array((0, import_node_crypto.sign)("sha256", data, { key: privateKey, dsaEncoding: "ieee-p1363" }));
65
+ return (0, import_crypto.signWithPrivateJwkAsync)(this.algorithm, this.privateKey, payload);
70
66
  }
71
67
  }
72
68
  function signerKeyToProvider(key) {
@@ -1,4 +1,5 @@
1
- import { createHash, createPrivateKey, randomUUID, sign as nodeSign } from "node:crypto";
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { signWithPrivateJwkAsync } from "./crypto.mjs";
2
3
  import { assertAdcpUse } from "./jwks-helpers.mjs";
3
4
  const ALLOW_IN_MEMORY_SIGNER_ENV = "ADCP_ALLOW_IN_MEMORY_SIGNER";
4
5
  class InMemorySigningProvider {
@@ -25,12 +26,7 @@ class InMemorySigningProvider {
25
26
  this.fingerprint = createHash("sha256").update(options.keyid).update("\0").update(options.privateKey.d).digest("hex").slice(0, 16);
26
27
  }
27
28
  async sign(payload) {
28
- const privateKey = createPrivateKey({ key: this.privateKey, format: "jwk" });
29
- const data = Buffer.from(payload);
30
- if (this.algorithm === "ed25519") {
31
- return new Uint8Array(nodeSign(null, data, privateKey));
32
- }
33
- return new Uint8Array(nodeSign("sha256", data, { key: privateKey, dsaEncoding: "ieee-p1363" }));
29
+ return signWithPrivateJwkAsync(this.algorithm, this.privateKey, payload);
34
30
  }
35
31
  }
36
32
  function signerKeyToProvider(key) {
@@ -191,8 +191,8 @@ async function verifyRequestSignature(request, options) {
191
191
  parsedInput.signatureParamsValue,
192
192
  canonicalizationProfile
193
193
  );
194
- const publicKey = (0, import_crypto.jwkToPublicKey)(jwk);
195
- const valid = (0, import_crypto.verifySignature)(parsedInput.params.alg, publicKey, Buffer.from(base, "utf8"), parsedSig.bytes);
194
+ (0, import_crypto.jwkToPublicKey)(jwk);
195
+ const valid = await (0, import_crypto.verifySignatureAsync)(parsedInput.params.alg, jwk, Buffer.from(base, "utf8"), parsedSig.bytes);
196
196
  if (!valid) {
197
197
  throw new import_errors.RequestSignatureError(
198
198
  "request_signature_invalid",
@@ -239,7 +239,7 @@ async function verifyRequestSignature(request, options) {
239
239
  "Delegated operator authorization expired during verification"
240
240
  );
241
241
  }
242
- const remaining = parsedInput.params.expires - now + import_types.CLOCK_SKEW_TOLERANCE_SECONDS;
242
+ const remaining = parsedInput.params.expires - now + import_types.CLOCK_SKEW_TOLERANCE_SECONDS + 1;
243
243
  const ttl = Math.max(remaining, import_types.MAX_SIGNATURE_WINDOW_SECONDS + import_types.CLOCK_SKEW_TOLERANCE_SECONDS);
244
244
  const insertResult = await options.replayStore.insert(jwk.kid, replayScope, parsedInput.params.nonce, ttl, now);
245
245
  if (insertResult === "replayed") {
@@ -16,7 +16,7 @@ import { RequestSignatureError } from "./errors.mjs";
16
16
  import { AgentResolverError } from "./agent-resolver/errors.mjs";
17
17
  import { parseStrictJson, StrictJsonError } from "./agent-resolver/strict-json.mjs";
18
18
  import { parseSignature, parseSignatureInput } from "./parser.mjs";
19
- import { jwkToPublicKey, verifySignature } from "./crypto.mjs";
19
+ import { jwkToPublicKey, verifySignatureAsync } from "./crypto.mjs";
20
20
  import { isUnresolvableOperation } from "./operation-resolution.mjs";
21
21
  import { containsWebhookAuthentication, WEBHOOK_AUTH_TRAVERSAL_DEPTH } from "./webhook-auth-detection.mjs";
22
22
  import {
@@ -180,8 +180,8 @@ async function verifyRequestSignature(request, options) {
180
180
  parsedInput.signatureParamsValue,
181
181
  canonicalizationProfile
182
182
  );
183
- const publicKey = jwkToPublicKey(jwk);
184
- const valid = verifySignature(parsedInput.params.alg, publicKey, Buffer.from(base, "utf8"), parsedSig.bytes);
183
+ jwkToPublicKey(jwk);
184
+ const valid = await verifySignatureAsync(parsedInput.params.alg, jwk, Buffer.from(base, "utf8"), parsedSig.bytes);
185
185
  if (!valid) {
186
186
  throw new RequestSignatureError(
187
187
  "request_signature_invalid",
@@ -228,7 +228,7 @@ async function verifyRequestSignature(request, options) {
228
228
  "Delegated operator authorization expired during verification"
229
229
  );
230
230
  }
231
- const remaining = parsedInput.params.expires - now + CLOCK_SKEW_TOLERANCE_SECONDS;
231
+ const remaining = parsedInput.params.expires - now + CLOCK_SKEW_TOLERANCE_SECONDS + 1;
232
232
  const ttl = Math.max(remaining, MAX_SIGNATURE_WINDOW_SECONDS + CLOCK_SKEW_TOLERANCE_SECONDS);
233
233
  const insertResult = await options.replayStore.insert(jwk.kid, replayScope, parsedInput.params.nonce, ttl, now);
234
234
  if (insertResult === "replayed") {