@astrasyncai/verification-gateway 5.8.0 → 5.9.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 (106) hide show
  1. package/README.md +1 -1
  2. package/dist/adapters/express.d.mts +1 -1
  3. package/dist/adapters/express.d.ts +1 -1
  4. package/dist/adapters/express.js +38 -7
  5. package/dist/adapters/express.js.map +1 -1
  6. package/dist/adapters/express.mjs +38 -7
  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 +2 -2
  11. package/dist/adapters/mcp.js.map +1 -1
  12. package/dist/adapters/mcp.mjs +2 -2
  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 +38 -7
  17. package/dist/adapters/nextjs.js.map +1 -1
  18. package/dist/adapters/nextjs.mjs +38 -7
  19. package/dist/adapters/nextjs.mjs.map +1 -1
  20. package/dist/adapters/sdk.d.mts +1 -1
  21. package/dist/adapters/sdk.d.ts +1 -1
  22. package/dist/adapters/sdk.js +2 -2
  23. package/dist/adapters/sdk.js.map +1 -1
  24. package/dist/adapters/sdk.mjs +2 -2
  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 +14 -6
  31. package/dist/bin/astrasync-codex-hook.js +14 -6
  32. package/dist/bin/astrasync-guard.js +14 -6
  33. package/dist/bin/astrasync.js +15 -6
  34. package/dist/browser/background.js +14 -6
  35. package/dist/browser/background.js.map +1 -1
  36. package/dist/browser/background.mjs +14 -6
  37. package/dist/browser/background.mjs.map +1 -1
  38. package/dist/cli/index.js +12 -4
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/cli/index.mjs +12 -4
  41. package/dist/cli/index.mjs.map +1 -1
  42. package/dist/codex/index.js +14 -6
  43. package/dist/codex/index.js.map +1 -1
  44. package/dist/codex/index.mjs +14 -6
  45. package/dist/codex/index.mjs.map +1 -1
  46. package/dist/cursor/extension.js +14 -6
  47. package/dist/cursor/extension.js.map +1 -1
  48. package/dist/cursor/extension.mjs +14 -6
  49. package/dist/cursor/extension.mjs.map +1 -1
  50. package/dist/edge-config.d.mts +24 -1
  51. package/dist/edge-config.d.ts +24 -1
  52. package/dist/edge-config.js +13 -5
  53. package/dist/edge-config.js.map +1 -1
  54. package/dist/edge-config.mjs +13 -5
  55. package/dist/edge-config.mjs.map +1 -1
  56. package/dist/edge-core/index.d.mts +14 -6
  57. package/dist/edge-core/index.d.ts +14 -6
  58. package/dist/edge-core/index.js +110 -16
  59. package/dist/edge-core/index.js.map +1 -1
  60. package/dist/edge-core/index.mjs +110 -16
  61. package/dist/edge-core/index.mjs.map +1 -1
  62. package/dist/gateway/gateway.js +14 -6
  63. package/dist/gateway/gateway.js.map +1 -1
  64. package/dist/gateway/gateway.mjs +14 -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 +73 -6
  69. package/dist/index.d.ts +73 -6
  70. package/dist/index.js +48 -7
  71. package/dist/index.js.map +1 -1
  72. package/dist/index.mjs +46 -7
  73. package/dist/index.mjs.map +1 -1
  74. package/dist/metadata-capture.d.mts +18 -1
  75. package/dist/metadata-capture.d.ts +18 -1
  76. package/dist/metadata-capture.js +10 -0
  77. package/dist/metadata-capture.js.map +1 -1
  78. package/dist/metadata-capture.mjs +8 -0
  79. package/dist/metadata-capture.mjs.map +1 -1
  80. package/dist/platform-signatures.d.mts +1 -1
  81. package/dist/platform-signatures.d.ts +1 -1
  82. package/dist/platform-signatures.js +24 -1
  83. package/dist/platform-signatures.js.map +1 -1
  84. package/dist/platform-signatures.mjs +24 -1
  85. package/dist/platform-signatures.mjs.map +1 -1
  86. package/dist/registration/index.js +1 -1
  87. package/dist/registration/index.js.map +1 -1
  88. package/dist/registration/index.mjs +1 -1
  89. package/dist/registration/index.mjs.map +1 -1
  90. package/dist/transport/index.js +1 -1
  91. package/dist/transport/index.js.map +1 -1
  92. package/dist/transport/index.mjs +1 -1
  93. package/dist/transport/index.mjs.map +1 -1
  94. package/dist/{types-BK_pRNSs.d.mts → types-CTmUpNpS.d.mts} +25 -2
  95. package/dist/{types-BK_pRNSs.d.ts → types-CTmUpNpS.d.ts} +25 -2
  96. package/dist/{types-CwY5IY-0.d.ts → types-CtFXmDzm.d.ts} +17 -2
  97. package/dist/{types-BCmHFdkJ.d.mts → types-DQrn_kei.d.mts} +17 -2
  98. package/dist/ui/index.d.mts +1 -1
  99. package/dist/ui/index.d.ts +1 -1
  100. package/dist/verify.d.mts +13 -1
  101. package/dist/verify.d.ts +13 -1
  102. package/dist/verify.js +2 -2
  103. package/dist/verify.js.map +1 -1
  104. package/dist/verify.mjs +2 -2
  105. package/dist/verify.mjs.map +1 -1
  106. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var SDK_VERSION = "5.8.0";
2
+ var SDK_VERSION = "5.9.0";
3
3
 
4
4
  // src/http.ts
5
5
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -25,7 +25,7 @@ var DEFAULT_EDGE_CONFIG = Object.freeze({
25
25
  mode: "observe",
26
26
  depth: "classify",
27
27
  pathRules: [],
28
- sampling: Object.freeze({ anonymousBeaconRate: 0.1 }),
28
+ sampling: Object.freeze({ anonymousBeaconRate: 1 }),
29
29
  failurePosture: "open"
30
30
  });
31
31
  var DEFAULT_TTL_MS = 60 * 1e3;
@@ -111,6 +111,12 @@ var KEY_FORMAT_PREFIXES = [
111
111
  var MAX_HEADERS = 64;
112
112
  var MAX_HEADER_VALUE_BYTES = 1024;
113
113
  var MAX_TOTAL_BYTES = 16 * 1024;
114
+ var DECLARED_SOURCE_MAX = 64;
115
+ var DECLARED_SOURCE_PATTERN = /^[a-z0-9][a-z0-9 ._/-]{0,63}$/;
116
+ function normalizeDeclaredSource(value) {
117
+ const trimmed = value?.trim().slice(0, DECLARED_SOURCE_MAX).toLowerCase();
118
+ return trimmed && DECLARED_SOURCE_PATTERN.test(trimmed) ? trimmed : void 0;
119
+ }
114
120
  function byteLength(s) {
115
121
  let bytes = 0;
116
122
  for (let i = 0; i < s.length; i++) {
@@ -214,7 +220,20 @@ var PLATFORM_AGENT_SIGNATURES = [
214
220
  {
215
221
  vendor: "gemini",
216
222
  displayName: "Google Gemini",
217
- uaPatterns: [/gemini/i, /google-gemini/i, /bard/i],
223
+ uaPatterns: [
224
+ /gemini/i,
225
+ /google-gemini/i,
226
+ /bard/i,
227
+ // Google's AI/agent fetcher tokens (VI uplift 1.3). These are the
228
+ // AI-training/agent crawlers, NOT the Search crawler — googlebot IP
229
+ // ranges attribute Search and are deliberately absent from
230
+ // vendor-ip-ranges. Anchored tokens: none appears in stock browser
231
+ // UAs, and `-` counts as a \b boundary so GoogleOther-Image/-Video
232
+ // match too.
233
+ /\bGoogle-Extended\b/i,
234
+ /\bGoogleOther\b/i,
235
+ /\bGoogle-CloudVertexBot\b/i
236
+ ],
218
237
  agentCardPatterns: [/gemini\.google\.com/i, /ai\.google\.dev/i],
219
238
  apiKeyFormatPatterns: [/^aiza/i],
220
239
  headerPatterns: [/^x-goog-user-project/i, /^x-goog-api-client/i]
@@ -260,6 +279,16 @@ var PLATFORM_AGENT_SIGNATURES = [
260
279
  uaPatterns: [/\bcomet\/\d/i],
261
280
  headerPatterns: [/^sec-ch-ua: .*comet/i]
262
281
  },
282
+ // The MCP bridge's own catalog fetches (VI uplift 1.5). Deliberately a
283
+ // DISTINCT UA from `astrasync-sdk/`: bridge fetches are buyer-agent
284
+ // traffic merchants should see (identified · unregistered), so this
285
+ // vendor is kept OUT of the self-traffic filter and the edge's SELF
286
+ // short-circuit.
287
+ {
288
+ vendor: "astrasync-bridge",
289
+ displayName: "AstraSync MCP bridge (buyer-agent catalog fetch)",
290
+ uaPatterns: [/^astrasync-bridge\//i]
291
+ },
263
292
  // Our own SDK self-identifies (sdkFetch stamps this UA) — first-party
264
293
  // traffic must never pollute the unknown/anonymous pool it exists to audit.
265
294
  {
@@ -790,7 +819,7 @@ async function verify(config, request, options) {
790
819
  name: apiResponse.agent.name,
791
820
  trustScore: apiResponse.agent.trustScore,
792
821
  trustLevel: getTrustLevel(apiResponse.agent.trustScore),
793
- blockchainVerified: apiResponse.agent.blockchainStatus === "verified",
822
+ blockchainAnchored: apiResponse.agent.blockchainStatus === "anchored",
794
823
  status: apiResponse.agent.agentStatus
795
824
  } : void 0;
796
825
  const developer = apiResponse.developer ? {
@@ -890,10 +919,24 @@ function requestUrl(req, host) {
890
919
  const qs = req.querystring ? `?${req.querystring}` : "";
891
920
  return `https://${host}${req.uri}${qs}`;
892
921
  }
893
- function buildObservedMetadata(req) {
922
+ var ATTEMPT_ID_RE = /^att_[0-9a-f]{32}$/;
923
+ function extractAttemptId(req) {
924
+ const header = headerValue(req, "x-astra-attempt-id");
925
+ if (header && ATTEMPT_ID_RE.test(header)) return header;
926
+ if (req.querystring) {
927
+ try {
928
+ const fromQuery = new URLSearchParams(req.querystring).get("astra_attempt");
929
+ if (fromQuery && ATTEMPT_ID_RE.test(fromQuery)) return fromQuery;
930
+ } catch {
931
+ }
932
+ }
933
+ return void 0;
934
+ }
935
+ function buildObservedMetadata(req, queryValueAllowlist) {
894
936
  const { headers, apiKeyFormat, platformHeaders, cookieCount } = sanitizeHeaders(req.headers);
895
937
  const connection = req.connection ?? {};
896
938
  const queryKeys = extractQueryKeys(req.querystring);
939
+ const queryParams = extractAllowlistedQueryParams(req.querystring, queryValueAllowlist);
897
940
  return {
898
941
  headers,
899
942
  ...apiKeyFormat && { apiKeyFormat },
@@ -901,6 +944,7 @@ function buildObservedMetadata(req) {
901
944
  ...Object.keys(connection).length > 0 && { connection },
902
945
  ...cookieCount !== void 0 && { cookieCount },
903
946
  ...queryKeys && { queryKeys },
947
+ ...queryParams && { queryParams },
904
948
  schemaVersion: CAPTURE_SCHEMA_VERSION
905
949
  };
906
950
  }
@@ -924,6 +968,29 @@ function extractQueryKeys(querystring) {
924
968
  }
925
969
  return keys.length > 0 ? keys : void 0;
926
970
  }
971
+ var MAX_QUERY_PARAMS = 16;
972
+ var MAX_QUERY_VALUE_CHARS = 256;
973
+ function extractAllowlistedQueryParams(querystring, allowlist) {
974
+ if (!querystring || !allowlist || allowlist.length === 0) return void 0;
975
+ let params;
976
+ try {
977
+ params = new URLSearchParams(querystring);
978
+ } catch {
979
+ return void 0;
980
+ }
981
+ const matches = (name) => allowlist.some(
982
+ (entry) => entry.endsWith("*") ? name.startsWith(entry.slice(0, -1)) : name === entry
983
+ );
984
+ const out = {};
985
+ let count = 0;
986
+ for (const [key, value] of params.entries()) {
987
+ const name = key.toLowerCase().slice(0, MAX_QUERY_KEY_CHARS);
988
+ if (!name || out[name] !== void 0 || !matches(name)) continue;
989
+ out[name] = value.slice(0, MAX_QUERY_VALUE_CHARS);
990
+ if (++count >= MAX_QUERY_PARAMS) break;
991
+ }
992
+ return count > 0 ? out : void 0;
993
+ }
927
994
 
928
995
  // src/edge-core/detect.ts
929
996
  var SD_JWT_PATTERN = /^eyJ[\w-]+\.[\w-]*\.[\w-]+~/;
@@ -1083,7 +1150,8 @@ function resolvePolicy(config, path) {
1083
1150
  return {
1084
1151
  mode: rule.mode ?? config.mode,
1085
1152
  depth: rule.depth ?? config.depth,
1086
- skip: rule.skip === true
1153
+ skip: rule.skip === true,
1154
+ ...rule.sampling && { sampling: rule.sampling }
1087
1155
  };
1088
1156
  }
1089
1157
  function classify(req, host, depth) {
@@ -1377,7 +1445,9 @@ async function withBudget(promise, ms) {
1377
1445
  if (timer) clearTimeout(timer);
1378
1446
  }
1379
1447
  }
1380
- async function emitBeacon(options, req, classification, budgetMs) {
1448
+ async function emitBeacon(options, req, classification, budgetMs, queryValueAllowlist) {
1449
+ const attemptId = extractAttemptId(req);
1450
+ const declaredSource = normalizeDeclaredSource(headerValue(req, "x-astra-source"));
1381
1451
  const budgeted = withBudget(
1382
1452
  reportUnregisteredAttempt(
1383
1453
  { apiBaseUrl: options.apiBaseUrl, counterpartyId: options.counterpartyId },
@@ -1388,12 +1458,20 @@ async function emitBeacon(options, req, classification, budgetMs) {
1388
1458
  userAgent: headerValue(req, "user-agent"),
1389
1459
  requestPath: req.uri,
1390
1460
  requestMethod: req.method,
1461
+ // Attempt-chain handle (header or ?astra_attempt= deep link) — joins
1462
+ // this beacon into the agent's research chain via pe_attempt_idx.
1463
+ ...attemptId && { attemptId },
1464
+ // First-class referer + accept: traffic-source and surface-classifier
1465
+ // inputs (previously buried inside observedMetadata.headers).
1466
+ referer: headerValue(req, "referer"),
1467
+ accept: headerValue(req, "accept"),
1468
+ ...declaredSource && { declaredSource },
1391
1469
  // Evidence fields the backend persists into the event record.
1392
1470
  protocol: classification.protocol,
1393
1471
  evidence: classification.evidence,
1394
1472
  // The full sanitized header + connection capture for the
1395
1473
  // unregistered caller (fire-and-forget, so free).
1396
- observedMetadata: buildObservedMetadata(req)
1474
+ observedMetadata: buildObservedMetadata(req, queryValueAllowlist)
1397
1475
  }
1398
1476
  ),
1399
1477
  budgetMs
@@ -1419,13 +1497,14 @@ function baseOutcome(classification) {
1419
1497
  protocol: classification.protocol
1420
1498
  };
1421
1499
  }
1422
- function buildVerificationRequest(options, req, classification, includeArtifacts) {
1500
+ function buildVerificationRequest(options, req, classification, includeArtifacts, queryValueAllowlist) {
1423
1501
  const pdlss = resolveHttpPdlss({
1424
1502
  method: req.method,
1425
1503
  astraPurpose: headerValue(req, "x-astra-purpose"),
1426
1504
  astraAction: headerValue(req, "x-astra-action")
1427
1505
  });
1428
1506
  const attemptId = headerValue(req, "x-astra-attempt-id");
1507
+ const declaredSource = normalizeDeclaredSource(headerValue(req, "x-astra-source"));
1429
1508
  return {
1430
1509
  ...attemptId && /^att_[0-9a-f]{32}$/.test(attemptId) && { attemptId },
1431
1510
  credentials: extractCredentials(req.headers, {}),
@@ -1440,10 +1519,11 @@ function buildVerificationRequest(options, req, classification, includeArtifacts
1440
1519
  userAgent: headerValue(req, "user-agent"),
1441
1520
  referer: headerValue(req, "referer"),
1442
1521
  host: headerValue(req, "host"),
1522
+ ...declaredSource && { declaredSource },
1443
1523
  // The full sanitized header + connection capture. The backend stores
1444
1524
  // it fire-and-forget (zero decision latency) and uses the key-format
1445
1525
  // / platform headers for attribution.
1446
- observedMetadata: buildObservedMetadata(req)
1526
+ observedMetadata: buildObservedMetadata(req, queryValueAllowlist)
1447
1527
  },
1448
1528
  ...includeArtifacts && classification.artifacts && { commerceArtifacts: classification.artifacts }
1449
1529
  };
@@ -1490,7 +1570,8 @@ function unavailableOutcome(classification, policy, reason, correlationId) {
1490
1570
  function isApiErrorResult(result) {
1491
1571
  return (result.failures ?? []).some((f) => f.dimension === "verify_access.api_error") === true && !result.misconfigured;
1492
1572
  }
1493
- async function runTier(options, req, classification, policy, apiKey, sampling) {
1573
+ async function runTier(options, req, classification, policy, apiKey, capture) {
1574
+ const { sampling, queryValueAllowlist } = capture;
1494
1575
  const budgets = options.budgets ?? {};
1495
1576
  const beaconMs = budgets.beaconMs ?? 300;
1496
1577
  const verifyMs = policy.mode === "enforce" ? budgets.verifyEnforceMs ?? 3e3 : budgets.verifyObserveMs ?? 1500;
@@ -1511,7 +1592,13 @@ async function runTier(options, req, classification, policy, apiKey, sampling) {
1511
1592
  const result = await withBudget(
1512
1593
  verify(
1513
1594
  gatewayConfig,
1514
- buildVerificationRequest(options, req, classification, policy.depth === "authorize")
1595
+ buildVerificationRequest(
1596
+ options,
1597
+ req,
1598
+ classification,
1599
+ policy.depth === "authorize",
1600
+ queryValueAllowlist
1601
+ )
1515
1602
  ),
1516
1603
  verifyMs
1517
1604
  );
@@ -1535,7 +1622,10 @@ async function runTier(options, req, classification, policy, apiKey, sampling) {
1535
1622
  case "identified": {
1536
1623
  if (policy.depth === "authorize" && classification.artifacts) {
1537
1624
  const result = await withBudget(
1538
- verify(gatewayConfig, buildVerificationRequest(options, req, classification, true)),
1625
+ verify(
1626
+ gatewayConfig,
1627
+ buildVerificationRequest(options, req, classification, true, queryValueAllowlist)
1628
+ ),
1539
1629
  verifyMs
1540
1630
  );
1541
1631
  if (!result) {
@@ -1555,7 +1645,7 @@ async function runTier(options, req, classification, policy, apiKey, sampling) {
1555
1645
  }
1556
1646
  return outcomeFromVerifyResult(classification, result);
1557
1647
  }
1558
- await emitBeacon(options, req, classification, beaconMs);
1648
+ await emitBeacon(options, req, classification, beaconMs, queryValueAllowlist);
1559
1649
  const outcome = baseOutcome(classification);
1560
1650
  if (policy.mode === "enforce" && policy.depth !== "classify") {
1561
1651
  outcome.decision = "deny";
@@ -1569,7 +1659,8 @@ async function runTier(options, req, classification, policy, apiKey, sampling) {
1569
1659
  options,
1570
1660
  req,
1571
1661
  { ...classification, protocol: classification.protocol ?? "ua-heuristic" },
1572
- beaconMs
1662
+ beaconMs,
1663
+ queryValueAllowlist
1573
1664
  );
1574
1665
  }
1575
1666
  return baseOutcome(classification);
@@ -1596,7 +1687,10 @@ async function evaluateEdgeRequest(options, req, config, apiKey) {
1596
1687
  if (classification.tier === "human" || classification.tier === "self") {
1597
1688
  return { policy, classification, application: passUntouched() };
1598
1689
  }
1599
- const outcome = await runTier(options, req, classification, policy, apiKey, config.sampling);
1690
+ const outcome = await runTier(options, req, classification, policy, apiKey, {
1691
+ sampling: policy.sampling ?? config.sampling,
1692
+ queryValueAllowlist: config.queryValueAllowlist
1693
+ });
1600
1694
  if (outcome.decision !== "allow") {
1601
1695
  options.log?.(
1602
1696
  "info",