@astrasyncai/verification-gateway 3.4.0 → 3.6.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 (84) hide show
  1. package/README.md +102 -0
  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 +113 -20
  7. package/dist/adapters/express.js.map +1 -1
  8. package/dist/adapters/express.mjs +113 -20
  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 +96 -20
  13. package/dist/adapters/mcp.js.map +1 -1
  14. package/dist/adapters/mcp.mjs +96 -20
  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 +101 -20
  19. package/dist/adapters/nextjs.js.map +1 -1
  20. package/dist/adapters/nextjs.mjs +101 -20
  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 +19 -16
  25. package/dist/adapters/sdk.js.map +1 -1
  26. package/dist/adapters/sdk.mjs +19 -16
  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 +22 -16
  31. package/dist/browser/background.js.map +1 -1
  32. package/dist/browser/background.mjs +22 -16
  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 +22 -16
  43. package/dist/cursor/extension.js.map +1 -1
  44. package/dist/cursor/extension.mjs +22 -16
  45. package/dist/cursor/extension.mjs.map +1 -1
  46. package/dist/{express-CeFvNWDD.d.mts → express-BnMO-H3y.d.mts} +1 -1
  47. package/dist/{express-RIh05wW2.d.ts → express-DQhDzNAt.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 +22 -16
  51. package/dist/gateway/gateway.js.map +1 -1
  52. package/dist/gateway/gateway.mjs +22 -16
  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-DgVBEiwI.d.mts → index-BT_aRn-I.d.mts} +1 -1
  57. package/dist/{index-BYu1FKMy.d.ts → index-D8-dvUFA.d.ts} +1 -1
  58. package/dist/{index-Bw4FeHMY.d.mts → index-WHKq2v17.d.mts} +5 -1
  59. package/dist/{index-C-K0WCrk.d.ts → index-rftma0ln.d.ts} +5 -1
  60. package/dist/index.d.mts +55 -9
  61. package/dist/index.d.ts +55 -9
  62. package/dist/index.js +184 -34
  63. package/dist/index.js.map +1 -1
  64. package/dist/index.mjs +182 -34
  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-xciaMpsZ.d.mts → nextjs-DFKYhxe6.d.mts} +1 -1
  69. package/dist/{nextjs--xR9zbSJ.d.ts → nextjs-DPj7ZNlq.d.ts} +1 -1
  70. package/dist/{sdk-FP7xT9F8.d.ts → sdk-CAcHgB5x.d.ts} +1 -1
  71. package/dist/{sdk-CJYCLMI0.d.mts → sdk-Cy3wAmDt.d.mts} +1 -1
  72. package/dist/transport/index.d.mts +2 -2
  73. package/dist/transport/index.d.ts +2 -2
  74. package/dist/transport/index.js +22 -4
  75. package/dist/transport/index.js.map +1 -1
  76. package/dist/transport/index.mjs +22 -4
  77. package/dist/transport/index.mjs.map +1 -1
  78. package/dist/{types-Cj92yKeA.d.mts → types-B-ubjHER.d.mts} +1 -1
  79. package/dist/{types-DOeL-dIw.d.ts → types-Bgn5gxHQ.d.ts} +1 -1
  80. package/dist/{types-Cwrvo30g.d.mts → types-CKe8O0lR.d.mts} +65 -3
  81. package/dist/{types-Cwrvo30g.d.ts → types-CKe8O0lR.d.ts} +65 -3
  82. package/dist/ui/index.d.mts +1 -1
  83. package/dist/ui/index.d.ts +1 -1
  84. package/package.json +1 -1
@@ -1,3 +1,3 @@
1
1
  import 'next/server';
2
- import '../types-Cwrvo30g.mjs';
3
- export { c as createMatcherConfig, a as createMiddleware } from '../nextjs-xciaMpsZ.mjs';
2
+ import '../types-CKe8O0lR.mjs';
3
+ export { c as createMatcherConfig, a as createMiddleware } from '../nextjs-DFKYhxe6.mjs';
@@ -1,3 +1,3 @@
1
1
  import 'next/server';
2
- import '../types-Cwrvo30g.js';
3
- export { c as createMatcherConfig, a as createMiddleware } from '../nextjs--xR9zbSJ.js';
2
+ import '../types-CKe8O0lR.js';
3
+ export { c as createMatcherConfig, a as createMiddleware } from '../nextjs-DPj7ZNlq.js';
@@ -35,6 +35,64 @@ __export(nextjs_exports, {
35
35
  });
36
36
  module.exports = __toCommonJS(nextjs_exports);
37
37
 
38
+ // src/adapters/stepup-poll.ts
39
+ var DEFAULT_POLL_INTERVAL_MS = 3e3;
40
+ var MIN_POLL_INTERVAL_MS = 250;
41
+ var FALLBACK_MAX_WAIT_MS = 5 * 60 * 1e3;
42
+ var EXPIRY_GRACE_MS = 5e3;
43
+ var POLL_REQUEST_TIMEOUT_MS = 1e4;
44
+ function resolvePollUrl(config, pollUrl) {
45
+ if (pollUrl.startsWith("http")) return pollUrl;
46
+ const origin = (config.apiBaseUrl ?? "").replace(/\/api\/?$/, "");
47
+ return origin + pollUrl;
48
+ }
49
+ async function pollStepUpStatus(config, approval) {
50
+ if (!approval.pollUrl) return null;
51
+ try {
52
+ const res = await fetch(resolvePollUrl(config, approval.pollUrl), {
53
+ method: "GET",
54
+ signal: AbortSignal.timeout(POLL_REQUEST_TIMEOUT_MS)
55
+ });
56
+ if (!res.ok) return null;
57
+ const body = await res.json();
58
+ const data = body?.data;
59
+ const status = data && typeof data === "object" ? data.status : body?.status;
60
+ return typeof status === "string" ? status : null;
61
+ } catch {
62
+ return null;
63
+ }
64
+ }
65
+ function resolveDeadline(config, approval) {
66
+ const now = Date.now();
67
+ const maxWait = config.stepUpMaxWaitMs ?? 0;
68
+ if (maxWait > 0) return now + maxWait;
69
+ if (approval.expiresAt) {
70
+ const expiry = Date.parse(approval.expiresAt);
71
+ if (!Number.isNaN(expiry)) return Math.max(now, expiry) + EXPIRY_GRACE_MS;
72
+ }
73
+ return now + FALLBACK_MAX_WAIT_MS;
74
+ }
75
+ function sleep(ms) {
76
+ return new Promise((resolve) => setTimeout(resolve, ms));
77
+ }
78
+ async function awaitStepUpApproval(config, approval) {
79
+ const deadline = resolveDeadline(config, approval);
80
+ const pollInterval = Math.max(
81
+ MIN_POLL_INTERVAL_MS,
82
+ config.stepUpPollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS
83
+ );
84
+ while (Date.now() < deadline) {
85
+ const status = await pollStepUpStatus(config, approval);
86
+ if (status && status !== "pending") {
87
+ return status;
88
+ }
89
+ const remaining = deadline - Date.now();
90
+ if (remaining <= 0) break;
91
+ await sleep(Math.min(pollInterval, remaining));
92
+ }
93
+ return "timeout";
94
+ }
95
+
38
96
  // src/access-levels.ts
39
97
  function getTrustLevel(score) {
40
98
  if (score >= 80) return "PLATINUM";
@@ -44,7 +102,7 @@ function getTrustLevel(score) {
44
102
  }
45
103
 
46
104
  // src/version.ts
47
- var SDK_VERSION = "3.3.0";
105
+ var SDK_VERSION = "3.6.0";
48
106
 
49
107
  // src/well-known.ts
50
108
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -62,10 +120,10 @@ var DEFAULT_CONFIG = {
62
120
  // through (`hasMinimumAccess('guidance', 'guidance') === true`).
63
121
  defaultAccessLevel: "none",
64
122
  // minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
65
- // Round-18.5 F4: cacheTtl deliberately unset. When undefined, cacheResult
66
- // applies the split default (60s autonomous / 300s step-up). When the
67
- // caller sets cacheTtl explicitly, that value is honoured uniformly.
68
- // Set cacheTtl: 0 to disable caching entirely.
123
+ // cacheTtl deliberately unset. When undefined, cacheResult applies the 60s
124
+ // default; the caller's explicit value is honoured for cacheable results.
125
+ // Denials and step-up escalations are NEVER cached (3.6.0) regardless of
126
+ // cacheTtl. Set cacheTtl: 0 to disable caching entirely.
69
127
  debug: false
70
128
  };
71
129
  var initCheckPerformed = false;
@@ -152,10 +210,9 @@ function getCachedResult(request, counterpartyId) {
152
210
  }
153
211
  return null;
154
212
  }
155
- var DEFAULT_AUTONOMOUS_TTL_SECONDS = 60;
156
- var DEFAULT_STEP_UP_TTL_SECONDS = 300;
213
+ var DEFAULT_CACHE_TTL_SECONDS = 60;
157
214
  function cacheResult(request, result, configuredTtl, counterpartyId) {
158
- const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : result.requiresStepUp ? DEFAULT_STEP_UP_TTL_SECONDS : DEFAULT_AUTONOMOUS_TTL_SECONDS;
215
+ const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : DEFAULT_CACHE_TTL_SECONDS;
159
216
  const key = getCacheKey(request, counterpartyId);
160
217
  verificationCache.set(key, {
161
218
  result,
@@ -297,7 +354,7 @@ async function callVerifyAccessAPI(config, request) {
297
354
  };
298
355
  }
299
356
  }
300
- async function verify(config, request) {
357
+ async function verify(config, request, options) {
301
358
  const mergedConfig = { ...DEFAULT_CONFIG, ...config };
302
359
  const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
303
360
  if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
@@ -313,7 +370,7 @@ async function verify(config, request) {
313
370
  "[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access-level decisions (the SDK reads access.accessLevel from the verify-access response). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side."
314
371
  );
315
372
  }
316
- if (mergedConfig.cacheTtl !== 0) {
373
+ if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {
317
374
  const cached = getCachedResult(request, mergedConfig.counterpartyId);
318
375
  if (cached) {
319
376
  if (mergedConfig.debug) {
@@ -333,6 +390,8 @@ async function verify(config, request) {
333
390
  console.log("[VerificationGateway] Calling verify-access API");
334
391
  }
335
392
  const apiResponse = await callVerifyAccessAPI(mergedConfig, enrichedRequest);
393
+ const rawServerDenialReasons = apiResponse.denialReasons;
394
+ const serverDenialReasons = Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0 ? rawServerDenialReasons : void 0;
336
395
  if (!apiResponse.success) {
337
396
  return createGuidanceResponse(mergedConfig, apiResponse.error, {
338
397
  source: "api_error",
@@ -354,7 +413,10 @@ async function verify(config, request) {
354
413
  // ALSO short-circuit on `!identityVerified || !policyAllowed` before
355
414
  // the gate check — belt-and-braces.
356
415
  accessLevel: "none",
357
- denialReasons: aggregatedFailures && aggregatedFailures.length > 0 ? aggregatedFailures.map((f) => f.message) : apiResponse.access?.reason ? [apiResponse.access.reason] : ["Access denied"],
416
+ // 3.6.0: the server now emits top-level denialReasons on every deny
417
+ // path — prefer it verbatim; the failure-message reconstruction remains
418
+ // as the fallback for older backends.
419
+ denialReasons: serverDenialReasons ?? (aggregatedFailures && aggregatedFailures.length > 0 ? aggregatedFailures.map((f) => f.message) : apiResponse.access?.reason ? [apiResponse.access.reason] : ["Access denied"]),
358
420
  failures: aggregatedFailures,
359
421
  requiresStepUp: apiResponse.access?.requiresStepUp,
360
422
  requiresApproval: apiResponse.access?.requiresApproval,
@@ -431,9 +493,7 @@ async function verify(config, request) {
431
493
  if (result.recommendation === "deny") {
432
494
  result.policyAllowed = false;
433
495
  result.accessLevel = "none";
434
- result.denialReasons = result.recommendationReasons || [
435
- "Access denied by AstraSync recommendation"
436
- ];
496
+ result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Access denied by AstraSync recommendation"];
437
497
  result.guidance = result.runtimeChallenge ? {
438
498
  message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
439
499
  registrationUrl: urls?.registrationUrl ?? "",
@@ -445,9 +505,10 @@ async function verify(config, request) {
445
505
  };
446
506
  } else if (result.recommendation === "step_up_required") {
447
507
  result.requiresStepUp = true;
448
- result.denialReasons = result.recommendationReasons || ["Step-up verification required"];
508
+ result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Step-up verification required"];
449
509
  }
450
- if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny") {
510
+ const escalates = result.requiresStepUp === true || result.requiresApproval === true || result.recommendation === "step_up_required";
511
+ if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny" && !escalates) {
451
512
  cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
452
513
  }
453
514
  return result;
@@ -1008,7 +1069,7 @@ function createMiddleware(options) {
1008
1069
  }
1009
1070
  const forwardedFor = request.headers.get("x-forwarded-for") || void 0;
1010
1071
  const originalClientIp = forwardedFor?.split(",")[0]?.trim();
1011
- const result = await verify(config, {
1072
+ const verificationRequest = {
1012
1073
  credentials,
1013
1074
  purpose,
1014
1075
  action: pdlssPair.action,
@@ -1025,7 +1086,17 @@ function createMiddleware(options) {
1025
1086
  forwardedFor,
1026
1087
  agentCardUrl: request.headers.get("x-astrasync-agent-card") || void 0
1027
1088
  }
1028
- });
1089
+ };
1090
+ let result = await verify(config, verificationRequest);
1091
+ let stepUpHoldOutcome;
1092
+ if (config.stepUpMaxWaitMs !== void 0 && result.identityVerified && requiresHumanApproval(result) && result.stepUpApproval?.pollUrl) {
1093
+ stepUpHoldOutcome = await awaitStepUpApproval(config, result.stepUpApproval);
1094
+ if (stepUpHoldOutcome === "approved") {
1095
+ result = await verify(config, verificationRequest, { bypassCache: true });
1096
+ } else {
1097
+ result.stepUpOutcome = stepUpHoldOutcome;
1098
+ }
1099
+ }
1029
1100
  const approvalRequired = result.identityVerified && result.policyAllowed && requiresHumanApproval(result);
1030
1101
  if (approvalRequired) annotateApprovalRequired(result);
1031
1102
  if (!result.identityVerified || !result.policyAllowed || approvalRequired) {
@@ -1040,10 +1111,17 @@ function createMiddleware(options) {
1040
1111
  message: result.denialReasons?.[0] || "Access denied",
1041
1112
  guidance: result.guidance,
1042
1113
  failures: result.failures,
1043
- stepUpApproval: result.stepUpApproval
1114
+ stepUpApproval: result.stepUpApproval,
1115
+ // 3.6.0: terminal outcome of an opt-in hold-and-poll wait.
1116
+ ...result.stepUpOutcome && { stepUpOutcome: result.stepUpOutcome }
1044
1117
  }
1045
1118
  },
1046
- { status: !result.identityVerified ? 401 : 403 }
1119
+ {
1120
+ status: !result.identityVerified ? 401 : 403,
1121
+ ...stepUpHoldOutcome && {
1122
+ headers: { "X-Astra-Step-Up": stepUpHoldOutcome }
1123
+ }
1124
+ }
1047
1125
  );
1048
1126
  }
1049
1127
  if (showCommerceShield) {
@@ -1062,6 +1140,9 @@ function createMiddleware(options) {
1062
1140
  "X-AstraSync-Verified",
1063
1141
  (result.identityVerified && result.policyAllowed).toString()
1064
1142
  );
1143
+ if (stepUpHoldOutcome) {
1144
+ response.headers.set("X-Astra-Step-Up", stepUpHoldOutcome);
1145
+ }
1065
1146
  response.headers.set("X-AstraSync-Identity-Verified", result.identityVerified.toString());
1066
1147
  response.headers.set("X-AstraSync-Policy-Allowed", result.policyAllowed.toString());
1067
1148
  response.headers.set("X-AstraSync-Access-Level", result.accessLevel);