@astrasyncai/verification-gateway 3.1.0 → 3.2.1

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 (79) hide show
  1. package/dist/adapter-interface/interface.d.mts +2 -2
  2. package/dist/adapter-interface/interface.d.ts +2 -2
  3. package/dist/adapters/express.d.mts +2 -2
  4. package/dist/adapters/express.d.ts +2 -2
  5. package/dist/adapters/express.js +46 -61
  6. package/dist/adapters/express.js.map +1 -1
  7. package/dist/adapters/express.mjs +46 -61
  8. package/dist/adapters/express.mjs.map +1 -1
  9. package/dist/adapters/mcp.d.mts +12 -7
  10. package/dist/adapters/mcp.d.ts +12 -7
  11. package/dist/adapters/mcp.js +60 -99
  12. package/dist/adapters/mcp.js.map +1 -1
  13. package/dist/adapters/mcp.mjs +60 -99
  14. package/dist/adapters/mcp.mjs.map +1 -1
  15. package/dist/adapters/nextjs.d.mts +2 -2
  16. package/dist/adapters/nextjs.d.ts +2 -2
  17. package/dist/adapters/nextjs.js +37 -30
  18. package/dist/adapters/nextjs.js.map +1 -1
  19. package/dist/adapters/nextjs.mjs +37 -30
  20. package/dist/adapters/nextjs.mjs.map +1 -1
  21. package/dist/adapters/sdk.d.mts +2 -2
  22. package/dist/adapters/sdk.d.ts +2 -2
  23. package/dist/adapters/sdk.js +25 -14
  24. package/dist/adapters/sdk.js.map +1 -1
  25. package/dist/adapters/sdk.mjs +25 -14
  26. package/dist/adapters/sdk.mjs.map +1 -1
  27. package/dist/agent/index.d.mts +2 -2
  28. package/dist/agent/index.d.ts +2 -2
  29. package/dist/browser/background.js +18 -21
  30. package/dist/browser/background.js.map +1 -1
  31. package/dist/browser/background.mjs +18 -21
  32. package/dist/browser/background.mjs.map +1 -1
  33. package/dist/browser/browser-adapter.d.mts +2 -2
  34. package/dist/browser/browser-adapter.d.ts +2 -2
  35. package/dist/cli/index.d.mts +2 -2
  36. package/dist/cli/index.d.ts +2 -2
  37. package/dist/cursor/cursor-adapter.d.mts +2 -2
  38. package/dist/cursor/cursor-adapter.d.ts +2 -2
  39. package/dist/cursor/extension.d.mts +2 -2
  40. package/dist/cursor/extension.d.ts +2 -2
  41. package/dist/cursor/extension.js +18 -21
  42. package/dist/cursor/extension.js.map +1 -1
  43. package/dist/cursor/extension.mjs +18 -21
  44. package/dist/cursor/extension.mjs.map +1 -1
  45. package/dist/{express-DavQ76oF.d.ts → express-BowlMHQF.d.ts} +1 -1
  46. package/dist/{express-DFVBlXr_.d.mts → express-CeoSdOAZ.d.mts} +1 -1
  47. package/dist/gateway/gateway.d.mts +2 -2
  48. package/dist/gateway/gateway.d.ts +2 -2
  49. package/dist/gateway/gateway.js +18 -21
  50. package/dist/gateway/gateway.js.map +1 -1
  51. package/dist/gateway/gateway.mjs +18 -21
  52. package/dist/gateway/gateway.mjs.map +1 -1
  53. package/dist/git-trigger/git-hooks.d.mts +2 -2
  54. package/dist/git-trigger/git-hooks.d.ts +2 -2
  55. package/dist/{index-BhL2R65s.d.mts → index-B51W8gn8.d.mts} +1 -1
  56. package/dist/{index-BhEgEiJL.d.ts → index-DBmlycVm.d.ts} +1 -1
  57. package/dist/{index-BVxantdv.d.mts → index-DtGziFEm.d.mts} +1 -1
  58. package/dist/{index-Dk2nIA4w.d.ts → index-DzXXBuLm.d.ts} +1 -1
  59. package/dist/index.d.mts +7 -7
  60. package/dist/index.d.ts +7 -7
  61. package/dist/index.js +87 -122
  62. package/dist/index.js.map +1 -1
  63. package/dist/index.mjs +87 -122
  64. package/dist/index.mjs.map +1 -1
  65. package/dist/local-evaluator/evaluator.d.mts +2 -2
  66. package/dist/local-evaluator/evaluator.d.ts +2 -2
  67. package/dist/{nextjs-D-maqrNz.d.mts → nextjs-BW1rzr1I.d.mts} +1 -1
  68. package/dist/{nextjs-BXLH1hJj.d.ts → nextjs-V_K0qlAQ.d.ts} +1 -1
  69. package/dist/{sdk-767LaEP8.d.mts → sdk-ZYgI7G9f.d.ts} +14 -3
  70. package/dist/{sdk-K8IgssHI.d.ts → sdk-e5jg7sqW.d.mts} +14 -3
  71. package/dist/transport/index.d.mts +2 -2
  72. package/dist/transport/index.d.ts +2 -2
  73. package/dist/{types-CyFwZ_Yu.d.mts → types-BNiLZY0i.d.mts} +1 -1
  74. package/dist/{types-WIRp_BP_.d.ts → types-DJi-u3fz.d.ts} +1 -1
  75. package/dist/{types-Cuh7ELfr.d.mts → types-rFh4VMH4.d.mts} +5 -2
  76. package/dist/{types-Cuh7ELfr.d.ts → types-rFh4VMH4.d.ts} +5 -2
  77. package/dist/ui/index.d.mts +1 -1
  78. package/dist/ui/index.d.ts +1 -1
  79. package/package.json +1 -1
@@ -1,24 +1,13 @@
1
1
  // src/access-levels.ts
2
- var ACCESS_LEVEL_HIERARCHY = {
3
- none: 0,
4
- restricted: 1,
5
- "read-only": 2,
6
- standard: 3,
7
- full: 4,
8
- internal: 5
9
- };
10
2
  function getTrustLevel(score) {
11
3
  if (score >= 80) return "PLATINUM";
12
4
  if (score >= 60) return "GOLD";
13
5
  if (score >= 40) return "SILVER";
14
6
  return "BRONZE";
15
7
  }
16
- function hasMinimumAccess(actual, required) {
17
- return ACCESS_LEVEL_HIERARCHY[actual] >= ACCESS_LEVEL_HIERARCHY[required];
18
- }
19
8
 
20
9
  // src/version.ts
21
- var SDK_VERSION = "3.1.0";
10
+ var SDK_VERSION = "3.2.1";
22
11
 
23
12
  // src/well-known.ts
24
13
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -123,7 +112,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
123
112
  }
124
113
  }
125
114
  var verificationCache = /* @__PURE__ */ new Map();
126
- function getCacheKey(request) {
115
+ function getCacheKey(request, counterpartyId) {
127
116
  const c = request.credentials;
128
117
  return [
129
118
  c.astraId || "",
@@ -136,6 +125,14 @@ function getCacheKey(request) {
136
125
  request.jurisdiction || "",
137
126
  request.transactionValue ?? "",
138
127
  request.currency || "",
128
+ // SECURITY (cross-merchant cache leak): the merchant identity is sent via
129
+ // `config.counterpartyId`, NOT on the request, so it was previously absent
130
+ // from the key — two verifies for the SAME agent/purpose/action/value but
131
+ // DIFFERENT merchants collided, and a grant at a permissive merchant (low
132
+ // trust floor) was served for a stricter one. Same bug class as the
133
+ // duration omission (F-A1-07). counterpartyId affects the backend verdict
134
+ // (trust floor / per-route policy), so it MUST key the cache.
135
+ counterpartyId || "",
139
136
  request.counterpartyUrl || "",
140
137
  request.counterpartyType || "",
141
138
  request.isSubAgentRequest ? "1" : "0",
@@ -159,8 +156,8 @@ function getCacheKey(request) {
159
156
  request.callerMetadata?.agentCardUrl || ""
160
157
  ].join("|");
161
158
  }
162
- function getCachedResult(request) {
163
- const key = getCacheKey(request);
159
+ function getCachedResult(request, counterpartyId) {
160
+ const key = getCacheKey(request, counterpartyId);
164
161
  const cached = verificationCache.get(key);
165
162
  if (cached && cached.expiresAt > Date.now()) {
166
163
  return cached.result;
@@ -172,9 +169,9 @@ function getCachedResult(request) {
172
169
  }
173
170
  var DEFAULT_AUTONOMOUS_TTL_SECONDS = 60;
174
171
  var DEFAULT_STEP_UP_TTL_SECONDS = 300;
175
- function cacheResult(request, result, configuredTtl) {
172
+ function cacheResult(request, result, configuredTtl, counterpartyId) {
176
173
  const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : result.requiresStepUp ? DEFAULT_STEP_UP_TTL_SECONDS : DEFAULT_AUTONOMOUS_TTL_SECONDS;
177
- const key = getCacheKey(request);
174
+ const key = getCacheKey(request, counterpartyId);
178
175
  verificationCache.set(key, {
179
176
  result,
180
177
  expiresAt: Date.now() + ttlSeconds * 1e3
@@ -366,7 +363,7 @@ async function verify(config, request) {
366
363
  );
367
364
  }
368
365
  if (mergedConfig.cacheTtl !== 0) {
369
- const cached = getCachedResult(request);
366
+ const cached = getCachedResult(request, mergedConfig.counterpartyId);
370
367
  if (cached) {
371
368
  if (mergedConfig.debug) {
372
369
  console.log("[VerificationGateway] Returning cached result");
@@ -418,8 +415,8 @@ async function verify(config, request) {
418
415
  verifiedAt: /* @__PURE__ */ new Date(),
419
416
  // Extract sessionId so decisions can be recorded for denials too
420
417
  sessionId: apiResponse.sessionId,
421
- // v2.3.10 (defect #34, round-4): anonymous traffic has no session →
422
- // correlationId is the linking key for paired local_override events.
418
+ // Anonymous traffic has no session → correlationId is the per-attempt
419
+ // linking key (the sessionId-equivalent for anonymous callers).
423
420
  correlationId: apiResponse.correlationId,
424
421
  recommendation: apiResponse.recommendation,
425
422
  recommendationReasons: apiResponse.recommendationReasons
@@ -493,17 +490,14 @@ async function verify(config, request) {
493
490
  };
494
491
  } else if (result.recommendation === "step_up_required") {
495
492
  result.requiresStepUp = true;
496
- if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
497
- result.accessLevel = "read-only";
498
- }
499
493
  result.denialReasons = result.recommendationReasons || ["Step-up verification required"];
500
494
  }
501
495
  if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny") {
502
- cacheResult(request, result, mergedConfig.cacheTtl);
496
+ cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
503
497
  }
504
498
  return result;
505
499
  }
506
- async function recordDecision(config, sessionId, decision, reason, override) {
500
+ async function recordDecision(config, sessionId, decision, reason) {
507
501
  const headers = { "Content-Type": "application/json" };
508
502
  if (config.apiKey) {
509
503
  headers["Authorization"] = `Bearer ${config.apiKey}`;
@@ -512,16 +506,7 @@ async function recordDecision(config, sessionId, decision, reason, override) {
512
506
  await fetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
513
507
  method: "POST",
514
508
  headers,
515
- body: JSON.stringify({
516
- decision,
517
- reason,
518
- ...override && {
519
- overriddenBy: override.overriddenBy,
520
- toolName: override.toolName,
521
- requestedLevel: override.requestedLevel,
522
- grantedLevel: override.grantedLevel
523
- }
524
- })
509
+ body: JSON.stringify({ decision, reason })
525
510
  }).catch(() => {
526
511
  });
527
512
  }
@@ -679,6 +664,19 @@ function resolveHttpPdlss(input) {
679
664
  return { purpose, action, purposeSource, actionSource };
680
665
  }
681
666
 
667
+ // src/adapters/approval-gate.ts
668
+ var APPROVAL_REASON = "Transaction is above the autonomous limit and requires human approval, which is not yet available \u2014 it cannot be completed automatically.";
669
+ function requiresHumanApproval(result) {
670
+ return result.requiresStepUp === true || result.requiresApproval === true;
671
+ }
672
+ function annotateApprovalRequired(result) {
673
+ result.failures = [
674
+ ...result.failures ?? [],
675
+ { dimension: "commerce.intent.approval_required", message: APPROVAL_REASON }
676
+ ];
677
+ result.denialReasons = [APPROVAL_REASON, ...result.denialReasons ?? []];
678
+ }
679
+
682
680
  // src/pdlss-pre-check.ts
683
681
  function performCounterpartyPreCheck(routeConfig, astraCreds, purpose) {
684
682
  const failures = [];
@@ -986,6 +984,16 @@ function createMiddleware(options) {
986
984
  onDenied(result, req, res);
987
985
  return;
988
986
  }
987
+ if (requiresHumanApproval(result)) {
988
+ annotateApprovalRequired(result);
989
+ if (shouldRecordDecisions && sessionId) {
990
+ recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
991
+ });
992
+ }
993
+ dedupeFailures(result);
994
+ onDenied(result, req, res);
995
+ return;
996
+ }
989
997
  if (!shouldEnforce) {
990
998
  if (config.setPassThroughHeader) {
991
999
  res.setHeader("X-Astra-Gateway-Mode", "enforced");
@@ -997,35 +1005,12 @@ function createMiddleware(options) {
997
1005
  }
998
1006
  return next();
999
1007
  }
1000
- if (!hasMinimumAccess(result.accessLevel, routeConfig.minAccessLevel)) {
1001
- const insufficientFailure = {
1002
- dimension: "access_level.insufficient",
1003
- message: `Endpoint requires accessLevel '${routeConfig.minAccessLevel}'; agent has '${result.accessLevel}'.`,
1004
- guidance: "Request elevated access via step-up verification (coming soon \u2014 ships this month). Step-up lets the agent owner approve a one-time elevation for this specific counterparty + purpose without changing the agent's baseline trust score."
1005
- };
1006
- result.failures = [...result.failures ?? [], insufficientFailure];
1007
- result.denialReasons = [...result.denialReasons ?? [], insufficientFailure.message];
1008
- if (!result.guidance && wellKnownUrls) {
1009
- result.guidance = {
1010
- message: insufficientFailure.message,
1011
- registrationUrl: wellKnownUrls.registrationUrl,
1012
- documentationUrl: wellKnownUrls.documentationUrl
1013
- };
1014
- }
1015
- if (shouldRecordDecisions && sessionId) {
1016
- recordDecision(config, sessionId, "denied", insufficientFailure.message).catch(() => {
1017
- });
1018
- }
1019
- dedupeFailures(result);
1020
- onDenied(result, req, res);
1021
- return;
1022
- }
1023
1008
  if (routeConfig.minTrustScore && result.agent) {
1024
1009
  if (result.agent.trustScore < routeConfig.minTrustScore) {
1025
1010
  const trustFailure = {
1026
- dimension: "access_level.insufficient",
1027
- message: `Trust score ${result.agent.trustScore} is below required ${routeConfig.minTrustScore} for this route.`,
1028
- guidance: "Request elevated access via step-up verification (coming soon \u2014 ships this month). Step-up lets the agent owner approve a one-time elevation for this specific counterparty + purpose without changing the agent's baseline trust score."
1011
+ dimension: "endpoint.trust",
1012
+ message: "Trust below the route requirement for this endpoint.",
1013
+ guidance: "Trust is below this route's floor. Trust is not overridable \u2014 the agent either meets the endpoint's trust policy or it doesn't. Raise the agent's trust via real signals (KYD, blockchain registration, agent-card), or have the operator lower the route's minTrustScore."
1029
1014
  };
1030
1015
  result.failures = [...result.failures ?? [], trustFailure];
1031
1016
  result.denialReasons = [trustFailure.message];