@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.
- package/README.md +54 -0
- package/dist/lib/core/ConversationTypes.d.mts +8 -3
- package/dist/lib/core/ConversationTypes.d.ts +8 -3
- package/dist/lib/core/SingleAgentClient.d.mts +15 -4
- package/dist/lib/core/SingleAgentClient.d.ts +15 -4
- package/dist/lib/core/SingleAgentClient.js +29 -8
- package/dist/lib/core/SingleAgentClient.mjs +29 -8
- package/dist/lib/core/TaskExecutor.js +5 -1
- package/dist/lib/core/TaskExecutor.mjs +5 -1
- package/dist/lib/errors/index.d.mts +9 -4
- package/dist/lib/errors/index.d.ts +9 -4
- package/dist/lib/identity-3.3/generated-compat.d.mts +34 -0
- package/dist/lib/identity-3.3/generated-compat.d.ts +34 -0
- package/dist/lib/identity-3.3/generated-compat.js +16 -0
- package/dist/lib/identity-3.3/generated-compat.mjs +0 -0
- package/dist/lib/identity-3.3/index.d.mts +2 -2
- package/dist/lib/identity-3.3/index.d.ts +2 -2
- package/dist/lib/identity-3.3/index.js +4 -0
- package/dist/lib/identity-3.3/index.mjs +5 -1
- package/dist/lib/identity-3.3/lifecycle.d.mts +17 -5
- package/dist/lib/identity-3.3/lifecycle.d.ts +17 -5
- package/dist/lib/identity-3.3/lifecycle.js +32 -5
- package/dist/lib/identity-3.3/lifecycle.mjs +38 -6
- package/dist/lib/identity-3.3/revocation.d.mts +39 -3
- package/dist/lib/identity-3.3/revocation.d.ts +39 -3
- package/dist/lib/identity-3.3/revocation.js +88 -18
- package/dist/lib/identity-3.3/revocation.mjs +89 -19
- package/dist/lib/identity-3.3/server.d.mts +12 -0
- package/dist/lib/identity-3.3/server.d.ts +12 -0
- package/dist/lib/identity-3.3/server.js +103 -43
- package/dist/lib/identity-3.3/server.mjs +111 -45
- package/dist/lib/identity-3.3/trust.d.mts +62 -1
- package/dist/lib/identity-3.3/trust.d.ts +62 -1
- package/dist/lib/identity-3.3/trust.js +126 -21
- package/dist/lib/identity-3.3/trust.mjs +124 -21
- package/dist/lib/identity-3.3/types.d.mts +39 -11
- package/dist/lib/identity-3.3/types.d.ts +39 -11
- package/dist/lib/index.d.mts +3 -3
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.js +8 -0
- package/dist/lib/index.mjs +9 -1
- package/dist/lib/negotiation/types.d.mts +20 -39
- package/dist/lib/negotiation/types.d.ts +20 -39
- package/dist/lib/protocols/index.d.mts +61 -25
- package/dist/lib/protocols/index.d.ts +61 -25
- package/dist/lib/protocols/index.js +11 -6
- package/dist/lib/protocols/index.mjs +5 -2
- package/dist/lib/protocols/mcp-modern.js +1 -0
- package/dist/lib/protocols/mcp-modern.mjs +2 -1
- package/dist/lib/protocols/mcp.js +1 -0
- package/dist/lib/protocols/mcp.mjs +2 -1
- package/dist/lib/protocols/responseSizeLimit.d.mts +91 -5
- package/dist/lib/protocols/responseSizeLimit.d.ts +91 -5
- package/dist/lib/protocols/responseSizeLimit.js +195 -31
- package/dist/lib/protocols/responseSizeLimit.mjs +192 -31
- package/dist/lib/reporting/bigquery/index.js +8 -0
- package/dist/lib/reporting/bigquery/index.mjs +8 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/auth-signature.d.mts +6 -1
- package/dist/lib/server/auth-signature.d.ts +6 -1
- package/dist/lib/server/auth-signature.js +24 -13
- package/dist/lib/server/auth-signature.mjs +29 -13
- package/dist/lib/server/auth.d.mts +2 -2
- package/dist/lib/server/auth.d.ts +2 -2
- package/dist/lib/server/create-adcp-server.js +31 -10
- package/dist/lib/server/create-adcp-server.mjs +37 -11
- package/dist/lib/signing/crypto.d.mts +15 -0
- package/dist/lib/signing/crypto.d.ts +15 -0
- package/dist/lib/signing/crypto.js +83 -3
- package/dist/lib/signing/crypto.mjs +86 -3
- package/dist/lib/signing/fetch-async.js +1 -1
- package/dist/lib/signing/fetch-async.mjs +1 -1
- package/dist/lib/signing/fetch.js +1 -1
- package/dist/lib/signing/fetch.mjs +1 -1
- package/dist/lib/signing/middleware.js +9 -0
- package/dist/lib/signing/middleware.mjs +14 -0
- package/dist/lib/signing/parser.d.mts +8 -5
- package/dist/lib/signing/parser.d.ts +8 -5
- package/dist/lib/signing/parser.js +77 -61
- package/dist/lib/signing/parser.mjs +77 -61
- package/dist/lib/signing/revocation.js +3 -0
- package/dist/lib/signing/revocation.mjs +3 -0
- package/dist/lib/signing/server.d.mts +1 -1
- package/dist/lib/signing/server.d.ts +1 -1
- package/dist/lib/signing/server.js +2 -0
- package/dist/lib/signing/server.mjs +2 -1
- package/dist/lib/signing/signer.js +2 -8
- package/dist/lib/signing/signer.mjs +3 -9
- package/dist/lib/signing/testing.js +2 -6
- package/dist/lib/signing/testing.mjs +3 -7
- package/dist/lib/signing/verifier.js +3 -3
- package/dist/lib/signing/verifier.mjs +4 -4
- package/dist/lib/signing/web-bot-auth.d.mts +84 -10
- package/dist/lib/signing/web-bot-auth.d.ts +84 -10
- package/dist/lib/signing/web-bot-auth.js +278 -88
- package/dist/lib/signing/web-bot-auth.mjs +279 -94
- package/dist/lib/signing/webhook-verifier.js +3 -3
- package/dist/lib/signing/webhook-verifier.mjs +4 -4
- package/dist/lib/substitution/compile.js +2 -1
- package/dist/lib/substitution/compile.mjs +2 -1
- package/dist/lib/substitution/consent-macros.d.mts +4 -0
- package/dist/lib/substitution/consent-macros.d.ts +4 -0
- package/dist/lib/substitution/consent-macros.js +45 -0
- package/dist/lib/substitution/consent-macros.mjs +20 -0
- package/dist/lib/substitution/index.d.mts +1 -1
- package/dist/lib/substitution/index.d.ts +1 -1
- package/dist/lib/substitution/index.js +2 -0
- package/dist/lib/substitution/index.mjs +2 -1
- package/dist/lib/substitution/translate.d.mts +15 -2
- package/dist/lib/substitution/translate.d.ts +15 -2
- package/dist/lib/substitution/translate.js +148 -26
- package/dist/lib/substitution/translate.mjs +147 -26
- package/dist/lib/testing/client.js +2 -1
- package/dist/lib/testing/client.mjs +2 -1
- package/dist/lib/testing/scenarios/capabilities.js +1 -1
- package/dist/lib/testing/scenarios/capabilities.mjs +1 -1
- package/dist/lib/testing/storyboard/request-signing/builder.js +2 -5
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +3 -6
- package/dist/lib/testing/storyboard/signer-grader/grader.js +2 -7
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs +2 -7
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/types/enums.generated.d.mts +3 -0
- package/dist/lib/types/enums.generated.d.ts +3 -0
- package/dist/lib/types/enums.generated.js +9 -0
- package/dist/lib/types/enums.generated.mjs +6 -0
- package/dist/lib/v2/projection/catalog-snapshot.js +3 -1
- package/dist/lib/v2/projection/catalog-snapshot.mjs +3 -1
- package/dist/lib/v2/projection/creative-delivery.d.mts +31 -9
- package/dist/lib/v2/projection/creative-delivery.d.ts +31 -9
- package/dist/lib/v2/projection/index.d.mts +1 -1
- package/dist/lib/v2/projection/index.d.ts +1 -1
- package/dist/lib/v2/projection/index.js +2 -0
- package/dist/lib/v2/projection/index.mjs +2 -0
- package/dist/lib/v2/projection/legacy-routes.d.mts +10 -0
- package/dist/lib/v2/projection/legacy-routes.d.ts +10 -0
- package/dist/lib/v2/projection/legacy-routes.js +7 -0
- package/dist/lib/v2/projection/legacy-routes.mjs +6 -0
- package/dist/lib/validation/schema-loader.js +25 -0
- package/dist/lib/validation/schema-loader.mjs +24 -0
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/docs/TYPE-SUMMARY.md +7 -2
- package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +3 -2
- package/docs/guides/REPORTING-LEDGER.md +15 -5
- package/docs/guides/REPORTING-OPERATIONS.md +17 -11
- package/docs/guides/UNIVERSAL-MACRO-COMPILATION.md +38 -0
- package/docs/guides/VALIDATE-YOUR-AGENT.md +12 -0
- package/docs/llms.txt +2 -2
- package/docs/migration-12-to-13.md +8 -0
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/docs/migration-agent-identity-3.3.md +150 -11
- 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
|
|
30
|
-
* profile (step 1) overrides that:
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
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
|
|
30
|
-
* profile (step 1) overrides that:
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
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
|
|
115
|
-
|
|
116
|
-
|
|
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
|
|
124
|
-
const keys = [];
|
|
118
|
+
function findDuplicateStructuredKey(input) {
|
|
125
119
|
let i = 0;
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
138
|
-
if (ch === '"') {
|
|
136
|
+
if (input[i] === '"') {
|
|
139
137
|
i++;
|
|
140
|
-
while (i <
|
|
141
|
-
if (input[i] === "\\"
|
|
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
|
-
|
|
145
|
+
return;
|
|
152
146
|
}
|
|
153
|
-
if (
|
|
147
|
+
if (input[i] === ":") {
|
|
154
148
|
i++;
|
|
155
|
-
while (i <
|
|
156
|
-
|
|
157
|
-
|
|
149
|
+
while (i < n && input[i] !== ":") i++;
|
|
150
|
+
i++;
|
|
151
|
+
return;
|
|
158
152
|
}
|
|
159
|
-
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
186
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
90
|
-
|
|
91
|
-
|
|
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
|
|
99
|
-
const keys = [];
|
|
93
|
+
function findDuplicateStructuredKey(input) {
|
|
100
94
|
let i = 0;
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
113
|
-
if (ch === '"') {
|
|
111
|
+
if (input[i] === '"') {
|
|
114
112
|
i++;
|
|
115
|
-
while (i <
|
|
116
|
-
if (input[i] === "\\"
|
|
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
|
-
|
|
120
|
+
return;
|
|
127
121
|
}
|
|
128
|
-
if (
|
|
122
|
+
if (input[i] === ":") {
|
|
129
123
|
i++;
|
|
130
|
-
while (i <
|
|
131
|
-
|
|
132
|
-
|
|
124
|
+
while (i < n && input[i] !== ":") i++;
|
|
125
|
+
i++;
|
|
126
|
+
return;
|
|
133
127
|
}
|
|
134
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
161
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
195
|
-
const valid = (0, import_crypto.
|
|
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,
|
|
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
|
-
|
|
184
|
-
const valid =
|
|
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") {
|