@astrasyncai/verification-gateway 5.21.2 → 5.22.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 (87) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +19 -7
  3. package/dist/adapters/express.js +60 -11
  4. package/dist/adapters/express.js.map +1 -1
  5. package/dist/adapters/express.mjs +60 -11
  6. package/dist/adapters/express.mjs.map +1 -1
  7. package/dist/adapters/mcp.js +34 -3
  8. package/dist/adapters/mcp.js.map +1 -1
  9. package/dist/adapters/mcp.mjs +34 -3
  10. package/dist/adapters/mcp.mjs.map +1 -1
  11. package/dist/adapters/nextjs.js +60 -11
  12. package/dist/adapters/nextjs.js.map +1 -1
  13. package/dist/adapters/nextjs.mjs +60 -11
  14. package/dist/adapters/nextjs.mjs.map +1 -1
  15. package/dist/adapters/sdk.js +1 -1
  16. package/dist/adapters/sdk.js.map +1 -1
  17. package/dist/adapters/sdk.mjs +1 -1
  18. package/dist/adapters/sdk.mjs.map +1 -1
  19. package/dist/agent/index.js +1 -1
  20. package/dist/agent/index.js.map +1 -1
  21. package/dist/agent/index.mjs +1 -1
  22. package/dist/agent/index.mjs.map +1 -1
  23. package/dist/bin/astrasync-claude-hook.js +1 -1
  24. package/dist/bin/astrasync-codex-hook.js +1 -1
  25. package/dist/bin/astrasync-guard.js +1 -1
  26. package/dist/bin/astrasync.js +1 -1
  27. package/dist/browser/background.js +1 -1
  28. package/dist/browser/background.js.map +1 -1
  29. package/dist/browser/background.mjs +1 -1
  30. package/dist/browser/background.mjs.map +1 -1
  31. package/dist/cli/index.js +1 -1
  32. package/dist/cli/index.js.map +1 -1
  33. package/dist/cli/index.mjs +1 -1
  34. package/dist/cli/index.mjs.map +1 -1
  35. package/dist/codex/index.js +1 -1
  36. package/dist/codex/index.js.map +1 -1
  37. package/dist/codex/index.mjs +1 -1
  38. package/dist/codex/index.mjs.map +1 -1
  39. package/dist/cursor/extension.js +1 -1
  40. package/dist/cursor/extension.js.map +1 -1
  41. package/dist/cursor/extension.mjs +1 -1
  42. package/dist/cursor/extension.mjs.map +1 -1
  43. package/dist/edge-config.js +1 -1
  44. package/dist/edge-config.js.map +1 -1
  45. package/dist/edge-config.mjs +1 -1
  46. package/dist/edge-config.mjs.map +1 -1
  47. package/dist/edge-core/index.d.mts +4 -1
  48. package/dist/edge-core/index.d.ts +4 -1
  49. package/dist/edge-core/index.js +45 -15
  50. package/dist/edge-core/index.js.map +1 -1
  51. package/dist/edge-core/index.mjs +45 -15
  52. package/dist/edge-core/index.mjs.map +1 -1
  53. package/dist/gateway/gateway.js +1 -1
  54. package/dist/gateway/gateway.js.map +1 -1
  55. package/dist/gateway/gateway.mjs +1 -1
  56. package/dist/gateway/gateway.mjs.map +1 -1
  57. package/dist/index.d.mts +20 -5
  58. package/dist/index.d.ts +20 -5
  59. package/dist/index.js +60 -11
  60. package/dist/index.js.map +1 -1
  61. package/dist/index.mjs +60 -11
  62. package/dist/index.mjs.map +1 -1
  63. package/dist/metadata-capture.d.mts +5 -3
  64. package/dist/metadata-capture.d.ts +5 -3
  65. package/dist/metadata-capture.js +33 -2
  66. package/dist/metadata-capture.js.map +1 -1
  67. package/dist/metadata-capture.mjs +33 -2
  68. package/dist/metadata-capture.mjs.map +1 -1
  69. package/dist/platform-signatures.d.mts +13 -0
  70. package/dist/platform-signatures.d.ts +13 -0
  71. package/dist/platform-signatures.js +26 -8
  72. package/dist/platform-signatures.js.map +1 -1
  73. package/dist/platform-signatures.mjs +26 -8
  74. package/dist/platform-signatures.mjs.map +1 -1
  75. package/dist/registration/index.js +1 -1
  76. package/dist/registration/index.js.map +1 -1
  77. package/dist/registration/index.mjs +1 -1
  78. package/dist/registration/index.mjs.map +1 -1
  79. package/dist/transport/index.js +1 -1
  80. package/dist/transport/index.js.map +1 -1
  81. package/dist/transport/index.mjs +1 -1
  82. package/dist/transport/index.mjs.map +1 -1
  83. package/dist/verify.js +1 -1
  84. package/dist/verify.js.map +1 -1
  85. package/dist/verify.mjs +1 -1
  86. package/dist/verify.mjs.map +1 -1
  87. package/package.json +3 -3
package/dist/index.d.mts CHANGED
@@ -155,9 +155,11 @@ declare function extractPlatformHeaders(sanitized: Record<string, string> | unde
155
155
  * `connection` keys the edge adapters populate natively, so SDK-only
156
156
  * deployments still get IP / geo / TLS attribution. Precedence per key:
157
157
  *
158
- * - `ip`: `cf-connecting-ip` > `fastly-client-ip` > `true-client-ip` >
159
- * `x-real-ip` > `cloudfront-viewer-address` (port stripped) > leftmost
160
- * `x-forwarded-for`
158
+ * - `ip`: `cf-connecting-ip` > `fastly-client-ip` > `incap-client-ip`
159
+ * (Imperva) > `true-client-ip` (Akamai et al.) > `x-real-ip` >
160
+ * `cloudfront-viewer-address` (port stripped) > leftmost `x-forwarded-for`
161
+ * - Akamai `x-akamai-edgescape` fills country / region / city / lat / long /
162
+ * timeZone / asn / continent where no header above supplied them
161
163
  * - `country`: `cf-ipcountry` > `x-vercel-ip-country` >
162
164
  * `cloudfront-viewer-country` > `fastly-geo-country`
163
165
  * - `region` / `city` / `timeZone`: Vercel then CloudFront viewer headers
@@ -5358,6 +5360,13 @@ interface PlatformDetectionInput {
5358
5360
  * provider — registry validation rejects ASN-only signatures.
5359
5361
  */
5360
5362
  asn?: string;
5363
+ /**
5364
+ * Round 31 — bot labels a customer's WAF attached to the request (AWS Bot
5365
+ * Control `…:bot:name:x`, Akamai Bot Manager bot name, Cloudflare
5366
+ * verified-bot category, Imperva client classification). Present only on
5367
+ * rows read from WAF security logs. Matched against `wafLabelPatterns`.
5368
+ */
5369
+ wafLabels?: string[];
5361
5370
  }
5362
5371
  /**
5363
5372
  * A signature definition, generic over the vendor key. The seed constant
@@ -5386,6 +5395,8 @@ interface PlatformSignatureDef<V extends string = string> {
5386
5395
  ja4Patterns?: RegExp[];
5387
5396
  /** Exact ASN strings this signature matches (never regex). */
5388
5397
  asnList?: string[];
5398
+ /** Patterns tested against each WAF bot label (round 31; see PlatformDetectionInput.wafLabels). */
5399
+ wafLabelPatterns?: RegExp[];
5389
5400
  }
5390
5401
  /**
5391
5402
  * A fingerprint whose vendor may be a dynamically-promoted (non-seed) key.
@@ -5403,6 +5414,10 @@ interface DynamicPlatformFingerprint {
5403
5414
  * platform UA strings drift between versions. False positives are tolerable —
5404
5415
  * the orphan record is informational, not enforcement.
5405
5416
  *
5417
+ * Round 31: `wafLabelPatterns` attribute rows read from a customer's WAF
5418
+ * security logs by the bot name THEIR WAF assigned; they never match inline
5419
+ * traffic (no labels there).
5420
+ *
5406
5421
  * NOT detectable here, by design (Oct 2026): Meta's Muse and OpenAI's Dots
5407
5422
  * publish no user agent and browse through real Chromium sessions that are
5408
5423
  * indistinguishable from a person's. There is no signature to find — don't
@@ -5472,7 +5487,7 @@ declare function detectRuntime(userAgent: string | undefined | null): string | u
5472
5487
  * silently (never throwing), so this is a no-op there — which is correct:
5473
5488
  * in a browser the page's real UA is the honest identity.
5474
5489
  */
5475
- declare const SDK_USER_AGENT = "astrasync-sdk/5.21.2";
5490
+ declare const SDK_USER_AGENT = "astrasync-sdk/5.22.0";
5476
5491
  declare const sdkFetch: typeof fetch;
5477
5492
 
5478
5493
  interface LocalPolicy {
@@ -5590,7 +5605,7 @@ declare function parseYaml(yamlContent: string): ParseResult;
5590
5605
  * is fine — bumping both in the release-ceremony commit keeps them
5591
5606
  * lockstep.
5592
5607
  */
5593
- declare const SDK_VERSION = "5.21.2";
5608
+ declare const SDK_VERSION = "5.22.0";
5594
5609
 
5595
5610
  /**
5596
5611
  * 5.15.0 — the `UCP-Agent` request header (UCP 2026-08-25): an RFC 8941
package/dist/index.d.ts CHANGED
@@ -155,9 +155,11 @@ declare function extractPlatformHeaders(sanitized: Record<string, string> | unde
155
155
  * `connection` keys the edge adapters populate natively, so SDK-only
156
156
  * deployments still get IP / geo / TLS attribution. Precedence per key:
157
157
  *
158
- * - `ip`: `cf-connecting-ip` > `fastly-client-ip` > `true-client-ip` >
159
- * `x-real-ip` > `cloudfront-viewer-address` (port stripped) > leftmost
160
- * `x-forwarded-for`
158
+ * - `ip`: `cf-connecting-ip` > `fastly-client-ip` > `incap-client-ip`
159
+ * (Imperva) > `true-client-ip` (Akamai et al.) > `x-real-ip` >
160
+ * `cloudfront-viewer-address` (port stripped) > leftmost `x-forwarded-for`
161
+ * - Akamai `x-akamai-edgescape` fills country / region / city / lat / long /
162
+ * timeZone / asn / continent where no header above supplied them
161
163
  * - `country`: `cf-ipcountry` > `x-vercel-ip-country` >
162
164
  * `cloudfront-viewer-country` > `fastly-geo-country`
163
165
  * - `region` / `city` / `timeZone`: Vercel then CloudFront viewer headers
@@ -5358,6 +5360,13 @@ interface PlatformDetectionInput {
5358
5360
  * provider — registry validation rejects ASN-only signatures.
5359
5361
  */
5360
5362
  asn?: string;
5363
+ /**
5364
+ * Round 31 — bot labels a customer's WAF attached to the request (AWS Bot
5365
+ * Control `…:bot:name:x`, Akamai Bot Manager bot name, Cloudflare
5366
+ * verified-bot category, Imperva client classification). Present only on
5367
+ * rows read from WAF security logs. Matched against `wafLabelPatterns`.
5368
+ */
5369
+ wafLabels?: string[];
5361
5370
  }
5362
5371
  /**
5363
5372
  * A signature definition, generic over the vendor key. The seed constant
@@ -5386,6 +5395,8 @@ interface PlatformSignatureDef<V extends string = string> {
5386
5395
  ja4Patterns?: RegExp[];
5387
5396
  /** Exact ASN strings this signature matches (never regex). */
5388
5397
  asnList?: string[];
5398
+ /** Patterns tested against each WAF bot label (round 31; see PlatformDetectionInput.wafLabels). */
5399
+ wafLabelPatterns?: RegExp[];
5389
5400
  }
5390
5401
  /**
5391
5402
  * A fingerprint whose vendor may be a dynamically-promoted (non-seed) key.
@@ -5403,6 +5414,10 @@ interface DynamicPlatformFingerprint {
5403
5414
  * platform UA strings drift between versions. False positives are tolerable —
5404
5415
  * the orphan record is informational, not enforcement.
5405
5416
  *
5417
+ * Round 31: `wafLabelPatterns` attribute rows read from a customer's WAF
5418
+ * security logs by the bot name THEIR WAF assigned; they never match inline
5419
+ * traffic (no labels there).
5420
+ *
5406
5421
  * NOT detectable here, by design (Oct 2026): Meta's Muse and OpenAI's Dots
5407
5422
  * publish no user agent and browse through real Chromium sessions that are
5408
5423
  * indistinguishable from a person's. There is no signature to find — don't
@@ -5472,7 +5487,7 @@ declare function detectRuntime(userAgent: string | undefined | null): string | u
5472
5487
  * silently (never throwing), so this is a no-op there — which is correct:
5473
5488
  * in a browser the page's real UA is the honest identity.
5474
5489
  */
5475
- declare const SDK_USER_AGENT = "astrasync-sdk/5.21.2";
5490
+ declare const SDK_USER_AGENT = "astrasync-sdk/5.22.0";
5476
5491
  declare const sdkFetch: typeof fetch;
5477
5492
 
5478
5493
  interface LocalPolicy {
@@ -5590,7 +5605,7 @@ declare function parseYaml(yamlContent: string): ParseResult;
5590
5605
  * is fine — bumping both in the release-ceremony commit keeps them
5591
5606
  * lockstep.
5592
5607
  */
5593
- declare const SDK_VERSION = "5.21.2";
5608
+ declare const SDK_VERSION = "5.22.0";
5594
5609
 
5595
5610
  /**
5596
5611
  * 5.15.0 — the `UCP-Agent` request header (UCP 2026-08-25): an RFC 8941
package/dist/index.js CHANGED
@@ -229,7 +229,7 @@ function getTrustLevel(score) {
229
229
  }
230
230
 
231
231
  // src/version.ts
232
- var SDK_VERSION = "5.21.2";
232
+ var SDK_VERSION = "5.22.0";
233
233
 
234
234
  // src/http.ts
235
235
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -1404,7 +1404,11 @@ var PLATFORM_HEADER_NAMES = /* @__PURE__ */ new Set([
1404
1404
  "x-goog-api-client",
1405
1405
  "user-agent",
1406
1406
  "x-agent-card-url",
1407
- "x-agent-provider"
1407
+ "x-agent-provider",
1408
+ // Round 31 — Web Bot Auth's Signature-Agent names the signing agent's
1409
+ // directory host (a public URL, never a secret). It attributes a signed
1410
+ // agent even when its UA is stock Chrome.
1411
+ "signature-agent"
1408
1412
  ]);
1409
1413
  var PLATFORM_HEADER_PREFIXES = [
1410
1414
  "x-goog-",
@@ -1535,7 +1539,12 @@ function extractPlatformHeaders(sanitized) {
1535
1539
  return out;
1536
1540
  }
1537
1541
  var CONNECTION_HEADER_SOURCES = [
1538
- ["ip", ["cf-connecting-ip", "fastly-client-ip", "true-client-ip", "x-real-ip"]],
1542
+ // Round 31: `incap-client-ip` = Imperva Cloud WAF; `true-client-ip` is
1543
+ // also Akamai's client-IP header when the property enables it.
1544
+ [
1545
+ "ip",
1546
+ ["cf-connecting-ip", "fastly-client-ip", "incap-client-ip", "true-client-ip", "x-real-ip"]
1547
+ ],
1539
1548
  [
1540
1549
  "country",
1541
1550
  ["cf-ipcountry", "x-vercel-ip-country", "cloudfront-viewer-country", "fastly-geo-country"]
@@ -1586,6 +1595,28 @@ function deriveConnectionFromHeaders(headers) {
1586
1595
  if (portMatch) connection.sourcePort = portMatch[1];
1587
1596
  if (!connection.ip && addr) connection.ip = addr.replace(/:\d+$/, "");
1588
1597
  }
1598
+ {
1599
+ const edgescape = (lower["x-akamai-edgescape"] ?? lower["akamai-edgescape"])?.trim();
1600
+ if (edgescape) {
1601
+ const fields = /* @__PURE__ */ new Map();
1602
+ for (const pair of edgescape.split(",")) {
1603
+ const i = pair.indexOf("=");
1604
+ if (i > 0) fields.set(pair.slice(0, i).trim().toLowerCase(), pair.slice(i + 1).trim());
1605
+ }
1606
+ const fill = (key, field) => {
1607
+ const v = fields.get(field);
1608
+ if (v && !connection[key]) connection[key] = v.slice(0, MAX_CONNECTION_VALUE_CHARS);
1609
+ };
1610
+ fill("country", "country_code");
1611
+ fill("region", "region_code");
1612
+ fill("city", "city");
1613
+ fill("latitude", "lat");
1614
+ fill("longitude", "long");
1615
+ fill("timeZone", "timezone");
1616
+ fill("asn", "asnum");
1617
+ fill("continent", "continent");
1618
+ }
1619
+ }
1589
1620
  if (!connection.ip) {
1590
1621
  const xff = lower["x-forwarded-for"];
1591
1622
  const client = xff?.split(",")[0]?.trim();
@@ -2284,7 +2315,8 @@ var PLATFORM_AGENT_SIGNATURES = [
2284
2315
  uaPatterns: [/claude/i, /anthropic/i],
2285
2316
  agentCardPatterns: [/anthropic\.com/i, /claude\.ai/i],
2286
2317
  apiKeyFormatPatterns: [/^sk-ant/i],
2287
- headerPatterns: [/^anthropic-version/i, /^anthropic-beta/i, /^x-anthropic-/i]
2318
+ headerPatterns: [/^anthropic-version/i, /^anthropic-beta/i, /^x-anthropic-/i],
2319
+ wafLabelPatterns: [/\bclaude/i, /\banthropic/i]
2288
2320
  },
2289
2321
  {
2290
2322
  vendor: "chatgpt",
@@ -2295,7 +2327,14 @@ var PLATFORM_AGENT_SIGNATURES = [
2295
2327
  uaPatterns: [/chatgpt/i, /openai/i, /gpt-?\d/i, /\bGPTBot\b/i, /\bOAI-SearchBot\b/i],
2296
2328
  agentCardPatterns: [/openai\.com/i, /chatgpt\.com/i],
2297
2329
  apiKeyFormatPatterns: [/^sk-proj/i, /^sk-svcacct/i],
2298
- headerPatterns: [/^openai-organization/i, /^openai-project/i, /^openai-version/i]
2330
+ headerPatterns: [
2331
+ /^openai-organization/i,
2332
+ /^openai-project/i,
2333
+ /^openai-version/i,
2334
+ // ChatGPT agent signs with Web Bot Auth under this directory host.
2335
+ /^signature-agent: "?https:\/\/chatgpt\.com/i
2336
+ ],
2337
+ wafLabelPatterns: [/\bgptbot\b/i, /\bchatgpt/i, /\boai-searchbot\b/i, /\bopenai/i]
2299
2338
  },
2300
2339
  {
2301
2340
  vendor: "gemini",
@@ -2316,7 +2355,8 @@ var PLATFORM_AGENT_SIGNATURES = [
2316
2355
  ],
2317
2356
  agentCardPatterns: [/gemini\.google\.com/i, /ai\.google\.dev/i],
2318
2357
  apiKeyFormatPatterns: [/^aiza/i],
2319
- headerPatterns: [/^x-goog-user-project/i, /^x-goog-api-client/i]
2358
+ headerPatterns: [/^x-goog-user-project/i, /^x-goog-api-client/i],
2359
+ wafLabelPatterns: [/\bgoogle-extended\b/i, /\bgoogleother\b/i, /\bgemini/i]
2320
2360
  },
2321
2361
  {
2322
2362
  vendor: "cursor",
@@ -2335,7 +2375,8 @@ var PLATFORM_AGENT_SIGNATURES = [
2335
2375
  displayName: "Perplexity",
2336
2376
  uaPatterns: [/perplexity/i],
2337
2377
  agentCardPatterns: [/perplexity\.ai/i],
2338
- apiKeyFormatPatterns: [/^pplx-/i]
2378
+ apiKeyFormatPatterns: [/^pplx-/i],
2379
+ wafLabelPatterns: [/\bperplexity/i]
2339
2380
  },
2340
2381
  // Round 30.1: xAI's documented crawlers (GrokBot/1.0, xAI-Grok/1.0,
2341
2382
  // Grok-DeepSearch/1.0). Anchored, versioned tokens — never in a stock UA.
@@ -2344,7 +2385,8 @@ var PLATFORM_AGENT_SIGNATURES = [
2344
2385
  displayName: "xAI Grok",
2345
2386
  uaPatterns: [/\bGrokBot\//i, /\bxAI-Grok\//i, /\bGrok-DeepSearch\//i],
2346
2387
  agentCardPatterns: [/\bx\.ai\b/i, /grok\.com/i],
2347
- apiKeyFormatPatterns: [/^xai-/i]
2388
+ apiKeyFormatPatterns: [/^xai-/i],
2389
+ wafLabelPatterns: [/\bgrok/i, /\bxai\b/i]
2348
2390
  },
2349
2391
  // Round 30.1: Meta AI's index and fetch crawlers. facebookexternalhit
2350
2392
  // (link previews) is deliberately NOT here — it stays a generic crawler.
@@ -2352,7 +2394,12 @@ var PLATFORM_AGENT_SIGNATURES = [
2352
2394
  vendor: "meta-ai",
2353
2395
  displayName: "Meta AI",
2354
2396
  uaPatterns: [/\bMeta-WebIndexer\b/i, /\bMeta-ExternalFetcher\b/i],
2355
- agentCardPatterns: [/meta\.ai/i]
2397
+ agentCardPatterns: [/meta\.ai/i],
2398
+ wafLabelPatterns: [
2399
+ /\bmeta-webindexer\b/i,
2400
+ /\bmeta-externalfetcher\b/i,
2401
+ /\bmeta-externalagent\b/i
2402
+ ]
2356
2403
  },
2357
2404
  // Agentic browsers — versioned-token patterns ONLY (a stock Chrome UA must
2358
2405
  // never match). Distinct vendor keys (not 'chatgpt'/'perplexity'): the
@@ -2400,6 +2447,7 @@ function matchPlatformSignature(signatures, input) {
2400
2447
  const apiKeyFormat = input.apiKeyFormat ?? "";
2401
2448
  const ja4 = input.ja4 ?? "";
2402
2449
  const asn = input.asn ?? "";
2450
+ const wafLabels = input.wafLabels ?? [];
2403
2451
  const headerLines = [];
2404
2452
  if (input.platformHeaders) {
2405
2453
  for (const [name, value] of Object.entries(input.platformHeaders)) {
@@ -2413,7 +2461,8 @@ function matchPlatformSignature(signatures, input) {
2413
2461
  const headerMatch = headerLines.length > 0 && sig.headerPatterns?.some((p) => headerLines.some((line) => p.test(line)));
2414
2462
  const ja4Match = ja4.length > 0 && sig.ja4Patterns?.some((p) => p.test(ja4));
2415
2463
  const asnMatch = asn.length > 0 && sig.asnList?.includes(asn);
2416
- if (uaMatch || cardMatch || keyMatch || headerMatch || ja4Match || asnMatch) {
2464
+ const wafMatch = wafLabels.length > 0 && sig.wafLabelPatterns?.some((p) => wafLabels.some((label) => p.test(label)));
2465
+ if (uaMatch || cardMatch || keyMatch || headerMatch || ja4Match || asnMatch || wafMatch) {
2417
2466
  const uaBase = ua.split(/[\s/]/)[0]?.toLowerCase() ?? "";
2418
2467
  const cardHost = (() => {
2419
2468
  try {
@@ -2422,7 +2471,7 @@ function matchPlatformSignature(signatures, input) {
2422
2471
  return "";
2423
2472
  }
2424
2473
  })();
2425
- const keyBasis = uaBase || cardHost || apiKeyFormat || ja4 || asn && `asn${asn}` || "unknown";
2474
+ const keyBasis = uaBase || cardHost || apiKeyFormat || ja4 || asn && `asn${asn}` || wafMatch && `waf:${wafLabels[0]?.toLowerCase()}` || "unknown";
2426
2475
  return {
2427
2476
  vendor: sig.vendor,
2428
2477
  fingerprintKey: `${sig.vendor}:${keyBasis}`,