@astrasyncai/verification-gateway 5.19.0 → 5.21.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 (111) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +53 -4
  3. package/dist/adapter-interface/interface.d.mts +2 -2
  4. package/dist/adapter-interface/interface.d.ts +2 -2
  5. package/dist/adapters/express.d.mts +1 -1
  6. package/dist/adapters/express.d.ts +1 -1
  7. package/dist/adapters/express.js +65 -16
  8. package/dist/adapters/express.js.map +1 -1
  9. package/dist/adapters/express.mjs +65 -16
  10. package/dist/adapters/express.mjs.map +1 -1
  11. package/dist/adapters/mcp.d.mts +23 -1
  12. package/dist/adapters/mcp.d.ts +23 -1
  13. package/dist/adapters/mcp.js +91 -16
  14. package/dist/adapters/mcp.js.map +1 -1
  15. package/dist/adapters/mcp.mjs +91 -16
  16. package/dist/adapters/mcp.mjs.map +1 -1
  17. package/dist/adapters/nextjs.d.mts +1 -1
  18. package/dist/adapters/nextjs.d.ts +1 -1
  19. package/dist/adapters/nextjs.js +57 -11
  20. package/dist/adapters/nextjs.js.map +1 -1
  21. package/dist/adapters/nextjs.mjs +57 -11
  22. package/dist/adapters/nextjs.mjs.map +1 -1
  23. package/dist/adapters/sdk.d.mts +35 -2
  24. package/dist/adapters/sdk.d.ts +35 -2
  25. package/dist/adapters/sdk.js +110 -11
  26. package/dist/adapters/sdk.js.map +1 -1
  27. package/dist/adapters/sdk.mjs +110 -11
  28. package/dist/adapters/sdk.mjs.map +1 -1
  29. package/dist/agent/index.d.mts +1 -1
  30. package/dist/agent/index.d.ts +1 -1
  31. package/dist/agent/index.js +1 -1
  32. package/dist/agent/index.js.map +1 -1
  33. package/dist/agent/index.mjs +1 -1
  34. package/dist/agent/index.mjs.map +1 -1
  35. package/dist/bin/astrasync-claude-hook.js +50 -12
  36. package/dist/bin/astrasync-codex-hook.js +50 -12
  37. package/dist/bin/astrasync-guard.js +50 -12
  38. package/dist/bin/astrasync.js +65 -13
  39. package/dist/browser/background.js +50 -12
  40. package/dist/browser/background.js.map +1 -1
  41. package/dist/browser/background.mjs +50 -12
  42. package/dist/browser/background.mjs.map +1 -1
  43. package/dist/cli/index.js +1 -1
  44. package/dist/cli/index.js.map +1 -1
  45. package/dist/cli/index.mjs +1 -1
  46. package/dist/cli/index.mjs.map +1 -1
  47. package/dist/codex/index.js +50 -12
  48. package/dist/codex/index.js.map +1 -1
  49. package/dist/codex/index.mjs +50 -12
  50. package/dist/codex/index.mjs.map +1 -1
  51. package/dist/cursor/extension.js +50 -12
  52. package/dist/cursor/extension.js.map +1 -1
  53. package/dist/cursor/extension.mjs +50 -12
  54. package/dist/cursor/extension.mjs.map +1 -1
  55. package/dist/edge-config.d.mts +1 -1
  56. package/dist/edge-config.d.ts +1 -1
  57. package/dist/edge-config.js +1 -1
  58. package/dist/edge-config.js.map +1 -1
  59. package/dist/edge-config.mjs +1 -1
  60. package/dist/edge-config.mjs.map +1 -1
  61. package/dist/edge-core/index.d.mts +1 -1
  62. package/dist/edge-core/index.d.ts +1 -1
  63. package/dist/edge-core/index.js +49 -11
  64. package/dist/edge-core/index.js.map +1 -1
  65. package/dist/edge-core/index.mjs +49 -11
  66. package/dist/edge-core/index.mjs.map +1 -1
  67. package/dist/gateway/gateway.d.mts +2 -2
  68. package/dist/gateway/gateway.d.ts +2 -2
  69. package/dist/gateway/gateway.js +50 -12
  70. package/dist/gateway/gateway.js.map +1 -1
  71. package/dist/gateway/gateway.mjs +50 -12
  72. package/dist/gateway/gateway.mjs.map +1 -1
  73. package/dist/git-trigger/git-hooks.d.mts +1 -1
  74. package/dist/git-trigger/git-hooks.d.ts +1 -1
  75. package/dist/index.d.mts +286 -8
  76. package/dist/index.d.ts +286 -8
  77. package/dist/index.js +532 -49
  78. package/dist/index.js.map +1 -1
  79. package/dist/index.mjs +522 -49
  80. package/dist/index.mjs.map +1 -1
  81. package/dist/local-evaluator/evaluator.d.mts +2 -2
  82. package/dist/local-evaluator/evaluator.d.ts +2 -2
  83. package/dist/registration/index.d.mts +11 -2
  84. package/dist/registration/index.d.ts +11 -2
  85. package/dist/registration/index.js +1 -1
  86. package/dist/registration/index.js.map +1 -1
  87. package/dist/registration/index.mjs +1 -1
  88. package/dist/registration/index.mjs.map +1 -1
  89. package/dist/transport/index.d.mts +1 -1
  90. package/dist/transport/index.d.ts +1 -1
  91. package/dist/transport/index.js +1 -1
  92. package/dist/transport/index.js.map +1 -1
  93. package/dist/transport/index.mjs +1 -1
  94. package/dist/transport/index.mjs.map +1 -1
  95. package/dist/{types-BoGjyon0.d.mts → types-B4zhOAlq.d.mts} +30 -1
  96. package/dist/{types-BRz2U0Pn.d.ts → types-B_HLhZ9n.d.ts} +1 -1
  97. package/dist/{types-BfILnheI.d.mts → types-CU17R4Nr.d.mts} +11 -0
  98. package/dist/{types-BfILnheI.d.ts → types-CU17R4Nr.d.ts} +11 -0
  99. package/dist/{types-eWyZuz-3.d.ts → types-CtBXnWuV.d.ts} +30 -1
  100. package/dist/{types-DqWPkiYl.d.mts → types-DHHyXtuZ.d.mts} +30 -1
  101. package/dist/{types-DqWPkiYl.d.ts → types-DHHyXtuZ.d.ts} +30 -1
  102. package/dist/{types-CfBpm3w5.d.mts → types-Djpz-L0w.d.mts} +1 -1
  103. package/dist/ui/index.d.mts +1 -1
  104. package/dist/ui/index.d.ts +1 -1
  105. package/dist/verify.d.mts +28 -3
  106. package/dist/verify.d.ts +28 -3
  107. package/dist/verify.js +71 -11
  108. package/dist/verify.js.map +1 -1
  109. package/dist/verify.mjs +69 -11
  110. package/dist/verify.mjs.map +1 -1
  111. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var SDK_VERSION = "5.19.0";
2
+ var SDK_VERSION = "5.21.0";
3
3
 
4
4
  // src/http.ts
5
5
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -438,6 +438,9 @@ async function callVerifyAccessAPI(config, request) {
438
438
  if (requestData.enableRuntimeChallenge)
439
439
  body.enableRuntimeChallenge = requestData.enableRuntimeChallenge;
440
440
  if (requestData.routePolicy) body.routePolicy = requestData.routePolicy;
441
+ if (config.actingProof?.connectorToken) {
442
+ body.actingProof = { connectorToken: config.actingProof.connectorToken };
443
+ }
441
444
  if (requestData.approvalHeldByRoute) body.approvalHeldByRoute = true;
442
445
  if (requestData.createSession) body.createSession = requestData.createSession;
443
446
  if (requestData.durationRequired) body.durationRequired = requestData.durationRequired;
@@ -605,22 +608,46 @@ async function verify(config, request, options) {
605
608
  "[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."
606
609
  );
607
610
  }
608
- const uncacheable = Boolean(request.commerceArtifacts);
611
+ const uncacheable = Boolean(request.commerceArtifacts) || Boolean(mergedConfig.actingProof);
609
612
  if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache && !uncacheable) {
610
613
  const cached = getCachedResult(request, mergedConfig.counterpartyId);
611
614
  if (cached) {
612
615
  if (mergedConfig.debug) {
613
616
  console.log("[VerificationGateway] Returning cached result");
614
617
  }
615
- const hit = { ...cached };
616
- if (request.attemptId) {
617
- hit.attemptId = request.attemptId;
618
- } else {
619
- delete hit.attemptId;
620
- }
621
- return hit;
618
+ return sharedVerdict(cached, request);
619
+ }
620
+ }
621
+ if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache && !uncacheable) {
622
+ const key = getCacheKey(request, mergedConfig.counterpartyId);
623
+ const pending = inflightVerifies.get(key);
624
+ if (pending) return sharedVerdict(await pending, request);
625
+ const flight = verifyViaApi(mergedConfig, request, urls, uncacheable);
626
+ inflightVerifies.set(key, flight);
627
+ try {
628
+ return await flight;
629
+ } finally {
630
+ inflightVerifies.delete(key);
622
631
  }
623
632
  }
633
+ return verifyViaApi(mergedConfig, request, urls, uncacheable);
634
+ }
635
+ var inflightVerifies = /* @__PURE__ */ new Map();
636
+ var sharedVerdicts = /* @__PURE__ */ new WeakSet();
637
+ function isSharedVerdict(result) {
638
+ return sharedVerdicts.has(result);
639
+ }
640
+ function sharedVerdict(source, request) {
641
+ const hit = { ...source };
642
+ if (request.attemptId) {
643
+ hit.attemptId = request.attemptId;
644
+ } else {
645
+ delete hit.attemptId;
646
+ }
647
+ sharedVerdicts.add(hit);
648
+ return hit;
649
+ }
650
+ async function verifyViaApi(mergedConfig, request, urls, uncacheable) {
624
651
  const enrichedRequest = { ...request };
625
652
  if (!enrichedRequest.counterpartyUrl && mergedConfig.counterpartyUrl) {
626
653
  enrichedRequest.counterpartyUrl = mergedConfig.counterpartyUrl;
@@ -699,7 +726,9 @@ async function verify(config, request, options) {
699
726
  fulfilment: apiResponse.fulfilment,
700
727
  mandates: apiResponse.mandates,
701
728
  kyaToken: apiResponse.kyaToken,
702
- aep: apiResponse.aep
729
+ aep: apiResponse.aep,
730
+ // 5.20.0 (round 29.1): non-fatal integration warnings (e.g. events_url_missing).
731
+ warnings: apiResponse.warnings
703
732
  };
704
733
  return result2;
705
734
  }
@@ -767,7 +796,9 @@ async function verify(config, request, options) {
767
796
  // 5.15.0: merchant-lane AP2 mandates + KYAPay identity token.
768
797
  mandates: apiResponse.mandates,
769
798
  kyaToken: apiResponse.kyaToken,
770
- aep: apiResponse.aep
799
+ aep: apiResponse.aep,
800
+ // 5.20.0 (round 29.1): non-fatal integration warnings (e.g. events_url_missing).
801
+ warnings: apiResponse.warnings
771
802
  };
772
803
  if (result.recommendation === "deny") {
773
804
  result.policyAllowed = false;
@@ -793,8 +824,18 @@ async function verify(config, request, options) {
793
824
  cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
794
825
  }
795
826
  }
827
+ notifyVerificationListeners(request, result);
796
828
  return result;
797
829
  }
830
+ var verificationListeners = /* @__PURE__ */ new Set();
831
+ function notifyVerificationListeners(request, result) {
832
+ for (const listener of verificationListeners) {
833
+ try {
834
+ listener(result, request);
835
+ } catch {
836
+ }
837
+ }
838
+ }
798
839
  async function recordDecision(config, sessionId, decision, reason) {
799
840
  const headers = { "Content-Type": "application/json" };
800
841
  if (config.apiKey) {
@@ -817,6 +858,7 @@ async function fetchRoutes(config, counterpartyId, options = {}) {
817
858
  headers["X-API-Key"] = config.apiKey;
818
859
  }
819
860
  try {
861
+ headers["X-AstraSync-SDK-Version"] = SDK_VERSION;
820
862
  const response = await sdkFetch(
821
863
  `${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes` + (options.codeGates?.length ? `?codeGates=${options.codeGates.map(encodeURIComponent).join(",")}` : ""),
822
864
  { method: "GET", headers }
@@ -831,6 +873,13 @@ async function fetchRoutes(config, counterpartyId, options = {}) {
831
873
  return null;
832
874
  }
833
875
  const body = await response.json();
876
+ const type = body.data?.counterpartyType;
877
+ if (typeof type === "string" && options.onEndpointType) {
878
+ try {
879
+ options.onEndpointType(type);
880
+ } catch {
881
+ }
882
+ }
834
883
  return body.data?.routes ?? [];
835
884
  } catch {
836
885
  return null;
@@ -1479,16 +1528,30 @@ function createMcpMiddleware(options) {
1479
1528
  failOnError = "closed",
1480
1529
  toolGatePrecedence = "code",
1481
1530
  routesRefreshMs,
1531
+ skipEvaluation,
1482
1532
  ...config
1483
1533
  } = options;
1534
+ const skipTools = new Set(skipEvaluation?.tools ?? []);
1535
+ const skipMethods = new Set(skipEvaluation?.methods ?? []);
1484
1536
  if (config.apiBaseUrl) {
1485
1537
  prefetchWellKnown(config.apiBaseUrl).catch(() => {
1486
1538
  });
1487
1539
  }
1488
1540
  const codeGatedTools = Object.entries(toolGates ?? {}).filter(([, g]) => g !== "observe").map(([name]) => name);
1541
+ let warnedEndpointType = false;
1542
+ const onEndpointType = (counterpartyType) => {
1543
+ if (counterpartyType === "mcp_server" || warnedEndpointType) return;
1544
+ warnedEndpointType = true;
1545
+ console.warn(
1546
+ `[VerificationGateway/MCP] counterpartyId ${config.counterpartyId} is a '${counterpartyType}' endpoint, not an 'mcp_server' endpoint. Dashboard tool rules are read from an mcp_server endpoint only: register a separate MCP endpoint for this server (same owner) and use its id here. See https://astrasync.ai/docs/mcp-integration#tool-rules.`
1547
+ );
1548
+ };
1489
1549
  const rulesCache = config.apiKey && config.counterpartyId ? createRoutesCache(config, {
1490
1550
  ...routesRefreshMs !== void 0 && { refreshMs: routesRefreshMs },
1491
- ...codeGatedTools.length && { fetchOptions: { codeGates: codeGatedTools } }
1551
+ fetchOptions: {
1552
+ ...codeGatedTools.length && { codeGates: codeGatedTools },
1553
+ onEndpointType
1554
+ }
1492
1555
  }) : void 0;
1493
1556
  return async (req, res, next) => {
1494
1557
  try {
@@ -1538,6 +1601,9 @@ function createMcpMiddleware(options) {
1538
1601
  return next();
1539
1602
  }
1540
1603
  }
1604
+ if (!parsed.toolName && skipMethods.has(parsed.method) && methodGates?.[parsed.method] === void 0) {
1605
+ return next();
1606
+ }
1541
1607
  const dashboardRules = rulesCache ? dashboardToolRules(await rulesCache.current()) : void 0;
1542
1608
  const gateDecision = resolveGate(parsed, {
1543
1609
  toolGates,
@@ -1545,6 +1611,9 @@ function createMcpMiddleware(options) {
1545
1611
  dashboardRules,
1546
1612
  toolGatePrecedence
1547
1613
  });
1614
+ if (!gateDecision.enforce && (parsed.toolName && skipTools.has(parsed.toolName) || !parsed.toolName && skipMethods.has(parsed.method))) {
1615
+ return next();
1616
+ }
1548
1617
  const credentials = extractCredentials(
1549
1618
  req.headers,
1550
1619
  req.query
@@ -1601,8 +1670,14 @@ function createMcpMiddleware(options) {
1601
1670
  const forwardedFor = req.headers["x-forwarded-for"];
1602
1671
  const forwardedForStr = Array.isArray(forwardedFor) ? forwardedFor.join(", ") : forwardedFor;
1603
1672
  const sourceIp = req.ip ?? (forwardedForStr ? forwardedForStr.split(",")[0].trim() : void 0);
1673
+ const attemptRaw = readSingleHeader(req.headers["x-astra-attempt-id"]);
1674
+ const metaAttempt = req.body?.params?._meta?.astrasync?.attemptId;
1675
+ const attemptId = [attemptRaw, metaAttempt].find(
1676
+ (v) => typeof v === "string" && /^att_[0-9a-f]{32}$/.test(v)
1677
+ );
1604
1678
  const verificationRequest = {
1605
1679
  credentials,
1680
+ ...attemptId && { attemptId },
1606
1681
  purpose: pdlss.purpose,
1607
1682
  action: pdlss.action,
1608
1683
  resource: pdlss.resource,
@@ -1664,14 +1739,14 @@ function createMcpMiddleware(options) {
1664
1739
  res.setHeader("X-Astra-Gateway-Mode", "enforced");
1665
1740
  res.setHeader("X-Astra-Gateway-Reason", "evaluated-not-enforced");
1666
1741
  }
1667
- if (shouldRecordDecisions && sessionId) {
1742
+ if (shouldRecordDecisions && sessionId && !isSharedVerdict(result)) {
1668
1743
  recordDecision(config, sessionId, "granted").catch(() => {
1669
1744
  });
1670
1745
  }
1671
1746
  return next();
1672
1747
  }
1673
1748
  if (!result.policyAllowed) {
1674
- if (shouldRecordDecisions && sessionId) {
1749
+ if (shouldRecordDecisions && sessionId && !isSharedVerdict(result)) {
1675
1750
  recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
1676
1751
  });
1677
1752
  }
@@ -1681,7 +1756,7 @@ function createMcpMiddleware(options) {
1681
1756
  }
1682
1757
  if (requiresHumanApproval(result)) {
1683
1758
  annotateApprovalRequired(result);
1684
- if (shouldRecordDecisions && sessionId) {
1759
+ if (shouldRecordDecisions && sessionId && !isSharedVerdict(result)) {
1685
1760
  recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
1686
1761
  });
1687
1762
  }
@@ -1699,7 +1774,7 @@ function createMcpMiddleware(options) {
1699
1774
  })
1700
1775
  );
1701
1776
  }
1702
- if (shouldRecordDecisions && sessionId) {
1777
+ if (shouldRecordDecisions && sessionId && !isSharedVerdict(result)) {
1703
1778
  recordDecision(config, sessionId, "granted").catch(() => {
1704
1779
  });
1705
1780
  }