@astrasyncai/verification-gateway 5.18.1 → 5.19.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 (113) hide show
  1. package/CHANGELOG.md +149 -0
  2. package/README.md +168 -4
  3. package/dist/adapters/express.d.mts +9 -1
  4. package/dist/adapters/express.d.ts +9 -1
  5. package/dist/adapters/express.js +96 -37
  6. package/dist/adapters/express.js.map +1 -1
  7. package/dist/adapters/express.mjs +96 -37
  8. package/dist/adapters/express.mjs.map +1 -1
  9. package/dist/adapters/http-pdlss.d.mts +7 -1
  10. package/dist/adapters/http-pdlss.d.ts +7 -1
  11. package/dist/adapters/http-pdlss.js +18 -2
  12. package/dist/adapters/http-pdlss.js.map +1 -1
  13. package/dist/adapters/http-pdlss.mjs +16 -1
  14. package/dist/adapters/http-pdlss.mjs.map +1 -1
  15. package/dist/adapters/kit-express.d.mts +93 -1
  16. package/dist/adapters/kit-express.d.ts +93 -1
  17. package/dist/adapters/kit-express.js +181 -2
  18. package/dist/adapters/kit-express.js.map +1 -1
  19. package/dist/adapters/kit-express.mjs +180 -2
  20. package/dist/adapters/kit-express.mjs.map +1 -1
  21. package/dist/adapters/mcp.d.mts +80 -9
  22. package/dist/adapters/mcp.d.ts +80 -9
  23. package/dist/adapters/mcp.js +153 -5
  24. package/dist/adapters/mcp.js.map +1 -1
  25. package/dist/adapters/mcp.mjs +151 -5
  26. package/dist/adapters/mcp.mjs.map +1 -1
  27. package/dist/adapters/nextjs.d.mts +1 -1
  28. package/dist/adapters/nextjs.d.ts +1 -1
  29. package/dist/adapters/nextjs.js +41 -4
  30. package/dist/adapters/nextjs.js.map +1 -1
  31. package/dist/adapters/nextjs.mjs +41 -4
  32. package/dist/adapters/nextjs.mjs.map +1 -1
  33. package/dist/adapters/sdk.d.mts +44 -1
  34. package/dist/adapters/sdk.d.ts +44 -1
  35. package/dist/adapters/sdk.js +76 -2
  36. package/dist/adapters/sdk.js.map +1 -1
  37. package/dist/adapters/sdk.mjs +76 -2
  38. package/dist/adapters/sdk.mjs.map +1 -1
  39. package/dist/agent/index.js +1 -1
  40. package/dist/agent/index.js.map +1 -1
  41. package/dist/agent/index.mjs +1 -1
  42. package/dist/agent/index.mjs.map +1 -1
  43. package/dist/bin/astrasync-claude-hook.js +46 -6
  44. package/dist/bin/astrasync-codex-hook.js +46 -6
  45. package/dist/bin/astrasync-guard.js +46 -6
  46. package/dist/bin/astrasync.js +77 -5
  47. package/dist/browser/background.js +46 -6
  48. package/dist/browser/background.js.map +1 -1
  49. package/dist/browser/background.mjs +46 -6
  50. package/dist/browser/background.mjs.map +1 -1
  51. package/dist/cli/index.js +1 -1
  52. package/dist/cli/index.js.map +1 -1
  53. package/dist/cli/index.mjs +1 -1
  54. package/dist/cli/index.mjs.map +1 -1
  55. package/dist/codex/index.js +46 -6
  56. package/dist/codex/index.js.map +1 -1
  57. package/dist/codex/index.mjs +46 -6
  58. package/dist/codex/index.mjs.map +1 -1
  59. package/dist/cursor/extension.js +46 -6
  60. package/dist/cursor/extension.js.map +1 -1
  61. package/dist/cursor/extension.mjs +46 -6
  62. package/dist/cursor/extension.mjs.map +1 -1
  63. package/dist/edge-config.d.mts +1 -1
  64. package/dist/edge-config.d.ts +1 -1
  65. package/dist/edge-config.js +1 -1
  66. package/dist/edge-config.js.map +1 -1
  67. package/dist/edge-config.mjs +1 -1
  68. package/dist/edge-config.mjs.map +1 -1
  69. package/dist/edge-core/index.d.mts +1 -1
  70. package/dist/edge-core/index.d.ts +1 -1
  71. package/dist/edge-core/index.js +21 -2
  72. package/dist/edge-core/index.js.map +1 -1
  73. package/dist/edge-core/index.mjs +21 -2
  74. package/dist/edge-core/index.mjs.map +1 -1
  75. package/dist/gateway/gateway.js +46 -6
  76. package/dist/gateway/gateway.js.map +1 -1
  77. package/dist/gateway/gateway.mjs +46 -6
  78. package/dist/gateway/gateway.mjs.map +1 -1
  79. package/dist/git-trigger/git-hooks.d.mts +1 -1
  80. package/dist/git-trigger/git-hooks.d.ts +1 -1
  81. package/dist/index.d.mts +541 -29
  82. package/dist/index.d.ts +541 -29
  83. package/dist/index.js +1171 -183
  84. package/dist/index.js.map +1 -1
  85. package/dist/index.mjs +1157 -173
  86. package/dist/index.mjs.map +1 -1
  87. package/dist/registration/index.js +1 -1
  88. package/dist/registration/index.js.map +1 -1
  89. package/dist/registration/index.mjs +1 -1
  90. package/dist/registration/index.mjs.map +1 -1
  91. package/dist/transport/index.js +3 -2
  92. package/dist/transport/index.js.map +1 -1
  93. package/dist/transport/index.mjs +3 -2
  94. package/dist/transport/index.mjs.map +1 -1
  95. package/dist/{types-3ObBpsnf.d.mts → types-BoGjyon0.d.mts} +81 -2
  96. package/dist/{types-Cns4l8gX.d.mts → types-DqWPkiYl.d.mts} +90 -12
  97. package/dist/{types-Cns4l8gX.d.ts → types-DqWPkiYl.d.ts} +90 -12
  98. package/dist/{types-BoxZEYPS.d.ts → types-eWyZuz-3.d.ts} +81 -2
  99. package/dist/ui/index.d.mts +1 -1
  100. package/dist/ui/index.d.ts +1 -1
  101. package/dist/verify.d.mts +23 -2
  102. package/dist/verify.d.ts +23 -2
  103. package/dist/verify.js +23 -4
  104. package/dist/verify.js.map +1 -1
  105. package/dist/verify.mjs +23 -4
  106. package/dist/verify.mjs.map +1 -1
  107. package/dist/webhooks.d.mts +16 -3
  108. package/dist/webhooks.d.ts +16 -3
  109. package/dist/webhooks.js +24 -13
  110. package/dist/webhooks.js.map +1 -1
  111. package/dist/webhooks.mjs +24 -13
  112. package/dist/webhooks.mjs.map +1 -1
  113. package/package.json +1 -1
@@ -452,7 +452,7 @@ function routePolicyOf(route) {
452
452
  }
453
453
 
454
454
  // src/version.ts
455
- var SDK_VERSION = "5.18.1";
455
+ var SDK_VERSION = "5.19.0";
456
456
 
457
457
  // src/http.ts
458
458
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -770,7 +770,12 @@ function getCacheKey(request, counterpartyId) {
770
770
  // its start_checkout quote was served the cached quote-leg grant (no
771
771
  // settlementOutcome) and never reached the backend. Same F-A1-07 bug class.
772
772
  request.commercePhase || "",
773
- request.checkoutSessionId || ""
773
+ request.checkoutSessionId || "",
774
+ // 5.19.0: a route_config purpose claim is checked server-side against
775
+ // the stored rule for this method + path, so it changes the verdict.
776
+ request.purposeSource || "",
777
+ request.requestMethod || "",
778
+ request.requestPath || ""
774
779
  ].join("|");
775
780
  }
776
781
  function getCachedResult(request, counterpartyId) {
@@ -978,6 +983,11 @@ async function callVerifyAccessAPI(config, request) {
978
983
  if (requestData.buyerEmail) body.buyerEmail = requestData.buyerEmail;
979
984
  if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
980
985
  if (requestData.attemptId) body.attemptId = requestData.attemptId;
986
+ if (requestData.purposeSource) body.purposeSource = requestData.purposeSource;
987
+ if (requestData.agentArtifacts) body.agentArtifacts = requestData.agentArtifacts;
988
+ if (requestData.metadata) body.metadata = requestData.metadata;
989
+ if (requestData.requestMethod) body.requestMethod = requestData.requestMethod;
990
+ if (requestData.requestPath) body.requestPath = requestData.requestPath;
981
991
  if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;
982
992
  body.sdkVersion = SDK_VERSION;
983
993
  if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
@@ -1167,9 +1177,18 @@ async function verify(config, request, options) {
1167
1177
  if (!apiResponse.access?.allowed) {
1168
1178
  const aggregatedFailures = apiResponse.access?.failures;
1169
1179
  const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true && !aggregatedFailures?.some((f) => REJECTED_IDENTITY_DIMENSIONS.has(f.dimension));
1180
+ const denyAgent = idVerifiedFromBackend && apiResponse.agent ? {
1181
+ astraId: apiResponse.agent.astraId,
1182
+ name: apiResponse.agent.name,
1183
+ trustScore: apiResponse.agent.trustScore,
1184
+ trustLevel: getTrustLevel(apiResponse.agent.trustScore),
1185
+ blockchainAnchored: apiResponse.agent.blockchainStatus === "anchored",
1186
+ status: apiResponse.agent.agentStatus
1187
+ } : void 0;
1170
1188
  const result2 = {
1171
1189
  identityVerified: idVerifiedFromBackend,
1172
1190
  policyAllowed: false,
1191
+ ...denyAgent && { agent: denyAgent },
1173
1192
  // 3.6.0: the server now emits top-level denialReasons on every deny
1174
1193
  // path — prefer it verbatim; the failure-message reconstruction remains
1175
1194
  // as the fallback for older backends.
@@ -1319,7 +1338,7 @@ async function recordDecision(config, sessionId, decision, reason) {
1319
1338
  });
1320
1339
  }
1321
1340
  var refusedPolicyReads = /* @__PURE__ */ new Set();
1322
- async function fetchRoutes(config, counterpartyId) {
1341
+ async function fetchRoutes(config, counterpartyId, options = {}) {
1323
1342
  if (!counterpartyId) return null;
1324
1343
  const headers = { "Content-Type": "application/json" };
1325
1344
  if (config.apiKey) {
@@ -1328,7 +1347,7 @@ async function fetchRoutes(config, counterpartyId) {
1328
1347
  }
1329
1348
  try {
1330
1349
  const response = await sdkFetch(
1331
- `${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,
1350
+ `${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes` + (options.codeGates?.length ? `?codeGates=${options.codeGates.map(encodeURIComponent).join(",")}` : ""),
1332
1351
  { method: "GET", headers }
1333
1352
  );
1334
1353
  if (!response.ok) {
@@ -1374,6 +1393,42 @@ async function reportCounterpartyPreCheckFailure(config, data) {
1374
1393
  });
1375
1394
  }
1376
1395
 
1396
+ // src/adapters/routes-cache.ts
1397
+ var DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1e3;
1398
+ function createRoutesCache(config, opts = {}) {
1399
+ const refreshMs = opts.refreshMs ?? DEFAULT_ROUTES_REFRESH_MS;
1400
+ let cached = [];
1401
+ let lastFetchAt = 0;
1402
+ let refreshing = null;
1403
+ async function refresh() {
1404
+ if (!config.counterpartyId) {
1405
+ opts.onNoCounterparty?.();
1406
+ return;
1407
+ }
1408
+ const fetched = await fetchRoutes(config, config.counterpartyId, opts.fetchOptions);
1409
+ if (fetched) {
1410
+ cached = fetched;
1411
+ lastFetchAt = Date.now();
1412
+ opts.onFetched?.(fetched);
1413
+ }
1414
+ }
1415
+ function start() {
1416
+ refreshing = refresh().catch(() => void 0).finally(() => {
1417
+ refreshing = null;
1418
+ });
1419
+ }
1420
+ start();
1421
+ return {
1422
+ async current() {
1423
+ if (refreshing) await refreshing.catch(() => {
1424
+ });
1425
+ if (config.counterpartyId && Date.now() - lastFetchAt > refreshMs) start();
1426
+ return cached;
1427
+ },
1428
+ peek: () => cached
1429
+ };
1430
+ }
1431
+
1377
1432
  // src/transport/http.ts
1378
1433
  var HEADER_PREFIX = "X-Astra-";
1379
1434
  function extractHttpCredentials(headers) {
@@ -1523,6 +1578,20 @@ function resolveHttpPdlss(input) {
1523
1578
  }
1524
1579
  return { purpose, action, purposeSource, actionSource };
1525
1580
  }
1581
+ function wirePurposeSource(source) {
1582
+ switch (source) {
1583
+ case "route_config":
1584
+ return "route_config";
1585
+ case "header":
1586
+ case "legacy_header":
1587
+ case "query":
1588
+ return "header";
1589
+ case "custom_extractor":
1590
+ return "body";
1591
+ default:
1592
+ return "default";
1593
+ }
1594
+ }
1526
1595
 
1527
1596
  // src/adapters/approval-gate.ts
1528
1597
  var APPROVAL_REASON = "Transaction is above the autonomous limit and requires human approval. The agent owner can approve or deny this transaction in the AstraSync dashboard.";
@@ -2323,7 +2392,6 @@ function defaultOnDenied(result, _req, res) {
2323
2392
  }
2324
2393
  });
2325
2394
  }
2326
- var DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1e3;
2327
2395
  function createMiddleware(options) {
2328
2396
  if ("routes" in options) {
2329
2397
  console.warn(
@@ -2339,7 +2407,7 @@ function createMiddleware(options) {
2339
2407
  recordDecisions,
2340
2408
  enableRuntimeChallenge = true,
2341
2409
  routesRefreshMs = DEFAULT_ROUTES_REFRESH_MS,
2342
- failOnError = "open",
2410
+ failOnError = "closed",
2343
2411
  caseInsensitiveRouteMatch = false,
2344
2412
  anonymousBeacon = true,
2345
2413
  trustVerifiedHop = false,
@@ -2363,26 +2431,19 @@ function createMiddleware(options) {
2363
2431
  rawHeaders: req.headers
2364
2432
  });
2365
2433
  } : void 0;
2366
- let cachedRoutes = [];
2367
- let lastFetchAt = 0;
2368
- let refreshing = null;
2369
2434
  let warnedNoCounterparty = false;
2370
2435
  let warnedEmptyRoutes = false;
2371
- async function refreshRoutes() {
2372
- if (!config.counterpartyId) {
2373
- if (!warnedNoCounterparty) {
2374
- console.warn(
2375
- "[VerificationGateway] No counterpartyId configured \u2014 falling through (allow all). Per-route policy lives in the AstraSync dashboard now; register the endpoint and set counterpartyId in your middleware config to enforce policy."
2376
- );
2377
- warnedNoCounterparty = true;
2378
- }
2379
- return;
2380
- }
2381
- const fetched = await fetchRoutes(config, config.counterpartyId);
2382
- if (fetched) {
2383
- cachedRoutes = fetched;
2384
- lastFetchAt = Date.now();
2385
- if (cachedRoutes.length === 0 && !warnedEmptyRoutes) {
2436
+ const routesCache = createRoutesCache(config, {
2437
+ refreshMs: routesRefreshMs,
2438
+ onNoCounterparty: () => {
2439
+ if (warnedNoCounterparty) return;
2440
+ console.warn(
2441
+ "[VerificationGateway] No counterpartyId configured \u2014 falling through (allow all). Per-route policy lives in the AstraSync dashboard now; register the endpoint and set counterpartyId in your middleware config to enforce policy."
2442
+ );
2443
+ warnedNoCounterparty = true;
2444
+ },
2445
+ onFetched: (routes) => {
2446
+ if (routes.length === 0 && !warnedEmptyRoutes) {
2386
2447
  const dashboard = config.dashboardUrl ?? "https://astrasync.ai/dashboard";
2387
2448
  console.warn(
2388
2449
  `[VerificationGateway] No route policy configured for ${config.counterpartyId}. Gateway is in pass-through mode for ALL traffic until you add at least one route. Configure at ${dashboard}/dashboard/endpoints/${config.counterpartyId}/routes`
@@ -2390,9 +2451,6 @@ function createMiddleware(options) {
2390
2451
  warnedEmptyRoutes = true;
2391
2452
  }
2392
2453
  }
2393
- }
2394
- refreshing = refreshRoutes().finally(() => {
2395
- refreshing = null;
2396
2454
  });
2397
2455
  return async (req, res, next) => {
2398
2456
  try {
@@ -2400,15 +2458,9 @@ function createMiddleware(options) {
2400
2458
  if (shouldSkip) {
2401
2459
  return next();
2402
2460
  }
2403
- if (refreshing) {
2404
- await refreshing.catch(() => {
2405
- });
2406
- }
2407
- if (config.counterpartyId && Date.now() - lastFetchAt > routesRefreshMs) {
2408
- refreshing = refreshRoutes().finally(() => {
2409
- refreshing = null;
2410
- });
2411
- }
2461
+ const cachedRoutes = (await routesCache.current()).filter(
2462
+ (r) => typeof r.pattern === "string" && !r.tool
2463
+ );
2412
2464
  const correlationId = req.headers["x-request-id"] || req.headers["x-correlation-id"];
2413
2465
  const matchedRoute = findRouteConfig(cachedRoutes, req.path, req.method, {
2414
2466
  caseInsensitive: caseInsensitiveRouteMatch,
@@ -2532,6 +2584,12 @@ function createMiddleware(options) {
2532
2584
  ...commerceArtifacts && { commerceArtifacts },
2533
2585
  purpose,
2534
2586
  action: pdlssPair.action,
2587
+ // 5.19.0: the source + the request line let verify-access check a
2588
+ // route purpose against the stored rule (item 20: an MPP paid leg
2589
+ // keeps `shopping.purchase` instead of `commerce.payment.execute`).
2590
+ purposeSource: wirePurposeSource(pdlssPair.purposeSource),
2591
+ requestMethod: req.method,
2592
+ requestPath: req.path,
2535
2593
  resource: req.path,
2536
2594
  createSession: shouldRecordDecisions,
2537
2595
  counterpartyUrl,
@@ -2609,7 +2667,8 @@ function createMiddleware(options) {
2609
2667
  return;
2610
2668
  }
2611
2669
  if (routeConfig.minTrustScore && result.agent) {
2612
- if (result.agent.trustScore < routeConfig.minTrustScore) {
2670
+ const score = result.agent.trustScore;
2671
+ if (typeof score !== "number" || score < routeConfig.minTrustScore) {
2613
2672
  const trustFailure = {
2614
2673
  dimension: "endpoint.trust",
2615
2674
  message: "Trust below the route requirement for this endpoint.",