@astrasyncai/verification-gateway 2.3.7 → 2.3.9

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 (84) hide show
  1. package/README.md +93 -10
  2. package/dist/adapter-interface/interface.d.mts +2 -2
  3. package/dist/adapter-interface/interface.d.ts +2 -2
  4. package/dist/adapters/express.d.mts +2 -2
  5. package/dist/adapters/express.d.ts +2 -2
  6. package/dist/adapters/express.js +81 -7
  7. package/dist/adapters/express.js.map +1 -1
  8. package/dist/adapters/express.mjs +81 -7
  9. package/dist/adapters/express.mjs.map +1 -1
  10. package/dist/adapters/mcp.d.mts +1 -1
  11. package/dist/adapters/mcp.d.ts +1 -1
  12. package/dist/adapters/mcp.js +84 -12
  13. package/dist/adapters/mcp.js.map +1 -1
  14. package/dist/adapters/mcp.mjs +84 -12
  15. package/dist/adapters/mcp.mjs.map +1 -1
  16. package/dist/adapters/nextjs.d.mts +2 -2
  17. package/dist/adapters/nextjs.d.ts +2 -2
  18. package/dist/adapters/nextjs.js +40 -6
  19. package/dist/adapters/nextjs.js.map +1 -1
  20. package/dist/adapters/nextjs.mjs +40 -6
  21. package/dist/adapters/nextjs.mjs.map +1 -1
  22. package/dist/adapters/sdk.d.mts +2 -2
  23. package/dist/adapters/sdk.d.ts +2 -2
  24. package/dist/adapters/sdk.js +40 -6
  25. package/dist/adapters/sdk.js.map +1 -1
  26. package/dist/adapters/sdk.mjs +40 -6
  27. package/dist/adapters/sdk.mjs.map +1 -1
  28. package/dist/agent/index.d.mts +2 -2
  29. package/dist/agent/index.d.ts +2 -2
  30. package/dist/browser/background.js +39 -5
  31. package/dist/browser/background.js.map +1 -1
  32. package/dist/browser/background.mjs +39 -5
  33. package/dist/browser/background.mjs.map +1 -1
  34. package/dist/browser/browser-adapter.d.mts +2 -2
  35. package/dist/browser/browser-adapter.d.ts +2 -2
  36. package/dist/cli/index.d.mts +2 -2
  37. package/dist/cli/index.d.ts +2 -2
  38. package/dist/cursor/cursor-adapter.d.mts +2 -2
  39. package/dist/cursor/cursor-adapter.d.ts +2 -2
  40. package/dist/cursor/extension.d.mts +2 -2
  41. package/dist/cursor/extension.d.ts +2 -2
  42. package/dist/cursor/extension.js +39 -5
  43. package/dist/cursor/extension.js.map +1 -1
  44. package/dist/cursor/extension.mjs +39 -5
  45. package/dist/cursor/extension.mjs.map +1 -1
  46. package/dist/{express-D9oRsseg.d.mts → express-BiB51d5t.d.mts} +1 -1
  47. package/dist/{express-DMSIl20m.d.ts → express-D6tEDU08.d.ts} +1 -1
  48. package/dist/gateway/gateway.d.mts +2 -2
  49. package/dist/gateway/gateway.d.ts +2 -2
  50. package/dist/gateway/gateway.js +39 -5
  51. package/dist/gateway/gateway.js.map +1 -1
  52. package/dist/gateway/gateway.mjs +39 -5
  53. package/dist/gateway/gateway.mjs.map +1 -1
  54. package/dist/git-trigger/git-hooks.d.mts +2 -2
  55. package/dist/git-trigger/git-hooks.d.ts +2 -2
  56. package/dist/{index-EwUWXC5T.d.ts → index-8DFMpITk.d.ts} +1 -1
  57. package/dist/{index-YNPs800Z.d.mts → index-B--6fiDp.d.mts} +1 -1
  58. package/dist/{index-Bn_7eGjb.d.mts → index-CAykfMWK.d.mts} +1 -1
  59. package/dist/{index-BtU9yFda.d.ts → index-Yt02MRyu.d.ts} +1 -1
  60. package/dist/index.d.mts +7 -7
  61. package/dist/index.d.ts +7 -7
  62. package/dist/index.js +87 -13
  63. package/dist/index.js.map +1 -1
  64. package/dist/index.mjs +87 -13
  65. package/dist/index.mjs.map +1 -1
  66. package/dist/local-evaluator/evaluator.d.mts +2 -2
  67. package/dist/local-evaluator/evaluator.d.ts +2 -2
  68. package/dist/{nextjs-B5ZBpHra.d.ts → nextjs-CK5F_tVZ.d.ts} +1 -1
  69. package/dist/{nextjs-BLtjRbc-.d.mts → nextjs-CpxqfQqD.d.mts} +1 -1
  70. package/dist/{sdk-BhkxvqnK.d.mts → sdk-BMvauMgP.d.ts} +9 -2
  71. package/dist/{sdk-YmE3RG8n.d.ts → sdk-yJjO7yzn.d.mts} +9 -2
  72. package/dist/transport/index.d.mts +2 -2
  73. package/dist/transport/index.d.ts +2 -2
  74. package/dist/{types-DxY5zt4z.d.mts → types-CKafuHDn.d.mts} +1 -1
  75. package/dist/{types-Bxqj1sKY.d.mts → types-UYT4GdPW.d.mts} +42 -4
  76. package/dist/{types-Bxqj1sKY.d.ts → types-UYT4GdPW.d.ts} +42 -4
  77. package/dist/{types-BecRpozv.d.ts → types-ppkhdldJ.d.ts} +1 -1
  78. package/dist/ui/index.d.mts +1 -1
  79. package/dist/ui/index.d.ts +1 -1
  80. package/dist/ui/index.js +3 -3
  81. package/dist/ui/index.js.map +1 -1
  82. package/dist/ui/index.mjs +3 -3
  83. package/dist/ui/index.mjs.map +1 -1
  84. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -7,7 +7,7 @@ var __export = (target, all) => {
7
7
  // src/access-levels.ts
8
8
  var ACCESS_LEVEL_HIERARCHY = {
9
9
  none: 0,
10
- guidance: 1,
10
+ restricted: 1,
11
11
  "read-only": 2,
12
12
  standard: 3,
13
13
  full: 4,
@@ -15,7 +15,7 @@ var ACCESS_LEVEL_HIERARCHY = {
15
15
  };
16
16
  var ACCESS_LEVEL_DESCRIPTIONS = {
17
17
  none: "No access - credentials required",
18
- guidance: "Guidance mode - registration information provided",
18
+ restricted: "Restricted access - registration prompt only",
19
19
  "read-only": "Read-only access - can browse but not modify",
20
20
  standard: "Standard access - normal operations per PDLSS policy",
21
21
  full: "Full access - all operations for high-trust agents",
@@ -23,7 +23,7 @@ var ACCESS_LEVEL_DESCRIPTIONS = {
23
23
  };
24
24
  var DEFAULT_TRUST_THRESHOLDS = {
25
25
  none: 0,
26
- guidance: 0,
26
+ restricted: 0,
27
27
  "read-only": 20,
28
28
  standard: 40,
29
29
  full: 70,
@@ -49,11 +49,11 @@ function getAccessLevelForScore(trustScore, thresholds = DEFAULT_TRUST_THRESHOLD
49
49
  if (trustScore >= thresholds.full) return "full";
50
50
  if (trustScore >= thresholds.standard) return "standard";
51
51
  if (trustScore >= thresholds["read-only"]) return "read-only";
52
- return "guidance";
52
+ return "restricted";
53
53
  }
54
54
  function determineAccessLevel(verified, trustScore, isOrgMember, customThresholds) {
55
55
  if (!verified) {
56
- return "guidance";
56
+ return "none";
57
57
  }
58
58
  if (isOrgMember) {
59
59
  return "internal";
@@ -74,7 +74,7 @@ function getCapabilities(accessLevel) {
74
74
  canAdmin: false,
75
75
  canAccessInternal: false
76
76
  };
77
- case "guidance":
77
+ case "restricted":
78
78
  return {
79
79
  canRead: false,
80
80
  canWrite: false,
@@ -128,7 +128,11 @@ function getCapabilities(accessLevel) {
128
128
  // src/verify.ts
129
129
  var DEFAULT_CONFIG = {
130
130
  apiBaseUrl: "https://astrasync.ai/api",
131
- defaultAccessLevel: "guidance",
131
+ // v2.3.9 (defect #30): default for unconfigured callers is `'none'` (no
132
+ // access). Pre-rename this defaulted to `'guidance'`, which combined with
133
+ // a route gated at `'guidance'` to silently let unverified traffic
134
+ // through (`hasMinimumAccess('guidance', 'guidance') === true`).
135
+ defaultAccessLevel: "none",
132
136
  // minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
133
137
  cacheTtl: 300,
134
138
  // 5 minutes
@@ -227,7 +231,12 @@ function createGuidanceResponse(config, reason) {
227
231
  };
228
232
  return {
229
233
  verified: false,
230
- accessLevel: "guidance",
234
+ // v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
235
+ // Adapters additionally short-circuit on `verified === false` before
236
+ // the gate check, but the access level still has to be honest at the
237
+ // data layer so downstream consumers (SDK adapters in other languages,
238
+ // custom integrations) inherit the correct semantics.
239
+ accessLevel: "none",
231
240
  guidance,
232
241
  denialReasons: reason ? [reason] : ["No valid agent credentials provided"],
233
242
  verifiedAt: /* @__PURE__ */ new Date()
@@ -284,6 +293,23 @@ async function callVerifyAccessAPI(config, request) {
284
293
  body: JSON.stringify(body)
285
294
  });
286
295
  const data = await response.json();
296
+ if (response.status === 410) {
297
+ return {
298
+ success: true,
299
+ access: {
300
+ allowed: false,
301
+ accessLevel: "none",
302
+ reason: "endpoint_deactivated",
303
+ failures: [
304
+ {
305
+ dimension: "endpoint.deactivated",
306
+ message: typeof data?.message === "string" ? data.message : "Endpoint has been deactivated",
307
+ guidance: typeof data?.guidance === "string" ? data.guidance : "Reactivate via POST /api/endpoints/{id}/reactivate, or update the URL on the calling agent."
308
+ }
309
+ ]
310
+ }
311
+ };
312
+ }
287
313
  if (!response.ok) {
288
314
  return {
289
315
  success: false,
@@ -337,7 +363,14 @@ async function verify(config, request) {
337
363
  const aggregatedFailures = apiResponse.access?.failures;
338
364
  const result2 = {
339
365
  verified: false,
340
- accessLevel: "guidance",
366
+ // v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
367
+ // Pre-rename this hardcoded `'guidance'`, which conflated with the
368
+ // colocated `guidance: {...}` help-payload object below and let
369
+ // denied requests pass any route gated at `'guidance'` because
370
+ // `hasMinimumAccess('guidance', 'guidance') === true`. Adapters now
371
+ // ALSO short-circuit on `verified === false` before the gate check —
372
+ // belt-and-braces.
373
+ accessLevel: "none",
341
374
  denialReasons: aggregatedFailures && aggregatedFailures.length > 0 ? aggregatedFailures.map((f) => f.message) : apiResponse.access?.reason ? [apiResponse.access.reason] : ["Access denied"],
342
375
  failures: aggregatedFailures,
343
376
  requiresStepUp: apiResponse.access?.requiresStepUp,
@@ -393,7 +426,8 @@ async function verify(config, request) {
393
426
  runtimeChallenge: apiResponse.runtimeChallenge,
394
427
  tokenGuidance: apiResponse.tokenGuidance,
395
428
  recommendation: apiResponse.recommendation,
396
- recommendationReasons: apiResponse.recommendationReasons
429
+ recommendationReasons: apiResponse.recommendationReasons,
430
+ warningHeader: apiResponse.warningHeader
397
431
  };
398
432
  if (result.recommendation === "deny") {
399
433
  result.verified = false;
@@ -420,7 +454,7 @@ async function verify(config, request) {
420
454
  }
421
455
  return result;
422
456
  }
423
- async function recordDecision(config, sessionId, decision, reason) {
457
+ async function recordDecision(config, sessionId, decision, reason, override) {
424
458
  const headers = { "Content-Type": "application/json" };
425
459
  if (config.apiKey) {
426
460
  headers["Authorization"] = `Bearer ${config.apiKey}`;
@@ -429,7 +463,16 @@ async function recordDecision(config, sessionId, decision, reason) {
429
463
  await fetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
430
464
  method: "POST",
431
465
  headers,
432
- body: JSON.stringify({ decision, reason })
466
+ body: JSON.stringify({
467
+ decision,
468
+ reason,
469
+ ...override && {
470
+ overriddenBy: override.overriddenBy,
471
+ toolName: override.toolName,
472
+ requestedLevel: override.requestedLevel,
473
+ grantedLevel: override.grantedLevel
474
+ }
475
+ })
433
476
  }).catch(() => {
434
477
  });
435
478
  }
@@ -666,6 +709,7 @@ function createMiddleware(options) {
666
709
  let lastFetchAt = 0;
667
710
  let refreshing = null;
668
711
  let warnedNoCounterparty = false;
712
+ let warnedEmptyRoutes = false;
669
713
  async function refreshRoutes() {
670
714
  if (!config.counterpartyId) {
671
715
  if (!warnedNoCounterparty) {
@@ -680,6 +724,13 @@ function createMiddleware(options) {
680
724
  if (fetched) {
681
725
  cachedRoutes = fetched;
682
726
  lastFetchAt = Date.now();
727
+ if (cachedRoutes.length === 0 && !warnedEmptyRoutes) {
728
+ const dashboard = config.dashboardUrl ?? "https://app.astrasync.ai";
729
+ console.warn(
730
+ `[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`
731
+ );
732
+ warnedEmptyRoutes = true;
733
+ }
683
734
  }
684
735
  }
685
736
  refreshing = refreshRoutes().finally(() => {
@@ -702,9 +753,20 @@ function createMiddleware(options) {
702
753
  }
703
754
  const routeConfig = findRouteConfig(cachedRoutes, req.path, req.method);
704
755
  if (!routeConfig) {
756
+ if (config.setPassThroughHeader) {
757
+ res.setHeader("X-Astra-Gateway-Mode", "pass-through");
758
+ res.setHeader(
759
+ "X-Astra-Gateway-Reason",
760
+ cachedRoutes.length === 0 ? "no-policy" : "no-match"
761
+ );
762
+ }
705
763
  return next();
706
764
  }
707
765
  if (routeConfig.minAccessLevel === "none") {
766
+ if (config.setPassThroughHeader) {
767
+ res.setHeader("X-Astra-Gateway-Mode", "pass-through");
768
+ res.setHeader("X-Astra-Gateway-Reason", "route-none");
769
+ }
708
770
  return next();
709
771
  }
710
772
  const credentials = customExtractCredentials ? customExtractCredentials(req) : defaultExtractCredentials(req);
@@ -763,6 +825,14 @@ function createMiddleware(options) {
763
825
  });
764
826
  req.agentVerification = result;
765
827
  const sessionId = result.sessionId;
828
+ if (!result.verified) {
829
+ if (shouldRecordDecisions && sessionId) {
830
+ recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
831
+ });
832
+ }
833
+ onDenied(result, req, res);
834
+ return;
835
+ }
766
836
  if (!hasMinimumAccess(result.accessLevel, routeConfig.minAccessLevel)) {
767
837
  if (shouldRecordDecisions && sessionId) {
768
838
  recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
@@ -788,6 +858,10 @@ function createMiddleware(options) {
788
858
  recordDecision(config, sessionId, "granted").catch(() => {
789
859
  });
790
860
  }
861
+ const enhancedResult = result;
862
+ if (enhancedResult.warningHeader) {
863
+ res.setHeader(enhancedResult.warningHeader.name, enhancedResult.warningHeader.value);
864
+ }
791
865
  next();
792
866
  } catch (error) {
793
867
  console.error("[VerificationGateway] Middleware error:", error);
@@ -1143,7 +1217,7 @@ function createMiddleware2(options) {
1143
1217
  agentCardUrl: request.headers.get("x-astrasync-agent-card") || void 0
1144
1218
  }
1145
1219
  });
1146
- if (!hasMinimumAccess(result.accessLevel, routeConfig.minAccessLevel)) {
1220
+ if (!result.verified || !hasMinimumAccess(result.accessLevel, routeConfig.minAccessLevel)) {
1147
1221
  if (pathname.startsWith("/api/")) {
1148
1222
  return NextResponse.json(
1149
1223
  {