@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.mjs
CHANGED
|
@@ -7,7 +7,7 @@ function getTrustLevel(score) {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
// src/version.ts
|
|
10
|
-
var SDK_VERSION = "3.
|
|
10
|
+
var SDK_VERSION = "3.7.0";
|
|
11
11
|
|
|
12
12
|
// src/well-known.ts
|
|
13
13
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -77,10 +77,10 @@ var DEFAULT_CONFIG = {
|
|
|
77
77
|
// through (`hasMinimumAccess('guidance', 'guidance') === true`).
|
|
78
78
|
defaultAccessLevel: "none",
|
|
79
79
|
// minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
// Set cacheTtl: 0 to disable caching entirely.
|
|
80
|
+
// cacheTtl deliberately unset. When undefined, cacheResult applies the 60s
|
|
81
|
+
// default; the caller's explicit value is honoured for cacheable results.
|
|
82
|
+
// Denials and step-up escalations are NEVER cached (3.6.0) regardless of
|
|
83
|
+
// cacheTtl. Set cacheTtl: 0 to disable caching entirely.
|
|
84
84
|
debug: false
|
|
85
85
|
};
|
|
86
86
|
var initCheckPerformed = false;
|
|
@@ -167,10 +167,9 @@ function getCachedResult(request, counterpartyId) {
|
|
|
167
167
|
}
|
|
168
168
|
return null;
|
|
169
169
|
}
|
|
170
|
-
var
|
|
171
|
-
var DEFAULT_STEP_UP_TTL_SECONDS = 300;
|
|
170
|
+
var DEFAULT_CACHE_TTL_SECONDS = 60;
|
|
172
171
|
function cacheResult(request, result, configuredTtl, counterpartyId) {
|
|
173
|
-
const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl :
|
|
172
|
+
const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : DEFAULT_CACHE_TTL_SECONDS;
|
|
174
173
|
const key = getCacheKey(request, counterpartyId);
|
|
175
174
|
verificationCache.set(key, {
|
|
176
175
|
result,
|
|
@@ -346,7 +345,7 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
346
345
|
};
|
|
347
346
|
}
|
|
348
347
|
}
|
|
349
|
-
async function verify(config, request) {
|
|
348
|
+
async function verify(config, request, options) {
|
|
350
349
|
const mergedConfig = { ...DEFAULT_CONFIG, ...config };
|
|
351
350
|
const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
|
|
352
351
|
if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
|
|
@@ -362,7 +361,7 @@ async function verify(config, request) {
|
|
|
362
361
|
"[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."
|
|
363
362
|
);
|
|
364
363
|
}
|
|
365
|
-
if (mergedConfig.cacheTtl !== 0) {
|
|
364
|
+
if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {
|
|
366
365
|
const cached = getCachedResult(request, mergedConfig.counterpartyId);
|
|
367
366
|
if (cached) {
|
|
368
367
|
if (mergedConfig.debug) {
|
|
@@ -382,6 +381,8 @@ async function verify(config, request) {
|
|
|
382
381
|
console.log("[VerificationGateway] Calling verify-access API");
|
|
383
382
|
}
|
|
384
383
|
const apiResponse = await callVerifyAccessAPI(mergedConfig, enrichedRequest);
|
|
384
|
+
const rawServerDenialReasons = apiResponse.denialReasons;
|
|
385
|
+
const serverDenialReasons = Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0 ? rawServerDenialReasons : void 0;
|
|
385
386
|
if (!apiResponse.success) {
|
|
386
387
|
return createGuidanceResponse(mergedConfig, apiResponse.error, {
|
|
387
388
|
source: "api_error",
|
|
@@ -403,7 +404,10 @@ async function verify(config, request) {
|
|
|
403
404
|
// ALSO short-circuit on `!identityVerified || !policyAllowed` before
|
|
404
405
|
// the gate check — belt-and-braces.
|
|
405
406
|
accessLevel: "none",
|
|
406
|
-
|
|
407
|
+
// 3.6.0: the server now emits top-level denialReasons on every deny
|
|
408
|
+
// path — prefer it verbatim; the failure-message reconstruction remains
|
|
409
|
+
// as the fallback for older backends.
|
|
410
|
+
denialReasons: serverDenialReasons ?? (aggregatedFailures && aggregatedFailures.length > 0 ? aggregatedFailures.map((f) => f.message) : apiResponse.access?.reason ? [apiResponse.access.reason] : ["Access denied"]),
|
|
407
411
|
failures: aggregatedFailures,
|
|
408
412
|
requiresStepUp: apiResponse.access?.requiresStepUp,
|
|
409
413
|
requiresApproval: apiResponse.access?.requiresApproval,
|
|
@@ -480,9 +484,7 @@ async function verify(config, request) {
|
|
|
480
484
|
if (result.recommendation === "deny") {
|
|
481
485
|
result.policyAllowed = false;
|
|
482
486
|
result.accessLevel = "none";
|
|
483
|
-
result.denialReasons = result.recommendationReasons
|
|
484
|
-
"Access denied by AstraSync recommendation"
|
|
485
|
-
];
|
|
487
|
+
result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Access denied by AstraSync recommendation"];
|
|
486
488
|
result.guidance = result.runtimeChallenge ? {
|
|
487
489
|
message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
|
|
488
490
|
registrationUrl: urls?.registrationUrl ?? "",
|
|
@@ -494,9 +496,10 @@ async function verify(config, request) {
|
|
|
494
496
|
};
|
|
495
497
|
} else if (result.recommendation === "step_up_required") {
|
|
496
498
|
result.requiresStepUp = true;
|
|
497
|
-
result.denialReasons = result.recommendationReasons
|
|
499
|
+
result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Step-up verification required"];
|
|
498
500
|
}
|
|
499
|
-
|
|
501
|
+
const escalates = result.requiresStepUp === true || result.requiresApproval === true || result.recommendation === "step_up_required";
|
|
502
|
+
if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny" && !escalates) {
|
|
500
503
|
cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
|
|
501
504
|
}
|
|
502
505
|
return result;
|
|
@@ -528,6 +531,64 @@ function annotateApprovalRequired(result) {
|
|
|
528
531
|
result.denialReasons = [APPROVAL_REASON, ...result.denialReasons ?? []];
|
|
529
532
|
}
|
|
530
533
|
|
|
534
|
+
// src/adapters/stepup-poll.ts
|
|
535
|
+
var DEFAULT_POLL_INTERVAL_MS = 3e3;
|
|
536
|
+
var MIN_POLL_INTERVAL_MS = 250;
|
|
537
|
+
var FALLBACK_MAX_WAIT_MS = 5 * 60 * 1e3;
|
|
538
|
+
var EXPIRY_GRACE_MS = 5e3;
|
|
539
|
+
var POLL_REQUEST_TIMEOUT_MS = 1e4;
|
|
540
|
+
function resolvePollUrl(config, pollUrl) {
|
|
541
|
+
if (pollUrl.startsWith("http")) return pollUrl;
|
|
542
|
+
const origin = (config.apiBaseUrl ?? "").replace(/\/api\/?$/, "");
|
|
543
|
+
return origin + pollUrl;
|
|
544
|
+
}
|
|
545
|
+
async function pollStepUpStatus(config, approval) {
|
|
546
|
+
if (!approval.pollUrl) return null;
|
|
547
|
+
try {
|
|
548
|
+
const res = await fetch(resolvePollUrl(config, approval.pollUrl), {
|
|
549
|
+
method: "GET",
|
|
550
|
+
signal: AbortSignal.timeout(POLL_REQUEST_TIMEOUT_MS)
|
|
551
|
+
});
|
|
552
|
+
if (!res.ok) return null;
|
|
553
|
+
const body = await res.json();
|
|
554
|
+
const data = body?.data;
|
|
555
|
+
const status = data && typeof data === "object" ? data.status : body?.status;
|
|
556
|
+
return typeof status === "string" ? status : null;
|
|
557
|
+
} catch {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
function resolveDeadline(config, approval) {
|
|
562
|
+
const now = Date.now();
|
|
563
|
+
const maxWait = config.stepUpMaxWaitMs ?? 0;
|
|
564
|
+
if (maxWait > 0) return now + maxWait;
|
|
565
|
+
if (approval.expiresAt) {
|
|
566
|
+
const expiry = Date.parse(approval.expiresAt);
|
|
567
|
+
if (!Number.isNaN(expiry)) return Math.max(now, expiry) + EXPIRY_GRACE_MS;
|
|
568
|
+
}
|
|
569
|
+
return now + FALLBACK_MAX_WAIT_MS;
|
|
570
|
+
}
|
|
571
|
+
function sleep(ms) {
|
|
572
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
573
|
+
}
|
|
574
|
+
async function awaitStepUpApproval(config, approval) {
|
|
575
|
+
const deadline = resolveDeadline(config, approval);
|
|
576
|
+
const pollInterval = Math.max(
|
|
577
|
+
MIN_POLL_INTERVAL_MS,
|
|
578
|
+
config.stepUpPollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS
|
|
579
|
+
);
|
|
580
|
+
while (Date.now() < deadline) {
|
|
581
|
+
const status = await pollStepUpStatus(config, approval);
|
|
582
|
+
if (status && status !== "pending") {
|
|
583
|
+
return status;
|
|
584
|
+
}
|
|
585
|
+
const remaining = deadline - Date.now();
|
|
586
|
+
if (remaining <= 0) break;
|
|
587
|
+
await sleep(Math.min(pollInterval, remaining));
|
|
588
|
+
}
|
|
589
|
+
return "timeout";
|
|
590
|
+
}
|
|
591
|
+
|
|
531
592
|
// src/transport/mcp-server.ts
|
|
532
593
|
var MCP_VERIFIED_HOP_HEADER = "X-Astra-Verified-Hop";
|
|
533
594
|
var MCP_VERIFIED_HOP_MAX_AGE_MS = 6e4;
|
|
@@ -691,7 +752,10 @@ function defaultMcpDenied(result, req, res) {
|
|
|
691
752
|
// Round-10: aggregated per-dimension detail + correlation handle.
|
|
692
753
|
failures: result.failures,
|
|
693
754
|
correlationId: result.correlationId,
|
|
694
|
-
stepUpApproval: result.stepUpApproval
|
|
755
|
+
stepUpApproval: result.stepUpApproval,
|
|
756
|
+
// 3.6.0: terminal outcome of an opt-in hold-and-poll wait (denied /
|
|
757
|
+
// expired / consumed / timeout). Absent when the feature is off.
|
|
758
|
+
...result.stepUpOutcome && { stepUpOutcome: result.stepUpOutcome }
|
|
695
759
|
}
|
|
696
760
|
}
|
|
697
761
|
});
|
|
@@ -832,7 +896,7 @@ function createMcpMiddleware(options) {
|
|
|
832
896
|
}
|
|
833
897
|
const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get("host")}${req.path}`;
|
|
834
898
|
const shouldRecordDecisions = recordDecisions !== false;
|
|
835
|
-
const
|
|
899
|
+
const verificationRequest = {
|
|
836
900
|
credentials,
|
|
837
901
|
purpose: pdlss.purpose,
|
|
838
902
|
action: pdlss.action,
|
|
@@ -850,9 +914,21 @@ function createMcpMiddleware(options) {
|
|
|
850
914
|
userAgent: req.headers["user-agent"],
|
|
851
915
|
host: req.headers.host
|
|
852
916
|
}
|
|
853
|
-
}
|
|
917
|
+
};
|
|
918
|
+
let result = await verify(config, verificationRequest);
|
|
854
919
|
req.agentVerification = result;
|
|
855
|
-
|
|
920
|
+
let sessionId = result.sessionId;
|
|
921
|
+
if (config.stepUpMaxWaitMs !== void 0 && result.identityVerified && requiresHumanApproval(result) && result.stepUpApproval?.pollUrl) {
|
|
922
|
+
const outcome = await awaitStepUpApproval(config, result.stepUpApproval);
|
|
923
|
+
res.setHeader("X-Astra-Step-Up", outcome);
|
|
924
|
+
if (outcome === "approved") {
|
|
925
|
+
result = await verify(config, verificationRequest, { bypassCache: true });
|
|
926
|
+
req.agentVerification = result;
|
|
927
|
+
sessionId = result.sessionId;
|
|
928
|
+
} else {
|
|
929
|
+
result.stepUpOutcome = outcome;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
856
932
|
if (!result.identityVerified || !result.policyAllowed) {
|
|
857
933
|
if (shouldRecordDecisions && sessionId) {
|
|
858
934
|
recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
|