@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.
- package/dist/adapter-interface/interface.d.mts +2 -2
- package/dist/adapter-interface/interface.d.ts +2 -2
- package/dist/adapters/express.d.mts +2 -2
- package/dist/adapters/express.d.ts +2 -2
- package/dist/adapters/express.js +145 -93
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +145 -93
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +29 -11
- package/dist/adapters/mcp.d.ts +29 -11
- package/dist/adapters/mcp.js +43 -102
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +43 -102
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.d.mts +2 -2
- package/dist/adapters/nextjs.d.ts +2 -2
- package/dist/adapters/nextjs.js +126 -56
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +126 -56
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.d.mts +2 -2
- package/dist/adapters/sdk.d.ts +2 -2
- package/dist/adapters/sdk.js +25 -14
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +25 -14
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.d.mts +2 -2
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.js +3 -0
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +3 -0
- package/dist/agent/index.mjs.map +1 -1
- package/dist/browser/background.js +18 -21
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +18 -21
- package/dist/browser/background.mjs.map +1 -1
- package/dist/browser/browser-adapter.d.mts +2 -2
- package/dist/browser/browser-adapter.d.ts +2 -2
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/cursor/cursor-adapter.d.mts +2 -2
- package/dist/cursor/cursor-adapter.d.ts +2 -2
- package/dist/cursor/extension.d.mts +2 -2
- package/dist/cursor/extension.d.ts +2 -2
- package/dist/cursor/extension.js +18 -21
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +18 -21
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/{express-CrfwoNAR.d.ts → express-BowlMHQF.d.ts} +1 -1
- package/dist/{express-ienhAXps.d.mts → express-CeoSdOAZ.d.mts} +1 -1
- package/dist/gateway/gateway.d.mts +2 -2
- package/dist/gateway/gateway.d.ts +2 -2
- package/dist/gateway/gateway.js +18 -21
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +18 -21
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +2 -2
- package/dist/git-trigger/git-hooks.d.ts +2 -2
- package/dist/{index-CEg_WG6y.d.mts → index-B51W8gn8.d.mts} +1 -1
- package/dist/{index-DC5f8eoQ.d.ts → index-DBmlycVm.d.ts} +1 -1
- package/dist/{index-B5e2IDWU.d.mts → index-DtGziFEm.d.mts} +1 -1
- package/dist/{index-CCdZxvAr.d.ts → index-DzXXBuLm.d.ts} +1 -1
- package/dist/index.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +209 -191
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +209 -191
- package/dist/index.mjs.map +1 -1
- package/dist/local-evaluator/evaluator.d.mts +2 -2
- package/dist/local-evaluator/evaluator.d.ts +2 -2
- package/dist/{nextjs-DSpisQst.d.mts → nextjs-BW1rzr1I.d.mts} +1 -1
- package/dist/{nextjs-66R1KW8e.d.ts → nextjs-V_K0qlAQ.d.ts} +1 -1
- package/dist/{sdk-5U_CBRpr.d.mts → sdk-ZYgI7G9f.d.ts} +14 -3
- package/dist/{sdk-Bm8np66n.d.ts → sdk-e5jg7sqW.d.mts} +14 -3
- package/dist/transport/index.d.mts +2 -2
- package/dist/transport/index.d.ts +2 -2
- package/dist/transport/index.js +10 -0
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs +10 -0
- package/dist/transport/index.mjs.map +1 -1
- package/dist/{types-CgDCUfo8.d.mts → types-BNiLZY0i.d.mts} +1 -1
- package/dist/{types-R5N4ET6x.d.ts → types-DJi-u3fz.d.ts} +1 -1
- package/dist/{types-B3USs-Kx.d.mts → types-rFh4VMH4.d.mts} +30 -2
- package/dist/{types-B3USs-Kx.d.ts → types-rFh4VMH4.d.ts} +30 -2
- package/dist/ui/index.d.mts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,24 +1,13 @@
|
|
|
1
1
|
// src/access-levels.ts
|
|
2
|
-
var ACCESS_LEVEL_HIERARCHY = {
|
|
3
|
-
none: 0,
|
|
4
|
-
restricted: 1,
|
|
5
|
-
"read-only": 2,
|
|
6
|
-
standard: 3,
|
|
7
|
-
full: 4,
|
|
8
|
-
internal: 5
|
|
9
|
-
};
|
|
10
2
|
function getTrustLevel(score) {
|
|
11
3
|
if (score >= 80) return "PLATINUM";
|
|
12
4
|
if (score >= 60) return "GOLD";
|
|
13
5
|
if (score >= 40) return "SILVER";
|
|
14
6
|
return "BRONZE";
|
|
15
7
|
}
|
|
16
|
-
function hasMinimumAccess(actual, required) {
|
|
17
|
-
return ACCESS_LEVEL_HIERARCHY[actual] >= ACCESS_LEVEL_HIERARCHY[required];
|
|
18
|
-
}
|
|
19
8
|
|
|
20
9
|
// src/version.ts
|
|
21
|
-
var SDK_VERSION = "3.
|
|
10
|
+
var SDK_VERSION = "3.2.0";
|
|
22
11
|
|
|
23
12
|
// src/well-known.ts
|
|
24
13
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -123,7 +112,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
|
|
|
123
112
|
}
|
|
124
113
|
}
|
|
125
114
|
var verificationCache = /* @__PURE__ */ new Map();
|
|
126
|
-
function getCacheKey(request) {
|
|
115
|
+
function getCacheKey(request, counterpartyId) {
|
|
127
116
|
const c = request.credentials;
|
|
128
117
|
return [
|
|
129
118
|
c.astraId || "",
|
|
@@ -136,6 +125,14 @@ function getCacheKey(request) {
|
|
|
136
125
|
request.jurisdiction || "",
|
|
137
126
|
request.transactionValue ?? "",
|
|
138
127
|
request.currency || "",
|
|
128
|
+
// SECURITY (cross-merchant cache leak): the merchant identity is sent via
|
|
129
|
+
// `config.counterpartyId`, NOT on the request, so it was previously absent
|
|
130
|
+
// from the key — two verifies for the SAME agent/purpose/action/value but
|
|
131
|
+
// DIFFERENT merchants collided, and a grant at a permissive merchant (low
|
|
132
|
+
// trust floor) was served for a stricter one. Same bug class as the
|
|
133
|
+
// duration omission (F-A1-07). counterpartyId affects the backend verdict
|
|
134
|
+
// (trust floor / per-route policy), so it MUST key the cache.
|
|
135
|
+
counterpartyId || "",
|
|
139
136
|
request.counterpartyUrl || "",
|
|
140
137
|
request.counterpartyType || "",
|
|
141
138
|
request.isSubAgentRequest ? "1" : "0",
|
|
@@ -159,8 +156,8 @@ function getCacheKey(request) {
|
|
|
159
156
|
request.callerMetadata?.agentCardUrl || ""
|
|
160
157
|
].join("|");
|
|
161
158
|
}
|
|
162
|
-
function getCachedResult(request) {
|
|
163
|
-
const key = getCacheKey(request);
|
|
159
|
+
function getCachedResult(request, counterpartyId) {
|
|
160
|
+
const key = getCacheKey(request, counterpartyId);
|
|
164
161
|
const cached = verificationCache.get(key);
|
|
165
162
|
if (cached && cached.expiresAt > Date.now()) {
|
|
166
163
|
return cached.result;
|
|
@@ -172,9 +169,9 @@ function getCachedResult(request) {
|
|
|
172
169
|
}
|
|
173
170
|
var DEFAULT_AUTONOMOUS_TTL_SECONDS = 60;
|
|
174
171
|
var DEFAULT_STEP_UP_TTL_SECONDS = 300;
|
|
175
|
-
function cacheResult(request, result, configuredTtl) {
|
|
172
|
+
function cacheResult(request, result, configuredTtl, counterpartyId) {
|
|
176
173
|
const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : result.requiresStepUp ? DEFAULT_STEP_UP_TTL_SECONDS : DEFAULT_AUTONOMOUS_TTL_SECONDS;
|
|
177
|
-
const key = getCacheKey(request);
|
|
174
|
+
const key = getCacheKey(request, counterpartyId);
|
|
178
175
|
verificationCache.set(key, {
|
|
179
176
|
result,
|
|
180
177
|
expiresAt: Date.now() + ttlSeconds * 1e3
|
|
@@ -366,7 +363,7 @@ async function verify(config, request) {
|
|
|
366
363
|
);
|
|
367
364
|
}
|
|
368
365
|
if (mergedConfig.cacheTtl !== 0) {
|
|
369
|
-
const cached = getCachedResult(request);
|
|
366
|
+
const cached = getCachedResult(request, mergedConfig.counterpartyId);
|
|
370
367
|
if (cached) {
|
|
371
368
|
if (mergedConfig.debug) {
|
|
372
369
|
console.log("[VerificationGateway] Returning cached result");
|
|
@@ -418,8 +415,8 @@ async function verify(config, request) {
|
|
|
418
415
|
verifiedAt: /* @__PURE__ */ new Date(),
|
|
419
416
|
// Extract sessionId so decisions can be recorded for denials too
|
|
420
417
|
sessionId: apiResponse.sessionId,
|
|
421
|
-
//
|
|
422
|
-
//
|
|
418
|
+
// Anonymous traffic has no session → correlationId is the per-attempt
|
|
419
|
+
// linking key (the sessionId-equivalent for anonymous callers).
|
|
423
420
|
correlationId: apiResponse.correlationId,
|
|
424
421
|
recommendation: apiResponse.recommendation,
|
|
425
422
|
recommendationReasons: apiResponse.recommendationReasons
|
|
@@ -493,17 +490,14 @@ async function verify(config, request) {
|
|
|
493
490
|
};
|
|
494
491
|
} else if (result.recommendation === "step_up_required") {
|
|
495
492
|
result.requiresStepUp = true;
|
|
496
|
-
if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
|
|
497
|
-
result.accessLevel = "read-only";
|
|
498
|
-
}
|
|
499
493
|
result.denialReasons = result.recommendationReasons || ["Step-up verification required"];
|
|
500
494
|
}
|
|
501
495
|
if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny") {
|
|
502
|
-
cacheResult(request, result, mergedConfig.cacheTtl);
|
|
496
|
+
cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
|
|
503
497
|
}
|
|
504
498
|
return result;
|
|
505
499
|
}
|
|
506
|
-
async function recordDecision(config, sessionId, decision, reason
|
|
500
|
+
async function recordDecision(config, sessionId, decision, reason) {
|
|
507
501
|
const headers = { "Content-Type": "application/json" };
|
|
508
502
|
if (config.apiKey) {
|
|
509
503
|
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
@@ -512,16 +506,7 @@ async function recordDecision(config, sessionId, decision, reason, override) {
|
|
|
512
506
|
await fetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
|
|
513
507
|
method: "POST",
|
|
514
508
|
headers,
|
|
515
|
-
body: JSON.stringify({
|
|
516
|
-
decision,
|
|
517
|
-
reason,
|
|
518
|
-
...override && {
|
|
519
|
-
overriddenBy: override.overriddenBy,
|
|
520
|
-
toolName: override.toolName,
|
|
521
|
-
requestedLevel: override.requestedLevel,
|
|
522
|
-
grantedLevel: override.grantedLevel
|
|
523
|
-
}
|
|
524
|
-
})
|
|
509
|
+
body: JSON.stringify({ decision, reason })
|
|
525
510
|
}).catch(() => {
|
|
526
511
|
});
|
|
527
512
|
}
|
|
@@ -576,6 +561,13 @@ function extractHttpCredentials(headers) {
|
|
|
576
561
|
purpose: { category, action }
|
|
577
562
|
};
|
|
578
563
|
}
|
|
564
|
+
const astraAction = getValue(`${HEADER_PREFIX}Action`) ?? getValue("x-astra-action");
|
|
565
|
+
if (astraAction) {
|
|
566
|
+
credentials.pdlss = {
|
|
567
|
+
...credentials.pdlss,
|
|
568
|
+
purpose: { category: credentials.pdlss?.purpose?.category ?? "", action: astraAction }
|
|
569
|
+
};
|
|
570
|
+
}
|
|
579
571
|
const duration = getValue(`${HEADER_PREFIX}Duration`) ?? getValue("x-astra-duration");
|
|
580
572
|
if (duration) {
|
|
581
573
|
credentials.pdlss = {
|
|
@@ -593,6 +585,85 @@ function extractHttpCredentials(headers) {
|
|
|
593
585
|
return credentials;
|
|
594
586
|
}
|
|
595
587
|
|
|
588
|
+
// src/adapters/http-pdlss.ts
|
|
589
|
+
var HTTP_METHOD_ACTION_TABLE = {
|
|
590
|
+
GET: "data.read",
|
|
591
|
+
HEAD: "data.read",
|
|
592
|
+
OPTIONS: "data.read",
|
|
593
|
+
POST: "data.write",
|
|
594
|
+
PUT: "data.write",
|
|
595
|
+
PATCH: "data.write",
|
|
596
|
+
DELETE: "data.delete"
|
|
597
|
+
};
|
|
598
|
+
var DEFAULT_HTTP_ACTION = "data.write";
|
|
599
|
+
var DEFAULT_HTTP_PURPOSE = "data";
|
|
600
|
+
function actionForHttpMethod(method) {
|
|
601
|
+
return HTTP_METHOD_ACTION_TABLE[method.toUpperCase()] ?? DEFAULT_HTTP_ACTION;
|
|
602
|
+
}
|
|
603
|
+
function normalizePurposeHeader(value) {
|
|
604
|
+
const colon = value.indexOf(":");
|
|
605
|
+
if (colon >= 0) {
|
|
606
|
+
return { purpose: value.slice(0, colon) };
|
|
607
|
+
}
|
|
608
|
+
const dot = value.indexOf(".");
|
|
609
|
+
if (dot > 0 && dot < value.length - 1) {
|
|
610
|
+
return { purpose: value.slice(0, dot), actionCandidate: value };
|
|
611
|
+
}
|
|
612
|
+
return { purpose: value };
|
|
613
|
+
}
|
|
614
|
+
function resolveHttpPdlss(input) {
|
|
615
|
+
const fromHeader = input.astraPurpose ? normalizePurposeHeader(input.astraPurpose) : void 0;
|
|
616
|
+
let action;
|
|
617
|
+
let actionSource;
|
|
618
|
+
if (input.routeAction) {
|
|
619
|
+
action = input.routeAction;
|
|
620
|
+
actionSource = "route_config";
|
|
621
|
+
} else if (input.hasCustomActionExtractor && input.customAction) {
|
|
622
|
+
action = input.customAction;
|
|
623
|
+
actionSource = "custom_extractor";
|
|
624
|
+
} else if (!input.hasCustomActionExtractor && input.astraAction) {
|
|
625
|
+
action = input.astraAction;
|
|
626
|
+
actionSource = "header";
|
|
627
|
+
} else if (!input.hasCustomActionExtractor && fromHeader?.actionCandidate) {
|
|
628
|
+
action = fromHeader.actionCandidate;
|
|
629
|
+
actionSource = "purpose_header_derived";
|
|
630
|
+
} else {
|
|
631
|
+
action = actionForHttpMethod(input.method);
|
|
632
|
+
actionSource = "method_table";
|
|
633
|
+
}
|
|
634
|
+
let purpose;
|
|
635
|
+
let purposeSource;
|
|
636
|
+
if (input.routePurpose) {
|
|
637
|
+
purpose = input.routePurpose;
|
|
638
|
+
purposeSource = "route_config";
|
|
639
|
+
} else if (input.hasCustomPurposeExtractor) {
|
|
640
|
+
if (input.customPurpose) {
|
|
641
|
+
purpose = input.customPurpose;
|
|
642
|
+
purposeSource = "custom_extractor";
|
|
643
|
+
}
|
|
644
|
+
} else if (fromHeader) {
|
|
645
|
+
purpose = fromHeader.purpose;
|
|
646
|
+
purposeSource = "header";
|
|
647
|
+
} else if (input.legacyPurpose) {
|
|
648
|
+
purpose = input.legacyPurpose;
|
|
649
|
+
purposeSource = "legacy_header";
|
|
650
|
+
} else if (input.queryPurpose) {
|
|
651
|
+
purpose = input.queryPurpose;
|
|
652
|
+
purposeSource = "query";
|
|
653
|
+
}
|
|
654
|
+
if (!purpose) {
|
|
655
|
+
const dot = action.indexOf(".");
|
|
656
|
+
if (dot > 0) {
|
|
657
|
+
purpose = action.slice(0, dot);
|
|
658
|
+
purposeSource = "action_derived";
|
|
659
|
+
} else {
|
|
660
|
+
purpose = DEFAULT_HTTP_PURPOSE;
|
|
661
|
+
purposeSource = "transport_default";
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return { purpose, action, purposeSource, actionSource };
|
|
665
|
+
}
|
|
666
|
+
|
|
596
667
|
// src/pdlss-pre-check.ts
|
|
597
668
|
function performCounterpartyPreCheck(routeConfig, astraCreds, purpose) {
|
|
598
669
|
const failures = [];
|
|
@@ -651,33 +722,25 @@ function defaultExtractCredentials(req) {
|
|
|
651
722
|
function extractAstraSyncCredentials(req) {
|
|
652
723
|
return extractHttpCredentials(req.headers);
|
|
653
724
|
}
|
|
654
|
-
function
|
|
655
|
-
|
|
656
|
-
if (
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
case "PUT":
|
|
674
|
-
case "PATCH":
|
|
675
|
-
return "write_data";
|
|
676
|
-
case "DELETE":
|
|
677
|
-
return "delete_data";
|
|
678
|
-
default:
|
|
679
|
-
return "general";
|
|
680
|
-
}
|
|
725
|
+
function headerValue(value) {
|
|
726
|
+
if (typeof value === "string") return value;
|
|
727
|
+
if (Array.isArray(value)) return value[0];
|
|
728
|
+
return void 0;
|
|
729
|
+
}
|
|
730
|
+
function resolveRequestPdlss(req, routeConfig, customExtractPurpose, customExtractAction) {
|
|
731
|
+
return resolveHttpPdlss({
|
|
732
|
+
method: req.method,
|
|
733
|
+
astraPurpose: headerValue(req.headers["x-astra-purpose"]),
|
|
734
|
+
astraAction: headerValue(req.headers["x-astra-action"]),
|
|
735
|
+
legacyPurpose: headerValue(req.headers["x-purpose"] ?? req.headers["X-Purpose"]),
|
|
736
|
+
queryPurpose: typeof req.query.purpose === "string" ? req.query.purpose : void 0,
|
|
737
|
+
routePurpose: routeConfig?.purpose,
|
|
738
|
+
routeAction: routeConfig?.action,
|
|
739
|
+
hasCustomPurposeExtractor: !!customExtractPurpose,
|
|
740
|
+
customPurpose: customExtractPurpose?.(req),
|
|
741
|
+
hasCustomActionExtractor: !!customExtractAction,
|
|
742
|
+
customAction: customExtractAction?.(req)
|
|
743
|
+
});
|
|
681
744
|
}
|
|
682
745
|
function matchRoute(pattern, path, opts) {
|
|
683
746
|
const regexPattern = pattern.replace(/\*/g, ".*").replace(/\//g, "\\/");
|
|
@@ -737,6 +800,7 @@ function createMiddleware(options) {
|
|
|
737
800
|
const {
|
|
738
801
|
extractCredentials: customExtractCredentials,
|
|
739
802
|
extractPurpose: customExtractPurpose,
|
|
803
|
+
extractAction: customExtractAction,
|
|
740
804
|
skipPaths = [],
|
|
741
805
|
onDenied = defaultOnDenied,
|
|
742
806
|
recordDecisions,
|
|
@@ -822,7 +886,21 @@ function createMiddleware(options) {
|
|
|
822
886
|
}
|
|
823
887
|
return next();
|
|
824
888
|
}
|
|
825
|
-
const
|
|
889
|
+
const pdlssPair = resolveRequestPdlss(
|
|
890
|
+
req,
|
|
891
|
+
routeConfig,
|
|
892
|
+
customExtractPurpose,
|
|
893
|
+
customExtractAction
|
|
894
|
+
);
|
|
895
|
+
const purpose = pdlssPair.purpose;
|
|
896
|
+
if (config.debug) {
|
|
897
|
+
console.debug("[express-middleware] pdlss resolved", {
|
|
898
|
+
purpose_source: pdlssPair.purposeSource,
|
|
899
|
+
resolved_purpose: pdlssPair.purpose,
|
|
900
|
+
action_source: pdlssPair.actionSource,
|
|
901
|
+
resolved_action: pdlssPair.action
|
|
902
|
+
});
|
|
903
|
+
}
|
|
826
904
|
const astraCreds = extractAstraSyncCredentials(req);
|
|
827
905
|
const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get("host")}`;
|
|
828
906
|
const preCheckFailures = performCounterpartyPreCheck(routeConfig, astraCreds, purpose);
|
|
@@ -866,10 +944,7 @@ function createMiddleware(options) {
|
|
|
866
944
|
const result = await verify(config, {
|
|
867
945
|
credentials,
|
|
868
946
|
purpose,
|
|
869
|
-
|
|
870
|
-
// Backend evaluator tolerates either case as defense-in-depth
|
|
871
|
-
// (round-18.6 batch 2); SDK emits canonical form.
|
|
872
|
-
action: req.method.toUpperCase(),
|
|
947
|
+
action: pdlssPair.action,
|
|
873
948
|
resource: req.path,
|
|
874
949
|
createSession: shouldRecordDecisions,
|
|
875
950
|
counterpartyUrl,
|
|
@@ -907,35 +982,12 @@ function createMiddleware(options) {
|
|
|
907
982
|
}
|
|
908
983
|
return next();
|
|
909
984
|
}
|
|
910
|
-
if (!hasMinimumAccess(result.accessLevel, routeConfig.minAccessLevel)) {
|
|
911
|
-
const insufficientFailure = {
|
|
912
|
-
dimension: "access_level.insufficient",
|
|
913
|
-
message: `Endpoint requires accessLevel '${routeConfig.minAccessLevel}'; agent has '${result.accessLevel}'.`,
|
|
914
|
-
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."
|
|
915
|
-
};
|
|
916
|
-
result.failures = [...result.failures ?? [], insufficientFailure];
|
|
917
|
-
result.denialReasons = [...result.denialReasons ?? [], insufficientFailure.message];
|
|
918
|
-
if (!result.guidance && wellKnownUrls) {
|
|
919
|
-
result.guidance = {
|
|
920
|
-
message: insufficientFailure.message,
|
|
921
|
-
registrationUrl: wellKnownUrls.registrationUrl,
|
|
922
|
-
documentationUrl: wellKnownUrls.documentationUrl
|
|
923
|
-
};
|
|
924
|
-
}
|
|
925
|
-
if (shouldRecordDecisions && sessionId) {
|
|
926
|
-
recordDecision(config, sessionId, "denied", insufficientFailure.message).catch(() => {
|
|
927
|
-
});
|
|
928
|
-
}
|
|
929
|
-
dedupeFailures(result);
|
|
930
|
-
onDenied(result, req, res);
|
|
931
|
-
return;
|
|
932
|
-
}
|
|
933
985
|
if (routeConfig.minTrustScore && result.agent) {
|
|
934
986
|
if (result.agent.trustScore < routeConfig.minTrustScore) {
|
|
935
987
|
const trustFailure = {
|
|
936
|
-
dimension: "
|
|
937
|
-
message:
|
|
938
|
-
guidance: "
|
|
988
|
+
dimension: "endpoint.trust",
|
|
989
|
+
message: "Trust below the route requirement for this endpoint.",
|
|
990
|
+
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."
|
|
939
991
|
};
|
|
940
992
|
result.failures = [...result.failures ?? [], trustFailure];
|
|
941
993
|
result.denialReasons = [trustFailure.message];
|