@astrasyncai/verification-gateway 3.0.0 → 3.2.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 (87) 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 +145 -93
  6. package/dist/adapters/express.js.map +1 -1
  7. package/dist/adapters/express.mjs +145 -93
  8. package/dist/adapters/express.mjs.map +1 -1
  9. package/dist/adapters/mcp.d.mts +29 -11
  10. package/dist/adapters/mcp.d.ts +29 -11
  11. package/dist/adapters/mcp.js +43 -102
  12. package/dist/adapters/mcp.js.map +1 -1
  13. package/dist/adapters/mcp.mjs +43 -102
  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 +126 -56
  18. package/dist/adapters/nextjs.js.map +1 -1
  19. package/dist/adapters/nextjs.mjs +126 -56
  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/agent/index.js +3 -0
  30. package/dist/agent/index.js.map +1 -1
  31. package/dist/agent/index.mjs +3 -0
  32. package/dist/agent/index.mjs.map +1 -1
  33. package/dist/browser/background.js +18 -21
  34. package/dist/browser/background.js.map +1 -1
  35. package/dist/browser/background.mjs +18 -21
  36. package/dist/browser/background.mjs.map +1 -1
  37. package/dist/browser/browser-adapter.d.mts +2 -2
  38. package/dist/browser/browser-adapter.d.ts +2 -2
  39. package/dist/cli/index.d.mts +2 -2
  40. package/dist/cli/index.d.ts +2 -2
  41. package/dist/cursor/cursor-adapter.d.mts +2 -2
  42. package/dist/cursor/cursor-adapter.d.ts +2 -2
  43. package/dist/cursor/extension.d.mts +2 -2
  44. package/dist/cursor/extension.d.ts +2 -2
  45. package/dist/cursor/extension.js +18 -21
  46. package/dist/cursor/extension.js.map +1 -1
  47. package/dist/cursor/extension.mjs +18 -21
  48. package/dist/cursor/extension.mjs.map +1 -1
  49. package/dist/{express-CrfwoNAR.d.ts → express-BowlMHQF.d.ts} +1 -1
  50. package/dist/{express-ienhAXps.d.mts → express-CeoSdOAZ.d.mts} +1 -1
  51. package/dist/gateway/gateway.d.mts +2 -2
  52. package/dist/gateway/gateway.d.ts +2 -2
  53. package/dist/gateway/gateway.js +18 -21
  54. package/dist/gateway/gateway.js.map +1 -1
  55. package/dist/gateway/gateway.mjs +18 -21
  56. package/dist/gateway/gateway.mjs.map +1 -1
  57. package/dist/git-trigger/git-hooks.d.mts +2 -2
  58. package/dist/git-trigger/git-hooks.d.ts +2 -2
  59. package/dist/{index-CEg_WG6y.d.mts → index-B51W8gn8.d.mts} +1 -1
  60. package/dist/{index-DC5f8eoQ.d.ts → index-DBmlycVm.d.ts} +1 -1
  61. package/dist/{index-B5e2IDWU.d.mts → index-DtGziFEm.d.mts} +1 -1
  62. package/dist/{index-CCdZxvAr.d.ts → index-DzXXBuLm.d.ts} +1 -1
  63. package/dist/index.d.mts +7 -7
  64. package/dist/index.d.ts +7 -7
  65. package/dist/index.js +209 -191
  66. package/dist/index.js.map +1 -1
  67. package/dist/index.mjs +209 -191
  68. package/dist/index.mjs.map +1 -1
  69. package/dist/local-evaluator/evaluator.d.mts +2 -2
  70. package/dist/local-evaluator/evaluator.d.ts +2 -2
  71. package/dist/{nextjs-DSpisQst.d.mts → nextjs-BW1rzr1I.d.mts} +1 -1
  72. package/dist/{nextjs-66R1KW8e.d.ts → nextjs-V_K0qlAQ.d.ts} +1 -1
  73. package/dist/{sdk-5U_CBRpr.d.mts → sdk-ZYgI7G9f.d.ts} +14 -3
  74. package/dist/{sdk-Bm8np66n.d.ts → sdk-e5jg7sqW.d.mts} +14 -3
  75. package/dist/transport/index.d.mts +2 -2
  76. package/dist/transport/index.d.ts +2 -2
  77. package/dist/transport/index.js +10 -0
  78. package/dist/transport/index.js.map +1 -1
  79. package/dist/transport/index.mjs +10 -0
  80. package/dist/transport/index.mjs.map +1 -1
  81. package/dist/{types-CgDCUfo8.d.mts → types-BNiLZY0i.d.mts} +1 -1
  82. package/dist/{types-R5N4ET6x.d.ts → types-DJi-u3fz.d.ts} +1 -1
  83. package/dist/{types-B3USs-Kx.d.mts → types-rFh4VMH4.d.mts} +30 -2
  84. package/dist/{types-B3USs-Kx.d.ts → types-rFh4VMH4.d.ts} +30 -2
  85. package/dist/ui/index.d.mts +1 -1
  86. package/dist/ui/index.d.ts +1 -1
  87. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { AstraSyncGateway } from '../gateway/gateway.mjs';
2
- import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-CgDCUfo8.mjs';
3
- import '../types-B3USs-Kx.mjs';
2
+ import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-BNiLZY0i.mjs';
3
+ import '../types-rFh4VMH4.mjs';
4
4
 
5
5
  /**
6
6
  * PlatformAdapter Interface
@@ -1,6 +1,6 @@
1
1
  import { AstraSyncGateway } from '../gateway/gateway.js';
2
- import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-R5N4ET6x.js';
3
- import '../types-B3USs-Kx.js';
2
+ import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-DJi-u3fz.js';
3
+ import '../types-rFh4VMH4.js';
4
4
 
5
5
  /**
6
6
  * PlatformAdapter Interface
@@ -1,3 +1,3 @@
1
1
  import 'express';
2
- import '../types-B3USs-Kx.mjs';
3
- export { c as createMiddleware, a as extractAstraSyncCredentials } from '../express-ienhAXps.mjs';
2
+ import '../types-rFh4VMH4.mjs';
3
+ export { c as createMiddleware, a as extractAstraSyncCredentials } from '../express-CeoSdOAZ.mjs';
@@ -1,3 +1,3 @@
1
1
  import 'express';
2
- import '../types-B3USs-Kx.js';
3
- export { c as createMiddleware, a as extractAstraSyncCredentials } from '../express-CrfwoNAR.js';
2
+ import '../types-rFh4VMH4.js';
3
+ export { c as createMiddleware, a as extractAstraSyncCredentials } from '../express-BowlMHQF.js';
@@ -26,26 +26,15 @@ __export(express_exports, {
26
26
  module.exports = __toCommonJS(express_exports);
27
27
 
28
28
  // src/access-levels.ts
29
- var ACCESS_LEVEL_HIERARCHY = {
30
- none: 0,
31
- restricted: 1,
32
- "read-only": 2,
33
- standard: 3,
34
- full: 4,
35
- internal: 5
36
- };
37
29
  function getTrustLevel(score) {
38
30
  if (score >= 80) return "PLATINUM";
39
31
  if (score >= 60) return "GOLD";
40
32
  if (score >= 40) return "SILVER";
41
33
  return "BRONZE";
42
34
  }
43
- function hasMinimumAccess(actual, required) {
44
- return ACCESS_LEVEL_HIERARCHY[actual] >= ACCESS_LEVEL_HIERARCHY[required];
45
- }
46
35
 
47
36
  // src/version.ts
48
- var SDK_VERSION = "3.0.0";
37
+ var SDK_VERSION = "3.2.0";
49
38
 
50
39
  // src/well-known.ts
51
40
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -150,7 +139,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
150
139
  }
151
140
  }
152
141
  var verificationCache = /* @__PURE__ */ new Map();
153
- function getCacheKey(request) {
142
+ function getCacheKey(request, counterpartyId) {
154
143
  const c = request.credentials;
155
144
  return [
156
145
  c.astraId || "",
@@ -163,6 +152,14 @@ function getCacheKey(request) {
163
152
  request.jurisdiction || "",
164
153
  request.transactionValue ?? "",
165
154
  request.currency || "",
155
+ // SECURITY (cross-merchant cache leak): the merchant identity is sent via
156
+ // `config.counterpartyId`, NOT on the request, so it was previously absent
157
+ // from the key — two verifies for the SAME agent/purpose/action/value but
158
+ // DIFFERENT merchants collided, and a grant at a permissive merchant (low
159
+ // trust floor) was served for a stricter one. Same bug class as the
160
+ // duration omission (F-A1-07). counterpartyId affects the backend verdict
161
+ // (trust floor / per-route policy), so it MUST key the cache.
162
+ counterpartyId || "",
166
163
  request.counterpartyUrl || "",
167
164
  request.counterpartyType || "",
168
165
  request.isSubAgentRequest ? "1" : "0",
@@ -186,8 +183,8 @@ function getCacheKey(request) {
186
183
  request.callerMetadata?.agentCardUrl || ""
187
184
  ].join("|");
188
185
  }
189
- function getCachedResult(request) {
190
- const key = getCacheKey(request);
186
+ function getCachedResult(request, counterpartyId) {
187
+ const key = getCacheKey(request, counterpartyId);
191
188
  const cached = verificationCache.get(key);
192
189
  if (cached && cached.expiresAt > Date.now()) {
193
190
  return cached.result;
@@ -199,9 +196,9 @@ function getCachedResult(request) {
199
196
  }
200
197
  var DEFAULT_AUTONOMOUS_TTL_SECONDS = 60;
201
198
  var DEFAULT_STEP_UP_TTL_SECONDS = 300;
202
- function cacheResult(request, result, configuredTtl) {
199
+ function cacheResult(request, result, configuredTtl, counterpartyId) {
203
200
  const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : result.requiresStepUp ? DEFAULT_STEP_UP_TTL_SECONDS : DEFAULT_AUTONOMOUS_TTL_SECONDS;
204
- const key = getCacheKey(request);
201
+ const key = getCacheKey(request, counterpartyId);
205
202
  verificationCache.set(key, {
206
203
  result,
207
204
  expiresAt: Date.now() + ttlSeconds * 1e3
@@ -393,7 +390,7 @@ async function verify(config, request) {
393
390
  );
394
391
  }
395
392
  if (mergedConfig.cacheTtl !== 0) {
396
- const cached = getCachedResult(request);
393
+ const cached = getCachedResult(request, mergedConfig.counterpartyId);
397
394
  if (cached) {
398
395
  if (mergedConfig.debug) {
399
396
  console.log("[VerificationGateway] Returning cached result");
@@ -445,8 +442,8 @@ async function verify(config, request) {
445
442
  verifiedAt: /* @__PURE__ */ new Date(),
446
443
  // Extract sessionId so decisions can be recorded for denials too
447
444
  sessionId: apiResponse.sessionId,
448
- // v2.3.10 (defect #34, round-4): anonymous traffic has no session →
449
- // correlationId is the linking key for paired local_override events.
445
+ // Anonymous traffic has no session → correlationId is the per-attempt
446
+ // linking key (the sessionId-equivalent for anonymous callers).
450
447
  correlationId: apiResponse.correlationId,
451
448
  recommendation: apiResponse.recommendation,
452
449
  recommendationReasons: apiResponse.recommendationReasons
@@ -520,17 +517,14 @@ async function verify(config, request) {
520
517
  };
521
518
  } else if (result.recommendation === "step_up_required") {
522
519
  result.requiresStepUp = true;
523
- if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
524
- result.accessLevel = "read-only";
525
- }
526
520
  result.denialReasons = result.recommendationReasons || ["Step-up verification required"];
527
521
  }
528
522
  if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny") {
529
- cacheResult(request, result, mergedConfig.cacheTtl);
523
+ cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
530
524
  }
531
525
  return result;
532
526
  }
533
- async function recordDecision(config, sessionId, decision, reason, override) {
527
+ async function recordDecision(config, sessionId, decision, reason) {
534
528
  const headers = { "Content-Type": "application/json" };
535
529
  if (config.apiKey) {
536
530
  headers["Authorization"] = `Bearer ${config.apiKey}`;
@@ -539,16 +533,7 @@ async function recordDecision(config, sessionId, decision, reason, override) {
539
533
  await fetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
540
534
  method: "POST",
541
535
  headers,
542
- body: JSON.stringify({
543
- decision,
544
- reason,
545
- ...override && {
546
- overriddenBy: override.overriddenBy,
547
- toolName: override.toolName,
548
- requestedLevel: override.requestedLevel,
549
- grantedLevel: override.grantedLevel
550
- }
551
- })
536
+ body: JSON.stringify({ decision, reason })
552
537
  }).catch(() => {
553
538
  });
554
539
  }
@@ -603,6 +588,13 @@ function extractHttpCredentials(headers) {
603
588
  purpose: { category, action }
604
589
  };
605
590
  }
591
+ const astraAction = getValue(`${HEADER_PREFIX}Action`) ?? getValue("x-astra-action");
592
+ if (astraAction) {
593
+ credentials.pdlss = {
594
+ ...credentials.pdlss,
595
+ purpose: { category: credentials.pdlss?.purpose?.category ?? "", action: astraAction }
596
+ };
597
+ }
606
598
  const duration = getValue(`${HEADER_PREFIX}Duration`) ?? getValue("x-astra-duration");
607
599
  if (duration) {
608
600
  credentials.pdlss = {
@@ -620,6 +612,85 @@ function extractHttpCredentials(headers) {
620
612
  return credentials;
621
613
  }
622
614
 
615
+ // src/adapters/http-pdlss.ts
616
+ var HTTP_METHOD_ACTION_TABLE = {
617
+ GET: "data.read",
618
+ HEAD: "data.read",
619
+ OPTIONS: "data.read",
620
+ POST: "data.write",
621
+ PUT: "data.write",
622
+ PATCH: "data.write",
623
+ DELETE: "data.delete"
624
+ };
625
+ var DEFAULT_HTTP_ACTION = "data.write";
626
+ var DEFAULT_HTTP_PURPOSE = "data";
627
+ function actionForHttpMethod(method) {
628
+ return HTTP_METHOD_ACTION_TABLE[method.toUpperCase()] ?? DEFAULT_HTTP_ACTION;
629
+ }
630
+ function normalizePurposeHeader(value) {
631
+ const colon = value.indexOf(":");
632
+ if (colon >= 0) {
633
+ return { purpose: value.slice(0, colon) };
634
+ }
635
+ const dot = value.indexOf(".");
636
+ if (dot > 0 && dot < value.length - 1) {
637
+ return { purpose: value.slice(0, dot), actionCandidate: value };
638
+ }
639
+ return { purpose: value };
640
+ }
641
+ function resolveHttpPdlss(input) {
642
+ const fromHeader = input.astraPurpose ? normalizePurposeHeader(input.astraPurpose) : void 0;
643
+ let action;
644
+ let actionSource;
645
+ if (input.routeAction) {
646
+ action = input.routeAction;
647
+ actionSource = "route_config";
648
+ } else if (input.hasCustomActionExtractor && input.customAction) {
649
+ action = input.customAction;
650
+ actionSource = "custom_extractor";
651
+ } else if (!input.hasCustomActionExtractor && input.astraAction) {
652
+ action = input.astraAction;
653
+ actionSource = "header";
654
+ } else if (!input.hasCustomActionExtractor && fromHeader?.actionCandidate) {
655
+ action = fromHeader.actionCandidate;
656
+ actionSource = "purpose_header_derived";
657
+ } else {
658
+ action = actionForHttpMethod(input.method);
659
+ actionSource = "method_table";
660
+ }
661
+ let purpose;
662
+ let purposeSource;
663
+ if (input.routePurpose) {
664
+ purpose = input.routePurpose;
665
+ purposeSource = "route_config";
666
+ } else if (input.hasCustomPurposeExtractor) {
667
+ if (input.customPurpose) {
668
+ purpose = input.customPurpose;
669
+ purposeSource = "custom_extractor";
670
+ }
671
+ } else if (fromHeader) {
672
+ purpose = fromHeader.purpose;
673
+ purposeSource = "header";
674
+ } else if (input.legacyPurpose) {
675
+ purpose = input.legacyPurpose;
676
+ purposeSource = "legacy_header";
677
+ } else if (input.queryPurpose) {
678
+ purpose = input.queryPurpose;
679
+ purposeSource = "query";
680
+ }
681
+ if (!purpose) {
682
+ const dot = action.indexOf(".");
683
+ if (dot > 0) {
684
+ purpose = action.slice(0, dot);
685
+ purposeSource = "action_derived";
686
+ } else {
687
+ purpose = DEFAULT_HTTP_PURPOSE;
688
+ purposeSource = "transport_default";
689
+ }
690
+ }
691
+ return { purpose, action, purposeSource, actionSource };
692
+ }
693
+
623
694
  // src/pdlss-pre-check.ts
624
695
  function performCounterpartyPreCheck(routeConfig, astraCreds, purpose) {
625
696
  const failures = [];
@@ -678,33 +749,25 @@ function defaultExtractCredentials(req) {
678
749
  function extractAstraSyncCredentials(req) {
679
750
  return extractHttpCredentials(req.headers);
680
751
  }
681
- function defaultExtractPurpose(req) {
682
- const astraPurpose = req.headers["x-astra-purpose"];
683
- if (astraPurpose) {
684
- const value = Array.isArray(astraPurpose) ? astraPurpose[0] : astraPurpose;
685
- const category = value.split(":")[0];
686
- return category;
687
- }
688
- const purposeHeader = req.headers["x-purpose"] || req.headers["X-Purpose"];
689
- if (purposeHeader) {
690
- return Array.isArray(purposeHeader) ? purposeHeader[0] : purposeHeader;
691
- }
692
- if (req.query.purpose && typeof req.query.purpose === "string") {
693
- return req.query.purpose;
694
- }
695
- switch (req.method) {
696
- case "GET":
697
- return "read_data";
698
- case "POST":
699
- return "write_data";
700
- case "PUT":
701
- case "PATCH":
702
- return "write_data";
703
- case "DELETE":
704
- return "delete_data";
705
- default:
706
- return "general";
707
- }
752
+ function headerValue(value) {
753
+ if (typeof value === "string") return value;
754
+ if (Array.isArray(value)) return value[0];
755
+ return void 0;
756
+ }
757
+ function resolveRequestPdlss(req, routeConfig, customExtractPurpose, customExtractAction) {
758
+ return resolveHttpPdlss({
759
+ method: req.method,
760
+ astraPurpose: headerValue(req.headers["x-astra-purpose"]),
761
+ astraAction: headerValue(req.headers["x-astra-action"]),
762
+ legacyPurpose: headerValue(req.headers["x-purpose"] ?? req.headers["X-Purpose"]),
763
+ queryPurpose: typeof req.query.purpose === "string" ? req.query.purpose : void 0,
764
+ routePurpose: routeConfig?.purpose,
765
+ routeAction: routeConfig?.action,
766
+ hasCustomPurposeExtractor: !!customExtractPurpose,
767
+ customPurpose: customExtractPurpose?.(req),
768
+ hasCustomActionExtractor: !!customExtractAction,
769
+ customAction: customExtractAction?.(req)
770
+ });
708
771
  }
709
772
  function matchRoute(pattern, path, opts) {
710
773
  const regexPattern = pattern.replace(/\*/g, ".*").replace(/\//g, "\\/");
@@ -764,6 +827,7 @@ function createMiddleware(options) {
764
827
  const {
765
828
  extractCredentials: customExtractCredentials,
766
829
  extractPurpose: customExtractPurpose,
830
+ extractAction: customExtractAction,
767
831
  skipPaths = [],
768
832
  onDenied = defaultOnDenied,
769
833
  recordDecisions,
@@ -849,7 +913,21 @@ function createMiddleware(options) {
849
913
  }
850
914
  return next();
851
915
  }
852
- const purpose = customExtractPurpose ? customExtractPurpose(req) : defaultExtractPurpose(req);
916
+ const pdlssPair = resolveRequestPdlss(
917
+ req,
918
+ routeConfig,
919
+ customExtractPurpose,
920
+ customExtractAction
921
+ );
922
+ const purpose = pdlssPair.purpose;
923
+ if (config.debug) {
924
+ console.debug("[express-middleware] pdlss resolved", {
925
+ purpose_source: pdlssPair.purposeSource,
926
+ resolved_purpose: pdlssPair.purpose,
927
+ action_source: pdlssPair.actionSource,
928
+ resolved_action: pdlssPair.action
929
+ });
930
+ }
853
931
  const astraCreds = extractAstraSyncCredentials(req);
854
932
  const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get("host")}`;
855
933
  const preCheckFailures = performCounterpartyPreCheck(routeConfig, astraCreds, purpose);
@@ -893,10 +971,7 @@ function createMiddleware(options) {
893
971
  const result = await verify(config, {
894
972
  credentials,
895
973
  purpose,
896
- // RFC 7230 § 3.1.1 — HTTP method tokens uppercase by IANA convention.
897
- // Backend evaluator tolerates either case as defense-in-depth
898
- // (round-18.6 batch 2); SDK emits canonical form.
899
- action: req.method.toUpperCase(),
974
+ action: pdlssPair.action,
900
975
  resource: req.path,
901
976
  createSession: shouldRecordDecisions,
902
977
  counterpartyUrl,
@@ -934,35 +1009,12 @@ function createMiddleware(options) {
934
1009
  }
935
1010
  return next();
936
1011
  }
937
- if (!hasMinimumAccess(result.accessLevel, routeConfig.minAccessLevel)) {
938
- const insufficientFailure = {
939
- dimension: "access_level.insufficient",
940
- message: `Endpoint requires accessLevel '${routeConfig.minAccessLevel}'; agent has '${result.accessLevel}'.`,
941
- 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."
942
- };
943
- result.failures = [...result.failures ?? [], insufficientFailure];
944
- result.denialReasons = [...result.denialReasons ?? [], insufficientFailure.message];
945
- if (!result.guidance && wellKnownUrls) {
946
- result.guidance = {
947
- message: insufficientFailure.message,
948
- registrationUrl: wellKnownUrls.registrationUrl,
949
- documentationUrl: wellKnownUrls.documentationUrl
950
- };
951
- }
952
- if (shouldRecordDecisions && sessionId) {
953
- recordDecision(config, sessionId, "denied", insufficientFailure.message).catch(() => {
954
- });
955
- }
956
- dedupeFailures(result);
957
- onDenied(result, req, res);
958
- return;
959
- }
960
1012
  if (routeConfig.minTrustScore && result.agent) {
961
1013
  if (result.agent.trustScore < routeConfig.minTrustScore) {
962
1014
  const trustFailure = {
963
- dimension: "access_level.insufficient",
964
- message: `Trust score ${result.agent.trustScore} is below required ${routeConfig.minTrustScore} for this route.`,
965
- 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."
1015
+ dimension: "endpoint.trust",
1016
+ message: "Trust below the route requirement for this endpoint.",
1017
+ 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."
966
1018
  };
967
1019
  result.failures = [...result.failures ?? [], trustFailure];
968
1020
  result.denialReasons = [trustFailure.message];