@astrasyncai/verification-gateway 3.1.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 +23 -61
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +23 -61
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +12 -7
- package/dist/adapters/mcp.d.ts +12 -7
- package/dist/adapters/mcp.js +38 -100
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +38 -100
- 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 +20 -29
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +20 -29
- 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/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-DavQ76oF.d.ts → express-BowlMHQF.d.ts} +1 -1
- package/dist/{express-DFVBlXr_.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-BhL2R65s.d.mts → index-B51W8gn8.d.mts} +1 -1
- package/dist/{index-BhEgEiJL.d.ts → index-DBmlycVm.d.ts} +1 -1
- package/dist/{index-BVxantdv.d.mts → index-DtGziFEm.d.mts} +1 -1
- package/dist/{index-Dk2nIA4w.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 +50 -121
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +50 -121
- 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-D-maqrNz.d.mts → nextjs-BW1rzr1I.d.mts} +1 -1
- package/dist/{nextjs-BXLH1hJj.d.ts → nextjs-V_K0qlAQ.d.ts} +1 -1
- package/dist/{sdk-767LaEP8.d.mts → sdk-ZYgI7G9f.d.ts} +14 -3
- package/dist/{sdk-K8IgssHI.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/{types-CyFwZ_Yu.d.mts → types-BNiLZY0i.d.mts} +1 -1
- package/dist/{types-WIRp_BP_.d.ts → types-DJi-u3fz.d.ts} +1 -1
- package/dist/{types-Cuh7ELfr.d.mts → types-rFh4VMH4.d.mts} +5 -2
- package/dist/{types-Cuh7ELfr.d.ts → types-rFh4VMH4.d.ts} +5 -2
- package/dist/ui/index.d.mts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/adapters/mcp.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request, Response, RequestHandler } from 'express';
|
|
2
|
-
import { A as AccessLevel, G as GatewayConfig, i as VerificationResult } from '../types-
|
|
2
|
+
import { A as AccessLevel, G as GatewayConfig, i as VerificationResult } from '../types-rFh4VMH4.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* MCP server-side helpers — companion to `transport/mcp.ts` (which handles the
|
|
@@ -264,16 +264,21 @@ interface McpMiddlewareOptions extends GatewayConfig {
|
|
|
264
264
|
* Per-tool gating for `tools/call` invocations. Tools not listed inherit
|
|
265
265
|
* the default tier from `mcpRiskTier` (`tools/call` → `'standard'`).
|
|
266
266
|
*
|
|
267
|
-
* Accepts both the shorthand access-level string and the full object shape
|
|
267
|
+
* Accepts both the shorthand access-level string and the full object shape.
|
|
268
|
+
* NOTE (3.2.0): the access-level band no longer gates, and a gated `tools/call`
|
|
269
|
+
* must carry a resolvable PDLSS **purpose** (the backend requires it). So the
|
|
270
|
+
* bare string shorthand — which carries no purpose — only works if the caller
|
|
271
|
+
* supplies the purpose another way (an `X-Astra-Purpose` header, or
|
|
272
|
+
* `params._meta.astrasync.purpose`); otherwise the call fails fast with a
|
|
273
|
+
* `PDLSS_PURPOSE_REQUIRED` 400. Prefer the **object form with `purpose`**:
|
|
268
274
|
* ```typescript
|
|
269
275
|
* toolGates: {
|
|
270
|
-
* browse_catalog: 'read-only',
|
|
271
|
-
*
|
|
272
|
-
*
|
|
276
|
+
* browse_catalog: 'read-only', // shorthand — purpose must come
|
|
277
|
+
* // from a header / _meta, else 400
|
|
278
|
+
* list_products: { purpose: 'shopping', // object form (recommended)
|
|
273
279
|
* action: 'shopping.search',
|
|
274
280
|
* resource: '/api/catalog' },
|
|
275
|
-
* start_checkout: {
|
|
276
|
-
* purpose: 'shopping',
|
|
281
|
+
* start_checkout: { purpose: 'shopping',
|
|
277
282
|
* action: 'shopping.purchase',
|
|
278
283
|
* resource: '/api/checkout/*' },
|
|
279
284
|
* }
|
package/dist/adapters/mcp.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request, Response, RequestHandler } from 'express';
|
|
2
|
-
import { A as AccessLevel, G as GatewayConfig, i as VerificationResult } from '../types-
|
|
2
|
+
import { A as AccessLevel, G as GatewayConfig, i as VerificationResult } from '../types-rFh4VMH4.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* MCP server-side helpers — companion to `transport/mcp.ts` (which handles the
|
|
@@ -264,16 +264,21 @@ interface McpMiddlewareOptions extends GatewayConfig {
|
|
|
264
264
|
* Per-tool gating for `tools/call` invocations. Tools not listed inherit
|
|
265
265
|
* the default tier from `mcpRiskTier` (`tools/call` → `'standard'`).
|
|
266
266
|
*
|
|
267
|
-
* Accepts both the shorthand access-level string and the full object shape
|
|
267
|
+
* Accepts both the shorthand access-level string and the full object shape.
|
|
268
|
+
* NOTE (3.2.0): the access-level band no longer gates, and a gated `tools/call`
|
|
269
|
+
* must carry a resolvable PDLSS **purpose** (the backend requires it). So the
|
|
270
|
+
* bare string shorthand — which carries no purpose — only works if the caller
|
|
271
|
+
* supplies the purpose another way (an `X-Astra-Purpose` header, or
|
|
272
|
+
* `params._meta.astrasync.purpose`); otherwise the call fails fast with a
|
|
273
|
+
* `PDLSS_PURPOSE_REQUIRED` 400. Prefer the **object form with `purpose`**:
|
|
268
274
|
* ```typescript
|
|
269
275
|
* toolGates: {
|
|
270
|
-
* browse_catalog: 'read-only',
|
|
271
|
-
*
|
|
272
|
-
*
|
|
276
|
+
* browse_catalog: 'read-only', // shorthand — purpose must come
|
|
277
|
+
* // from a header / _meta, else 400
|
|
278
|
+
* list_products: { purpose: 'shopping', // object form (recommended)
|
|
273
279
|
* action: 'shopping.search',
|
|
274
280
|
* resource: '/api/catalog' },
|
|
275
|
-
* start_checkout: {
|
|
276
|
-
* purpose: 'shopping',
|
|
281
|
+
* start_checkout: { purpose: 'shopping',
|
|
277
282
|
* action: 'shopping.purchase',
|
|
278
283
|
* resource: '/api/checkout/*' },
|
|
279
284
|
* }
|
package/dist/adapters/mcp.js
CHANGED
|
@@ -32,26 +32,15 @@ __export(mcp_exports, {
|
|
|
32
32
|
module.exports = __toCommonJS(mcp_exports);
|
|
33
33
|
|
|
34
34
|
// src/access-levels.ts
|
|
35
|
-
var ACCESS_LEVEL_HIERARCHY = {
|
|
36
|
-
none: 0,
|
|
37
|
-
restricted: 1,
|
|
38
|
-
"read-only": 2,
|
|
39
|
-
standard: 3,
|
|
40
|
-
full: 4,
|
|
41
|
-
internal: 5
|
|
42
|
-
};
|
|
43
35
|
function getTrustLevel(score) {
|
|
44
36
|
if (score >= 80) return "PLATINUM";
|
|
45
37
|
if (score >= 60) return "GOLD";
|
|
46
38
|
if (score >= 40) return "SILVER";
|
|
47
39
|
return "BRONZE";
|
|
48
40
|
}
|
|
49
|
-
function hasMinimumAccess(actual, required) {
|
|
50
|
-
return ACCESS_LEVEL_HIERARCHY[actual] >= ACCESS_LEVEL_HIERARCHY[required];
|
|
51
|
-
}
|
|
52
41
|
|
|
53
42
|
// src/version.ts
|
|
54
|
-
var SDK_VERSION = "3.
|
|
43
|
+
var SDK_VERSION = "3.2.0";
|
|
55
44
|
|
|
56
45
|
// src/well-known.ts
|
|
57
46
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -156,7 +145,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
|
|
|
156
145
|
}
|
|
157
146
|
}
|
|
158
147
|
var verificationCache = /* @__PURE__ */ new Map();
|
|
159
|
-
function getCacheKey(request) {
|
|
148
|
+
function getCacheKey(request, counterpartyId) {
|
|
160
149
|
const c = request.credentials;
|
|
161
150
|
return [
|
|
162
151
|
c.astraId || "",
|
|
@@ -169,6 +158,14 @@ function getCacheKey(request) {
|
|
|
169
158
|
request.jurisdiction || "",
|
|
170
159
|
request.transactionValue ?? "",
|
|
171
160
|
request.currency || "",
|
|
161
|
+
// SECURITY (cross-merchant cache leak): the merchant identity is sent via
|
|
162
|
+
// `config.counterpartyId`, NOT on the request, so it was previously absent
|
|
163
|
+
// from the key — two verifies for the SAME agent/purpose/action/value but
|
|
164
|
+
// DIFFERENT merchants collided, and a grant at a permissive merchant (low
|
|
165
|
+
// trust floor) was served for a stricter one. Same bug class as the
|
|
166
|
+
// duration omission (F-A1-07). counterpartyId affects the backend verdict
|
|
167
|
+
// (trust floor / per-route policy), so it MUST key the cache.
|
|
168
|
+
counterpartyId || "",
|
|
172
169
|
request.counterpartyUrl || "",
|
|
173
170
|
request.counterpartyType || "",
|
|
174
171
|
request.isSubAgentRequest ? "1" : "0",
|
|
@@ -192,8 +189,8 @@ function getCacheKey(request) {
|
|
|
192
189
|
request.callerMetadata?.agentCardUrl || ""
|
|
193
190
|
].join("|");
|
|
194
191
|
}
|
|
195
|
-
function getCachedResult(request) {
|
|
196
|
-
const key = getCacheKey(request);
|
|
192
|
+
function getCachedResult(request, counterpartyId) {
|
|
193
|
+
const key = getCacheKey(request, counterpartyId);
|
|
197
194
|
const cached = verificationCache.get(key);
|
|
198
195
|
if (cached && cached.expiresAt > Date.now()) {
|
|
199
196
|
return cached.result;
|
|
@@ -205,9 +202,9 @@ function getCachedResult(request) {
|
|
|
205
202
|
}
|
|
206
203
|
var DEFAULT_AUTONOMOUS_TTL_SECONDS = 60;
|
|
207
204
|
var DEFAULT_STEP_UP_TTL_SECONDS = 300;
|
|
208
|
-
function cacheResult(request, result, configuredTtl) {
|
|
205
|
+
function cacheResult(request, result, configuredTtl, counterpartyId) {
|
|
209
206
|
const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : result.requiresStepUp ? DEFAULT_STEP_UP_TTL_SECONDS : DEFAULT_AUTONOMOUS_TTL_SECONDS;
|
|
210
|
-
const key = getCacheKey(request);
|
|
207
|
+
const key = getCacheKey(request, counterpartyId);
|
|
211
208
|
verificationCache.set(key, {
|
|
212
209
|
result,
|
|
213
210
|
expiresAt: Date.now() + ttlSeconds * 1e3
|
|
@@ -399,7 +396,7 @@ async function verify(config, request) {
|
|
|
399
396
|
);
|
|
400
397
|
}
|
|
401
398
|
if (mergedConfig.cacheTtl !== 0) {
|
|
402
|
-
const cached = getCachedResult(request);
|
|
399
|
+
const cached = getCachedResult(request, mergedConfig.counterpartyId);
|
|
403
400
|
if (cached) {
|
|
404
401
|
if (mergedConfig.debug) {
|
|
405
402
|
console.log("[VerificationGateway] Returning cached result");
|
|
@@ -451,8 +448,8 @@ async function verify(config, request) {
|
|
|
451
448
|
verifiedAt: /* @__PURE__ */ new Date(),
|
|
452
449
|
// Extract sessionId so decisions can be recorded for denials too
|
|
453
450
|
sessionId: apiResponse.sessionId,
|
|
454
|
-
//
|
|
455
|
-
//
|
|
451
|
+
// Anonymous traffic has no session → correlationId is the per-attempt
|
|
452
|
+
// linking key (the sessionId-equivalent for anonymous callers).
|
|
456
453
|
correlationId: apiResponse.correlationId,
|
|
457
454
|
recommendation: apiResponse.recommendation,
|
|
458
455
|
recommendationReasons: apiResponse.recommendationReasons
|
|
@@ -526,17 +523,14 @@ async function verify(config, request) {
|
|
|
526
523
|
};
|
|
527
524
|
} else if (result.recommendation === "step_up_required") {
|
|
528
525
|
result.requiresStepUp = true;
|
|
529
|
-
if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
|
|
530
|
-
result.accessLevel = "read-only";
|
|
531
|
-
}
|
|
532
526
|
result.denialReasons = result.recommendationReasons || ["Step-up verification required"];
|
|
533
527
|
}
|
|
534
528
|
if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny") {
|
|
535
|
-
cacheResult(request, result, mergedConfig.cacheTtl);
|
|
529
|
+
cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
|
|
536
530
|
}
|
|
537
531
|
return result;
|
|
538
532
|
}
|
|
539
|
-
async function recordDecision(config, sessionId, decision, reason
|
|
533
|
+
async function recordDecision(config, sessionId, decision, reason) {
|
|
540
534
|
const headers = { "Content-Type": "application/json" };
|
|
541
535
|
if (config.apiKey) {
|
|
542
536
|
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
@@ -545,36 +539,7 @@ async function recordDecision(config, sessionId, decision, reason, override) {
|
|
|
545
539
|
await fetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
|
|
546
540
|
method: "POST",
|
|
547
541
|
headers,
|
|
548
|
-
body: JSON.stringify({
|
|
549
|
-
decision,
|
|
550
|
-
reason,
|
|
551
|
-
...override && {
|
|
552
|
-
overriddenBy: override.overriddenBy,
|
|
553
|
-
toolName: override.toolName,
|
|
554
|
-
requestedLevel: override.requestedLevel,
|
|
555
|
-
grantedLevel: override.grantedLevel
|
|
556
|
-
}
|
|
557
|
-
})
|
|
558
|
-
}).catch(() => {
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
async function recordAnonymousLocalOverride(config, correlationId, override, reason) {
|
|
562
|
-
const headers = { "Content-Type": "application/json" };
|
|
563
|
-
if (config.apiKey) {
|
|
564
|
-
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
565
|
-
headers["X-API-Key"] = config.apiKey;
|
|
566
|
-
}
|
|
567
|
-
await fetch(`${config.apiBaseUrl}/agents/verify-access/local-override`, {
|
|
568
|
-
method: "POST",
|
|
569
|
-
headers,
|
|
570
|
-
body: JSON.stringify({
|
|
571
|
-
correlationId,
|
|
572
|
-
reason,
|
|
573
|
-
overriddenBy: override.overriddenBy,
|
|
574
|
-
toolName: override.toolName,
|
|
575
|
-
requestedLevel: override.requestedLevel,
|
|
576
|
-
grantedLevel: override.grantedLevel
|
|
577
|
-
})
|
|
542
|
+
body: JSON.stringify({ decision, reason })
|
|
578
543
|
}).catch(() => {
|
|
579
544
|
});
|
|
580
545
|
}
|
|
@@ -791,7 +756,6 @@ function createMcpMiddleware(options) {
|
|
|
791
756
|
return next();
|
|
792
757
|
}
|
|
793
758
|
req.mcpRequest = parsed;
|
|
794
|
-
const wellKnownUrls = config.apiBaseUrl ? await getWellKnownUrls(config.apiBaseUrl).catch(() => void 0) : void 0;
|
|
795
759
|
const headerRaw = req.headers["x-astra-id"] ?? req.headers["x-astra-agentid"];
|
|
796
760
|
const headerAstraId = typeof headerRaw === "string" ? headerRaw : Array.isArray(headerRaw) ? headerRaw[0] : void 0;
|
|
797
761
|
const bodyAstraId = parsed.agentIdFromBody;
|
|
@@ -828,7 +792,7 @@ function createMcpMiddleware(options) {
|
|
|
828
792
|
return next();
|
|
829
793
|
}
|
|
830
794
|
}
|
|
831
|
-
const { level: minAccessLevel
|
|
795
|
+
const { level: minAccessLevel } = resolveMinAccessLevel(parsed, {
|
|
832
796
|
toolGates,
|
|
833
797
|
methodGates
|
|
834
798
|
});
|
|
@@ -864,6 +828,23 @@ function createMcpMiddleware(options) {
|
|
|
864
828
|
resolved_action: pdlss.action
|
|
865
829
|
});
|
|
866
830
|
}
|
|
831
|
+
if (!pdlss.purpose) {
|
|
832
|
+
const id = req.body?.id ?? null;
|
|
833
|
+
res.status(400).json({
|
|
834
|
+
jsonrpc: "2.0",
|
|
835
|
+
id,
|
|
836
|
+
error: {
|
|
837
|
+
code: -32602,
|
|
838
|
+
message: "PDLSS_PURPOSE_REQUIRED",
|
|
839
|
+
data: {
|
|
840
|
+
dimension: "pdlss.purpose",
|
|
841
|
+
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.",
|
|
842
|
+
resolvedAction: pdlss.action
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
867
848
|
const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get("host")}${req.path}`;
|
|
868
849
|
const shouldRecordDecisions = recordDecisions !== false;
|
|
869
850
|
const result = await verify(config, {
|
|
@@ -887,7 +868,6 @@ function createMcpMiddleware(options) {
|
|
|
887
868
|
});
|
|
888
869
|
req.agentVerification = result;
|
|
889
870
|
const sessionId = result.sessionId;
|
|
890
|
-
const correlationId = result.correlationId;
|
|
891
871
|
if (!result.identityVerified || !result.policyAllowed) {
|
|
892
872
|
if (shouldRecordDecisions && sessionId) {
|
|
893
873
|
recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
|
|
@@ -908,48 +888,6 @@ function createMcpMiddleware(options) {
|
|
|
908
888
|
}
|
|
909
889
|
return next();
|
|
910
890
|
}
|
|
911
|
-
if (!hasMinimumAccess(result.accessLevel, minAccessLevel)) {
|
|
912
|
-
const insufficientFailure = {
|
|
913
|
-
dimension: "access_level.insufficient",
|
|
914
|
-
message: `Tool requires accessLevel '${minAccessLevel}'; agent has '${result.accessLevel}'.`,
|
|
915
|
-
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."
|
|
916
|
-
};
|
|
917
|
-
result.failures = [...result.failures ?? [], insufficientFailure];
|
|
918
|
-
result.denialReasons = [...result.denialReasons ?? [], insufficientFailure.message];
|
|
919
|
-
if (!result.guidance && wellKnownUrls) {
|
|
920
|
-
result.guidance = {
|
|
921
|
-
message: insufficientFailure.message,
|
|
922
|
-
registrationUrl: wellKnownUrls.registrationUrl,
|
|
923
|
-
documentationUrl: wellKnownUrls.documentationUrl
|
|
924
|
-
};
|
|
925
|
-
}
|
|
926
|
-
if (shouldRecordDecisions) {
|
|
927
|
-
const overrideKind = gateSource === "toolGate" ? "toolGate" : gateSource === "methodGate" ? "methodGate" : "other";
|
|
928
|
-
const override = {
|
|
929
|
-
overriddenBy: overrideKind,
|
|
930
|
-
...parsed.toolName && { toolName: parsed.toolName },
|
|
931
|
-
requestedLevel: minAccessLevel,
|
|
932
|
-
grantedLevel: result.accessLevel
|
|
933
|
-
};
|
|
934
|
-
if (sessionId) {
|
|
935
|
-
recordDecision(config, sessionId, "denied", result.denialReasons?.[0], override).catch(
|
|
936
|
-
() => {
|
|
937
|
-
}
|
|
938
|
-
);
|
|
939
|
-
} else if (correlationId) {
|
|
940
|
-
recordAnonymousLocalOverride(
|
|
941
|
-
config,
|
|
942
|
-
correlationId,
|
|
943
|
-
override,
|
|
944
|
-
result.denialReasons?.[0]
|
|
945
|
-
).catch(() => {
|
|
946
|
-
});
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
dedupeFailures(result);
|
|
950
|
-
onDenied(result, req, res);
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
953
891
|
if (effectiveAstraId) {
|
|
954
892
|
res.setHeader(
|
|
955
893
|
MCP_VERIFIED_HOP_HEADER,
|