@astrasyncai/verification-gateway 2.4.4 → 2.4.5
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/README.md +82 -0
- 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 +4 -0
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +4 -0
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +54 -18
- package/dist/adapters/mcp.d.ts +54 -18
- package/dist/adapters/mcp.js +76 -23
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +76 -23
- 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 +4 -0
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +4 -0
- 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 +4 -0
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +4 -0
- 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 +4 -0
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +4 -0
- 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 +4 -0
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +4 -0
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/{express-Ck2RHZLT.d.mts → express-D5hAJ2Gv.d.mts} +1 -1
- package/dist/{express-DZmEzCgo.d.ts → express-XCkk7BsJ.d.ts} +1 -1
- package/dist/gateway/gateway.d.mts +2 -2
- package/dist/gateway/gateway.d.ts +2 -2
- package/dist/gateway/gateway.js +4 -0
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +4 -0
- 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-6Jus6yWU.d.ts → index-Bstl43HI.d.ts} +1 -1
- package/dist/{index-BgKghi19.d.ts → index-CH4TfcbL.d.ts} +1 -1
- package/dist/{index-D698fDOk.d.mts → index-TS4SGvf4.d.mts} +1 -1
- package/dist/{index-BZZTOfrI.d.mts → index-u08qcXq9.d.mts} +1 -1
- package/dist/index.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -0
- 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-93PHcE-i.d.mts → nextjs-CFA0J_4x.d.mts} +1 -1
- package/dist/{nextjs-t_ix2zQZ.d.ts → nextjs-DP2EpI-4.d.ts} +1 -1
- package/dist/{sdk-BFwzjYjl.d.mts → sdk-C8W54WZS.d.mts} +1 -1
- package/dist/{sdk-Chq02d82.d.ts → sdk-CwwCGDzK.d.ts} +1 -1
- package/dist/transport/index.d.mts +2 -2
- package/dist/transport/index.d.ts +2 -2
- package/dist/{types-CVT-sorC.d.mts → types-CbZOkIr-.d.mts} +21 -15
- package/dist/{types-CVT-sorC.d.ts → types-CbZOkIr-.d.ts} +21 -15
- package/dist/{types-CLP_TDu5.d.ts → types-DXNkr61h.d.ts} +1 -1
- package/dist/{types-y13mmzbA.d.mts → types-tBNFSbw_.d.mts} +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.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request, Response, RequestHandler } from 'express';
|
|
2
|
-
import { a as AccessLevel, G as GatewayConfig, V as VerificationResult } from '../types-
|
|
2
|
+
import { a as AccessLevel, G as GatewayConfig, V as VerificationResult } from '../types-CbZOkIr-.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* MCP server-side helpers — companion to `transport/mcp.ts` (which handles the
|
|
@@ -80,12 +80,27 @@ interface ParsedMcpRequest {
|
|
|
80
80
|
*/
|
|
81
81
|
agentIdFromBody?: string;
|
|
82
82
|
/**
|
|
83
|
-
* Round-12 (F19): purpose from
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
83
|
+
* Round-12 (F19) + round-13 (R13-1): purpose extracted from the MCP body
|
|
84
|
+
* with the symmetric precedence chain. Sourced from `_meta.astrasync.purpose`
|
|
85
|
+
* (canonical SDK location) OR `params.arguments.purpose` (legacy /
|
|
86
|
+
* conventional callers). The discriminator is on `purposeSourceFromBody`.
|
|
87
|
+
* Adapter combines this with the `X-Astra-Purpose` header (header wins)
|
|
88
|
+
* before mapping; final fallback at `mcpToPdlss` is `'mcp_invoke'`.
|
|
87
89
|
*/
|
|
88
90
|
purposeFromBody?: string;
|
|
91
|
+
/** Which body location resolved `purposeFromBody`. */
|
|
92
|
+
purposeSourceFromBody?: 'meta' | 'tool_argument';
|
|
93
|
+
/**
|
|
94
|
+
* Round-13 (R13-2): action extracted from the MCP body with the same
|
|
95
|
+
* symmetric chain as purpose. Sourced from `_meta.astrasync.action`
|
|
96
|
+
* (canonical) OR `params.arguments.action` (legacy). Adapter combines
|
|
97
|
+
* with the `X-Astra-Action` header (header wins) before mapping; final
|
|
98
|
+
* fallback at `mcpToPdlss` is the transport-layer default
|
|
99
|
+
* (`tools/call:<toolname>` or just `<method>`).
|
|
100
|
+
*/
|
|
101
|
+
actionFromBody?: string;
|
|
102
|
+
/** Which body location resolved `actionFromBody`. */
|
|
103
|
+
actionSourceFromBody?: 'meta' | 'tool_argument';
|
|
89
104
|
/** True for handshake methods that must succeed before any tool call. */
|
|
90
105
|
isInitialize: boolean;
|
|
91
106
|
/** True for `tools/call`. */
|
|
@@ -121,23 +136,44 @@ interface McpPdlssMapping {
|
|
|
121
136
|
action: string;
|
|
122
137
|
resource: string;
|
|
123
138
|
/**
|
|
124
|
-
* Round-
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
139
|
+
* Round-13 (R13-1 / R13-2): the resolution channel for purpose and
|
|
140
|
+
* action — disjoint enums sharing the same structure per
|
|
141
|
+
* `feedback_symmetric_fallbacks_for_symmetric_concepts.md`. Adapters
|
|
142
|
+
* log both at debug level so partners can confirm header / body
|
|
143
|
+
* pass-through, support can triage tickets, and we can watch the
|
|
144
|
+
* `default_*` / `transport_layer` decay over time as integrations
|
|
145
|
+
* mature.
|
|
146
|
+
*
|
|
147
|
+
* Round-12 (F19) used a narrower `purposeSource: 'header' |
|
|
148
|
+
* 'tool_argument' | 'default_mcp_invoke'` — round-13 widens to also
|
|
149
|
+
* carry the `_meta` source distinct from `tool_argument`, so the round-13
|
|
150
|
+
* R13-1 fallback (which now reads both `_meta.astrasync.purpose` AND
|
|
151
|
+
* `params.arguments.purpose`) can report WHICH body location resolved.
|
|
128
152
|
*/
|
|
129
|
-
purposeSource: 'header' | 'tool_argument' | 'default_mcp_invoke';
|
|
153
|
+
purposeSource: 'header' | 'meta' | 'tool_argument' | 'default_mcp_invoke';
|
|
154
|
+
actionSource: 'header' | 'meta' | 'tool_argument' | 'transport_layer';
|
|
130
155
|
}
|
|
131
156
|
/**
|
|
132
|
-
* Round-
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
157
|
+
* Round-13 (R13-1 + R13-2) — canonical precedence chain documented ONCE,
|
|
158
|
+
* applied identically to both purpose and action. Per
|
|
159
|
+
* `feedback_symmetric_fallbacks_for_symmetric_concepts.md` — drift
|
|
160
|
+
* between two paired concepts generates the same support-ticket class
|
|
161
|
+
* repeatedly, so the resolution order is:
|
|
162
|
+
*
|
|
163
|
+
* 1. `X-Astra-<concept>` HTTP header (caller's explicit override)
|
|
164
|
+
* 2. `params._meta.astrasync.<concept>` body field (canonical SDK location)
|
|
165
|
+
* 3. `params.arguments.<concept>` body field (legacy / conventional)
|
|
166
|
+
* 4. Transport-layer default:
|
|
167
|
+
* purpose → 'mcp_invoke'
|
|
168
|
+
* action → '<method>:<toolName>' (or just '<method>')
|
|
169
|
+
*
|
|
170
|
+
* The header tier is the adapter's job (it has `req.headers` access);
|
|
171
|
+
* this function takes the resolved `headerPurpose` / `headerAction`
|
|
172
|
+
* inputs and combines them with the body extraction already done in
|
|
173
|
+
* `parseMcpJsonRpc`. The discriminator is reported on `purposeSource` /
|
|
174
|
+
* `actionSource` for debug logging.
|
|
139
175
|
*/
|
|
140
|
-
declare function mcpToPdlss(parsed: ParsedMcpRequest, headerPurpose?: string,
|
|
176
|
+
declare function mcpToPdlss(parsed: ParsedMcpRequest, headerPurpose?: string, headerAction?: string): McpPdlssMapping;
|
|
141
177
|
/**
|
|
142
178
|
* Recommended minimum access level per method type. The MCP middleware uses
|
|
143
179
|
* this to split low-risk handshake / introspection traffic from high-risk
|
package/dist/adapters/mcp.js
CHANGED
|
@@ -50,6 +50,9 @@ function hasMinimumAccess(actual, required) {
|
|
|
50
50
|
return ACCESS_LEVEL_HIERARCHY[actual] >= ACCESS_LEVEL_HIERARCHY[required];
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
// src/version.ts
|
|
54
|
+
var SDK_VERSION = "2.4.5";
|
|
55
|
+
|
|
53
56
|
// src/verify.ts
|
|
54
57
|
var DEFAULT_CONFIG = {
|
|
55
58
|
apiBaseUrl: "https://astrasync.ai/api",
|
|
@@ -208,6 +211,7 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
208
211
|
if (requestData.runtimeChallengeOptions)
|
|
209
212
|
body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
|
|
210
213
|
if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;
|
|
214
|
+
body.sdkVersion = SDK_VERSION;
|
|
211
215
|
if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
|
|
212
216
|
const meta = {
|
|
213
217
|
...requestData.clientIp && { sourceIp: requestData.clientIp },
|
|
@@ -491,16 +495,17 @@ function parseMcpJsonRpc(body) {
|
|
|
491
495
|
if (method === "initialize" && params && typeof params.protocolVersion === "string") {
|
|
492
496
|
protocolVersion = params.protocolVersion;
|
|
493
497
|
}
|
|
494
|
-
let agentIdFromBody;
|
|
495
498
|
const meta = params?._meta;
|
|
496
499
|
const astrasyncMeta = meta?.astrasync;
|
|
500
|
+
const args = params?.arguments;
|
|
501
|
+
let agentIdFromBody;
|
|
497
502
|
if (astrasyncMeta && typeof astrasyncMeta.agentId === "string") {
|
|
498
503
|
agentIdFromBody = astrasyncMeta.agentId;
|
|
499
|
-
} else {
|
|
500
|
-
|
|
501
|
-
if (args && typeof args.agent_id === "string") agentIdFromBody = args.agent_id;
|
|
504
|
+
} else if (args && typeof args.agent_id === "string") {
|
|
505
|
+
agentIdFromBody = args.agent_id;
|
|
502
506
|
}
|
|
503
|
-
const
|
|
507
|
+
const purposeBodyResult = extractFromMcpBody(astrasyncMeta, args, "purpose");
|
|
508
|
+
const actionBodyResult = extractFromMcpBody(astrasyncMeta, args, "action");
|
|
504
509
|
const isInitialize = method === "initialize";
|
|
505
510
|
const isToolCall = method === "tools/call";
|
|
506
511
|
const isIntrospection = method === "tools/list" || method === "prompts/list" || method === "resources/list" || method === "ping" || method === "notifications/initialized";
|
|
@@ -509,22 +514,51 @@ function parseMcpJsonRpc(body) {
|
|
|
509
514
|
...toolName ? { toolName } : {},
|
|
510
515
|
...protocolVersion ? { protocolVersion } : {},
|
|
511
516
|
...agentIdFromBody ? { agentIdFromBody } : {},
|
|
512
|
-
...
|
|
517
|
+
...purposeBodyResult.value ? { purposeFromBody: purposeBodyResult.value } : {},
|
|
518
|
+
...purposeBodyResult.source ? { purposeSourceFromBody: purposeBodyResult.source } : {},
|
|
519
|
+
...actionBodyResult.value ? { actionFromBody: actionBodyResult.value } : {},
|
|
520
|
+
...actionBodyResult.source ? { actionSourceFromBody: actionBodyResult.source } : {},
|
|
513
521
|
isInitialize,
|
|
514
522
|
isToolCall,
|
|
515
523
|
isIntrospection
|
|
516
524
|
};
|
|
517
525
|
}
|
|
518
|
-
function
|
|
519
|
-
|
|
526
|
+
function extractFromMcpBody(astrasyncMeta, args, key) {
|
|
527
|
+
if (astrasyncMeta && typeof astrasyncMeta[key] === "string") {
|
|
528
|
+
return { value: astrasyncMeta[key], source: "meta" };
|
|
529
|
+
}
|
|
530
|
+
if (args && typeof args[key] === "string") {
|
|
531
|
+
return { value: args[key], source: "tool_argument" };
|
|
532
|
+
}
|
|
533
|
+
return { value: void 0, source: void 0 };
|
|
534
|
+
}
|
|
535
|
+
function mcpToPdlss(parsed, headerPurpose, headerAction) {
|
|
520
536
|
const resource = parsed.toolName ? `mcp:tool/${parsed.toolName}` : `mcp:method/${parsed.method}`;
|
|
537
|
+
let purpose;
|
|
538
|
+
let purposeSource;
|
|
521
539
|
if (headerPurpose) {
|
|
522
|
-
|
|
540
|
+
purpose = headerPurpose;
|
|
541
|
+
purposeSource = "header";
|
|
542
|
+
} else if (parsed.purposeFromBody && parsed.purposeSourceFromBody) {
|
|
543
|
+
purpose = parsed.purposeFromBody;
|
|
544
|
+
purposeSource = parsed.purposeSourceFromBody;
|
|
545
|
+
} else {
|
|
546
|
+
purpose = "mcp_invoke";
|
|
547
|
+
purposeSource = "default_mcp_invoke";
|
|
523
548
|
}
|
|
524
|
-
|
|
525
|
-
|
|
549
|
+
let action;
|
|
550
|
+
let actionSource;
|
|
551
|
+
if (headerAction) {
|
|
552
|
+
action = headerAction;
|
|
553
|
+
actionSource = "header";
|
|
554
|
+
} else if (parsed.actionFromBody && parsed.actionSourceFromBody) {
|
|
555
|
+
action = parsed.actionFromBody;
|
|
556
|
+
actionSource = parsed.actionSourceFromBody;
|
|
557
|
+
} else {
|
|
558
|
+
action = parsed.toolName ? `${parsed.method}:${parsed.toolName}` : parsed.method;
|
|
559
|
+
actionSource = "transport_layer";
|
|
526
560
|
}
|
|
527
|
-
return { purpose
|
|
561
|
+
return { purpose, action, resource, purposeSource, actionSource };
|
|
528
562
|
}
|
|
529
563
|
function mcpRiskTier(parsed) {
|
|
530
564
|
if (parsed.isInitialize || parsed.method === "notifications/initialized") return "none";
|
|
@@ -535,6 +569,11 @@ function mcpRiskTier(parsed) {
|
|
|
535
569
|
}
|
|
536
570
|
|
|
537
571
|
// src/adapters/mcp.ts
|
|
572
|
+
function readSingleHeader(value) {
|
|
573
|
+
if (typeof value === "string") return value;
|
|
574
|
+
if (Array.isArray(value)) return value[0];
|
|
575
|
+
return void 0;
|
|
576
|
+
}
|
|
538
577
|
function defaultMcpDenied(result, req, res) {
|
|
539
578
|
const id = req.body?.id ?? null;
|
|
540
579
|
const status = result.verified ? 403 : 401;
|
|
@@ -629,25 +668,28 @@ function createMcpMiddleware(options) {
|
|
|
629
668
|
toolGates,
|
|
630
669
|
methodGates
|
|
631
670
|
});
|
|
632
|
-
|
|
671
|
+
const credentials = extractCredentials(
|
|
672
|
+
req.headers,
|
|
673
|
+
req.query
|
|
674
|
+
);
|
|
675
|
+
if (effectiveAstraId) credentials.astraId = effectiveAstraId;
|
|
676
|
+
const shouldEnforce = minAccessLevel !== "none";
|
|
677
|
+
if (minAccessLevel === "none" && (!config.evaluateAlwaysIfCredentialed || !credentials.astraId)) {
|
|
633
678
|
if (config.setPassThroughHeader) {
|
|
634
679
|
res.setHeader("X-Astra-Gateway-Mode", "unenforced");
|
|
635
680
|
res.setHeader("X-Astra-Gateway-Reason", "mcp-tier-none");
|
|
636
681
|
}
|
|
637
682
|
return next();
|
|
638
683
|
}
|
|
639
|
-
const
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
);
|
|
643
|
-
if (effectiveAstraId) credentials.astraId = effectiveAstraId;
|
|
644
|
-
const headerPurposeRaw = req.headers["x-astra-purpose"];
|
|
645
|
-
const headerPurpose = typeof headerPurposeRaw === "string" ? headerPurposeRaw : Array.isArray(headerPurposeRaw) ? headerPurposeRaw[0] : void 0;
|
|
646
|
-
const pdlss = mcpToPdlss(parsed, headerPurpose, parsed.purposeFromBody);
|
|
684
|
+
const headerPurpose = readSingleHeader(req.headers["x-astra-purpose"]);
|
|
685
|
+
const headerAction = readSingleHeader(req.headers["x-astra-action"]);
|
|
686
|
+
const pdlss = mcpToPdlss(parsed, headerPurpose, headerAction);
|
|
647
687
|
if (config.debug) {
|
|
648
|
-
console.debug("[mcp-middleware]
|
|
688
|
+
console.debug("[mcp-middleware] pdlss resolved", {
|
|
649
689
|
purpose_source: pdlss.purposeSource,
|
|
650
|
-
resolved_purpose: pdlss.purpose
|
|
690
|
+
resolved_purpose: pdlss.purpose,
|
|
691
|
+
action_source: pdlss.actionSource,
|
|
692
|
+
resolved_action: pdlss.action
|
|
651
693
|
});
|
|
652
694
|
}
|
|
653
695
|
const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get("host")}${req.path}`;
|
|
@@ -682,6 +724,17 @@ function createMcpMiddleware(options) {
|
|
|
682
724
|
onDenied(result, req, res);
|
|
683
725
|
return;
|
|
684
726
|
}
|
|
727
|
+
if (!shouldEnforce) {
|
|
728
|
+
if (config.setPassThroughHeader) {
|
|
729
|
+
res.setHeader("X-Astra-Gateway-Mode", "enforced");
|
|
730
|
+
res.setHeader("X-Astra-Gateway-Reason", "evaluated-not-enforced");
|
|
731
|
+
}
|
|
732
|
+
if (shouldRecordDecisions && sessionId) {
|
|
733
|
+
recordDecision(config, sessionId, "granted").catch(() => {
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
return next();
|
|
737
|
+
}
|
|
685
738
|
if (!hasMinimumAccess(result.accessLevel, minAccessLevel)) {
|
|
686
739
|
const insufficientFailure = {
|
|
687
740
|
dimension: "access_level.insufficient",
|