@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,6 +1,6 @@
1
1
  import { AstraSyncGateway } from '../gateway/gateway.mjs';
2
- import { V as VerificationDecision, P as PDLSSContext } from '../types-CyFwZ_Yu.mjs';
3
- import '../types-Cuh7ELfr.mjs';
2
+ import { V as VerificationDecision, P as PDLSSContext } from '../types-BNiLZY0i.mjs';
3
+ import '../types-rFh4VMH4.mjs';
4
4
 
5
5
  /**
6
6
  * Git Trigger — Enterprise git push / PR verification
@@ -1,6 +1,6 @@
1
1
  import { AstraSyncGateway } from '../gateway/gateway.js';
2
- import { V as VerificationDecision, P as PDLSSContext } from '../types-WIRp_BP_.js';
3
- import '../types-Cuh7ELfr.js';
2
+ import { V as VerificationDecision, P as PDLSSContext } from '../types-DJi-u3fz.js';
3
+ import '../types-rFh4VMH4.js';
4
4
 
5
5
  /**
6
6
  * Git Trigger — Enterprise git push / PR verification
@@ -1,4 +1,4 @@
1
- import { b as AstraSyncCredentials, f as ProtocolTransport } from './types-Cuh7ELfr.mjs';
1
+ import { b as AstraSyncCredentials, f as ProtocolTransport } from './types-rFh4VMH4.mjs';
2
2
  import { JWK } from 'jose';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { b as AstraSyncCredentials, f as ProtocolTransport, G as GatewayConfig } from './types-Cuh7ELfr.js';
1
+ import { b as AstraSyncCredentials, f as ProtocolTransport, G as GatewayConfig } from './types-rFh4VMH4.js';
2
2
 
3
3
  /**
4
4
  * AgentClient — Credential Presentation
@@ -1,4 +1,4 @@
1
- import { b as AstraSyncCredentials, f as ProtocolTransport, G as GatewayConfig } from './types-Cuh7ELfr.mjs';
1
+ import { b as AstraSyncCredentials, f as ProtocolTransport, G as GatewayConfig } from './types-rFh4VMH4.mjs';
2
2
 
3
3
  /**
4
4
  * AgentClient — Credential Presentation
@@ -1,4 +1,4 @@
1
- import { b as AstraSyncCredentials, f as ProtocolTransport } from './types-Cuh7ELfr.js';
1
+ import { b as AstraSyncCredentials, f as ProtocolTransport } from './types-rFh4VMH4.js';
2
2
  import { JWK } from 'jose';
3
3
 
4
4
  /**
package/dist/index.d.mts CHANGED
@@ -1,12 +1,12 @@
1
- import { a as AgentCredentials, G as GatewayConfig, A as AccessLevel, V as VerificationRequest, i as VerificationResult } from './types-Cuh7ELfr.mjs';
2
- export { b as AstraSyncCredentials, C as CommerceShieldProps, c as CounterpartyType, E as EnhancedVerificationResult, d as ExpressMiddlewareOptions, e as GuidanceInfo, N as NextJsMiddlewareOptions, P as PDLSSInfo, f as ProtocolTransport, R as RouteAccessConfig, g as RuntimeChallengeResult, S as SDKOptions, T as TokenGuidance, h as TrustLevel, j as VerifiedAgent, k as VerifiedDeveloper, l as VerifiedOrganization } from './types-Cuh7ELfr.mjs';
3
- export { A as ACCESS_LEVEL_DESCRIPTIONS, a as ACCESS_LEVEL_HIERARCHY, b as AccessCapabilities, D as DEFAULT_TRUST_THRESHOLDS, T as TRUST_LEVEL_RANGES, d as determineAccessLevel, g as getAccessLevelForScore, e as getCapabilities, f as getTrustLevel, h as hasMinimumAccess, s as sdk } from './sdk-767LaEP8.mjs';
4
- export { e as express } from './express-DFVBlXr_.mjs';
5
- export { n as nextjs } from './nextjs-D-maqrNz.mjs';
6
- export { aR as extractMcpCredentials, bg as setMcpMeta, b1 as transport } from './index-BhL2R65s.mjs';
1
+ import { a as AgentCredentials, G as GatewayConfig, A as AccessLevel, V as VerificationRequest, i as VerificationResult } from './types-rFh4VMH4.mjs';
2
+ export { b as AstraSyncCredentials, C as CommerceShieldProps, c as CounterpartyType, E as EnhancedVerificationResult, d as ExpressMiddlewareOptions, e as GuidanceInfo, N as NextJsMiddlewareOptions, P as PDLSSInfo, f as ProtocolTransport, R as RouteAccessConfig, g as RuntimeChallengeResult, S as SDKOptions, T as TokenGuidance, h as TrustLevel, j as VerifiedAgent, k as VerifiedDeveloper, l as VerifiedOrganization } from './types-rFh4VMH4.mjs';
3
+ export { A as ACCESS_LEVEL_DESCRIPTIONS, a as ACCESS_LEVEL_HIERARCHY, b as AccessCapabilities, D as DEFAULT_TRUST_THRESHOLDS, T as TRUST_LEVEL_RANGES, d as determineAccessLevel, g as getAccessLevelForScore, e as getCapabilities, f as getTrustLevel, h as hasMinimumAccess, s as sdk } from './sdk-e5jg7sqW.mjs';
4
+ export { e as express } from './express-CeoSdOAZ.mjs';
5
+ export { n as nextjs } from './nextjs-BW1rzr1I.mjs';
6
+ export { aR as extractMcpCredentials, bg as setMcpMeta, b1 as transport } from './index-B51W8gn8.mjs';
7
7
  export { McpMiddlewareOptions, ToolGateConfig, createMcpMiddleware } from './adapters/mcp.mjs';
8
8
  export { AgentProtocol, AgentRecord, AstraSync, AstraSyncConfig, AstraSyncError, AuthenticationError, BuildGuidanceParams, FrameworkConfig, GuidanceEnvelope, HealthResponse, KYDRequiredError, ModelConfig, PDLSSConfig, PDLSSDuration, PDLSSLimits, PDLSSPurpose, PDLSSScope, PDLSSSelfInstantiation, PendingRegistrationResponse, PollRegistrationResult, RegisterOptions, RegisterResult, RegistrationDeniedError, RegistrationExpiredError, RegistrationResponse, RegistrationTimeoutError, VerifyResponse, WaitForApprovalOptions, buildGuidance } from './registration/index.mjs';
9
- export { A as AgentClient, C as ChallengeHandler, i as agent, r as recordDecision } from './index-BVxantdv.mjs';
9
+ export { A as AgentClient, C as ChallengeHandler, i as agent, r as recordDecision } from './index-DtGziFEm.mjs';
10
10
  import 'express';
11
11
  import 'next/server';
12
12
  import 'jose';
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { a as AgentCredentials, G as GatewayConfig, A as AccessLevel, V as VerificationRequest, i as VerificationResult } from './types-Cuh7ELfr.js';
2
- export { b as AstraSyncCredentials, C as CommerceShieldProps, c as CounterpartyType, E as EnhancedVerificationResult, d as ExpressMiddlewareOptions, e as GuidanceInfo, N as NextJsMiddlewareOptions, P as PDLSSInfo, f as ProtocolTransport, R as RouteAccessConfig, g as RuntimeChallengeResult, S as SDKOptions, T as TokenGuidance, h as TrustLevel, j as VerifiedAgent, k as VerifiedDeveloper, l as VerifiedOrganization } from './types-Cuh7ELfr.js';
3
- export { A as ACCESS_LEVEL_DESCRIPTIONS, a as ACCESS_LEVEL_HIERARCHY, b as AccessCapabilities, D as DEFAULT_TRUST_THRESHOLDS, T as TRUST_LEVEL_RANGES, d as determineAccessLevel, g as getAccessLevelForScore, e as getCapabilities, f as getTrustLevel, h as hasMinimumAccess, s as sdk } from './sdk-K8IgssHI.js';
4
- export { e as express } from './express-DavQ76oF.js';
5
- export { n as nextjs } from './nextjs-BXLH1hJj.js';
6
- export { aR as extractMcpCredentials, bg as setMcpMeta, b1 as transport } from './index-Dk2nIA4w.js';
1
+ import { a as AgentCredentials, G as GatewayConfig, A as AccessLevel, V as VerificationRequest, i as VerificationResult } from './types-rFh4VMH4.js';
2
+ export { b as AstraSyncCredentials, C as CommerceShieldProps, c as CounterpartyType, E as EnhancedVerificationResult, d as ExpressMiddlewareOptions, e as GuidanceInfo, N as NextJsMiddlewareOptions, P as PDLSSInfo, f as ProtocolTransport, R as RouteAccessConfig, g as RuntimeChallengeResult, S as SDKOptions, T as TokenGuidance, h as TrustLevel, j as VerifiedAgent, k as VerifiedDeveloper, l as VerifiedOrganization } from './types-rFh4VMH4.js';
3
+ export { A as ACCESS_LEVEL_DESCRIPTIONS, a as ACCESS_LEVEL_HIERARCHY, b as AccessCapabilities, D as DEFAULT_TRUST_THRESHOLDS, T as TRUST_LEVEL_RANGES, d as determineAccessLevel, g as getAccessLevelForScore, e as getCapabilities, f as getTrustLevel, h as hasMinimumAccess, s as sdk } from './sdk-ZYgI7G9f.js';
4
+ export { e as express } from './express-BowlMHQF.js';
5
+ export { n as nextjs } from './nextjs-V_K0qlAQ.js';
6
+ export { aR as extractMcpCredentials, bg as setMcpMeta, b1 as transport } from './index-DzXXBuLm.js';
7
7
  export { McpMiddlewareOptions, ToolGateConfig, createMcpMiddleware } from './adapters/mcp.js';
8
8
  export { AgentProtocol, AgentRecord, AstraSync, AstraSyncConfig, AstraSyncError, AuthenticationError, BuildGuidanceParams, FrameworkConfig, GuidanceEnvelope, HealthResponse, KYDRequiredError, ModelConfig, PDLSSConfig, PDLSSDuration, PDLSSLimits, PDLSSPurpose, PDLSSScope, PDLSSSelfInstantiation, PendingRegistrationResponse, PollRegistrationResult, RegisterOptions, RegisterResult, RegistrationDeniedError, RegistrationExpiredError, RegistrationResponse, RegistrationTimeoutError, VerifyResponse, WaitForApprovalOptions, buildGuidance } from './registration/index.js';
9
- export { A as AgentClient, C as ChallengeHandler, i as agent, r as recordDecision } from './index-BhEgEiJL.js';
9
+ export { A as AgentClient, C as ChallengeHandler, i as agent, r as recordDecision } from './index-DBmlycVm.js';
10
10
  import 'express';
11
11
  import 'next/server';
12
12
  import 'jose';
package/dist/index.js CHANGED
@@ -192,7 +192,7 @@ function getCapabilities(accessLevel) {
192
192
  }
193
193
 
194
194
  // src/version.ts
195
- var SDK_VERSION = "3.1.0";
195
+ var SDK_VERSION = "3.2.1";
196
196
 
197
197
  // src/well-known.ts
198
198
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -297,7 +297,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
297
297
  }
298
298
  }
299
299
  var verificationCache = /* @__PURE__ */ new Map();
300
- function getCacheKey(request) {
300
+ function getCacheKey(request, counterpartyId) {
301
301
  const c = request.credentials;
302
302
  return [
303
303
  c.astraId || "",
@@ -310,6 +310,14 @@ function getCacheKey(request) {
310
310
  request.jurisdiction || "",
311
311
  request.transactionValue ?? "",
312
312
  request.currency || "",
313
+ // SECURITY (cross-merchant cache leak): the merchant identity is sent via
314
+ // `config.counterpartyId`, NOT on the request, so it was previously absent
315
+ // from the key — two verifies for the SAME agent/purpose/action/value but
316
+ // DIFFERENT merchants collided, and a grant at a permissive merchant (low
317
+ // trust floor) was served for a stricter one. Same bug class as the
318
+ // duration omission (F-A1-07). counterpartyId affects the backend verdict
319
+ // (trust floor / per-route policy), so it MUST key the cache.
320
+ counterpartyId || "",
313
321
  request.counterpartyUrl || "",
314
322
  request.counterpartyType || "",
315
323
  request.isSubAgentRequest ? "1" : "0",
@@ -333,8 +341,8 @@ function getCacheKey(request) {
333
341
  request.callerMetadata?.agentCardUrl || ""
334
342
  ].join("|");
335
343
  }
336
- function getCachedResult(request) {
337
- const key = getCacheKey(request);
344
+ function getCachedResult(request, counterpartyId) {
345
+ const key = getCacheKey(request, counterpartyId);
338
346
  const cached = verificationCache.get(key);
339
347
  if (cached && cached.expiresAt > Date.now()) {
340
348
  return cached.result;
@@ -346,9 +354,9 @@ function getCachedResult(request) {
346
354
  }
347
355
  var DEFAULT_AUTONOMOUS_TTL_SECONDS = 60;
348
356
  var DEFAULT_STEP_UP_TTL_SECONDS = 300;
349
- function cacheResult(request, result, configuredTtl) {
357
+ function cacheResult(request, result, configuredTtl, counterpartyId) {
350
358
  const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : result.requiresStepUp ? DEFAULT_STEP_UP_TTL_SECONDS : DEFAULT_AUTONOMOUS_TTL_SECONDS;
351
- const key = getCacheKey(request);
359
+ const key = getCacheKey(request, counterpartyId);
352
360
  verificationCache.set(key, {
353
361
  result,
354
362
  expiresAt: Date.now() + ttlSeconds * 1e3
@@ -546,7 +554,7 @@ async function verify(config, request) {
546
554
  );
547
555
  }
548
556
  if (mergedConfig.cacheTtl !== 0) {
549
- const cached = getCachedResult(request);
557
+ const cached = getCachedResult(request, mergedConfig.counterpartyId);
550
558
  if (cached) {
551
559
  if (mergedConfig.debug) {
552
560
  console.log("[VerificationGateway] Returning cached result");
@@ -598,8 +606,8 @@ async function verify(config, request) {
598
606
  verifiedAt: /* @__PURE__ */ new Date(),
599
607
  // Extract sessionId so decisions can be recorded for denials too
600
608
  sessionId: apiResponse.sessionId,
601
- // v2.3.10 (defect #34, round-4): anonymous traffic has no session →
602
- // correlationId is the linking key for paired local_override events.
609
+ // Anonymous traffic has no session → correlationId is the per-attempt
610
+ // linking key (the sessionId-equivalent for anonymous callers).
603
611
  correlationId: apiResponse.correlationId,
604
612
  recommendation: apiResponse.recommendation,
605
613
  recommendationReasons: apiResponse.recommendationReasons
@@ -673,17 +681,14 @@ async function verify(config, request) {
673
681
  };
674
682
  } else if (result.recommendation === "step_up_required") {
675
683
  result.requiresStepUp = true;
676
- if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
677
- result.accessLevel = "read-only";
678
- }
679
684
  result.denialReasons = result.recommendationReasons || ["Step-up verification required"];
680
685
  }
681
686
  if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny") {
682
- cacheResult(request, result, mergedConfig.cacheTtl);
687
+ cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
683
688
  }
684
689
  return result;
685
690
  }
686
- async function recordDecision(config, sessionId, decision, reason, override) {
691
+ async function recordDecision(config, sessionId, decision, reason) {
687
692
  const headers = { "Content-Type": "application/json" };
688
693
  if (config.apiKey) {
689
694
  headers["Authorization"] = `Bearer ${config.apiKey}`;
@@ -692,36 +697,7 @@ async function recordDecision(config, sessionId, decision, reason, override) {
692
697
  await fetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
693
698
  method: "POST",
694
699
  headers,
695
- body: JSON.stringify({
696
- decision,
697
- reason,
698
- ...override && {
699
- overriddenBy: override.overriddenBy,
700
- toolName: override.toolName,
701
- requestedLevel: override.requestedLevel,
702
- grantedLevel: override.grantedLevel
703
- }
704
- })
705
- }).catch(() => {
706
- });
707
- }
708
- async function recordAnonymousLocalOverride(config, correlationId, override, reason) {
709
- const headers = { "Content-Type": "application/json" };
710
- if (config.apiKey) {
711
- headers["Authorization"] = `Bearer ${config.apiKey}`;
712
- headers["X-API-Key"] = config.apiKey;
713
- }
714
- await fetch(`${config.apiBaseUrl}/agents/verify-access/local-override`, {
715
- method: "POST",
716
- headers,
717
- body: JSON.stringify({
718
- correlationId,
719
- reason,
720
- overriddenBy: override.overriddenBy,
721
- toolName: override.toolName,
722
- requestedLevel: override.requestedLevel,
723
- grantedLevel: override.grantedLevel
724
- })
700
+ body: JSON.stringify({ decision, reason })
725
701
  }).catch(() => {
726
702
  });
727
703
  }
@@ -922,6 +898,19 @@ function resolveHttpPdlss(input) {
922
898
  return { purpose, action, purposeSource, actionSource };
923
899
  }
924
900
 
901
+ // src/adapters/approval-gate.ts
902
+ var APPROVAL_REASON = "Transaction is above the autonomous limit and requires human approval, which is not yet available \u2014 it cannot be completed automatically.";
903
+ function requiresHumanApproval(result) {
904
+ return result.requiresStepUp === true || result.requiresApproval === true;
905
+ }
906
+ function annotateApprovalRequired(result) {
907
+ result.failures = [
908
+ ...result.failures ?? [],
909
+ { dimension: "commerce.intent.approval_required", message: APPROVAL_REASON }
910
+ ];
911
+ result.denialReasons = [APPROVAL_REASON, ...result.denialReasons ?? []];
912
+ }
913
+
925
914
  // src/pdlss-pre-check.ts
926
915
  function performCounterpartyPreCheck(routeConfig, astraCreds, purpose) {
927
916
  const failures = [];
@@ -1229,6 +1218,16 @@ function createMiddleware(options) {
1229
1218
  onDenied(result, req, res);
1230
1219
  return;
1231
1220
  }
1221
+ if (requiresHumanApproval(result)) {
1222
+ annotateApprovalRequired(result);
1223
+ if (shouldRecordDecisions && sessionId) {
1224
+ recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
1225
+ });
1226
+ }
1227
+ dedupeFailures(result);
1228
+ onDenied(result, req, res);
1229
+ return;
1230
+ }
1232
1231
  if (!shouldEnforce) {
1233
1232
  if (config.setPassThroughHeader) {
1234
1233
  res.setHeader("X-Astra-Gateway-Mode", "enforced");
@@ -1240,35 +1239,12 @@ function createMiddleware(options) {
1240
1239
  }
1241
1240
  return next();
1242
1241
  }
1243
- if (!hasMinimumAccess(result.accessLevel, routeConfig.minAccessLevel)) {
1244
- const insufficientFailure = {
1245
- dimension: "access_level.insufficient",
1246
- message: `Endpoint requires accessLevel '${routeConfig.minAccessLevel}'; agent has '${result.accessLevel}'.`,
1247
- 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."
1248
- };
1249
- result.failures = [...result.failures ?? [], insufficientFailure];
1250
- result.denialReasons = [...result.denialReasons ?? [], insufficientFailure.message];
1251
- if (!result.guidance && wellKnownUrls) {
1252
- result.guidance = {
1253
- message: insufficientFailure.message,
1254
- registrationUrl: wellKnownUrls.registrationUrl,
1255
- documentationUrl: wellKnownUrls.documentationUrl
1256
- };
1257
- }
1258
- if (shouldRecordDecisions && sessionId) {
1259
- recordDecision(config, sessionId, "denied", insufficientFailure.message).catch(() => {
1260
- });
1261
- }
1262
- dedupeFailures(result);
1263
- onDenied(result, req, res);
1264
- return;
1265
- }
1266
1242
  if (routeConfig.minTrustScore && result.agent) {
1267
1243
  if (result.agent.trustScore < routeConfig.minTrustScore) {
1268
1244
  const trustFailure = {
1269
- dimension: "access_level.insufficient",
1270
- message: `Trust score ${result.agent.trustScore} is below required ${routeConfig.minTrustScore} for this route.`,
1271
- 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."
1245
+ dimension: "endpoint.trust",
1246
+ message: "Trust below the route requirement for this endpoint.",
1247
+ 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."
1272
1248
  };
1273
1249
  result.failures = [...result.failures ?? [], trustFailure];
1274
1250
  result.denialReasons = [trustFailure.message];
@@ -1699,7 +1675,9 @@ function createMiddleware2(options) {
1699
1675
  agentCardUrl: request.headers.get("x-astrasync-agent-card") || void 0
1700
1676
  }
1701
1677
  });
1702
- if (!result.identityVerified || !result.policyAllowed || !hasMinimumAccess(result.accessLevel, routeConfig.minAccessLevel)) {
1678
+ const approvalRequired = result.identityVerified && result.policyAllowed && requiresHumanApproval(result);
1679
+ if (approvalRequired) annotateApprovalRequired(result);
1680
+ if (!result.identityVerified || !result.policyAllowed || approvalRequired) {
1703
1681
  if (pathname.startsWith("/api/")) {
1704
1682
  return NextResponse.json(
1705
1683
  {
@@ -1707,11 +1685,10 @@ function createMiddleware2(options) {
1707
1685
  error: {
1708
1686
  // Round-18 G4: 401 → identity missing (re-auth); 403 → identity
1709
1687
  // OK, policy denied (update PDLSS / step up).
1710
- code: !result.identityVerified ? "UNAUTHORIZED" : "INSUFFICIENT_ACCESS",
1688
+ code: !result.identityVerified ? "UNAUTHORIZED" : "POLICY_DENIED",
1711
1689
  message: result.denialReasons?.[0] || "Access denied",
1712
- accessLevel: result.accessLevel,
1713
- required: routeConfig.minAccessLevel,
1714
- guidance: result.guidance
1690
+ guidance: result.guidance,
1691
+ failures: result.failures
1715
1692
  }
1716
1693
  },
1717
1694
  { status: !result.identityVerified ? 401 : 403 }
@@ -1738,7 +1715,6 @@ function createMiddleware2(options) {
1738
1715
  response.headers.set("X-AstraSync-Access-Level", result.accessLevel);
1739
1716
  if (result.agent) {
1740
1717
  response.headers.set("X-AstraSync-Agent-Id", result.agent.astraId);
1741
- response.headers.set("X-AstraSync-Trust-Score", result.agent.trustScore.toString());
1742
1718
  }
1743
1719
  return response;
1744
1720
  };
@@ -1812,7 +1788,13 @@ var VerificationGatewayClient = class {
1812
1788
  return this.executeWithRetry(() => quickVerify(this.config, credentials));
1813
1789
  }
1814
1790
  /**
1815
- * Check if an agent has a specific access level
1791
+ * Check if an agent has a specific access level.
1792
+ *
1793
+ * @deprecated 3.2.0 — the access-level band is informational only; it no
1794
+ * longer gates in the middleware adapters (post-3.1.0 feedback #1). This
1795
+ * explicit opt-in query still works, but prefer gating on the server-side
1796
+ * policy decision (identity + policy + trust) or per-route `minTrustScore`.
1797
+ * Explicit per-route condition→constraint rules are the Phase-2 successor.
1816
1798
  */
1817
1799
  async hasAccess(credentials, requiredLevel) {
1818
1800
  const result = await this.quickVerify(credentials);
@@ -4656,7 +4638,6 @@ function createMcpMiddleware(options) {
4656
4638
  return next();
4657
4639
  }
4658
4640
  req.mcpRequest = parsed;
4659
- const wellKnownUrls = config.apiBaseUrl ? await getWellKnownUrls(config.apiBaseUrl).catch(() => void 0) : void 0;
4660
4641
  const headerRaw = req.headers["x-astra-id"] ?? req.headers["x-astra-agentid"];
4661
4642
  const headerAstraId = typeof headerRaw === "string" ? headerRaw : Array.isArray(headerRaw) ? headerRaw[0] : void 0;
4662
4643
  const bodyAstraId = parsed.agentIdFromBody;
@@ -4693,7 +4674,7 @@ function createMcpMiddleware(options) {
4693
4674
  return next();
4694
4675
  }
4695
4676
  }
4696
- const { level: minAccessLevel, source: gateSource } = resolveMinAccessLevel(parsed, {
4677
+ const { level: minAccessLevel } = resolveMinAccessLevel(parsed, {
4697
4678
  toolGates,
4698
4679
  methodGates
4699
4680
  });
@@ -4729,6 +4710,23 @@ function createMcpMiddleware(options) {
4729
4710
  resolved_action: pdlss.action
4730
4711
  });
4731
4712
  }
4713
+ if (!pdlss.purpose) {
4714
+ const id = req.body?.id ?? null;
4715
+ res.status(400).json({
4716
+ jsonrpc: "2.0",
4717
+ id,
4718
+ error: {
4719
+ code: -32602,
4720
+ message: "PDLSS_PURPOSE_REQUIRED",
4721
+ data: {
4722
+ dimension: "pdlss.purpose",
4723
+ detail: "This tool is access-gated but the call declared no PDLSS purpose. Supply a bare-category purpose via the X-Astra-Purpose header or params._meta.astrasync.purpose, or have the merchant set the tool\u2019s purpose in its toolGate config.",
4724
+ resolvedAction: pdlss.action
4725
+ }
4726
+ }
4727
+ });
4728
+ return;
4729
+ }
4732
4730
  const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get("host")}${req.path}`;
4733
4731
  const shouldRecordDecisions = recordDecisions !== false;
4734
4732
  const result = await verify(config, {
@@ -4752,7 +4750,6 @@ function createMcpMiddleware(options) {
4752
4750
  });
4753
4751
  req.agentVerification = result;
4754
4752
  const sessionId = result.sessionId;
4755
- const correlationId = result.correlationId;
4756
4753
  if (!result.identityVerified || !result.policyAllowed) {
4757
4754
  if (shouldRecordDecisions && sessionId) {
4758
4755
  recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
@@ -4762,6 +4759,16 @@ function createMcpMiddleware(options) {
4762
4759
  onDenied(result, req, res);
4763
4760
  return;
4764
4761
  }
4762
+ if (requiresHumanApproval(result)) {
4763
+ annotateApprovalRequired(result);
4764
+ if (shouldRecordDecisions && sessionId) {
4765
+ recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
4766
+ });
4767
+ }
4768
+ dedupeFailures2(result);
4769
+ onDenied(result, req, res);
4770
+ return;
4771
+ }
4765
4772
  if (!shouldEnforce) {
4766
4773
  if (config.setPassThroughHeader) {
4767
4774
  res.setHeader("X-Astra-Gateway-Mode", "enforced");
@@ -4773,48 +4780,6 @@ function createMcpMiddleware(options) {
4773
4780
  }
4774
4781
  return next();
4775
4782
  }
4776
- if (!hasMinimumAccess(result.accessLevel, minAccessLevel)) {
4777
- const insufficientFailure = {
4778
- dimension: "access_level.insufficient",
4779
- message: `Tool requires accessLevel '${minAccessLevel}'; agent has '${result.accessLevel}'.`,
4780
- 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."
4781
- };
4782
- result.failures = [...result.failures ?? [], insufficientFailure];
4783
- result.denialReasons = [...result.denialReasons ?? [], insufficientFailure.message];
4784
- if (!result.guidance && wellKnownUrls) {
4785
- result.guidance = {
4786
- message: insufficientFailure.message,
4787
- registrationUrl: wellKnownUrls.registrationUrl,
4788
- documentationUrl: wellKnownUrls.documentationUrl
4789
- };
4790
- }
4791
- if (shouldRecordDecisions) {
4792
- const overrideKind = gateSource === "toolGate" ? "toolGate" : gateSource === "methodGate" ? "methodGate" : "other";
4793
- const override = {
4794
- overriddenBy: overrideKind,
4795
- ...parsed.toolName && { toolName: parsed.toolName },
4796
- requestedLevel: minAccessLevel,
4797
- grantedLevel: result.accessLevel
4798
- };
4799
- if (sessionId) {
4800
- recordDecision(config, sessionId, "denied", result.denialReasons?.[0], override).catch(
4801
- () => {
4802
- }
4803
- );
4804
- } else if (correlationId) {
4805
- recordAnonymousLocalOverride(
4806
- config,
4807
- correlationId,
4808
- override,
4809
- result.denialReasons?.[0]
4810
- ).catch(() => {
4811
- });
4812
- }
4813
- }
4814
- dedupeFailures2(result);
4815
- onDenied(result, req, res);
4816
- return;
4817
- }
4818
4783
  if (effectiveAstraId) {
4819
4784
  res.setHeader(
4820
4785
  MCP_VERIFIED_HOP_HEADER,