@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,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-
|
|
3
|
-
import '../types-
|
|
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-
|
|
3
|
-
import '../types-
|
|
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-
|
|
3
|
-
export { c as createMiddleware, a as extractAstraSyncCredentials } from '../express-
|
|
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-
|
|
3
|
-
export { c as createMiddleware, a as extractAstraSyncCredentials } from '../express-
|
|
2
|
+
import '../types-rFh4VMH4.js';
|
|
3
|
+
export { c as createMiddleware, a as extractAstraSyncCredentials } from '../express-BowlMHQF.js';
|
package/dist/adapters/express.js
CHANGED
|
@@ -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.
|
|
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
|
-
//
|
|
449
|
-
//
|
|
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
|
|
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
|
|
682
|
-
|
|
683
|
-
if (
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
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
|
|
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
|
-
|
|
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: "
|
|
964
|
-
message:
|
|
965
|
-
guidance: "
|
|
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];
|