@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.js
CHANGED
|
@@ -51,7 +51,7 @@ function hasMinimumAccess(actual, required) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// src/version.ts
|
|
54
|
-
var SDK_VERSION = "2.4.
|
|
54
|
+
var SDK_VERSION = "2.4.13";
|
|
55
55
|
|
|
56
56
|
// src/verify.ts
|
|
57
57
|
var DEFAULT_CONFIG = {
|
|
@@ -70,22 +70,27 @@ var DEFAULT_CONFIG = {
|
|
|
70
70
|
};
|
|
71
71
|
var initCheckPerformed = false;
|
|
72
72
|
var deprecationWarningShown = false;
|
|
73
|
-
async function performInitCheck(apiBaseUrl, debug) {
|
|
73
|
+
async function performInitCheck(apiBaseUrl, debug, strictInit) {
|
|
74
74
|
initCheckPerformed = true;
|
|
75
75
|
try {
|
|
76
76
|
const probeUrl = `${apiBaseUrl}/agents/verify-access`;
|
|
77
77
|
const response = await fetch(probeUrl, { method: "HEAD" });
|
|
78
78
|
const contentType = response.headers.get("content-type") ?? "";
|
|
79
79
|
if (contentType.startsWith("text/html")) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
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).`;
|
|
81
|
+
if (strictInit) {
|
|
82
|
+
throw new Error(`${message} (strictInit=true)`);
|
|
83
|
+
}
|
|
84
|
+
console.warn(`${message} Set disableInitChecks: true on GatewayConfig to silence.`);
|
|
83
85
|
} else if (debug) {
|
|
84
86
|
console.log(
|
|
85
87
|
`[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
|
|
86
88
|
);
|
|
87
89
|
}
|
|
88
90
|
} catch (err) {
|
|
91
|
+
if (strictInit) {
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
89
94
|
if (debug) {
|
|
90
95
|
console.log(`[VerificationGateway] init check failed (non-blocking): ${String(err)}`);
|
|
91
96
|
}
|
|
@@ -109,7 +114,23 @@ function getCacheKey(request) {
|
|
|
109
114
|
request.counterpartyType || "",
|
|
110
115
|
request.isSubAgentRequest ? "1" : "0",
|
|
111
116
|
request.parentAgentId || "",
|
|
112
|
-
request.subAgentDepth ?? ""
|
|
117
|
+
request.subAgentDepth ?? "",
|
|
118
|
+
// Audit F-A1-07: previously-missing dimensions that DO affect the
|
|
119
|
+
// backend verdict. Without these, two requests with different
|
|
120
|
+
// durations (e.g. 60s vs 86400s) collided on the same cache key and
|
|
121
|
+
// the shorter-duration allow served the longer-duration request.
|
|
122
|
+
request.durationRequired ?? "",
|
|
123
|
+
request.invocationProtocol || "",
|
|
124
|
+
request.enableRuntimeChallenge ? "1" : "0",
|
|
125
|
+
// callerMetadata fields contribute to risk model; include the ones
|
|
126
|
+
// backend reads. sourceIp/userAgent/forwardedFor change per-request
|
|
127
|
+
// so their inclusion effectively forces a re-check for any varying
|
|
128
|
+
// client (the right behavior — IP-driven anomaly scoring shouldn't
|
|
129
|
+
// be cached across IPs).
|
|
130
|
+
request.callerMetadata?.sourceIp || "",
|
|
131
|
+
request.callerMetadata?.userAgent || "",
|
|
132
|
+
request.callerMetadata?.forwardedFor || "",
|
|
133
|
+
request.callerMetadata?.agentCardUrl || ""
|
|
113
134
|
].join("|");
|
|
114
135
|
}
|
|
115
136
|
function getCachedResult(request) {
|
|
@@ -135,9 +156,13 @@ function cacheResult(request, result, configuredTtl) {
|
|
|
135
156
|
}
|
|
136
157
|
function extractCredentials(headers, query) {
|
|
137
158
|
const credentials = {};
|
|
159
|
+
const ASTRA_ID_PATTERN = /^ASTRAE?-[A-Za-z0-9_-]{1,64}$/;
|
|
138
160
|
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"];
|
|
139
161
|
if (astraIdHeader) {
|
|
140
|
-
|
|
162
|
+
const raw = Array.isArray(astraIdHeader) ? astraIdHeader[0] : typeof astraIdHeader === "string" ? astraIdHeader : void 0;
|
|
163
|
+
if (typeof raw === "string" && ASTRA_ID_PATTERN.test(raw)) {
|
|
164
|
+
credentials.astraId = raw;
|
|
165
|
+
}
|
|
141
166
|
}
|
|
142
167
|
const apiKeyHeader = headers["x-api-key"] || headers["X-Api-Key"] || headers["X-API-KEY"];
|
|
143
168
|
if (apiKeyHeader) {
|
|
@@ -146,9 +171,11 @@ function extractCredentials(headers, query) {
|
|
|
146
171
|
const authHeader = headers["authorization"] || headers["Authorization"];
|
|
147
172
|
if (authHeader) {
|
|
148
173
|
const authValue = Array.isArray(authHeader) ? authHeader[0] : authHeader;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
174
|
+
if (typeof authValue === "string") {
|
|
175
|
+
credentials.authorizationHeader = authValue;
|
|
176
|
+
if (authValue.startsWith("Bearer ")) {
|
|
177
|
+
credentials.jwt = authValue.slice(7);
|
|
178
|
+
}
|
|
152
179
|
}
|
|
153
180
|
}
|
|
154
181
|
if (query) {
|
|
@@ -166,7 +193,7 @@ function createGuidanceResponse(config, reason, options = {}) {
|
|
|
166
193
|
const isApiError = source === "api_error";
|
|
167
194
|
const guidance = isApiError ? {
|
|
168
195
|
message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
|
|
169
|
-
registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
|
|
196
|
+
registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/agents/register`,
|
|
170
197
|
documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
|
|
171
198
|
steps: [
|
|
172
199
|
"Retry the request with exponential backoff",
|
|
@@ -174,7 +201,7 @@ function createGuidanceResponse(config, reason, options = {}) {
|
|
|
174
201
|
]
|
|
175
202
|
} : {
|
|
176
203
|
message: "This service verifies AI agents before granting access. Please register your agent with AstraSync.",
|
|
177
|
-
registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
|
|
204
|
+
registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/agents/register`,
|
|
178
205
|
documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
|
|
179
206
|
steps: [
|
|
180
207
|
"Register for an AstraSync account",
|
|
@@ -251,12 +278,8 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
251
278
|
"Content-Type": "application/json",
|
|
252
279
|
...config.customHeaders
|
|
253
280
|
};
|
|
254
|
-
if (credentials.authorizationHeader) {
|
|
255
|
-
headers["Authorization"] = credentials.authorizationHeader;
|
|
256
|
-
} else if (config.apiKey) {
|
|
257
|
-
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
258
|
-
}
|
|
259
281
|
if (config.apiKey) {
|
|
282
|
+
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
260
283
|
headers["X-API-Key"] = config.apiKey;
|
|
261
284
|
}
|
|
262
285
|
try {
|
|
@@ -302,7 +325,11 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
302
325
|
async function verify(config, request) {
|
|
303
326
|
const mergedConfig = { ...DEFAULT_CONFIG, ...config };
|
|
304
327
|
if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
|
|
305
|
-
|
|
328
|
+
if (mergedConfig.strictInit) {
|
|
329
|
+
await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
|
|
330
|
+
} else {
|
|
331
|
+
void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
|
|
332
|
+
}
|
|
306
333
|
}
|
|
307
334
|
if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
|
|
308
335
|
deprecationWarningShown = true;
|
|
@@ -356,7 +383,7 @@ async function verify(config, request) {
|
|
|
356
383
|
requiresApproval: apiResponse.access?.requiresApproval,
|
|
357
384
|
guidance: {
|
|
358
385
|
message: apiResponse.access?.reason || "Access denied by PDLSS policy",
|
|
359
|
-
registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/register`,
|
|
386
|
+
registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/agents/register`,
|
|
360
387
|
documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
|
|
361
388
|
},
|
|
362
389
|
verifiedAt: /* @__PURE__ */ new Date(),
|
|
@@ -426,13 +453,15 @@ async function verify(config, request) {
|
|
|
426
453
|
result.denialReasons = result.recommendationReasons || [
|
|
427
454
|
"Access denied by AstraSync recommendation"
|
|
428
455
|
];
|
|
429
|
-
|
|
430
|
-
result.
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
456
|
+
result.guidance = result.runtimeChallenge ? {
|
|
457
|
+
message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
|
|
458
|
+
registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/agents/register`,
|
|
459
|
+
documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/runtime-challenge`
|
|
460
|
+
} : {
|
|
461
|
+
message: result.recommendationReasons?.[0] || "Access denied by AstraSync recommendation",
|
|
462
|
+
registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/agents/register`,
|
|
463
|
+
documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
|
|
464
|
+
};
|
|
436
465
|
} else if (result.recommendation === "step_up_required") {
|
|
437
466
|
result.requiresStepUp = true;
|
|
438
467
|
if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
|
|
@@ -590,7 +619,7 @@ function mcpToPdlss(parsed, headerPurpose, headerAction) {
|
|
|
590
619
|
action = parsed.actionFromBody;
|
|
591
620
|
actionSource = parsed.actionSourceFromBody;
|
|
592
621
|
} else {
|
|
593
|
-
action = parsed.toolName ? `${parsed.method}:${parsed.toolName}` : parsed.method;
|
|
622
|
+
action = parsed.toolName ? parsed.method === "tools/call" ? parsed.toolName : `${parsed.method}:${parsed.toolName}` : parsed.method;
|
|
594
623
|
actionSource = "transport_layer";
|
|
595
624
|
}
|
|
596
625
|
return { purpose, action, resource, purposeSource, actionSource };
|
|
@@ -609,6 +638,17 @@ function readSingleHeader(value) {
|
|
|
609
638
|
if (Array.isArray(value)) return value[0];
|
|
610
639
|
return void 0;
|
|
611
640
|
}
|
|
641
|
+
function dedupeFailures(result) {
|
|
642
|
+
if (result.failures && result.failures.length > 1) {
|
|
643
|
+
const seen = /* @__PURE__ */ new Set();
|
|
644
|
+
result.failures = result.failures.filter((f) => {
|
|
645
|
+
const key = `${f.dimension}|${f.message}|${f.guidance ?? ""}`;
|
|
646
|
+
if (seen.has(key)) return false;
|
|
647
|
+
seen.add(key);
|
|
648
|
+
return true;
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
}
|
|
612
652
|
function defaultMcpDenied(result, req, res) {
|
|
613
653
|
const id = req.body?.id ?? null;
|
|
614
654
|
const status = !result.identityVerified ? 401 : 403;
|
|
@@ -648,10 +688,11 @@ function createMcpMiddleware(options) {
|
|
|
648
688
|
onAgentIdMismatch = "reject",
|
|
649
689
|
skip = false,
|
|
650
690
|
onDenied = defaultMcpDenied,
|
|
651
|
-
trustVerifiedHop =
|
|
691
|
+
trustVerifiedHop = false,
|
|
652
692
|
verifiedHopMaxAgeMs,
|
|
653
693
|
recordDecisions,
|
|
654
694
|
enableRuntimeChallenge = true,
|
|
695
|
+
failOnError = "open",
|
|
655
696
|
...config
|
|
656
697
|
} = options;
|
|
657
698
|
return async (req, res, next) => {
|
|
@@ -759,6 +800,7 @@ function createMcpMiddleware(options) {
|
|
|
759
800
|
recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
|
|
760
801
|
});
|
|
761
802
|
}
|
|
803
|
+
dedupeFailures(result);
|
|
762
804
|
onDenied(result, req, res);
|
|
763
805
|
return;
|
|
764
806
|
}
|
|
@@ -804,6 +846,7 @@ function createMcpMiddleware(options) {
|
|
|
804
846
|
});
|
|
805
847
|
}
|
|
806
848
|
}
|
|
849
|
+
dedupeFailures(result);
|
|
807
850
|
onDenied(result, req, res);
|
|
808
851
|
return;
|
|
809
852
|
}
|
|
@@ -827,7 +870,30 @@ function createMcpMiddleware(options) {
|
|
|
827
870
|
}
|
|
828
871
|
next();
|
|
829
872
|
} catch (error) {
|
|
873
|
+
const errorClass = error instanceof Error ? error.constructor.name : typeof error;
|
|
874
|
+
const correlationId = req.headers["x-request-id"] || req.headers["x-correlation-id"] || `gen-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
830
875
|
console.error("[VerificationGateway/MCP] Middleware error:", error);
|
|
876
|
+
console.warn(
|
|
877
|
+
`[SHADOW] would-have-denied: errorClass=${errorClass} route=${req.method}:${req.path} merchantId=${config.counterpartyId ?? "unknown"} correlationId=${correlationId}`
|
|
878
|
+
);
|
|
879
|
+
if (failOnError === "closed") {
|
|
880
|
+
const result = {
|
|
881
|
+
identityVerified: false,
|
|
882
|
+
policyAllowed: false,
|
|
883
|
+
accessLevel: "none",
|
|
884
|
+
denialReasons: [`MCP middleware internal error: ${errorClass}`],
|
|
885
|
+
failures: [
|
|
886
|
+
{
|
|
887
|
+
dimension: "middleware.internal_error",
|
|
888
|
+
message: `Middleware threw ${errorClass} \u2014 failing closed`
|
|
889
|
+
}
|
|
890
|
+
],
|
|
891
|
+
verifiedAt: /* @__PURE__ */ new Date(),
|
|
892
|
+
correlationId
|
|
893
|
+
};
|
|
894
|
+
dedupeFailures(result);
|
|
895
|
+
return onDenied(result, req, res);
|
|
896
|
+
}
|
|
831
897
|
next();
|
|
832
898
|
}
|
|
833
899
|
};
|