@astrasyncai/verification-gateway 3.5.0 → 3.7.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/README.md +16 -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 +96 -20
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +96 -20
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.d.ts +1 -1
- package/dist/adapters/mcp.js +96 -20
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +96 -20
- 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 +101 -20
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +101 -20
- 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 +19 -16
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +19 -16
- 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/bin/astrasync-claude-hook.js +4791 -0
- package/dist/bin/astrasync-guard.js +5990 -0
- package/dist/bin/astrasync.js +6840 -330
- package/dist/browser/background.js +22 -16
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +22 -16
- 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/claude-code/claude-code-adapter.d.mts +96 -0
- package/dist/claude-code/claude-code-adapter.d.ts +96 -0
- package/dist/claude-code/claude-code-adapter.js +277 -0
- package/dist/claude-code/claude-code-adapter.js.map +1 -0
- package/dist/claude-code/claude-code-adapter.mjs +249 -0
- package/dist/claude-code/claude-code-adapter.mjs.map +1 -0
- 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 +22 -16
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +22 -16
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/{express-BH5ADAyb.d.mts → express-BnMO-H3y.d.mts} +1 -1
- package/dist/{express-jUzLIoep.d.ts → express-DQhDzNAt.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 +22 -16
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +22 -16
- 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-aZHAWujT.d.mts → index-BT_aRn-I.d.mts} +1 -1
- package/dist/{index-DlCnmpJH.d.ts → index-D8-dvUFA.d.ts} +1 -1
- package/dist/{index-BR2nmxBU.d.mts → index-WHKq2v17.d.mts} +1 -1
- package/dist/{index-DEixUCu0.d.ts → index-rftma0ln.d.ts} +1 -1
- package/dist/index.d.mts +55 -9
- package/dist/index.d.ts +55 -9
- package/dist/index.js +145 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +143 -30
- 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-LTeoPqMH.d.mts → nextjs-DFKYhxe6.d.mts} +1 -1
- package/dist/{nextjs-DfXOd0Au.d.ts → nextjs-DPj7ZNlq.d.ts} +1 -1
- package/dist/{sdk-LmvyDVpL.d.ts → sdk-CAcHgB5x.d.ts} +1 -1
- package/dist/{sdk-DKhwVL9X.d.mts → sdk-Cy3wAmDt.d.mts} +1 -1
- package/dist/transport/index.d.mts +2 -2
- package/dist/transport/index.d.ts +2 -2
- package/dist/{types-C8HyQEaz.d.mts → types-B-ubjHER.d.mts} +1 -1
- package/dist/{types-xofemo0G.d.ts → types-Bgn5gxHQ.d.ts} +1 -1
- package/dist/{types-DrDIouvO.d.mts → types-CKe8O0lR.d.mts} +41 -1
- package/dist/{types-DrDIouvO.d.ts → types-CKe8O0lR.d.ts} +41 -1
- package/dist/ui/index.d.mts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/package.json +9 -2
package/dist/adapters/mcp.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request, Response, RequestHandler } from 'express';
|
|
2
|
-
import { a as AccessLevel, G as GatewayConfig,
|
|
2
|
+
import { a as AccessLevel, G as GatewayConfig, n as VerificationResult } from '../types-CKe8O0lR.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* MCP server-side helpers — companion to `transport/mcp.ts` (which handles the
|
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,
|
|
2
|
+
import { a as AccessLevel, G as GatewayConfig, n as VerificationResult } from '../types-CKe8O0lR.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* MCP server-side helpers — companion to `transport/mcp.ts` (which handles the
|
package/dist/adapters/mcp.js
CHANGED
|
@@ -40,7 +40,7 @@ function getTrustLevel(score) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
// src/version.ts
|
|
43
|
-
var SDK_VERSION = "3.
|
|
43
|
+
var SDK_VERSION = "3.7.0";
|
|
44
44
|
|
|
45
45
|
// src/well-known.ts
|
|
46
46
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -110,10 +110,10 @@ var DEFAULT_CONFIG = {
|
|
|
110
110
|
// through (`hasMinimumAccess('guidance', 'guidance') === true`).
|
|
111
111
|
defaultAccessLevel: "none",
|
|
112
112
|
// minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
// Set cacheTtl: 0 to disable caching entirely.
|
|
113
|
+
// cacheTtl deliberately unset. When undefined, cacheResult applies the 60s
|
|
114
|
+
// default; the caller's explicit value is honoured for cacheable results.
|
|
115
|
+
// Denials and step-up escalations are NEVER cached (3.6.0) regardless of
|
|
116
|
+
// cacheTtl. Set cacheTtl: 0 to disable caching entirely.
|
|
117
117
|
debug: false
|
|
118
118
|
};
|
|
119
119
|
var initCheckPerformed = false;
|
|
@@ -200,10 +200,9 @@ function getCachedResult(request, counterpartyId) {
|
|
|
200
200
|
}
|
|
201
201
|
return null;
|
|
202
202
|
}
|
|
203
|
-
var
|
|
204
|
-
var DEFAULT_STEP_UP_TTL_SECONDS = 300;
|
|
203
|
+
var DEFAULT_CACHE_TTL_SECONDS = 60;
|
|
205
204
|
function cacheResult(request, result, configuredTtl, counterpartyId) {
|
|
206
|
-
const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl :
|
|
205
|
+
const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : DEFAULT_CACHE_TTL_SECONDS;
|
|
207
206
|
const key = getCacheKey(request, counterpartyId);
|
|
208
207
|
verificationCache.set(key, {
|
|
209
208
|
result,
|
|
@@ -379,7 +378,7 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
379
378
|
};
|
|
380
379
|
}
|
|
381
380
|
}
|
|
382
|
-
async function verify(config, request) {
|
|
381
|
+
async function verify(config, request, options) {
|
|
383
382
|
const mergedConfig = { ...DEFAULT_CONFIG, ...config };
|
|
384
383
|
const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
|
|
385
384
|
if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
|
|
@@ -395,7 +394,7 @@ async function verify(config, request) {
|
|
|
395
394
|
"[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access-level decisions (the SDK reads access.accessLevel from the verify-access response). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side."
|
|
396
395
|
);
|
|
397
396
|
}
|
|
398
|
-
if (mergedConfig.cacheTtl !== 0) {
|
|
397
|
+
if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {
|
|
399
398
|
const cached = getCachedResult(request, mergedConfig.counterpartyId);
|
|
400
399
|
if (cached) {
|
|
401
400
|
if (mergedConfig.debug) {
|
|
@@ -415,6 +414,8 @@ async function verify(config, request) {
|
|
|
415
414
|
console.log("[VerificationGateway] Calling verify-access API");
|
|
416
415
|
}
|
|
417
416
|
const apiResponse = await callVerifyAccessAPI(mergedConfig, enrichedRequest);
|
|
417
|
+
const rawServerDenialReasons = apiResponse.denialReasons;
|
|
418
|
+
const serverDenialReasons = Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0 ? rawServerDenialReasons : void 0;
|
|
418
419
|
if (!apiResponse.success) {
|
|
419
420
|
return createGuidanceResponse(mergedConfig, apiResponse.error, {
|
|
420
421
|
source: "api_error",
|
|
@@ -436,7 +437,10 @@ async function verify(config, request) {
|
|
|
436
437
|
// ALSO short-circuit on `!identityVerified || !policyAllowed` before
|
|
437
438
|
// the gate check — belt-and-braces.
|
|
438
439
|
accessLevel: "none",
|
|
439
|
-
|
|
440
|
+
// 3.6.0: the server now emits top-level denialReasons on every deny
|
|
441
|
+
// path — prefer it verbatim; the failure-message reconstruction remains
|
|
442
|
+
// as the fallback for older backends.
|
|
443
|
+
denialReasons: serverDenialReasons ?? (aggregatedFailures && aggregatedFailures.length > 0 ? aggregatedFailures.map((f) => f.message) : apiResponse.access?.reason ? [apiResponse.access.reason] : ["Access denied"]),
|
|
440
444
|
failures: aggregatedFailures,
|
|
441
445
|
requiresStepUp: apiResponse.access?.requiresStepUp,
|
|
442
446
|
requiresApproval: apiResponse.access?.requiresApproval,
|
|
@@ -513,9 +517,7 @@ async function verify(config, request) {
|
|
|
513
517
|
if (result.recommendation === "deny") {
|
|
514
518
|
result.policyAllowed = false;
|
|
515
519
|
result.accessLevel = "none";
|
|
516
|
-
result.denialReasons = result.recommendationReasons
|
|
517
|
-
"Access denied by AstraSync recommendation"
|
|
518
|
-
];
|
|
520
|
+
result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Access denied by AstraSync recommendation"];
|
|
519
521
|
result.guidance = result.runtimeChallenge ? {
|
|
520
522
|
message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
|
|
521
523
|
registrationUrl: urls?.registrationUrl ?? "",
|
|
@@ -527,9 +529,10 @@ async function verify(config, request) {
|
|
|
527
529
|
};
|
|
528
530
|
} else if (result.recommendation === "step_up_required") {
|
|
529
531
|
result.requiresStepUp = true;
|
|
530
|
-
result.denialReasons = result.recommendationReasons
|
|
532
|
+
result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Step-up verification required"];
|
|
531
533
|
}
|
|
532
|
-
|
|
534
|
+
const escalates = result.requiresStepUp === true || result.requiresApproval === true || result.recommendation === "step_up_required";
|
|
535
|
+
if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny" && !escalates) {
|
|
533
536
|
cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
|
|
534
537
|
}
|
|
535
538
|
return result;
|
|
@@ -561,6 +564,64 @@ function annotateApprovalRequired(result) {
|
|
|
561
564
|
result.denialReasons = [APPROVAL_REASON, ...result.denialReasons ?? []];
|
|
562
565
|
}
|
|
563
566
|
|
|
567
|
+
// src/adapters/stepup-poll.ts
|
|
568
|
+
var DEFAULT_POLL_INTERVAL_MS = 3e3;
|
|
569
|
+
var MIN_POLL_INTERVAL_MS = 250;
|
|
570
|
+
var FALLBACK_MAX_WAIT_MS = 5 * 60 * 1e3;
|
|
571
|
+
var EXPIRY_GRACE_MS = 5e3;
|
|
572
|
+
var POLL_REQUEST_TIMEOUT_MS = 1e4;
|
|
573
|
+
function resolvePollUrl(config, pollUrl) {
|
|
574
|
+
if (pollUrl.startsWith("http")) return pollUrl;
|
|
575
|
+
const origin = (config.apiBaseUrl ?? "").replace(/\/api\/?$/, "");
|
|
576
|
+
return origin + pollUrl;
|
|
577
|
+
}
|
|
578
|
+
async function pollStepUpStatus(config, approval) {
|
|
579
|
+
if (!approval.pollUrl) return null;
|
|
580
|
+
try {
|
|
581
|
+
const res = await fetch(resolvePollUrl(config, approval.pollUrl), {
|
|
582
|
+
method: "GET",
|
|
583
|
+
signal: AbortSignal.timeout(POLL_REQUEST_TIMEOUT_MS)
|
|
584
|
+
});
|
|
585
|
+
if (!res.ok) return null;
|
|
586
|
+
const body = await res.json();
|
|
587
|
+
const data = body?.data;
|
|
588
|
+
const status = data && typeof data === "object" ? data.status : body?.status;
|
|
589
|
+
return typeof status === "string" ? status : null;
|
|
590
|
+
} catch {
|
|
591
|
+
return null;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
function resolveDeadline(config, approval) {
|
|
595
|
+
const now = Date.now();
|
|
596
|
+
const maxWait = config.stepUpMaxWaitMs ?? 0;
|
|
597
|
+
if (maxWait > 0) return now + maxWait;
|
|
598
|
+
if (approval.expiresAt) {
|
|
599
|
+
const expiry = Date.parse(approval.expiresAt);
|
|
600
|
+
if (!Number.isNaN(expiry)) return Math.max(now, expiry) + EXPIRY_GRACE_MS;
|
|
601
|
+
}
|
|
602
|
+
return now + FALLBACK_MAX_WAIT_MS;
|
|
603
|
+
}
|
|
604
|
+
function sleep(ms) {
|
|
605
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
606
|
+
}
|
|
607
|
+
async function awaitStepUpApproval(config, approval) {
|
|
608
|
+
const deadline = resolveDeadline(config, approval);
|
|
609
|
+
const pollInterval = Math.max(
|
|
610
|
+
MIN_POLL_INTERVAL_MS,
|
|
611
|
+
config.stepUpPollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS
|
|
612
|
+
);
|
|
613
|
+
while (Date.now() < deadline) {
|
|
614
|
+
const status = await pollStepUpStatus(config, approval);
|
|
615
|
+
if (status && status !== "pending") {
|
|
616
|
+
return status;
|
|
617
|
+
}
|
|
618
|
+
const remaining = deadline - Date.now();
|
|
619
|
+
if (remaining <= 0) break;
|
|
620
|
+
await sleep(Math.min(pollInterval, remaining));
|
|
621
|
+
}
|
|
622
|
+
return "timeout";
|
|
623
|
+
}
|
|
624
|
+
|
|
564
625
|
// src/transport/mcp-server.ts
|
|
565
626
|
var MCP_VERIFIED_HOP_HEADER = "X-Astra-Verified-Hop";
|
|
566
627
|
var MCP_VERIFIED_HOP_MAX_AGE_MS = 6e4;
|
|
@@ -724,7 +785,10 @@ function defaultMcpDenied(result, req, res) {
|
|
|
724
785
|
// Round-10: aggregated per-dimension detail + correlation handle.
|
|
725
786
|
failures: result.failures,
|
|
726
787
|
correlationId: result.correlationId,
|
|
727
|
-
stepUpApproval: result.stepUpApproval
|
|
788
|
+
stepUpApproval: result.stepUpApproval,
|
|
789
|
+
// 3.6.0: terminal outcome of an opt-in hold-and-poll wait (denied /
|
|
790
|
+
// expired / consumed / timeout). Absent when the feature is off.
|
|
791
|
+
...result.stepUpOutcome && { stepUpOutcome: result.stepUpOutcome }
|
|
728
792
|
}
|
|
729
793
|
}
|
|
730
794
|
});
|
|
@@ -865,7 +929,7 @@ function createMcpMiddleware(options) {
|
|
|
865
929
|
}
|
|
866
930
|
const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get("host")}${req.path}`;
|
|
867
931
|
const shouldRecordDecisions = recordDecisions !== false;
|
|
868
|
-
const
|
|
932
|
+
const verificationRequest = {
|
|
869
933
|
credentials,
|
|
870
934
|
purpose: pdlss.purpose,
|
|
871
935
|
action: pdlss.action,
|
|
@@ -883,9 +947,21 @@ function createMcpMiddleware(options) {
|
|
|
883
947
|
userAgent: req.headers["user-agent"],
|
|
884
948
|
host: req.headers.host
|
|
885
949
|
}
|
|
886
|
-
}
|
|
950
|
+
};
|
|
951
|
+
let result = await verify(config, verificationRequest);
|
|
887
952
|
req.agentVerification = result;
|
|
888
|
-
|
|
953
|
+
let sessionId = result.sessionId;
|
|
954
|
+
if (config.stepUpMaxWaitMs !== void 0 && result.identityVerified && requiresHumanApproval(result) && result.stepUpApproval?.pollUrl) {
|
|
955
|
+
const outcome = await awaitStepUpApproval(config, result.stepUpApproval);
|
|
956
|
+
res.setHeader("X-Astra-Step-Up", outcome);
|
|
957
|
+
if (outcome === "approved") {
|
|
958
|
+
result = await verify(config, verificationRequest, { bypassCache: true });
|
|
959
|
+
req.agentVerification = result;
|
|
960
|
+
sessionId = result.sessionId;
|
|
961
|
+
} else {
|
|
962
|
+
result.stepUpOutcome = outcome;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
889
965
|
if (!result.identityVerified || !result.policyAllowed) {
|
|
890
966
|
if (shouldRecordDecisions && sessionId) {
|
|
891
967
|
recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
|