@astrasyncai/verification-gateway 4.5.1 → 5.0.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 (140) hide show
  1. package/README.md +1 -1
  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 +11 -33
  7. package/dist/adapters/express.js.map +1 -1
  8. package/dist/adapters/express.mjs +11 -33
  9. package/dist/adapters/express.mjs.map +1 -1
  10. package/dist/adapters/mcp.d.mts +2 -2
  11. package/dist/adapters/mcp.d.ts +2 -2
  12. package/dist/adapters/mcp.js +28 -65
  13. package/dist/adapters/mcp.js.map +1 -1
  14. package/dist/adapters/mcp.mjs +27 -64
  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 +9 -30
  19. package/dist/adapters/nextjs.js.map +1 -1
  20. package/dist/adapters/nextjs.mjs +9 -30
  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 +8 -124
  25. package/dist/adapters/sdk.js.map +1 -1
  26. package/dist/adapters/sdk.mjs +8 -122
  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/agent/index.js +1 -1
  31. package/dist/agent/index.js.map +1 -1
  32. package/dist/agent/index.mjs +1 -1
  33. package/dist/agent/index.mjs.map +1 -1
  34. package/dist/bin/astrasync-claude-hook.js +63 -41
  35. package/dist/bin/astrasync-codex-hook.js +63 -41
  36. package/dist/bin/astrasync-guard.js +63 -41
  37. package/dist/bin/astrasync.js +75 -48
  38. package/dist/browser/background.js +63 -41
  39. package/dist/browser/background.js.map +1 -1
  40. package/dist/browser/background.mjs +63 -41
  41. package/dist/browser/background.mjs.map +1 -1
  42. package/dist/browser/browser-adapter.d.mts +2 -2
  43. package/dist/browser/browser-adapter.d.ts +2 -2
  44. package/dist/claude-code/claude-code-adapter.d.mts +2 -2
  45. package/dist/claude-code/claude-code-adapter.d.ts +2 -2
  46. package/dist/cli/index.d.mts +2 -2
  47. package/dist/cli/index.d.ts +2 -2
  48. package/dist/cli/index.js +33 -6
  49. package/dist/cli/index.js.map +1 -1
  50. package/dist/cli/index.mjs +33 -6
  51. package/dist/cli/index.mjs.map +1 -1
  52. package/dist/codex/index.d.mts +2 -2
  53. package/dist/codex/index.d.ts +2 -2
  54. package/dist/codex/index.js +63 -41
  55. package/dist/codex/index.js.map +1 -1
  56. package/dist/codex/index.mjs +63 -41
  57. package/dist/codex/index.mjs.map +1 -1
  58. package/dist/cursor/cursor-adapter.d.mts +2 -2
  59. package/dist/cursor/cursor-adapter.d.ts +2 -2
  60. package/dist/cursor/extension.d.mts +2 -2
  61. package/dist/cursor/extension.d.ts +2 -2
  62. package/dist/cursor/extension.js +63 -41
  63. package/dist/cursor/extension.js.map +1 -1
  64. package/dist/cursor/extension.mjs +63 -41
  65. package/dist/cursor/extension.mjs.map +1 -1
  66. package/dist/edge-config.d.mts +1 -1
  67. package/dist/edge-config.d.ts +1 -1
  68. package/dist/edge-config.js +1 -1
  69. package/dist/edge-config.js.map +1 -1
  70. package/dist/edge-config.mjs +1 -1
  71. package/dist/edge-config.mjs.map +1 -1
  72. package/dist/edge-core/index.d.mts +1 -3
  73. package/dist/edge-core/index.d.ts +1 -3
  74. package/dist/edge-core/index.js +11 -33
  75. package/dist/edge-core/index.js.map +1 -1
  76. package/dist/edge-core/index.mjs +11 -33
  77. package/dist/edge-core/index.mjs.map +1 -1
  78. package/dist/{express-DaqL11tx.d.ts → express-B5lWuemA.d.ts} +1 -1
  79. package/dist/{express-CR6F3njD.d.mts → express-Dm-snUuY.d.mts} +1 -1
  80. package/dist/gateway/gateway.d.mts +2 -2
  81. package/dist/gateway/gateway.d.ts +2 -2
  82. package/dist/gateway/gateway.js +63 -41
  83. package/dist/gateway/gateway.js.map +1 -1
  84. package/dist/gateway/gateway.mjs +63 -41
  85. package/dist/gateway/gateway.mjs.map +1 -1
  86. package/dist/git-trigger/git-hooks.d.mts +2 -2
  87. package/dist/git-trigger/git-hooks.d.ts +2 -2
  88. package/dist/{index-Cub7lK-T.d.mts → index-B5k_vUmK.d.mts} +1 -1
  89. package/dist/{index-BfIxCYIZ.d.ts → index-BOzM6xUq.d.mts} +1 -2
  90. package/dist/{index-CwAh7Tln.d.mts → index-dRfxUdFA.d.ts} +1 -2
  91. package/dist/{index-B5Ts1WtM.d.ts → index-y8xToocF.d.ts} +1 -1
  92. package/dist/index.d.mts +10 -10
  93. package/dist/index.d.ts +10 -10
  94. package/dist/index.js +30 -217
  95. package/dist/index.js.map +1 -1
  96. package/dist/index.mjs +30 -210
  97. package/dist/index.mjs.map +1 -1
  98. package/dist/local-evaluator/evaluator.d.mts +2 -2
  99. package/dist/local-evaluator/evaluator.d.ts +2 -2
  100. package/dist/local-evaluator/evaluator.js +22 -7
  101. package/dist/local-evaluator/evaluator.js.map +1 -1
  102. package/dist/local-evaluator/evaluator.mjs +22 -7
  103. package/dist/local-evaluator/evaluator.mjs.map +1 -1
  104. package/dist/{mcp-BgBJu4Jl.d.mts → mcp-DgsyQiQq.d.mts} +53 -52
  105. package/dist/{mcp--DgKOwfu.d.ts → mcp-OosmAcKf.d.ts} +53 -52
  106. package/dist/{nextjs-DlX6xwbU.d.mts → nextjs-B1sBdEav.d.mts} +1 -1
  107. package/dist/{nextjs-DL6uE1ye.d.ts → nextjs-DoRmhV_Z.d.ts} +1 -1
  108. package/dist/registration/index.d.mts +5 -1
  109. package/dist/registration/index.d.ts +5 -1
  110. package/dist/registration/index.js +1 -1
  111. package/dist/registration/index.js.map +1 -1
  112. package/dist/registration/index.mjs +1 -1
  113. package/dist/registration/index.mjs.map +1 -1
  114. package/dist/sdk-B83N3xKc.d.mts +142 -0
  115. package/dist/sdk-H_9BTNBS.d.ts +142 -0
  116. package/dist/transport/index.d.mts +2 -2
  117. package/dist/transport/index.d.ts +2 -2
  118. package/dist/transport/index.js +1 -1
  119. package/dist/transport/index.js.map +1 -1
  120. package/dist/transport/index.mjs +1 -1
  121. package/dist/transport/index.mjs.map +1 -1
  122. package/dist/{types-DwSfO7Sb.d.ts → types-BK2POWNc.d.ts} +23 -50
  123. package/dist/{types-C0zfSXMB.d.mts → types-CJjZvPr9.d.mts} +23 -50
  124. package/dist/{types-C7Rb-w0d.d.mts → types-CXf3q4kZ.d.ts} +14 -3
  125. package/dist/{types-nIh3HtuA.d.ts → types-DQmop7ZW.d.mts} +14 -3
  126. package/dist/ui/index.d.mts +2 -17
  127. package/dist/ui/index.d.ts +2 -17
  128. package/dist/ui/index.js +1 -43
  129. package/dist/ui/index.js.map +1 -1
  130. package/dist/ui/index.mjs +1 -42
  131. package/dist/ui/index.mjs.map +1 -1
  132. package/dist/verify.d.mts +3 -4
  133. package/dist/verify.d.ts +3 -4
  134. package/dist/verify.js +8 -28
  135. package/dist/verify.js.map +1 -1
  136. package/dist/verify.mjs +8 -28
  137. package/dist/verify.mjs.map +1 -1
  138. package/package.json +1 -1
  139. package/dist/sdk-Bbh9B_dw.d.mts +0 -215
  140. package/dist/sdk-C6SASmsh.d.ts +0 -215
@@ -260,9 +260,9 @@ var LocalEvaluator = class {
260
260
  if (scopeBlock) {
261
261
  return { recommendation: "DENY", reason: scopeBlock };
262
262
  }
263
- const limitViolation = this.checkLimits(context);
264
- if (limitViolation) {
265
- return { recommendation: "DENY", reason: limitViolation };
263
+ const limitDecision = this.checkLimits(context);
264
+ if (limitDecision) {
265
+ return limitDecision;
266
266
  }
267
267
  if (context.purpose === "sub_agent.spawn" && this.policy.selfInstantiation) {
268
268
  if (!this.policy.selfInstantiation.allowed) {
@@ -327,9 +327,21 @@ var LocalEvaluator = class {
327
327
  checkLimits(context) {
328
328
  const limits = this.policy.limits;
329
329
  if (!limits) return null;
330
- if (limits.maxTransactionAmount !== void 0 && context.transactionValue !== void 0) {
331
- if (context.transactionValue > limits.maxTransactionAmount) {
332
- return `Transaction value ${context.transactionValue} exceeds limit ${limits.maxTransactionAmount}`;
330
+ const value = context.transactionValue;
331
+ if (value !== void 0 && value > 0 && (limits.autonomousThreshold !== void 0 || limits.maxTransactionAmount !== void 0)) {
332
+ const autonomousThreshold = limits.autonomousThreshold ?? 0;
333
+ const hardLimit = limits.maxTransactionAmount ?? limits.autonomousThreshold ?? 0;
334
+ if (value > autonomousThreshold) {
335
+ if (value >= hardLimit) {
336
+ return {
337
+ recommendation: "DENY",
338
+ reason: `Transaction value ${value} at or above Hard Limit ${hardLimit}`
339
+ };
340
+ }
341
+ return {
342
+ recommendation: "MANUAL_REVIEW",
343
+ reason: `Transaction value ${value} is in the human-approval band (${autonomousThreshold}, ${hardLimit})`
344
+ };
333
345
  }
334
346
  }
335
347
  if (limits.maxRequestsPerHour !== void 0) {
@@ -342,7 +354,10 @@ var LocalEvaluator = class {
342
354
  } else {
343
355
  entry.count++;
344
356
  if (entry.count > limits.maxRequestsPerHour) {
345
- return `Rate limit exceeded: ${entry.count}/${limits.maxRequestsPerHour} requests per hour`;
357
+ return {
358
+ recommendation: "DENY",
359
+ reason: `Rate limit exceeded: ${entry.count}/${limits.maxRequestsPerHour} requests per hour`
360
+ };
346
361
  }
347
362
  }
348
363
  }
@@ -3551,10 +3566,16 @@ function validatePurpose(purpose, path) {
3551
3566
  errors.push({ path: `${path}.targets`, message: "targets must be an array of strings" });
3552
3567
  }
3553
3568
  if (p.blockedPatterns !== void 0 && !isStringArray(p.blockedPatterns)) {
3554
- errors.push({ path: `${path}.blockedPatterns`, message: "blockedPatterns must be an array of strings" });
3569
+ errors.push({
3570
+ path: `${path}.blockedPatterns`,
3571
+ message: "blockedPatterns must be an array of strings"
3572
+ });
3555
3573
  }
3556
3574
  if (p.requiresApproval !== void 0 && typeof p.requiresApproval !== "boolean") {
3557
- errors.push({ path: `${path}.requiresApproval`, message: "requiresApproval must be a boolean" });
3575
+ errors.push({
3576
+ path: `${path}.requiresApproval`,
3577
+ message: "requiresApproval must be a boolean"
3578
+ });
3558
3579
  }
3559
3580
  return errors;
3560
3581
  }
@@ -3577,11 +3598,29 @@ function validateLimits(limits, path) {
3577
3598
  return [{ path, message: "limits must be an object" }];
3578
3599
  }
3579
3600
  const l = limits;
3601
+ if (l.autonomousThreshold !== void 0 && typeof l.autonomousThreshold !== "number") {
3602
+ errors.push({
3603
+ path: `${path}.autonomousThreshold`,
3604
+ message: "autonomousThreshold must be a number"
3605
+ });
3606
+ }
3580
3607
  if (l.maxTransactionAmount !== void 0 && typeof l.maxTransactionAmount !== "number") {
3581
- errors.push({ path: `${path}.maxTransactionAmount`, message: "maxTransactionAmount must be a number" });
3608
+ errors.push({
3609
+ path: `${path}.maxTransactionAmount`,
3610
+ message: "maxTransactionAmount must be a number"
3611
+ });
3612
+ }
3613
+ if (typeof l.autonomousThreshold === "number" && typeof l.maxTransactionAmount === "number" && l.autonomousThreshold > l.maxTransactionAmount) {
3614
+ errors.push({
3615
+ path: `${path}.autonomousThreshold`,
3616
+ message: "autonomousThreshold (Autonomous Limit) must be <= maxTransactionAmount (Hard Limit)"
3617
+ });
3582
3618
  }
3583
3619
  if (l.maxRequestsPerHour !== void 0 && typeof l.maxRequestsPerHour !== "number") {
3584
- errors.push({ path: `${path}.maxRequestsPerHour`, message: "maxRequestsPerHour must be a number" });
3620
+ errors.push({
3621
+ path: `${path}.maxRequestsPerHour`,
3622
+ message: "maxRequestsPerHour must be a number"
3623
+ });
3585
3624
  }
3586
3625
  if (l.currency !== void 0 && typeof l.currency !== "string") {
3587
3626
  errors.push({ path: `${path}.currency`, message: "currency must be a string" });
@@ -3596,7 +3635,10 @@ function validateRiskThresholds(thresholds, path) {
3596
3635
  const t = thresholds;
3597
3636
  for (const range of ["autoAllow", "requireApproval", "autoBlock"]) {
3598
3637
  if (!t[range] || typeof t[range] !== "object") {
3599
- errors.push({ path: `${path}.${range}`, message: `${range} is required and must be an object with min and max` });
3638
+ errors.push({
3639
+ path: `${path}.${range}`,
3640
+ message: `${range} is required and must be an object with min and max`
3641
+ });
3600
3642
  continue;
3601
3643
  }
3602
3644
  const r = t[range];
@@ -3692,7 +3734,7 @@ function verifyLocal(evaluator, context) {
3692
3734
  return evaluator.evaluate(context);
3693
3735
  }
3694
3736
 
3695
- // src/access-levels.ts
3737
+ // src/trust-levels.ts
3696
3738
  function getTrustLevel(score) {
3697
3739
  if (score >= 80) return "PLATINUM";
3698
3740
  if (score >= 60) return "GOLD";
@@ -3701,7 +3743,7 @@ function getTrustLevel(score) {
3701
3743
  }
3702
3744
 
3703
3745
  // src/version.ts
3704
- var SDK_VERSION = "4.5.1";
3746
+ var SDK_VERSION = "5.0.0";
3705
3747
 
3706
3748
  // src/http.ts
3707
3749
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -3731,11 +3773,6 @@ function getCachedWellKnownUrls(apiBaseUrl) {
3731
3773
  // src/verify.ts
3732
3774
  var DEFAULT_CONFIG = {
3733
3775
  apiBaseUrl: "https://astrasync.ai/api",
3734
- // v2.3.9 (defect #30): default for unconfigured callers is `'none'` (no
3735
- // access). Pre-rename this defaulted to `'guidance'`, which combined with
3736
- // a route gated at `'guidance'` to silently let unverified traffic
3737
- // through (`hasMinimumAccess('guidance', 'guidance') === true`).
3738
- defaultAccessLevel: "none",
3739
3776
  // minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
3740
3777
  // cacheTtl deliberately unset. When undefined, cacheResult applies the 60s
3741
3778
  // default; the caller's explicit value is honoured for cacheable results.
@@ -3896,13 +3933,6 @@ function createGuidanceResponse(_config, reason, options = {}) {
3896
3933
  // policy is not evaluated (we never reached the gate).
3897
3934
  identityVerified: false,
3898
3935
  policyAllowed: false,
3899
- // v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
3900
- // Adapters additionally short-circuit on `!identityVerified ||
3901
- // !policyAllowed` before the gate check, but the access level still has
3902
- // to be honest at the data layer so downstream consumers (SDK adapters
3903
- // in other languages, custom integrations) inherit the correct
3904
- // semantics.
3905
- accessLevel: "none",
3906
3936
  guidance,
3907
3937
  denialReasons: reason ? [reason] : ["No valid agent credentials provided"],
3908
3938
  // Round-10 (#47, O5): on API-error fallback, surface a typed failure so
@@ -3925,6 +3955,11 @@ function createGuidanceResponse(_config, reason, options = {}) {
3925
3955
  // 4.0.0: typed marker so adapters render the misconfig envelope (503 +
3926
3956
  // MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.
3927
3957
  ...isMisconfig && { misconfigured: true },
3958
+ // 4.6.0: a transient api_error is retryable — mark it so consumers surface
3959
+ // "temporarily unavailable, retry" (recommendation 'error') instead of
3960
+ // coercing the absent recommendation to a policy 'deny'. Misconfig is
3961
+ // deterministic and intentionally NOT marked retryable.
3962
+ ...isApiError && { retryable: true },
3928
3963
  correlationId: options.correlationId,
3929
3964
  attemptId: options.attemptId,
3930
3965
  verifiedAt: /* @__PURE__ */ new Date()
@@ -3991,7 +4026,6 @@ async function callVerifyAccessAPI(config, request) {
3991
4026
  attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
3992
4027
  access: {
3993
4028
  allowed: false,
3994
- accessLevel: "none",
3995
4029
  reason: "endpoint_deactivated",
3996
4030
  failures: [
3997
4031
  {
@@ -4054,7 +4088,7 @@ async function verify(config, request, options) {
4054
4088
  if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
4055
4089
  deprecationWarningShown = true;
4056
4090
  console.warn(
4057
- "[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."
4091
+ "[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."
4058
4092
  );
4059
4093
  }
4060
4094
  if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {
@@ -4100,14 +4134,6 @@ async function verify(config, request, options) {
4100
4134
  const result2 = {
4101
4135
  identityVerified: idVerifiedFromBackend,
4102
4136
  policyAllowed: false,
4103
- // v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
4104
- // Pre-rename this hardcoded `'guidance'`, which conflated with the
4105
- // colocated `guidance: {...}` help-payload object below and let
4106
- // denied requests pass any route gated at `'guidance'` because
4107
- // `hasMinimumAccess('guidance', 'guidance') === true`. Adapters now
4108
- // ALSO short-circuit on `!identityVerified || !policyAllowed` before
4109
- // the gate check — belt-and-braces.
4110
- accessLevel: "none",
4111
4137
  // 3.6.0: the server now emits top-level denialReasons on every deny
4112
4138
  // path — prefer it verbatim; the failure-message reconstruction remains
4113
4139
  // as the fallback for older backends.
@@ -4156,7 +4182,6 @@ async function verify(config, request, options) {
4156
4182
  trustScore: apiResponse.organization.trustScore
4157
4183
  } : void 0;
4158
4184
  const verificationContext = apiResponse.verificationContext;
4159
- const accessLevel = apiResponse.access?.accessLevel ?? "standard";
4160
4185
  const result = {
4161
4186
  // 4.5.0 (probe F1): read idVerified from verificationContext with the
4162
4187
  // SAME absent⇒false default as the deny branch. The previous `!== false`
@@ -4168,7 +4193,6 @@ async function verify(config, request, options) {
4168
4193
  // this load-bearing must never be defaulted on.
4169
4194
  identityVerified: apiResponse.verificationContext?.idVerified === true,
4170
4195
  policyAllowed: true,
4171
- accessLevel,
4172
4196
  agent,
4173
4197
  developer,
4174
4198
  organization,
@@ -4195,7 +4219,6 @@ async function verify(config, request, options) {
4195
4219
  };
4196
4220
  if (result.recommendation === "deny") {
4197
4221
  result.policyAllowed = false;
4198
- result.accessLevel = "none";
4199
4222
  result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Access denied by AstraSync recommendation"];
4200
4223
  result.guidance = result.runtimeChallenge ? {
4201
4224
  message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
@@ -4308,7 +4331,6 @@ function toGatewayConfig(config) {
4308
4331
  return {
4309
4332
  apiBaseUrl: config.apiBaseUrl || "https://api.astrasync.ai",
4310
4333
  apiKey: config.apiKey,
4311
- defaultAccessLevel: config.defaultAccessLevel,
4312
4334
  minTrustScore: config.minTrustScore,
4313
4335
  minTrustScoreForFull: config.minTrustScoreForFull,
4314
4336
  cacheTtl: config.cacheTtl,
@@ -4336,7 +4358,7 @@ function toDecision(result) {
4336
4358
  if (result.identityVerified && result.policyAllowed) {
4337
4359
  return {
4338
4360
  recommendation: "ALLOW",
4339
- reason: `Verified with access level: ${result.accessLevel}`,
4361
+ reason: result.agent?.trustScore ? `Verified (trust score ${result.agent.trustScore})` : "Verified",
4340
4362
  trustScore: result.agent?.trustScore,
4341
4363
  sessionId: "sessionId" in result ? result.sessionId : void 0
4342
4364
  };
@@ -259,9 +259,9 @@ var LocalEvaluator = class {
259
259
  if (scopeBlock) {
260
260
  return { recommendation: "DENY", reason: scopeBlock };
261
261
  }
262
- const limitViolation = this.checkLimits(context);
263
- if (limitViolation) {
264
- return { recommendation: "DENY", reason: limitViolation };
262
+ const limitDecision = this.checkLimits(context);
263
+ if (limitDecision) {
264
+ return limitDecision;
265
265
  }
266
266
  if (context.purpose === "sub_agent.spawn" && this.policy.selfInstantiation) {
267
267
  if (!this.policy.selfInstantiation.allowed) {
@@ -326,9 +326,21 @@ var LocalEvaluator = class {
326
326
  checkLimits(context) {
327
327
  const limits = this.policy.limits;
328
328
  if (!limits) return null;
329
- if (limits.maxTransactionAmount !== void 0 && context.transactionValue !== void 0) {
330
- if (context.transactionValue > limits.maxTransactionAmount) {
331
- return `Transaction value ${context.transactionValue} exceeds limit ${limits.maxTransactionAmount}`;
329
+ const value = context.transactionValue;
330
+ if (value !== void 0 && value > 0 && (limits.autonomousThreshold !== void 0 || limits.maxTransactionAmount !== void 0)) {
331
+ const autonomousThreshold = limits.autonomousThreshold ?? 0;
332
+ const hardLimit = limits.maxTransactionAmount ?? limits.autonomousThreshold ?? 0;
333
+ if (value > autonomousThreshold) {
334
+ if (value >= hardLimit) {
335
+ return {
336
+ recommendation: "DENY",
337
+ reason: `Transaction value ${value} at or above Hard Limit ${hardLimit}`
338
+ };
339
+ }
340
+ return {
341
+ recommendation: "MANUAL_REVIEW",
342
+ reason: `Transaction value ${value} is in the human-approval band (${autonomousThreshold}, ${hardLimit})`
343
+ };
332
344
  }
333
345
  }
334
346
  if (limits.maxRequestsPerHour !== void 0) {
@@ -341,7 +353,10 @@ var LocalEvaluator = class {
341
353
  } else {
342
354
  entry.count++;
343
355
  if (entry.count > limits.maxRequestsPerHour) {
344
- return `Rate limit exceeded: ${entry.count}/${limits.maxRequestsPerHour} requests per hour`;
356
+ return {
357
+ recommendation: "DENY",
358
+ reason: `Rate limit exceeded: ${entry.count}/${limits.maxRequestsPerHour} requests per hour`
359
+ };
345
360
  }
346
361
  }
347
362
  }
@@ -3550,10 +3565,16 @@ function validatePurpose(purpose, path) {
3550
3565
  errors.push({ path: `${path}.targets`, message: "targets must be an array of strings" });
3551
3566
  }
3552
3567
  if (p.blockedPatterns !== void 0 && !isStringArray(p.blockedPatterns)) {
3553
- errors.push({ path: `${path}.blockedPatterns`, message: "blockedPatterns must be an array of strings" });
3568
+ errors.push({
3569
+ path: `${path}.blockedPatterns`,
3570
+ message: "blockedPatterns must be an array of strings"
3571
+ });
3554
3572
  }
3555
3573
  if (p.requiresApproval !== void 0 && typeof p.requiresApproval !== "boolean") {
3556
- errors.push({ path: `${path}.requiresApproval`, message: "requiresApproval must be a boolean" });
3574
+ errors.push({
3575
+ path: `${path}.requiresApproval`,
3576
+ message: "requiresApproval must be a boolean"
3577
+ });
3557
3578
  }
3558
3579
  return errors;
3559
3580
  }
@@ -3576,11 +3597,29 @@ function validateLimits(limits, path) {
3576
3597
  return [{ path, message: "limits must be an object" }];
3577
3598
  }
3578
3599
  const l = limits;
3600
+ if (l.autonomousThreshold !== void 0 && typeof l.autonomousThreshold !== "number") {
3601
+ errors.push({
3602
+ path: `${path}.autonomousThreshold`,
3603
+ message: "autonomousThreshold must be a number"
3604
+ });
3605
+ }
3579
3606
  if (l.maxTransactionAmount !== void 0 && typeof l.maxTransactionAmount !== "number") {
3580
- errors.push({ path: `${path}.maxTransactionAmount`, message: "maxTransactionAmount must be a number" });
3607
+ errors.push({
3608
+ path: `${path}.maxTransactionAmount`,
3609
+ message: "maxTransactionAmount must be a number"
3610
+ });
3611
+ }
3612
+ if (typeof l.autonomousThreshold === "number" && typeof l.maxTransactionAmount === "number" && l.autonomousThreshold > l.maxTransactionAmount) {
3613
+ errors.push({
3614
+ path: `${path}.autonomousThreshold`,
3615
+ message: "autonomousThreshold (Autonomous Limit) must be <= maxTransactionAmount (Hard Limit)"
3616
+ });
3581
3617
  }
3582
3618
  if (l.maxRequestsPerHour !== void 0 && typeof l.maxRequestsPerHour !== "number") {
3583
- errors.push({ path: `${path}.maxRequestsPerHour`, message: "maxRequestsPerHour must be a number" });
3619
+ errors.push({
3620
+ path: `${path}.maxRequestsPerHour`,
3621
+ message: "maxRequestsPerHour must be a number"
3622
+ });
3584
3623
  }
3585
3624
  if (l.currency !== void 0 && typeof l.currency !== "string") {
3586
3625
  errors.push({ path: `${path}.currency`, message: "currency must be a string" });
@@ -3595,7 +3634,10 @@ function validateRiskThresholds(thresholds, path) {
3595
3634
  const t = thresholds;
3596
3635
  for (const range of ["autoAllow", "requireApproval", "autoBlock"]) {
3597
3636
  if (!t[range] || typeof t[range] !== "object") {
3598
- errors.push({ path: `${path}.${range}`, message: `${range} is required and must be an object with min and max` });
3637
+ errors.push({
3638
+ path: `${path}.${range}`,
3639
+ message: `${range} is required and must be an object with min and max`
3640
+ });
3599
3641
  continue;
3600
3642
  }
3601
3643
  const r = t[range];
@@ -3691,7 +3733,7 @@ function verifyLocal(evaluator, context) {
3691
3733
  return evaluator.evaluate(context);
3692
3734
  }
3693
3735
 
3694
- // src/access-levels.ts
3736
+ // src/trust-levels.ts
3695
3737
  function getTrustLevel(score) {
3696
3738
  if (score >= 80) return "PLATINUM";
3697
3739
  if (score >= 60) return "GOLD";
@@ -3700,7 +3742,7 @@ function getTrustLevel(score) {
3700
3742
  }
3701
3743
 
3702
3744
  // src/version.ts
3703
- var SDK_VERSION = "4.5.1";
3745
+ var SDK_VERSION = "5.0.0";
3704
3746
 
3705
3747
  // src/http.ts
3706
3748
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -3730,11 +3772,6 @@ function getCachedWellKnownUrls(apiBaseUrl) {
3730
3772
  // src/verify.ts
3731
3773
  var DEFAULT_CONFIG = {
3732
3774
  apiBaseUrl: "https://astrasync.ai/api",
3733
- // v2.3.9 (defect #30): default for unconfigured callers is `'none'` (no
3734
- // access). Pre-rename this defaulted to `'guidance'`, which combined with
3735
- // a route gated at `'guidance'` to silently let unverified traffic
3736
- // through (`hasMinimumAccess('guidance', 'guidance') === true`).
3737
- defaultAccessLevel: "none",
3738
3775
  // minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
3739
3776
  // cacheTtl deliberately unset. When undefined, cacheResult applies the 60s
3740
3777
  // default; the caller's explicit value is honoured for cacheable results.
@@ -3895,13 +3932,6 @@ function createGuidanceResponse(_config, reason, options = {}) {
3895
3932
  // policy is not evaluated (we never reached the gate).
3896
3933
  identityVerified: false,
3897
3934
  policyAllowed: false,
3898
- // v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
3899
- // Adapters additionally short-circuit on `!identityVerified ||
3900
- // !policyAllowed` before the gate check, but the access level still has
3901
- // to be honest at the data layer so downstream consumers (SDK adapters
3902
- // in other languages, custom integrations) inherit the correct
3903
- // semantics.
3904
- accessLevel: "none",
3905
3935
  guidance,
3906
3936
  denialReasons: reason ? [reason] : ["No valid agent credentials provided"],
3907
3937
  // Round-10 (#47, O5): on API-error fallback, surface a typed failure so
@@ -3924,6 +3954,11 @@ function createGuidanceResponse(_config, reason, options = {}) {
3924
3954
  // 4.0.0: typed marker so adapters render the misconfig envelope (503 +
3925
3955
  // MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.
3926
3956
  ...isMisconfig && { misconfigured: true },
3957
+ // 4.6.0: a transient api_error is retryable — mark it so consumers surface
3958
+ // "temporarily unavailable, retry" (recommendation 'error') instead of
3959
+ // coercing the absent recommendation to a policy 'deny'. Misconfig is
3960
+ // deterministic and intentionally NOT marked retryable.
3961
+ ...isApiError && { retryable: true },
3927
3962
  correlationId: options.correlationId,
3928
3963
  attemptId: options.attemptId,
3929
3964
  verifiedAt: /* @__PURE__ */ new Date()
@@ -3990,7 +4025,6 @@ async function callVerifyAccessAPI(config, request) {
3990
4025
  attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
3991
4026
  access: {
3992
4027
  allowed: false,
3993
- accessLevel: "none",
3994
4028
  reason: "endpoint_deactivated",
3995
4029
  failures: [
3996
4030
  {
@@ -4053,7 +4087,7 @@ async function verify(config, request, options) {
4053
4087
  if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
4054
4088
  deprecationWarningShown = true;
4055
4089
  console.warn(
4056
- "[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."
4090
+ "[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."
4057
4091
  );
4058
4092
  }
4059
4093
  if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {
@@ -4099,14 +4133,6 @@ async function verify(config, request, options) {
4099
4133
  const result2 = {
4100
4134
  identityVerified: idVerifiedFromBackend,
4101
4135
  policyAllowed: false,
4102
- // v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
4103
- // Pre-rename this hardcoded `'guidance'`, which conflated with the
4104
- // colocated `guidance: {...}` help-payload object below and let
4105
- // denied requests pass any route gated at `'guidance'` because
4106
- // `hasMinimumAccess('guidance', 'guidance') === true`. Adapters now
4107
- // ALSO short-circuit on `!identityVerified || !policyAllowed` before
4108
- // the gate check — belt-and-braces.
4109
- accessLevel: "none",
4110
4136
  // 3.6.0: the server now emits top-level denialReasons on every deny
4111
4137
  // path — prefer it verbatim; the failure-message reconstruction remains
4112
4138
  // as the fallback for older backends.
@@ -4155,7 +4181,6 @@ async function verify(config, request, options) {
4155
4181
  trustScore: apiResponse.organization.trustScore
4156
4182
  } : void 0;
4157
4183
  const verificationContext = apiResponse.verificationContext;
4158
- const accessLevel = apiResponse.access?.accessLevel ?? "standard";
4159
4184
  const result = {
4160
4185
  // 4.5.0 (probe F1): read idVerified from verificationContext with the
4161
4186
  // SAME absent⇒false default as the deny branch. The previous `!== false`
@@ -4167,7 +4192,6 @@ async function verify(config, request, options) {
4167
4192
  // this load-bearing must never be defaulted on.
4168
4193
  identityVerified: apiResponse.verificationContext?.idVerified === true,
4169
4194
  policyAllowed: true,
4170
- accessLevel,
4171
4195
  agent,
4172
4196
  developer,
4173
4197
  organization,
@@ -4194,7 +4218,6 @@ async function verify(config, request, options) {
4194
4218
  };
4195
4219
  if (result.recommendation === "deny") {
4196
4220
  result.policyAllowed = false;
4197
- result.accessLevel = "none";
4198
4221
  result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Access denied by AstraSync recommendation"];
4199
4222
  result.guidance = result.runtimeChallenge ? {
4200
4223
  message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
@@ -4307,7 +4330,6 @@ function toGatewayConfig(config) {
4307
4330
  return {
4308
4331
  apiBaseUrl: config.apiBaseUrl || "https://api.astrasync.ai",
4309
4332
  apiKey: config.apiKey,
4310
- defaultAccessLevel: config.defaultAccessLevel,
4311
4333
  minTrustScore: config.minTrustScore,
4312
4334
  minTrustScoreForFull: config.minTrustScoreForFull,
4313
4335
  cacheTtl: config.cacheTtl,
@@ -4335,7 +4357,7 @@ function toDecision(result) {
4335
4357
  if (result.identityVerified && result.policyAllowed) {
4336
4358
  return {
4337
4359
  recommendation: "ALLOW",
4338
- reason: `Verified with access level: ${result.accessLevel}`,
4360
+ reason: result.agent?.trustScore ? `Verified (trust score ${result.agent.trustScore})` : "Verified",
4339
4361
  trustScore: result.agent?.trustScore,
4340
4362
  sessionId: "sessionId" in result ? result.sessionId : void 0
4341
4363
  };