@astrasyncai/verification-gateway 5.14.0 → 5.15.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 (98) hide show
  1. package/README.md +27 -17
  2. package/dist/adapters/express.d.mts +1 -1
  3. package/dist/adapters/express.d.ts +1 -1
  4. package/dist/adapters/express.js +477 -240
  5. package/dist/adapters/express.js.map +1 -1
  6. package/dist/adapters/express.mjs +477 -240
  7. package/dist/adapters/express.mjs.map +1 -1
  8. package/dist/adapters/mcp.d.mts +1 -1
  9. package/dist/adapters/mcp.d.ts +1 -1
  10. package/dist/adapters/mcp.js +20 -6
  11. package/dist/adapters/mcp.js.map +1 -1
  12. package/dist/adapters/mcp.mjs +20 -6
  13. package/dist/adapters/mcp.mjs.map +1 -1
  14. package/dist/adapters/nextjs.d.mts +1 -1
  15. package/dist/adapters/nextjs.d.ts +1 -1
  16. package/dist/adapters/nextjs.js +460 -239
  17. package/dist/adapters/nextjs.js.map +1 -1
  18. package/dist/adapters/nextjs.mjs +460 -239
  19. package/dist/adapters/nextjs.mjs.map +1 -1
  20. package/dist/adapters/sdk.d.mts +18 -10
  21. package/dist/adapters/sdk.d.ts +18 -10
  22. package/dist/adapters/sdk.js +80 -23
  23. package/dist/adapters/sdk.js.map +1 -1
  24. package/dist/adapters/sdk.mjs +80 -23
  25. package/dist/adapters/sdk.mjs.map +1 -1
  26. package/dist/agent/index.js +1 -1
  27. package/dist/agent/index.js.map +1 -1
  28. package/dist/agent/index.mjs +1 -1
  29. package/dist/agent/index.mjs.map +1 -1
  30. package/dist/bin/astrasync-claude-hook.js +55 -11
  31. package/dist/bin/astrasync-codex-hook.js +55 -11
  32. package/dist/bin/astrasync-guard.js +55 -11
  33. package/dist/bin/astrasync.js +288 -33
  34. package/dist/browser/background.js +50 -6
  35. package/dist/browser/background.js.map +1 -1
  36. package/dist/browser/background.mjs +60 -6
  37. package/dist/browser/background.mjs.map +1 -1
  38. package/dist/cli/index.js +1 -1
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/cli/index.mjs +1 -1
  41. package/dist/cli/index.mjs.map +1 -1
  42. package/dist/codex/index.js +55 -11
  43. package/dist/codex/index.js.map +1 -1
  44. package/dist/codex/index.mjs +65 -11
  45. package/dist/codex/index.mjs.map +1 -1
  46. package/dist/cursor/extension.js +55 -11
  47. package/dist/cursor/extension.js.map +1 -1
  48. package/dist/cursor/extension.mjs +65 -11
  49. package/dist/cursor/extension.mjs.map +1 -1
  50. package/dist/edge-config.d.mts +31 -2
  51. package/dist/edge-config.d.ts +31 -2
  52. package/dist/edge-config.js +35 -5
  53. package/dist/edge-config.js.map +1 -1
  54. package/dist/edge-config.mjs +32 -4
  55. package/dist/edge-config.mjs.map +1 -1
  56. package/dist/edge-core/index.d.mts +11 -2
  57. package/dist/edge-core/index.d.ts +11 -2
  58. package/dist/edge-core/index.js +93 -10
  59. package/dist/edge-core/index.js.map +1 -1
  60. package/dist/edge-core/index.mjs +91 -10
  61. package/dist/edge-core/index.mjs.map +1 -1
  62. package/dist/gateway/gateway.js +50 -6
  63. package/dist/gateway/gateway.js.map +1 -1
  64. package/dist/gateway/gateway.mjs +60 -6
  65. package/dist/gateway/gateway.mjs.map +1 -1
  66. package/dist/git-trigger/git-hooks.d.mts +1 -1
  67. package/dist/git-trigger/git-hooks.d.ts +1 -1
  68. package/dist/index.d.mts +1314 -34
  69. package/dist/index.d.ts +1314 -34
  70. package/dist/index.js +5116 -2612
  71. package/dist/index.js.map +1 -1
  72. package/dist/index.mjs +5063 -2614
  73. package/dist/index.mjs.map +1 -1
  74. package/dist/registration/index.d.mts +28 -2
  75. package/dist/registration/index.d.ts +28 -2
  76. package/dist/registration/index.js +18 -3
  77. package/dist/registration/index.js.map +1 -1
  78. package/dist/registration/index.mjs +15 -2
  79. package/dist/registration/index.mjs.map +1 -1
  80. package/dist/transport/index.d.mts +7 -5
  81. package/dist/transport/index.d.ts +7 -5
  82. package/dist/transport/index.js +61 -5
  83. package/dist/transport/index.js.map +1 -1
  84. package/dist/transport/index.mjs +67 -11
  85. package/dist/transport/index.mjs.map +1 -1
  86. package/dist/{types-C_b4QTyO.d.ts → types-DtJjlW4O.d.ts} +104 -10
  87. package/dist/{types-BCkwBA84.d.mts → types-Dxf9DBpr.d.mts} +106 -12
  88. package/dist/{types-BCkwBA84.d.ts → types-Dxf9DBpr.d.ts} +106 -12
  89. package/dist/{types-DlshIIR-.d.mts → types-Eg6VoBNH.d.mts} +104 -10
  90. package/dist/ui/index.d.mts +1 -1
  91. package/dist/ui/index.d.ts +1 -1
  92. package/dist/verify.d.mts +1 -1
  93. package/dist/verify.d.ts +1 -1
  94. package/dist/verify.js +20 -6
  95. package/dist/verify.js.map +1 -1
  96. package/dist/verify.mjs +20 -6
  97. package/dist/verify.mjs.map +1 -1
  98. package/package.json +1 -1
@@ -35,8 +35,422 @@ __export(nextjs_exports, {
35
35
  });
36
36
  module.exports = __toCommonJS(nextjs_exports);
37
37
 
38
+ // src/metadata-capture.ts
39
+ var CAPTURE_SCHEMA_VERSION = 1;
40
+ var SECRET_HEADER_NAMES = /* @__PURE__ */ new Set([
41
+ "cookie",
42
+ "set-cookie",
43
+ "x-csrf-token",
44
+ "proxy-authorization",
45
+ "x-astrasync-signature",
46
+ "x-astrasync-secret",
47
+ "x-hub-signature",
48
+ "x-hub-signature-256",
49
+ // Short-lived verify dedupe token — must never persist in stored metadata.
50
+ "x-astra-verified-hop"
51
+ ]);
52
+ var SECRET_HEADER_PREFIXES = ["x-astrasync-", "kya-", "kya_"];
53
+ var CREDENTIAL_HEADER_NAMES = /* @__PURE__ */ new Set([
54
+ "authorization",
55
+ "x-api-key",
56
+ "x-goog-api-key",
57
+ "api-key"
58
+ ]);
59
+ function isSignatureHeader(name) {
60
+ return name === "signature" || name.endsWith("-signature") || name.endsWith("-signature-256");
61
+ }
62
+ var PLATFORM_HEADER_NAMES = /* @__PURE__ */ new Set([
63
+ "openai-organization",
64
+ "openai-project",
65
+ "openai-version",
66
+ "openai-processing-ms",
67
+ "anthropic-version",
68
+ "anthropic-beta",
69
+ "x-goog-user-project",
70
+ "x-goog-api-client",
71
+ "user-agent",
72
+ "x-agent-card-url",
73
+ "x-agent-provider"
74
+ ]);
75
+ var PLATFORM_HEADER_PREFIXES = [
76
+ "x-goog-",
77
+ "x-stainless-",
78
+ "x-anthropic-",
79
+ "x-openai-",
80
+ "sec-ch-"
81
+ ];
82
+ var KEY_FORMAT_PREFIXES = [
83
+ "sk-ant-api03",
84
+ "sk-ant-api",
85
+ "sk-ant",
86
+ "sk-proj",
87
+ "sk-svcacct",
88
+ "sk-or-v1",
89
+ "sk-or",
90
+ "sk-lf",
91
+ "sk-",
92
+ "gsk_",
93
+ "aiza",
94
+ "ya29",
95
+ "ghp_",
96
+ "gho_",
97
+ "github_pat_",
98
+ "xai-",
99
+ "pplx-",
100
+ "r8_",
101
+ "hf_",
102
+ "astra-",
103
+ "astrae-"
104
+ ];
105
+ var MAX_HEADERS = 64;
106
+ var MAX_HEADER_VALUE_BYTES = 1024;
107
+ var MAX_TOTAL_BYTES = 16 * 1024;
108
+ function byteLength(s) {
109
+ let bytes = 0;
110
+ for (let i = 0; i < s.length; i++) {
111
+ const code = s.charCodeAt(i);
112
+ if (code < 128) bytes += 1;
113
+ else if (code < 2048) bytes += 2;
114
+ else if (code >= 55296 && code <= 56319) {
115
+ bytes += 4;
116
+ i++;
117
+ } else bytes += 3;
118
+ }
119
+ return bytes;
120
+ }
121
+ function extractApiKeyFormat(rawValue) {
122
+ if (!rawValue) return void 0;
123
+ let value = rawValue.trim();
124
+ const spaceIdx = value.indexOf(" ");
125
+ if (spaceIdx > 0) {
126
+ const scheme = value.slice(0, spaceIdx).toLowerCase();
127
+ if (scheme === "bearer" || scheme === "basic" || scheme === "token") {
128
+ value = value.slice(spaceIdx + 1).trim();
129
+ }
130
+ }
131
+ const lower = value.toLowerCase();
132
+ for (const prefix of KEY_FORMAT_PREFIXES) {
133
+ if (lower.startsWith(prefix)) {
134
+ return prefix;
135
+ }
136
+ }
137
+ return void 0;
138
+ }
139
+ function isSecretHeader(name) {
140
+ if (SECRET_HEADER_NAMES.has(name)) return true;
141
+ if (SECRET_HEADER_PREFIXES.some((p) => name.startsWith(p))) return true;
142
+ if (isSignatureHeader(name)) return true;
143
+ return false;
144
+ }
145
+ function isPlatformHeader(name) {
146
+ if (PLATFORM_HEADER_NAMES.has(name)) return true;
147
+ return PLATFORM_HEADER_PREFIXES.some((p) => name.startsWith(p));
148
+ }
149
+ function sanitizeHeaders(raw) {
150
+ const headers = {};
151
+ const platformHeaders = {};
152
+ let apiKeyFormat;
153
+ let cookieCount;
154
+ let totalBytes = 0;
155
+ let count = 0;
156
+ if (!raw) return { headers };
157
+ for (const rawName of Object.keys(raw)) {
158
+ if (count >= MAX_HEADERS) break;
159
+ const name = rawName.toLowerCase();
160
+ const rawValue = raw[rawName];
161
+ if (rawValue === void 0) continue;
162
+ const joined = Array.isArray(rawValue) ? rawValue.join(", ") : String(rawValue);
163
+ if (CREDENTIAL_HEADER_NAMES.has(name)) {
164
+ const fmt = extractApiKeyFormat(joined);
165
+ if (fmt && !apiKeyFormat) apiKeyFormat = fmt;
166
+ continue;
167
+ }
168
+ if (name === "cookie") {
169
+ cookieCount = joined.split(";").filter((s) => s.trim().length > 0).length;
170
+ }
171
+ if (isSecretHeader(name)) continue;
172
+ let value = joined;
173
+ if (byteLength(value) > MAX_HEADER_VALUE_BYTES) {
174
+ value = value.slice(0, MAX_HEADER_VALUE_BYTES);
175
+ }
176
+ const entryBytes = byteLength(name) + byteLength(value);
177
+ if (totalBytes + entryBytes > MAX_TOTAL_BYTES) continue;
178
+ totalBytes += entryBytes;
179
+ count++;
180
+ headers[name] = value;
181
+ if (isPlatformHeader(name)) platformHeaders[name] = value;
182
+ }
183
+ const result = { headers };
184
+ if (apiKeyFormat) result.apiKeyFormat = apiKeyFormat;
185
+ if (Object.keys(platformHeaders).length > 0) result.platformHeaders = platformHeaders;
186
+ if (cookieCount !== void 0) result.cookieCount = cookieCount;
187
+ return result;
188
+ }
189
+ var CONNECTION_HEADER_SOURCES = [
190
+ ["ip", ["cf-connecting-ip", "fastly-client-ip", "true-client-ip", "x-real-ip"]],
191
+ [
192
+ "country",
193
+ ["cf-ipcountry", "x-vercel-ip-country", "cloudfront-viewer-country", "fastly-geo-country"]
194
+ ],
195
+ ["region", ["x-vercel-ip-country-region", "cloudfront-viewer-country-region"]],
196
+ ["countryRegionName", ["cloudfront-viewer-country-region-name"]],
197
+ ["city", ["x-vercel-ip-city", "cloudfront-viewer-city"]],
198
+ ["latitude", ["x-vercel-ip-latitude", "cloudfront-viewer-latitude"]],
199
+ ["longitude", ["x-vercel-ip-longitude", "cloudfront-viewer-longitude"]],
200
+ ["postalCode", ["x-vercel-ip-postal-code", "cloudfront-viewer-postal-code"]],
201
+ ["asn", ["cloudfront-viewer-asn"]],
202
+ ["tlsVersion", ["cloudfront-viewer-tls"]],
203
+ ["httpVersion", ["cloudfront-viewer-http-version"]],
204
+ ["timeZone", ["x-vercel-ip-timezone", "cloudfront-viewer-time-zone"]],
205
+ ["metroCode", ["cloudfront-viewer-metro-code"]],
206
+ // TLS fingerprints can only be computed where TLS terminates. When a CDN
207
+ // terminates TLS in front of the merchant, its fingerprint headers ARE the
208
+ // connection-layer truth — normalising them here is the permanent design.
209
+ // CloudFront delivers JA3/JA4 only via an origin request policy and only
210
+ // for HTTPS viewer connections.
211
+ ["tlsFingerprint", ["cf-ja3-hash", "cloudfront-viewer-ja3-fingerprint"]],
212
+ ["ja4", ["cf-ja4", "cloudfront-viewer-ja4-fingerprint"]],
213
+ // Header-structure fingerprint: browser/SDK-distinctive header ordering.
214
+ ["headerOrder", ["cloudfront-viewer-header-order"]],
215
+ ["headerCount", ["cloudfront-viewer-header-count"]]
216
+ ];
217
+ var MAX_CONNECTION_VALUE_CHARS = 256;
218
+ function deriveConnectionFromHeaders(headers) {
219
+ if (!headers) return void 0;
220
+ const lower = {};
221
+ for (const name of Object.keys(headers)) {
222
+ const value = headers[name];
223
+ if (typeof value === "string" && value.length > 0) lower[name.toLowerCase()] = value;
224
+ }
225
+ const connection = {};
226
+ for (const [key, sources] of CONNECTION_HEADER_SOURCES) {
227
+ for (const source of sources) {
228
+ const value = lower[source]?.trim();
229
+ if (value) {
230
+ connection[key] = value.slice(0, MAX_CONNECTION_VALUE_CHARS);
231
+ break;
232
+ }
233
+ }
234
+ }
235
+ {
236
+ const addr = lower["cloudfront-viewer-address"]?.trim();
237
+ const portMatch = addr?.match(/:(\d+)$/);
238
+ if (portMatch) connection.sourcePort = portMatch[1];
239
+ if (!connection.ip && addr) connection.ip = addr.replace(/:\d+$/, "");
240
+ }
241
+ if (!connection.ip) {
242
+ const xff = lower["x-forwarded-for"];
243
+ const client = xff?.split(",")[0]?.trim();
244
+ if (client) connection.ip = client;
245
+ }
246
+ if (!connection.tlsCipher) {
247
+ const cipher = connection.tlsVersion?.split(":")[1];
248
+ if (cipher) connection.tlsCipher = cipher;
249
+ }
250
+ return Object.keys(connection).length > 0 ? connection : void 0;
251
+ }
252
+ function buildSdkObservedMetadata(rawHeaders) {
253
+ const { headers, apiKeyFormat, platformHeaders, cookieCount } = sanitizeHeaders(rawHeaders);
254
+ const flat = {};
255
+ if (rawHeaders) {
256
+ for (const name of Object.keys(rawHeaders)) {
257
+ const value = rawHeaders[name];
258
+ if (value === void 0) continue;
259
+ flat[name.toLowerCase()] = Array.isArray(value) ? value.join(", ") : String(value);
260
+ }
261
+ }
262
+ const connection = deriveConnectionFromHeaders(flat);
263
+ return {
264
+ headers,
265
+ ...apiKeyFormat && { apiKeyFormat },
266
+ ...platformHeaders && { platformHeaders },
267
+ ...connection && { connection },
268
+ ...cookieCount !== void 0 && { cookieCount },
269
+ schemaVersion: CAPTURE_SCHEMA_VERSION
270
+ };
271
+ }
272
+
273
+ // src/edge-core/request.ts
274
+ function headerValue(req, name) {
275
+ return req.headers[name.toLowerCase()];
276
+ }
277
+ function requestUrl(req, host) {
278
+ const qs = req.querystring ? `?${req.querystring}` : "";
279
+ return `https://${host}${req.uri}${qs}`;
280
+ }
281
+
282
+ // src/edge-core/detect.ts
283
+ var SD_JWT_PATTERN = /^eyJ[\w-]+\.[\w-]*\.[\w-]+~/;
284
+ function decodeBase64Url(seg) {
285
+ const b64 = seg.replace(/-/g, "+").replace(/_/g, "/");
286
+ const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
287
+ const binary = atob(padded);
288
+ const bytes = new Uint8Array(binary.length);
289
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
290
+ return new TextDecoder().decode(bytes);
291
+ }
292
+ function sniffJwtHeader(compact) {
293
+ try {
294
+ const seg = compact.split(".")[0];
295
+ return JSON.parse(decodeBase64Url(seg));
296
+ } catch {
297
+ return void 0;
298
+ }
299
+ }
300
+ function parseJsonBody(bodyText) {
301
+ if (!bodyText) return void 0;
302
+ try {
303
+ const parsed = JSON.parse(bodyText);
304
+ return typeof parsed === "object" && parsed !== null ? parsed : void 0;
305
+ } catch {
306
+ return void 0;
307
+ }
308
+ }
309
+ function detectCommerce(req, host) {
310
+ const url = requestUrl(req, host);
311
+ const method = req.method;
312
+ const headers = req.headers;
313
+ const jsonBody = parseJsonBody(req.bodyText);
314
+ const truncated = req.bodyTruncated ? { bodyTruncated: true } : {};
315
+ const authHeader = headerValue(req, "authorization");
316
+ const bearer = authHeader?.replace(/^Bearer\s+/i, "");
317
+ const mandateHeader = headerValue(req, "x-payment-mandate") ?? headerValue(req, "payment-mandate");
318
+ const sdJwtCandidate = [mandateHeader, bearer].find((v) => v && SD_JWT_PATTERN.test(v));
319
+ if (sdJwtCandidate) {
320
+ const typ = sniffJwtHeader(sdJwtCandidate)?.typ;
321
+ return {
322
+ protocol: "vi-sd-jwt",
323
+ artifacts: { viSdJwt: sdJwtCandidate },
324
+ evidence: { typ, ...truncated }
325
+ };
326
+ }
327
+ const signature = headerValue(req, "signature");
328
+ const signatureInput = headerValue(req, "signature-input");
329
+ if (signature && signatureInput) {
330
+ const signatureAgent = headerValue(req, "signature-agent");
331
+ const registryHint = headerValue(req, "x-agent-registry");
332
+ const lowerInput = signatureInput.toLowerCase();
333
+ const protocol = signatureAgent ? "rfc9421-web-bot-auth" : registryHint?.toLowerCase().includes("visa") || lowerInput.includes("visa") ? "rfc9421-tap" : registryHint?.toLowerCase().includes("mastercard") || lowerInput.includes("mastercard") ? "rfc9421-agent-pay" : "rfc9421";
334
+ return {
335
+ protocol,
336
+ artifacts: {
337
+ rfc9421: { headers, method, url, ...req.bodyText && { body: req.bodyText } }
338
+ },
339
+ evidence: {
340
+ ...signatureAgent && { signatureAgent },
341
+ ...registryHint && { registryHint },
342
+ keyid: signatureInput.match(/keyid="([^"]+)"/)?.[1],
343
+ ...truncated
344
+ }
345
+ };
346
+ }
347
+ const acpTimestamp = headerValue(req, "timestamp");
348
+ if (signature && !signatureInput && (acpTimestamp || headerValue(req, "idempotency-key"))) {
349
+ return {
350
+ protocol: "acp",
351
+ artifacts: {
352
+ acpRequest: {
353
+ method,
354
+ url,
355
+ headers,
356
+ ...req.bodyText && { rawBody: req.bodyText },
357
+ ...jsonBody && { body: jsonBody }
358
+ }
359
+ },
360
+ evidence: { hasTimestamp: Boolean(acpTimestamp), ...truncated }
361
+ };
362
+ }
363
+ if (/\/checkout[-_]sessions(\/|$)/.test(req.uri)) {
364
+ return {
365
+ protocol: "ucp",
366
+ artifacts: { ucpRequest: { method, url, ...jsonBody && { body: jsonBody } } },
367
+ evidence: { path: req.uri, ...truncated }
368
+ };
369
+ }
370
+ if (jsonBody) {
371
+ const intent = jsonBody.intent_mandate ?? jsonBody.intentMandate;
372
+ const cart = jsonBody.cart_mandate ?? jsonBody.cartMandate;
373
+ const payment = jsonBody.payment_mandate ?? jsonBody.paymentMandate;
374
+ if (typeof intent === "string" || typeof cart === "string" || typeof payment === "string") {
375
+ return {
376
+ protocol: "ap2",
377
+ artifacts: {
378
+ ap2Mandates: {
379
+ ...typeof intent === "string" && { intent },
380
+ ...typeof cart === "string" && { cart },
381
+ ...typeof payment === "string" && { payment }
382
+ }
383
+ },
384
+ evidence: {
385
+ mandatesPresent: [
386
+ typeof intent === "string" && "intent",
387
+ typeof cart === "string" && "cart",
388
+ typeof payment === "string" && "payment"
389
+ ].filter(Boolean),
390
+ ...truncated
391
+ }
392
+ };
393
+ }
394
+ }
395
+ if (authHeader && /^Payment\s+/i.test(authHeader) || headerValue(req, "payment-authorization")) {
396
+ return {
397
+ protocol: "mpp",
398
+ artifacts: {
399
+ mppRequest: {
400
+ method,
401
+ url,
402
+ headers,
403
+ ...req.bodyText && { rawBody: req.bodyText },
404
+ ...jsonBody && { body: jsonBody }
405
+ }
406
+ },
407
+ evidence: truncated
408
+ };
409
+ }
410
+ if (headerValue(req, "payment-signature") || headerValue(req, "x-payment")) {
411
+ return {
412
+ protocol: "x402",
413
+ artifacts: {
414
+ x402Request: { method, url, headers, ...jsonBody && { body: jsonBody } }
415
+ },
416
+ evidence: truncated
417
+ };
418
+ }
419
+ return void 0;
420
+ }
421
+
422
+ // src/adapters/commerce-detect.ts
423
+ var MAX_BODY_BYTES = 64 * 1024;
424
+ function detect(req, host) {
425
+ try {
426
+ return detectCommerce(req, host)?.artifacts;
427
+ } catch {
428
+ return void 0;
429
+ }
430
+ }
431
+ async function detectFetchCommerce(request) {
432
+ const url = new URL(request.url);
433
+ const headers = {};
434
+ request.headers.forEach((v, k) => headers[k.toLowerCase()] = v);
435
+ let bodyText;
436
+ const length = Number(headers["content-length"] ?? 0);
437
+ if (request.method !== "GET" && request.method !== "HEAD" && length <= MAX_BODY_BYTES) {
438
+ bodyText = await request.clone().text().catch(() => void 0);
439
+ }
440
+ return detect(
441
+ {
442
+ method: request.method,
443
+ uri: url.pathname,
444
+ querystring: url.search.replace(/^\?/, ""),
445
+ headers,
446
+ ...bodyText ? { bodyText } : {}
447
+ },
448
+ headers["x-forwarded-host"] ?? url.host
449
+ );
450
+ }
451
+
38
452
  // src/version.ts
39
- var SDK_VERSION = "5.14.0";
453
+ var SDK_VERSION = "5.15.0";
40
454
 
41
455
  // src/http.ts
42
456
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -500,6 +914,7 @@ async function callVerifyAccessAPI(config, request) {
500
914
  if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;
501
915
  if (requestData.commercePhase) body.commercePhase = requestData.commercePhase;
502
916
  if (requestData.checkoutSessionId) body.checkoutSessionId = requestData.checkoutSessionId;
917
+ if (requestData.checkoutJwt) body.checkoutJwt = requestData.checkoutJwt;
503
918
  if (requestData.checkoutItems) body.checkoutItems = requestData.checkoutItems;
504
919
  if (requestData.buyerEmail) body.buyerEmail = requestData.buyerEmail;
505
920
  if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
@@ -650,7 +1065,8 @@ async function verify(config, request, options) {
650
1065
  "[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access decisions (verified ID + runtime challenge + PDLSS + trust score). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side."
651
1066
  );
652
1067
  }
653
- if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {
1068
+ const uncacheable = Boolean(request.commerceArtifacts);
1069
+ if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache && !uncacheable) {
654
1070
  const cached = getCachedResult(request, mergedConfig.counterpartyId);
655
1071
  if (cached) {
656
1072
  if (mergedConfig.debug) {
@@ -731,7 +1147,10 @@ async function verify(config, request, options) {
731
1147
  // MERCHANT caller only (bridge callers strip it before the agent plane).
732
1148
  settlementToken: apiResponse.settlementToken,
733
1149
  // 5.6.0: fulfilment contact — merchant-only lane, same strip rule.
734
- fulfilment: apiResponse.fulfilment
1150
+ fulfilment: apiResponse.fulfilment,
1151
+ mandates: apiResponse.mandates,
1152
+ kyaToken: apiResponse.kyaToken,
1153
+ aep: apiResponse.aep
735
1154
  };
736
1155
  return result2;
737
1156
  }
@@ -741,7 +1160,10 @@ async function verify(config, request, options) {
741
1160
  trustScore: apiResponse.agent.trustScore,
742
1161
  trustLevel: getTrustLevel(apiResponse.agent.trustScore),
743
1162
  blockchainAnchored: apiResponse.agent.blockchainStatus === "anchored",
744
- status: apiResponse.agent.agentStatus
1163
+ status: apiResponse.agent.agentStatus,
1164
+ ...apiResponse.agent.protocolIdentities && {
1165
+ protocolIdentities: apiResponse.agent.protocolIdentities
1166
+ }
745
1167
  } : void 0;
746
1168
  const developer = apiResponse.developer ? {
747
1169
  astradId: apiResponse.developer.kyaOwnerId,
@@ -792,7 +1214,11 @@ async function verify(config, request, options) {
792
1214
  settlementOutcome: apiResponse.settlementOutcome,
793
1215
  settlementToken: apiResponse.settlementToken,
794
1216
  // 5.6.0: fulfilment contact — merchant-only lane, same strip rule.
795
- fulfilment: apiResponse.fulfilment
1217
+ fulfilment: apiResponse.fulfilment,
1218
+ // 5.15.0: merchant-lane AP2 mandates + KYAPay identity token.
1219
+ mandates: apiResponse.mandates,
1220
+ kyaToken: apiResponse.kyaToken,
1221
+ aep: apiResponse.aep
796
1222
  };
797
1223
  if (result.recommendation === "deny") {
798
1224
  result.policyAllowed = false;
@@ -812,7 +1238,9 @@ async function verify(config, request, options) {
812
1238
  }
813
1239
  const escalates = result.requiresStepUp === true || result.requiresApproval === true || result.recommendation === "step_up_required";
814
1240
  if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny" && !escalates) {
815
- cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
1241
+ if (!uncacheable) {
1242
+ cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
1243
+ }
816
1244
  }
817
1245
  return result;
818
1246
  }
@@ -966,239 +1394,30 @@ function performCounterpartyPreCheck(routeConfig, astraCreds, purpose) {
966
1394
  return failures;
967
1395
  }
968
1396
 
969
- // src/metadata-capture.ts
970
- var CAPTURE_SCHEMA_VERSION = 1;
971
- var SECRET_HEADER_NAMES = /* @__PURE__ */ new Set([
972
- "cookie",
973
- "set-cookie",
974
- "x-csrf-token",
975
- "proxy-authorization",
976
- "x-astrasync-signature",
977
- "x-astrasync-secret",
978
- "x-hub-signature",
979
- "x-hub-signature-256",
980
- // Short-lived verify dedupe token — must never persist in stored metadata.
981
- "x-astra-verified-hop"
982
- ]);
983
- var SECRET_HEADER_PREFIXES = ["x-astrasync-", "kya-", "kya_"];
984
- var CREDENTIAL_HEADER_NAMES = /* @__PURE__ */ new Set([
985
- "authorization",
986
- "x-api-key",
987
- "x-goog-api-key",
988
- "api-key"
989
- ]);
990
- function isSignatureHeader(name) {
991
- return name === "signature" || name.endsWith("-signature") || name.endsWith("-signature-256");
992
- }
993
- var PLATFORM_HEADER_NAMES = /* @__PURE__ */ new Set([
994
- "openai-organization",
995
- "openai-project",
996
- "openai-version",
997
- "openai-processing-ms",
998
- "anthropic-version",
999
- "anthropic-beta",
1000
- "x-goog-user-project",
1001
- "x-goog-api-client",
1002
- "user-agent",
1003
- "x-agent-card-url",
1004
- "x-agent-provider"
1005
- ]);
1006
- var PLATFORM_HEADER_PREFIXES = [
1007
- "x-goog-",
1008
- "x-stainless-",
1009
- "x-anthropic-",
1010
- "x-openai-",
1011
- "sec-ch-"
1012
- ];
1013
- var KEY_FORMAT_PREFIXES = [
1014
- "sk-ant-api03",
1015
- "sk-ant-api",
1016
- "sk-ant",
1017
- "sk-proj",
1018
- "sk-svcacct",
1019
- "sk-or-v1",
1020
- "sk-or",
1021
- "sk-lf",
1022
- "sk-",
1023
- "gsk_",
1024
- "aiza",
1025
- "ya29",
1026
- "ghp_",
1027
- "gho_",
1028
- "github_pat_",
1029
- "xai-",
1030
- "pplx-",
1031
- "r8_",
1032
- "hf_",
1033
- "astra-",
1034
- "astrae-"
1035
- ];
1036
- var MAX_HEADERS = 64;
1037
- var MAX_HEADER_VALUE_BYTES = 1024;
1038
- var MAX_TOTAL_BYTES = 16 * 1024;
1039
- function byteLength(s) {
1040
- let bytes = 0;
1041
- for (let i = 0; i < s.length; i++) {
1042
- const code = s.charCodeAt(i);
1043
- if (code < 128) bytes += 1;
1044
- else if (code < 2048) bytes += 2;
1045
- else if (code >= 55296 && code <= 56319) {
1046
- bytes += 4;
1047
- i++;
1048
- } else bytes += 3;
1049
- }
1050
- return bytes;
1051
- }
1052
- function extractApiKeyFormat(rawValue) {
1053
- if (!rawValue) return void 0;
1054
- let value = rawValue.trim();
1055
- const spaceIdx = value.indexOf(" ");
1056
- if (spaceIdx > 0) {
1057
- const scheme = value.slice(0, spaceIdx).toLowerCase();
1058
- if (scheme === "bearer" || scheme === "basic" || scheme === "token") {
1059
- value = value.slice(spaceIdx + 1).trim();
1060
- }
1061
- }
1062
- const lower = value.toLowerCase();
1063
- for (const prefix of KEY_FORMAT_PREFIXES) {
1064
- if (lower.startsWith(prefix)) {
1065
- return prefix;
1066
- }
1067
- }
1068
- return void 0;
1069
- }
1070
- function isSecretHeader(name) {
1071
- if (SECRET_HEADER_NAMES.has(name)) return true;
1072
- if (SECRET_HEADER_PREFIXES.some((p) => name.startsWith(p))) return true;
1073
- if (isSignatureHeader(name)) return true;
1074
- return false;
1075
- }
1076
- function isPlatformHeader(name) {
1077
- if (PLATFORM_HEADER_NAMES.has(name)) return true;
1078
- return PLATFORM_HEADER_PREFIXES.some((p) => name.startsWith(p));
1079
- }
1080
- function sanitizeHeaders(raw) {
1081
- const headers = {};
1082
- const platformHeaders = {};
1083
- let apiKeyFormat;
1084
- let cookieCount;
1085
- let totalBytes = 0;
1086
- let count = 0;
1087
- if (!raw) return { headers };
1088
- for (const rawName of Object.keys(raw)) {
1089
- if (count >= MAX_HEADERS) break;
1090
- const name = rawName.toLowerCase();
1091
- const rawValue = raw[rawName];
1092
- if (rawValue === void 0) continue;
1093
- const joined = Array.isArray(rawValue) ? rawValue.join(", ") : String(rawValue);
1094
- if (CREDENTIAL_HEADER_NAMES.has(name)) {
1095
- const fmt = extractApiKeyFormat(joined);
1096
- if (fmt && !apiKeyFormat) apiKeyFormat = fmt;
1097
- continue;
1098
- }
1099
- if (name === "cookie") {
1100
- cookieCount = joined.split(";").filter((s) => s.trim().length > 0).length;
1101
- }
1102
- if (isSecretHeader(name)) continue;
1103
- let value = joined;
1104
- if (byteLength(value) > MAX_HEADER_VALUE_BYTES) {
1105
- value = value.slice(0, MAX_HEADER_VALUE_BYTES);
1106
- }
1107
- const entryBytes = byteLength(name) + byteLength(value);
1108
- if (totalBytes + entryBytes > MAX_TOTAL_BYTES) continue;
1109
- totalBytes += entryBytes;
1110
- count++;
1111
- headers[name] = value;
1112
- if (isPlatformHeader(name)) platformHeaders[name] = value;
1113
- }
1114
- const result = { headers };
1115
- if (apiKeyFormat) result.apiKeyFormat = apiKeyFormat;
1116
- if (Object.keys(platformHeaders).length > 0) result.platformHeaders = platformHeaders;
1117
- if (cookieCount !== void 0) result.cookieCount = cookieCount;
1118
- return result;
1119
- }
1120
- var CONNECTION_HEADER_SOURCES = [
1121
- ["ip", ["cf-connecting-ip", "fastly-client-ip", "true-client-ip", "x-real-ip"]],
1122
- [
1123
- "country",
1124
- ["cf-ipcountry", "x-vercel-ip-country", "cloudfront-viewer-country", "fastly-geo-country"]
1125
- ],
1126
- ["region", ["x-vercel-ip-country-region", "cloudfront-viewer-country-region"]],
1127
- ["countryRegionName", ["cloudfront-viewer-country-region-name"]],
1128
- ["city", ["x-vercel-ip-city", "cloudfront-viewer-city"]],
1129
- ["latitude", ["x-vercel-ip-latitude", "cloudfront-viewer-latitude"]],
1130
- ["longitude", ["x-vercel-ip-longitude", "cloudfront-viewer-longitude"]],
1131
- ["postalCode", ["x-vercel-ip-postal-code", "cloudfront-viewer-postal-code"]],
1132
- ["asn", ["cloudfront-viewer-asn"]],
1133
- ["tlsVersion", ["cloudfront-viewer-tls"]],
1134
- ["httpVersion", ["cloudfront-viewer-http-version"]],
1135
- ["timeZone", ["x-vercel-ip-timezone", "cloudfront-viewer-time-zone"]],
1136
- ["metroCode", ["cloudfront-viewer-metro-code"]],
1137
- // TLS fingerprints can only be computed where TLS terminates. When a CDN
1138
- // terminates TLS in front of the merchant, its fingerprint headers ARE the
1139
- // connection-layer truth — normalising them here is the permanent design.
1140
- // CloudFront delivers JA3/JA4 only via an origin request policy and only
1141
- // for HTTPS viewer connections.
1142
- ["tlsFingerprint", ["cf-ja3-hash", "cloudfront-viewer-ja3-fingerprint"]],
1143
- ["ja4", ["cf-ja4", "cloudfront-viewer-ja4-fingerprint"]],
1144
- // Header-structure fingerprint: browser/SDK-distinctive header ordering.
1145
- ["headerOrder", ["cloudfront-viewer-header-order"]],
1146
- ["headerCount", ["cloudfront-viewer-header-count"]]
1147
- ];
1148
- var MAX_CONNECTION_VALUE_CHARS = 256;
1149
- function deriveConnectionFromHeaders(headers) {
1150
- if (!headers) return void 0;
1151
- const lower = {};
1152
- for (const name of Object.keys(headers)) {
1153
- const value = headers[name];
1154
- if (typeof value === "string" && value.length > 0) lower[name.toLowerCase()] = value;
1155
- }
1156
- const connection = {};
1157
- for (const [key, sources] of CONNECTION_HEADER_SOURCES) {
1158
- for (const source of sources) {
1159
- const value = lower[source]?.trim();
1160
- if (value) {
1161
- connection[key] = value.slice(0, MAX_CONNECTION_VALUE_CHARS);
1162
- break;
1163
- }
1397
+ // src/route-pattern.ts
1398
+ function routePatternToRegExp(pattern, opts = {}) {
1399
+ let source = "";
1400
+ for (let i = 0; i < pattern.length; i++) {
1401
+ const ch = pattern[i];
1402
+ if (ch === "*") {
1403
+ source += ".*";
1404
+ } else if (ch === ":" && /[A-Za-z_]/.test(pattern[i + 1] ?? "") && (i === 0 || pattern[i - 1] === "/")) {
1405
+ let j = i + 1;
1406
+ while (j < pattern.length && /[A-Za-z0-9_]/.test(pattern[j])) j++;
1407
+ source += "[^/]+";
1408
+ i = j - 1;
1409
+ } else {
1410
+ source += ch.replace(/[.+?^${}()|[\]\\/]/g, "\\$&");
1164
1411
  }
1165
1412
  }
1166
- {
1167
- const addr = lower["cloudfront-viewer-address"]?.trim();
1168
- const portMatch = addr?.match(/:(\d+)$/);
1169
- if (portMatch) connection.sourcePort = portMatch[1];
1170
- if (!connection.ip && addr) connection.ip = addr.replace(/:\d+$/, "");
1171
- }
1172
- if (!connection.ip) {
1173
- const xff = lower["x-forwarded-for"];
1174
- const client = xff?.split(",")[0]?.trim();
1175
- if (client) connection.ip = client;
1176
- }
1177
- if (!connection.tlsCipher) {
1178
- const cipher = connection.tlsVersion?.split(":")[1];
1179
- if (cipher) connection.tlsCipher = cipher;
1413
+ try {
1414
+ return new RegExp(`^${source}$`, opts.caseInsensitive ? "i" : "");
1415
+ } catch {
1416
+ return null;
1180
1417
  }
1181
- return Object.keys(connection).length > 0 ? connection : void 0;
1182
1418
  }
1183
- function buildSdkObservedMetadata(rawHeaders) {
1184
- const { headers, apiKeyFormat, platformHeaders, cookieCount } = sanitizeHeaders(rawHeaders);
1185
- const flat = {};
1186
- if (rawHeaders) {
1187
- for (const name of Object.keys(rawHeaders)) {
1188
- const value = rawHeaders[name];
1189
- if (value === void 0) continue;
1190
- flat[name.toLowerCase()] = Array.isArray(value) ? value.join(", ") : String(value);
1191
- }
1192
- }
1193
- const connection = deriveConnectionFromHeaders(flat);
1194
- return {
1195
- headers,
1196
- ...apiKeyFormat && { apiKeyFormat },
1197
- ...platformHeaders && { platformHeaders },
1198
- ...connection && { connection },
1199
- ...cookieCount !== void 0 && { cookieCount },
1200
- schemaVersion: CAPTURE_SCHEMA_VERSION
1201
- };
1419
+ function matchRoutePattern(pattern, path, opts = {}) {
1420
+ return routePatternToRegExp(pattern, opts)?.test(path) ?? false;
1202
1421
  }
1203
1422
 
1204
1423
  // src/edge-config.ts
@@ -1233,6 +1452,7 @@ function isEdgeConfig(value) {
1233
1452
  if (r.sampling !== void 0 && !isSamplingShape(r.sampling)) return false;
1234
1453
  }
1235
1454
  if (!isSamplingShape(v.sampling)) return false;
1455
+ if (v.minTls !== void 0 && v.minTls !== "1.2" && v.minTls !== "1.3") return false;
1236
1456
  if (v.queryValueAllowlist !== void 0) {
1237
1457
  if (!Array.isArray(v.queryValueAllowlist) || v.queryValueAllowlist.length > 16 || !v.queryValueAllowlist.every((e) => typeof e === "string" && e.length > 0 && e.length <= 64)) {
1238
1458
  return false;
@@ -1948,9 +2168,7 @@ function extractCredentialsFromNextRequest(request) {
1948
2168
  return credentials;
1949
2169
  }
1950
2170
  function matchRoute(pattern, path) {
1951
- const regexPattern = pattern.replace(/\*/g, ".*").replace(/\//g, "\\/");
1952
- const regex = new RegExp(`^${regexPattern}$`);
1953
- return regex.test(path);
2171
+ return matchRoutePattern(pattern, path);
1954
2172
  }
1955
2173
  function findRouteConfig(routes, path, method) {
1956
2174
  return routes.find((route) => {
@@ -2141,7 +2359,8 @@ function createMiddleware(options) {
2141
2359
  skipPaths = [],
2142
2360
  showInterstitial,
2143
2361
  showCommerceShield,
2144
- enableRuntimeChallenge = true,
2362
+ // Round 27.8: opt-in only (the merchant turns it on); was default-on.
2363
+ enableRuntimeChallenge = false,
2145
2364
  routesRefreshMs = DEFAULT_ROUTES_REFRESH_MS,
2146
2365
  anonymousBeacon = true,
2147
2366
  trustVerifiedHop = false,
@@ -2278,8 +2497,10 @@ function createMiddleware(options) {
2278
2497
  const originalClientIp = forwardedFor?.split(",")[0]?.trim();
2279
2498
  const attemptHeader = request.headers.get("x-astra-attempt-id");
2280
2499
  const inboundAttemptId = attemptHeader && /^att_[0-9a-f]{32}$/.test(attemptHeader) ? attemptHeader : void 0;
2500
+ const commerceArtifacts = await detectFetchCommerce(request);
2281
2501
  const verificationRequest = {
2282
2502
  credentials,
2503
+ ...commerceArtifacts && { commerceArtifacts },
2283
2504
  purpose,
2284
2505
  action: pdlssPair.action,
2285
2506
  resource: pathname,