@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
package/dist/adapters/nextjs.mjs
CHANGED
|
@@ -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;
|
|
@@ -71,7 +60,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
|
|
|
71
60
|
}
|
|
72
61
|
}
|
|
73
62
|
var verificationCache = /* @__PURE__ */ new Map();
|
|
74
|
-
function getCacheKey(request) {
|
|
63
|
+
function getCacheKey(request, counterpartyId) {
|
|
75
64
|
const c = request.credentials;
|
|
76
65
|
return [
|
|
77
66
|
c.astraId || "",
|
|
@@ -84,6 +73,14 @@ function getCacheKey(request) {
|
|
|
84
73
|
request.jurisdiction || "",
|
|
85
74
|
request.transactionValue ?? "",
|
|
86
75
|
request.currency || "",
|
|
76
|
+
// SECURITY (cross-merchant cache leak): the merchant identity is sent via
|
|
77
|
+
// `config.counterpartyId`, NOT on the request, so it was previously absent
|
|
78
|
+
// from the key — two verifies for the SAME agent/purpose/action/value but
|
|
79
|
+
// DIFFERENT merchants collided, and a grant at a permissive merchant (low
|
|
80
|
+
// trust floor) was served for a stricter one. Same bug class as the
|
|
81
|
+
// duration omission (F-A1-07). counterpartyId affects the backend verdict
|
|
82
|
+
// (trust floor / per-route policy), so it MUST key the cache.
|
|
83
|
+
counterpartyId || "",
|
|
87
84
|
request.counterpartyUrl || "",
|
|
88
85
|
request.counterpartyType || "",
|
|
89
86
|
request.isSubAgentRequest ? "1" : "0",
|
|
@@ -107,8 +104,8 @@ function getCacheKey(request) {
|
|
|
107
104
|
request.callerMetadata?.agentCardUrl || ""
|
|
108
105
|
].join("|");
|
|
109
106
|
}
|
|
110
|
-
function getCachedResult(request) {
|
|
111
|
-
const key = getCacheKey(request);
|
|
107
|
+
function getCachedResult(request, counterpartyId) {
|
|
108
|
+
const key = getCacheKey(request, counterpartyId);
|
|
112
109
|
const cached = verificationCache.get(key);
|
|
113
110
|
if (cached && cached.expiresAt > Date.now()) {
|
|
114
111
|
return cached.result;
|
|
@@ -120,9 +117,9 @@ function getCachedResult(request) {
|
|
|
120
117
|
}
|
|
121
118
|
var DEFAULT_AUTONOMOUS_TTL_SECONDS = 60;
|
|
122
119
|
var DEFAULT_STEP_UP_TTL_SECONDS = 300;
|
|
123
|
-
function cacheResult(request, result, configuredTtl) {
|
|
120
|
+
function cacheResult(request, result, configuredTtl, counterpartyId) {
|
|
124
121
|
const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : result.requiresStepUp ? DEFAULT_STEP_UP_TTL_SECONDS : DEFAULT_AUTONOMOUS_TTL_SECONDS;
|
|
125
|
-
const key = getCacheKey(request);
|
|
122
|
+
const key = getCacheKey(request, counterpartyId);
|
|
126
123
|
verificationCache.set(key, {
|
|
127
124
|
result,
|
|
128
125
|
expiresAt: Date.now() + ttlSeconds * 1e3
|
|
@@ -280,7 +277,7 @@ async function verify(config, request) {
|
|
|
280
277
|
);
|
|
281
278
|
}
|
|
282
279
|
if (mergedConfig.cacheTtl !== 0) {
|
|
283
|
-
const cached = getCachedResult(request);
|
|
280
|
+
const cached = getCachedResult(request, mergedConfig.counterpartyId);
|
|
284
281
|
if (cached) {
|
|
285
282
|
if (mergedConfig.debug) {
|
|
286
283
|
console.log("[VerificationGateway] Returning cached result");
|
|
@@ -332,8 +329,8 @@ async function verify(config, request) {
|
|
|
332
329
|
verifiedAt: /* @__PURE__ */ new Date(),
|
|
333
330
|
// Extract sessionId so decisions can be recorded for denials too
|
|
334
331
|
sessionId: apiResponse.sessionId,
|
|
335
|
-
//
|
|
336
|
-
//
|
|
332
|
+
// Anonymous traffic has no session → correlationId is the per-attempt
|
|
333
|
+
// linking key (the sessionId-equivalent for anonymous callers).
|
|
337
334
|
correlationId: apiResponse.correlationId,
|
|
338
335
|
recommendation: apiResponse.recommendation,
|
|
339
336
|
recommendationReasons: apiResponse.recommendationReasons
|
|
@@ -407,13 +404,10 @@ async function verify(config, request) {
|
|
|
407
404
|
};
|
|
408
405
|
} else if (result.recommendation === "step_up_required") {
|
|
409
406
|
result.requiresStepUp = true;
|
|
410
|
-
if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
|
|
411
|
-
result.accessLevel = "read-only";
|
|
412
|
-
}
|
|
413
407
|
result.denialReasons = result.recommendationReasons || ["Step-up verification required"];
|
|
414
408
|
}
|
|
415
409
|
if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny") {
|
|
416
|
-
cacheResult(request, result, mergedConfig.cacheTtl);
|
|
410
|
+
cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
|
|
417
411
|
}
|
|
418
412
|
return result;
|
|
419
413
|
}
|
|
@@ -468,6 +462,13 @@ function extractHttpCredentials(headers) {
|
|
|
468
462
|
purpose: { category, action }
|
|
469
463
|
};
|
|
470
464
|
}
|
|
465
|
+
const astraAction = getValue(`${HEADER_PREFIX}Action`) ?? getValue("x-astra-action");
|
|
466
|
+
if (astraAction) {
|
|
467
|
+
credentials.pdlss = {
|
|
468
|
+
...credentials.pdlss,
|
|
469
|
+
purpose: { category: credentials.pdlss?.purpose?.category ?? "", action: astraAction }
|
|
470
|
+
};
|
|
471
|
+
}
|
|
471
472
|
const duration = getValue(`${HEADER_PREFIX}Duration`) ?? getValue("x-astra-duration");
|
|
472
473
|
if (duration) {
|
|
473
474
|
credentials.pdlss = {
|
|
@@ -533,6 +534,85 @@ function performCounterpartyPreCheck(routeConfig, astraCreds, purpose) {
|
|
|
533
534
|
return failures;
|
|
534
535
|
}
|
|
535
536
|
|
|
537
|
+
// src/adapters/http-pdlss.ts
|
|
538
|
+
var HTTP_METHOD_ACTION_TABLE = {
|
|
539
|
+
GET: "data.read",
|
|
540
|
+
HEAD: "data.read",
|
|
541
|
+
OPTIONS: "data.read",
|
|
542
|
+
POST: "data.write",
|
|
543
|
+
PUT: "data.write",
|
|
544
|
+
PATCH: "data.write",
|
|
545
|
+
DELETE: "data.delete"
|
|
546
|
+
};
|
|
547
|
+
var DEFAULT_HTTP_ACTION = "data.write";
|
|
548
|
+
var DEFAULT_HTTP_PURPOSE = "data";
|
|
549
|
+
function actionForHttpMethod(method) {
|
|
550
|
+
return HTTP_METHOD_ACTION_TABLE[method.toUpperCase()] ?? DEFAULT_HTTP_ACTION;
|
|
551
|
+
}
|
|
552
|
+
function normalizePurposeHeader(value) {
|
|
553
|
+
const colon = value.indexOf(":");
|
|
554
|
+
if (colon >= 0) {
|
|
555
|
+
return { purpose: value.slice(0, colon) };
|
|
556
|
+
}
|
|
557
|
+
const dot = value.indexOf(".");
|
|
558
|
+
if (dot > 0 && dot < value.length - 1) {
|
|
559
|
+
return { purpose: value.slice(0, dot), actionCandidate: value };
|
|
560
|
+
}
|
|
561
|
+
return { purpose: value };
|
|
562
|
+
}
|
|
563
|
+
function resolveHttpPdlss(input) {
|
|
564
|
+
const fromHeader = input.astraPurpose ? normalizePurposeHeader(input.astraPurpose) : void 0;
|
|
565
|
+
let action;
|
|
566
|
+
let actionSource;
|
|
567
|
+
if (input.routeAction) {
|
|
568
|
+
action = input.routeAction;
|
|
569
|
+
actionSource = "route_config";
|
|
570
|
+
} else if (input.hasCustomActionExtractor && input.customAction) {
|
|
571
|
+
action = input.customAction;
|
|
572
|
+
actionSource = "custom_extractor";
|
|
573
|
+
} else if (!input.hasCustomActionExtractor && input.astraAction) {
|
|
574
|
+
action = input.astraAction;
|
|
575
|
+
actionSource = "header";
|
|
576
|
+
} else if (!input.hasCustomActionExtractor && fromHeader?.actionCandidate) {
|
|
577
|
+
action = fromHeader.actionCandidate;
|
|
578
|
+
actionSource = "purpose_header_derived";
|
|
579
|
+
} else {
|
|
580
|
+
action = actionForHttpMethod(input.method);
|
|
581
|
+
actionSource = "method_table";
|
|
582
|
+
}
|
|
583
|
+
let purpose;
|
|
584
|
+
let purposeSource;
|
|
585
|
+
if (input.routePurpose) {
|
|
586
|
+
purpose = input.routePurpose;
|
|
587
|
+
purposeSource = "route_config";
|
|
588
|
+
} else if (input.hasCustomPurposeExtractor) {
|
|
589
|
+
if (input.customPurpose) {
|
|
590
|
+
purpose = input.customPurpose;
|
|
591
|
+
purposeSource = "custom_extractor";
|
|
592
|
+
}
|
|
593
|
+
} else if (fromHeader) {
|
|
594
|
+
purpose = fromHeader.purpose;
|
|
595
|
+
purposeSource = "header";
|
|
596
|
+
} else if (input.legacyPurpose) {
|
|
597
|
+
purpose = input.legacyPurpose;
|
|
598
|
+
purposeSource = "legacy_header";
|
|
599
|
+
} else if (input.queryPurpose) {
|
|
600
|
+
purpose = input.queryPurpose;
|
|
601
|
+
purposeSource = "query";
|
|
602
|
+
}
|
|
603
|
+
if (!purpose) {
|
|
604
|
+
const dot = action.indexOf(".");
|
|
605
|
+
if (dot > 0) {
|
|
606
|
+
purpose = action.slice(0, dot);
|
|
607
|
+
purposeSource = "action_derived";
|
|
608
|
+
} else {
|
|
609
|
+
purpose = DEFAULT_HTTP_PURPOSE;
|
|
610
|
+
purposeSource = "transport_default";
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return { purpose, action, purposeSource, actionSource };
|
|
614
|
+
}
|
|
615
|
+
|
|
536
616
|
// src/adapters/nextjs.ts
|
|
537
617
|
function escapeHtml(value) {
|
|
538
618
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -593,28 +673,15 @@ function extractAstraSyncCredentialsFromNextRequest(request) {
|
|
|
593
673
|
});
|
|
594
674
|
return extractHttpCredentials(headers);
|
|
595
675
|
}
|
|
596
|
-
function
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
}
|
|
605
|
-
switch (request.method.toUpperCase()) {
|
|
606
|
-
case "GET":
|
|
607
|
-
return "read_data";
|
|
608
|
-
case "POST":
|
|
609
|
-
return "write_data";
|
|
610
|
-
case "PUT":
|
|
611
|
-
case "PATCH":
|
|
612
|
-
return "write_data";
|
|
613
|
-
case "DELETE":
|
|
614
|
-
return "delete_data";
|
|
615
|
-
default:
|
|
616
|
-
return "general";
|
|
617
|
-
}
|
|
676
|
+
function resolveNextPdlss(request, routeConfig) {
|
|
677
|
+
return resolveHttpPdlss({
|
|
678
|
+
method: request.method,
|
|
679
|
+
astraPurpose: request.headers.get("x-astra-purpose") ?? void 0,
|
|
680
|
+
astraAction: request.headers.get("x-astra-action") ?? void 0,
|
|
681
|
+
legacyPurpose: request.headers.get("x-purpose") ?? void 0,
|
|
682
|
+
routePurpose: routeConfig?.purpose,
|
|
683
|
+
routeAction: routeConfig?.action
|
|
684
|
+
});
|
|
618
685
|
}
|
|
619
686
|
function generateCommerceShieldHtml(result, options) {
|
|
620
687
|
const title = escapeHtml(options.commerceShield?.title || "AstraSync Agent Verification");
|
|
@@ -827,7 +894,16 @@ function createMiddleware(options) {
|
|
|
827
894
|
}
|
|
828
895
|
const credentials = extractCredentialsFromNextRequest(request);
|
|
829
896
|
const counterpartyUrl = config.counterpartyUrl || request.nextUrl.origin;
|
|
830
|
-
const
|
|
897
|
+
const pdlssPair = resolveNextPdlss(request, routeConfig);
|
|
898
|
+
const purpose = pdlssPair.purpose;
|
|
899
|
+
if (config.debug) {
|
|
900
|
+
console.debug("[nextjs-middleware] pdlss resolved", {
|
|
901
|
+
purpose_source: pdlssPair.purposeSource,
|
|
902
|
+
resolved_purpose: pdlssPair.purpose,
|
|
903
|
+
action_source: pdlssPair.actionSource,
|
|
904
|
+
resolved_action: pdlssPair.action
|
|
905
|
+
});
|
|
906
|
+
}
|
|
831
907
|
const astraCreds = extractAstraSyncCredentialsFromNextRequest(request);
|
|
832
908
|
const preCheckFailures = performCounterpartyPreCheck(routeConfig, astraCreds, purpose);
|
|
833
909
|
if (preCheckFailures.length > 0) {
|
|
@@ -881,10 +957,7 @@ function createMiddleware(options) {
|
|
|
881
957
|
const result = await verify(config, {
|
|
882
958
|
credentials,
|
|
883
959
|
purpose,
|
|
884
|
-
|
|
885
|
-
// Backend evaluator tolerates either case as defense-in-depth
|
|
886
|
-
// (round-18.6 batch 2); SDK emits canonical form.
|
|
887
|
-
action: request.method.toUpperCase(),
|
|
960
|
+
action: pdlssPair.action,
|
|
888
961
|
resource: pathname,
|
|
889
962
|
counterpartyUrl,
|
|
890
963
|
counterpartyType: config.counterpartyType || "website",
|
|
@@ -899,7 +972,7 @@ function createMiddleware(options) {
|
|
|
899
972
|
agentCardUrl: request.headers.get("x-astrasync-agent-card") || void 0
|
|
900
973
|
}
|
|
901
974
|
});
|
|
902
|
-
if (!result.identityVerified || !result.policyAllowed
|
|
975
|
+
if (!result.identityVerified || !result.policyAllowed) {
|
|
903
976
|
if (pathname.startsWith("/api/")) {
|
|
904
977
|
return NextResponse.json(
|
|
905
978
|
{
|
|
@@ -907,10 +980,8 @@ function createMiddleware(options) {
|
|
|
907
980
|
error: {
|
|
908
981
|
// Round-18 G4: 401 → identity missing (re-auth); 403 → identity
|
|
909
982
|
// OK, policy denied (update PDLSS / step up).
|
|
910
|
-
code: !result.identityVerified ? "UNAUTHORIZED" : "
|
|
983
|
+
code: !result.identityVerified ? "UNAUTHORIZED" : "POLICY_DENIED",
|
|
911
984
|
message: result.denialReasons?.[0] || "Access denied",
|
|
912
|
-
accessLevel: result.accessLevel,
|
|
913
|
-
required: routeConfig.minAccessLevel,
|
|
914
985
|
guidance: result.guidance
|
|
915
986
|
}
|
|
916
987
|
},
|
|
@@ -938,7 +1009,6 @@ function createMiddleware(options) {
|
|
|
938
1009
|
response.headers.set("X-AstraSync-Access-Level", result.accessLevel);
|
|
939
1010
|
if (result.agent) {
|
|
940
1011
|
response.headers.set("X-AstraSync-Agent-Id", result.agent.astraId);
|
|
941
|
-
response.headers.set("X-AstraSync-Trust-Score", result.agent.trustScore.toString());
|
|
942
1012
|
}
|
|
943
1013
|
return response;
|
|
944
1014
|
};
|