@astrasyncai/verification-gateway 2.4.11 → 2.4.14
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 +129 -36
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +129 -36
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +26 -4
- package/dist/adapters/mcp.d.ts +26 -4
- package/dist/adapters/mcp.js +94 -28
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +94 -28
- 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 +75 -29
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +75 -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 +45 -22
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +45 -22
- 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 +29 -0
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +29 -0
- package/dist/agent/index.mjs.map +1 -1
- package/dist/browser/background.js +86 -24
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +86 -24
- 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 +86 -24
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +86 -24
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/{express-C1ePFB7n.d.ts → express-CrfwoNAR.d.ts} +1 -1
- package/dist/{express-4WStX3PV.d.mts → express-ienhAXps.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 +86 -24
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +86 -24
- 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-ChPX4WHl.d.mts → index-B5e2IDWU.d.mts} +1 -1
- package/dist/{index-CzJMCgEy.d.ts → index-CCdZxvAr.d.ts} +71 -6
- package/dist/{index-D8IEntil.d.mts → index-CEg_WG6y.d.mts} +71 -6
- package/dist/{index-Cjm-zBeZ.d.ts → index-DC5f8eoQ.d.ts} +1 -1
- package/dist/index.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +344 -73
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +344 -73
- 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/local-evaluator/evaluator.js +12 -2
- package/dist/local-evaluator/evaluator.js.map +1 -1
- package/dist/local-evaluator/evaluator.mjs +12 -2
- package/dist/local-evaluator/evaluator.mjs.map +1 -1
- package/dist/{nextjs-BIORS__0.d.ts → nextjs-66R1KW8e.d.ts} +1 -1
- package/dist/{nextjs-CjzHdaXA.d.mts → nextjs-DSpisQst.d.mts} +1 -1
- package/dist/{sdk-Chhz-FcT.d.mts → sdk-5U_CBRpr.d.mts} +1 -1
- package/dist/{sdk-CqTEQAc6.d.ts → sdk-Bm8np66n.d.ts} +1 -1
- package/dist/transport/index.d.mts +2 -2
- package/dist/transport/index.d.ts +2 -2
- package/dist/transport/index.js +146 -28
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs +146 -28
- package/dist/transport/index.mjs.map +1 -1
- package/dist/{types-L15pYd2c.d.mts → types-B3USs-Kx.d.mts} +42 -1
- package/dist/{types-L15pYd2c.d.ts → types-B3USs-Kx.d.ts} +42 -1
- package/dist/{types-DNK2BgIf.d.mts → types-CgDCUfo8.d.mts} +1 -1
- package/dist/{types-DoWIuzfj.d.ts → types-R5N4ET6x.d.ts} +1 -1
- 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.mjs
CHANGED
|
@@ -18,7 +18,7 @@ function hasMinimumAccess(actual, required) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// src/version.ts
|
|
21
|
-
var SDK_VERSION = "2.4.
|
|
21
|
+
var SDK_VERSION = "2.4.13";
|
|
22
22
|
|
|
23
23
|
// src/verify.ts
|
|
24
24
|
var DEFAULT_CONFIG = {
|
|
@@ -37,22 +37,27 @@ var DEFAULT_CONFIG = {
|
|
|
37
37
|
};
|
|
38
38
|
var initCheckPerformed = false;
|
|
39
39
|
var deprecationWarningShown = false;
|
|
40
|
-
async function performInitCheck(apiBaseUrl, debug) {
|
|
40
|
+
async function performInitCheck(apiBaseUrl, debug, strictInit) {
|
|
41
41
|
initCheckPerformed = true;
|
|
42
42
|
try {
|
|
43
43
|
const probeUrl = `${apiBaseUrl}/agents/verify-access`;
|
|
44
44
|
const response = await fetch(probeUrl, { method: "HEAD" });
|
|
45
45
|
const contentType = response.headers.get("content-type") ?? "";
|
|
46
46
|
if (contentType.startsWith("text/html")) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
const message = `[VerificationGateway] apiBaseUrl '${apiBaseUrl}' returned HTML (content-type: ${contentType}). This usually means apiBaseUrl is pointing at a marketing site instead of the API. Expected: 'https://astrasync.ai/api' (prod) or 'https://staging.astrasync.ai/api' (staging).`;
|
|
48
|
+
if (strictInit) {
|
|
49
|
+
throw new Error(`${message} (strictInit=true)`);
|
|
50
|
+
}
|
|
51
|
+
console.warn(`${message} Set disableInitChecks: true on GatewayConfig to silence.`);
|
|
50
52
|
} else if (debug) {
|
|
51
53
|
console.log(
|
|
52
54
|
`[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
|
|
53
55
|
);
|
|
54
56
|
}
|
|
55
57
|
} catch (err) {
|
|
58
|
+
if (strictInit) {
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
56
61
|
if (debug) {
|
|
57
62
|
console.log(`[VerificationGateway] init check failed (non-blocking): ${String(err)}`);
|
|
58
63
|
}
|
|
@@ -76,7 +81,23 @@ function getCacheKey(request) {
|
|
|
76
81
|
request.counterpartyType || "",
|
|
77
82
|
request.isSubAgentRequest ? "1" : "0",
|
|
78
83
|
request.parentAgentId || "",
|
|
79
|
-
request.subAgentDepth ?? ""
|
|
84
|
+
request.subAgentDepth ?? "",
|
|
85
|
+
// Audit F-A1-07: previously-missing dimensions that DO affect the
|
|
86
|
+
// backend verdict. Without these, two requests with different
|
|
87
|
+
// durations (e.g. 60s vs 86400s) collided on the same cache key and
|
|
88
|
+
// the shorter-duration allow served the longer-duration request.
|
|
89
|
+
request.durationRequired ?? "",
|
|
90
|
+
request.invocationProtocol || "",
|
|
91
|
+
request.enableRuntimeChallenge ? "1" : "0",
|
|
92
|
+
// callerMetadata fields contribute to risk model; include the ones
|
|
93
|
+
// backend reads. sourceIp/userAgent/forwardedFor change per-request
|
|
94
|
+
// so their inclusion effectively forces a re-check for any varying
|
|
95
|
+
// client (the right behavior — IP-driven anomaly scoring shouldn't
|
|
96
|
+
// be cached across IPs).
|
|
97
|
+
request.callerMetadata?.sourceIp || "",
|
|
98
|
+
request.callerMetadata?.userAgent || "",
|
|
99
|
+
request.callerMetadata?.forwardedFor || "",
|
|
100
|
+
request.callerMetadata?.agentCardUrl || ""
|
|
80
101
|
].join("|");
|
|
81
102
|
}
|
|
82
103
|
function getCachedResult(request) {
|
|
@@ -102,9 +123,13 @@ function cacheResult(request, result, configuredTtl) {
|
|
|
102
123
|
}
|
|
103
124
|
function extractCredentials(headers, query) {
|
|
104
125
|
const credentials = {};
|
|
126
|
+
const ASTRA_ID_PATTERN = /^ASTRAE?-[A-Za-z0-9_-]{1,64}$/;
|
|
105
127
|
const astraIdHeader = headers["x-astra-id"] || headers["X-Astra-Id"] || headers["X-ASTRA-ID"] || headers["x-astra-agentid"] || headers["X-Astra-AgentId"] || headers["x-astra-agent-id"] || headers["X-Astra-Agent-Id"] || headers["X-ASTRA-AGENT-ID"];
|
|
106
128
|
if (astraIdHeader) {
|
|
107
|
-
|
|
129
|
+
const raw = Array.isArray(astraIdHeader) ? astraIdHeader[0] : typeof astraIdHeader === "string" ? astraIdHeader : void 0;
|
|
130
|
+
if (typeof raw === "string" && ASTRA_ID_PATTERN.test(raw)) {
|
|
131
|
+
credentials.astraId = raw;
|
|
132
|
+
}
|
|
108
133
|
}
|
|
109
134
|
const apiKeyHeader = headers["x-api-key"] || headers["X-Api-Key"] || headers["X-API-KEY"];
|
|
110
135
|
if (apiKeyHeader) {
|
|
@@ -113,9 +138,11 @@ function extractCredentials(headers, query) {
|
|
|
113
138
|
const authHeader = headers["authorization"] || headers["Authorization"];
|
|
114
139
|
if (authHeader) {
|
|
115
140
|
const authValue = Array.isArray(authHeader) ? authHeader[0] : authHeader;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
141
|
+
if (typeof authValue === "string") {
|
|
142
|
+
credentials.authorizationHeader = authValue;
|
|
143
|
+
if (authValue.startsWith("Bearer ")) {
|
|
144
|
+
credentials.jwt = authValue.slice(7);
|
|
145
|
+
}
|
|
119
146
|
}
|
|
120
147
|
}
|
|
121
148
|
if (query) {
|
|
@@ -133,7 +160,7 @@ function createGuidanceResponse(config, reason, options = {}) {
|
|
|
133
160
|
const isApiError = source === "api_error";
|
|
134
161
|
const guidance = isApiError ? {
|
|
135
162
|
message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
|
|
136
|
-
registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
|
|
163
|
+
registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/agents/register`,
|
|
137
164
|
documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
|
|
138
165
|
steps: [
|
|
139
166
|
"Retry the request with exponential backoff",
|
|
@@ -141,7 +168,7 @@ function createGuidanceResponse(config, reason, options = {}) {
|
|
|
141
168
|
]
|
|
142
169
|
} : {
|
|
143
170
|
message: "This service verifies AI agents before granting access. Please register your agent with AstraSync.",
|
|
144
|
-
registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
|
|
171
|
+
registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/agents/register`,
|
|
145
172
|
documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
|
|
146
173
|
steps: [
|
|
147
174
|
"Register for an AstraSync account",
|
|
@@ -218,12 +245,8 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
218
245
|
"Content-Type": "application/json",
|
|
219
246
|
...config.customHeaders
|
|
220
247
|
};
|
|
221
|
-
if (credentials.authorizationHeader) {
|
|
222
|
-
headers["Authorization"] = credentials.authorizationHeader;
|
|
223
|
-
} else if (config.apiKey) {
|
|
224
|
-
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
225
|
-
}
|
|
226
248
|
if (config.apiKey) {
|
|
249
|
+
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
227
250
|
headers["X-API-Key"] = config.apiKey;
|
|
228
251
|
}
|
|
229
252
|
try {
|
|
@@ -269,7 +292,11 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
269
292
|
async function verify(config, request) {
|
|
270
293
|
const mergedConfig = { ...DEFAULT_CONFIG, ...config };
|
|
271
294
|
if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
|
|
272
|
-
|
|
295
|
+
if (mergedConfig.strictInit) {
|
|
296
|
+
await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
|
|
297
|
+
} else {
|
|
298
|
+
void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
|
|
299
|
+
}
|
|
273
300
|
}
|
|
274
301
|
if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
|
|
275
302
|
deprecationWarningShown = true;
|
|
@@ -323,7 +350,7 @@ async function verify(config, request) {
|
|
|
323
350
|
requiresApproval: apiResponse.access?.requiresApproval,
|
|
324
351
|
guidance: {
|
|
325
352
|
message: apiResponse.access?.reason || "Access denied by PDLSS policy",
|
|
326
|
-
registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/register`,
|
|
353
|
+
registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/agents/register`,
|
|
327
354
|
documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
|
|
328
355
|
},
|
|
329
356
|
verifiedAt: /* @__PURE__ */ new Date(),
|
|
@@ -393,13 +420,15 @@ async function verify(config, request) {
|
|
|
393
420
|
result.denialReasons = result.recommendationReasons || [
|
|
394
421
|
"Access denied by AstraSync recommendation"
|
|
395
422
|
];
|
|
396
|
-
|
|
397
|
-
result.
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
423
|
+
result.guidance = result.runtimeChallenge ? {
|
|
424
|
+
message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
|
|
425
|
+
registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/agents/register`,
|
|
426
|
+
documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/runtime-challenge`
|
|
427
|
+
} : {
|
|
428
|
+
message: result.recommendationReasons?.[0] || "Access denied by AstraSync recommendation",
|
|
429
|
+
registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/agents/register`,
|
|
430
|
+
documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
|
|
431
|
+
};
|
|
403
432
|
} else if (result.recommendation === "step_up_required") {
|
|
404
433
|
result.requiresStepUp = true;
|
|
405
434
|
if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
|
|
@@ -557,7 +586,7 @@ function mcpToPdlss(parsed, headerPurpose, headerAction) {
|
|
|
557
586
|
action = parsed.actionFromBody;
|
|
558
587
|
actionSource = parsed.actionSourceFromBody;
|
|
559
588
|
} else {
|
|
560
|
-
action = parsed.toolName ? `${parsed.method}:${parsed.toolName}` : parsed.method;
|
|
589
|
+
action = parsed.toolName ? parsed.method === "tools/call" ? parsed.toolName : `${parsed.method}:${parsed.toolName}` : parsed.method;
|
|
561
590
|
actionSource = "transport_layer";
|
|
562
591
|
}
|
|
563
592
|
return { purpose, action, resource, purposeSource, actionSource };
|
|
@@ -576,6 +605,17 @@ function readSingleHeader(value) {
|
|
|
576
605
|
if (Array.isArray(value)) return value[0];
|
|
577
606
|
return void 0;
|
|
578
607
|
}
|
|
608
|
+
function dedupeFailures(result) {
|
|
609
|
+
if (result.failures && result.failures.length > 1) {
|
|
610
|
+
const seen = /* @__PURE__ */ new Set();
|
|
611
|
+
result.failures = result.failures.filter((f) => {
|
|
612
|
+
const key = `${f.dimension}|${f.message}|${f.guidance ?? ""}`;
|
|
613
|
+
if (seen.has(key)) return false;
|
|
614
|
+
seen.add(key);
|
|
615
|
+
return true;
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
}
|
|
579
619
|
function defaultMcpDenied(result, req, res) {
|
|
580
620
|
const id = req.body?.id ?? null;
|
|
581
621
|
const status = !result.identityVerified ? 401 : 403;
|
|
@@ -615,10 +655,11 @@ function createMcpMiddleware(options) {
|
|
|
615
655
|
onAgentIdMismatch = "reject",
|
|
616
656
|
skip = false,
|
|
617
657
|
onDenied = defaultMcpDenied,
|
|
618
|
-
trustVerifiedHop =
|
|
658
|
+
trustVerifiedHop = false,
|
|
619
659
|
verifiedHopMaxAgeMs,
|
|
620
660
|
recordDecisions,
|
|
621
661
|
enableRuntimeChallenge = true,
|
|
662
|
+
failOnError = "open",
|
|
622
663
|
...config
|
|
623
664
|
} = options;
|
|
624
665
|
return async (req, res, next) => {
|
|
@@ -726,6 +767,7 @@ function createMcpMiddleware(options) {
|
|
|
726
767
|
recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
|
|
727
768
|
});
|
|
728
769
|
}
|
|
770
|
+
dedupeFailures(result);
|
|
729
771
|
onDenied(result, req, res);
|
|
730
772
|
return;
|
|
731
773
|
}
|
|
@@ -771,6 +813,7 @@ function createMcpMiddleware(options) {
|
|
|
771
813
|
});
|
|
772
814
|
}
|
|
773
815
|
}
|
|
816
|
+
dedupeFailures(result);
|
|
774
817
|
onDenied(result, req, res);
|
|
775
818
|
return;
|
|
776
819
|
}
|
|
@@ -794,7 +837,30 @@ function createMcpMiddleware(options) {
|
|
|
794
837
|
}
|
|
795
838
|
next();
|
|
796
839
|
} catch (error) {
|
|
840
|
+
const errorClass = error instanceof Error ? error.constructor.name : typeof error;
|
|
841
|
+
const correlationId = req.headers["x-request-id"] || req.headers["x-correlation-id"] || `gen-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
797
842
|
console.error("[VerificationGateway/MCP] Middleware error:", error);
|
|
843
|
+
console.warn(
|
|
844
|
+
`[SHADOW] would-have-denied: errorClass=${errorClass} route=${req.method}:${req.path} merchantId=${config.counterpartyId ?? "unknown"} correlationId=${correlationId}`
|
|
845
|
+
);
|
|
846
|
+
if (failOnError === "closed") {
|
|
847
|
+
const result = {
|
|
848
|
+
identityVerified: false,
|
|
849
|
+
policyAllowed: false,
|
|
850
|
+
accessLevel: "none",
|
|
851
|
+
denialReasons: [`MCP middleware internal error: ${errorClass}`],
|
|
852
|
+
failures: [
|
|
853
|
+
{
|
|
854
|
+
dimension: "middleware.internal_error",
|
|
855
|
+
message: `Middleware threw ${errorClass} \u2014 failing closed`
|
|
856
|
+
}
|
|
857
|
+
],
|
|
858
|
+
verifiedAt: /* @__PURE__ */ new Date(),
|
|
859
|
+
correlationId
|
|
860
|
+
};
|
|
861
|
+
dedupeFailures(result);
|
|
862
|
+
return onDenied(result, req, res);
|
|
863
|
+
}
|
|
798
864
|
next();
|
|
799
865
|
}
|
|
800
866
|
};
|