@astrasyncai/verification-gateway 4.5.1 → 5.0.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 +1 -1
- 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 +11 -33
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +11 -33
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +2 -2
- package/dist/adapters/mcp.d.ts +2 -2
- package/dist/adapters/mcp.js +28 -65
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +27 -64
- 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 +9 -30
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +9 -30
- 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 +8 -124
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +8 -122
- 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 +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +1 -1
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +63 -41
- package/dist/bin/astrasync-codex-hook.js +63 -41
- package/dist/bin/astrasync-guard.js +63 -41
- package/dist/bin/astrasync.js +75 -48
- package/dist/browser/background.js +63 -41
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +63 -41
- 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 +2 -2
- package/dist/claude-code/claude-code-adapter.d.ts +2 -2
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +33 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +33 -6
- package/dist/cli/index.mjs.map +1 -1
- package/dist/codex/index.d.mts +2 -2
- package/dist/codex/index.d.ts +2 -2
- package/dist/codex/index.js +63 -41
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +63 -41
- package/dist/codex/index.mjs.map +1 -1
- 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 +63 -41
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +63 -41
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.d.mts +1 -1
- package/dist/edge-config.d.ts +1 -1
- package/dist/edge-config.js +1 -1
- package/dist/edge-config.js.map +1 -1
- package/dist/edge-config.mjs +1 -1
- package/dist/edge-config.mjs.map +1 -1
- package/dist/edge-core/index.d.mts +1 -3
- package/dist/edge-core/index.d.ts +1 -3
- package/dist/edge-core/index.js +11 -33
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +11 -33
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/{express-DaqL11tx.d.ts → express-B5lWuemA.d.ts} +1 -1
- package/dist/{express-CR6F3njD.d.mts → express-Dm-snUuY.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 +63 -41
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +63 -41
- 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-Cub7lK-T.d.mts → index-B5k_vUmK.d.mts} +1 -1
- package/dist/{index-BfIxCYIZ.d.ts → index-BOzM6xUq.d.mts} +1 -2
- package/dist/{index-CwAh7Tln.d.mts → index-dRfxUdFA.d.ts} +1 -2
- package/dist/{index-B5Ts1WtM.d.ts → index-y8xToocF.d.ts} +1 -1
- package/dist/index.d.mts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +30 -217
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +30 -210
- 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 +22 -7
- package/dist/local-evaluator/evaluator.js.map +1 -1
- package/dist/local-evaluator/evaluator.mjs +22 -7
- package/dist/local-evaluator/evaluator.mjs.map +1 -1
- package/dist/{mcp-BgBJu4Jl.d.mts → mcp-DgsyQiQq.d.mts} +53 -52
- package/dist/{mcp--DgKOwfu.d.ts → mcp-OosmAcKf.d.ts} +53 -52
- package/dist/{nextjs-DlX6xwbU.d.mts → nextjs-B1sBdEav.d.mts} +1 -1
- package/dist/{nextjs-DL6uE1ye.d.ts → nextjs-DoRmhV_Z.d.ts} +1 -1
- package/dist/registration/index.d.mts +5 -1
- package/dist/registration/index.d.ts +5 -1
- package/dist/registration/index.js +1 -1
- package/dist/registration/index.js.map +1 -1
- package/dist/registration/index.mjs +1 -1
- package/dist/registration/index.mjs.map +1 -1
- package/dist/sdk-B83N3xKc.d.mts +142 -0
- package/dist/sdk-H_9BTNBS.d.ts +142 -0
- package/dist/transport/index.d.mts +2 -2
- package/dist/transport/index.d.ts +2 -2
- package/dist/transport/index.js +1 -1
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs +1 -1
- package/dist/transport/index.mjs.map +1 -1
- package/dist/{types-DwSfO7Sb.d.ts → types-BK2POWNc.d.ts} +23 -50
- package/dist/{types-C0zfSXMB.d.mts → types-CJjZvPr9.d.mts} +23 -50
- package/dist/{types-C7Rb-w0d.d.mts → types-CXf3q4kZ.d.ts} +14 -3
- package/dist/{types-nIh3HtuA.d.ts → types-DQmop7ZW.d.mts} +14 -3
- package/dist/ui/index.d.mts +2 -17
- package/dist/ui/index.d.ts +2 -17
- package/dist/ui/index.js +1 -43
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/index.mjs +1 -42
- package/dist/ui/index.mjs.map +1 -1
- package/dist/verify.d.mts +3 -4
- package/dist/verify.d.ts +3 -4
- package/dist/verify.js +8 -28
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +8 -28
- package/dist/verify.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/sdk-Bbh9B_dw.d.mts +0 -215
- package/dist/sdk-C6SASmsh.d.ts +0 -215
|
@@ -260,9 +260,9 @@ var LocalEvaluator = class {
|
|
|
260
260
|
if (scopeBlock) {
|
|
261
261
|
return { recommendation: "DENY", reason: scopeBlock };
|
|
262
262
|
}
|
|
263
|
-
const
|
|
264
|
-
if (
|
|
265
|
-
return
|
|
263
|
+
const limitDecision = this.checkLimits(context);
|
|
264
|
+
if (limitDecision) {
|
|
265
|
+
return limitDecision;
|
|
266
266
|
}
|
|
267
267
|
if (context.purpose === "sub_agent.spawn" && this.policy.selfInstantiation) {
|
|
268
268
|
if (!this.policy.selfInstantiation.allowed) {
|
|
@@ -327,9 +327,21 @@ var LocalEvaluator = class {
|
|
|
327
327
|
checkLimits(context) {
|
|
328
328
|
const limits = this.policy.limits;
|
|
329
329
|
if (!limits) return null;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
330
|
+
const value = context.transactionValue;
|
|
331
|
+
if (value !== void 0 && value > 0 && (limits.autonomousThreshold !== void 0 || limits.maxTransactionAmount !== void 0)) {
|
|
332
|
+
const autonomousThreshold = limits.autonomousThreshold ?? 0;
|
|
333
|
+
const hardLimit = limits.maxTransactionAmount ?? limits.autonomousThreshold ?? 0;
|
|
334
|
+
if (value > autonomousThreshold) {
|
|
335
|
+
if (value >= hardLimit) {
|
|
336
|
+
return {
|
|
337
|
+
recommendation: "DENY",
|
|
338
|
+
reason: `Transaction value ${value} at or above Hard Limit ${hardLimit}`
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
recommendation: "MANUAL_REVIEW",
|
|
343
|
+
reason: `Transaction value ${value} is in the human-approval band (${autonomousThreshold}, ${hardLimit})`
|
|
344
|
+
};
|
|
333
345
|
}
|
|
334
346
|
}
|
|
335
347
|
if (limits.maxRequestsPerHour !== void 0) {
|
|
@@ -342,7 +354,10 @@ var LocalEvaluator = class {
|
|
|
342
354
|
} else {
|
|
343
355
|
entry.count++;
|
|
344
356
|
if (entry.count > limits.maxRequestsPerHour) {
|
|
345
|
-
return
|
|
357
|
+
return {
|
|
358
|
+
recommendation: "DENY",
|
|
359
|
+
reason: `Rate limit exceeded: ${entry.count}/${limits.maxRequestsPerHour} requests per hour`
|
|
360
|
+
};
|
|
346
361
|
}
|
|
347
362
|
}
|
|
348
363
|
}
|
|
@@ -3551,10 +3566,16 @@ function validatePurpose(purpose, path) {
|
|
|
3551
3566
|
errors.push({ path: `${path}.targets`, message: "targets must be an array of strings" });
|
|
3552
3567
|
}
|
|
3553
3568
|
if (p.blockedPatterns !== void 0 && !isStringArray(p.blockedPatterns)) {
|
|
3554
|
-
errors.push({
|
|
3569
|
+
errors.push({
|
|
3570
|
+
path: `${path}.blockedPatterns`,
|
|
3571
|
+
message: "blockedPatterns must be an array of strings"
|
|
3572
|
+
});
|
|
3555
3573
|
}
|
|
3556
3574
|
if (p.requiresApproval !== void 0 && typeof p.requiresApproval !== "boolean") {
|
|
3557
|
-
errors.push({
|
|
3575
|
+
errors.push({
|
|
3576
|
+
path: `${path}.requiresApproval`,
|
|
3577
|
+
message: "requiresApproval must be a boolean"
|
|
3578
|
+
});
|
|
3558
3579
|
}
|
|
3559
3580
|
return errors;
|
|
3560
3581
|
}
|
|
@@ -3577,11 +3598,29 @@ function validateLimits(limits, path) {
|
|
|
3577
3598
|
return [{ path, message: "limits must be an object" }];
|
|
3578
3599
|
}
|
|
3579
3600
|
const l = limits;
|
|
3601
|
+
if (l.autonomousThreshold !== void 0 && typeof l.autonomousThreshold !== "number") {
|
|
3602
|
+
errors.push({
|
|
3603
|
+
path: `${path}.autonomousThreshold`,
|
|
3604
|
+
message: "autonomousThreshold must be a number"
|
|
3605
|
+
});
|
|
3606
|
+
}
|
|
3580
3607
|
if (l.maxTransactionAmount !== void 0 && typeof l.maxTransactionAmount !== "number") {
|
|
3581
|
-
errors.push({
|
|
3608
|
+
errors.push({
|
|
3609
|
+
path: `${path}.maxTransactionAmount`,
|
|
3610
|
+
message: "maxTransactionAmount must be a number"
|
|
3611
|
+
});
|
|
3612
|
+
}
|
|
3613
|
+
if (typeof l.autonomousThreshold === "number" && typeof l.maxTransactionAmount === "number" && l.autonomousThreshold > l.maxTransactionAmount) {
|
|
3614
|
+
errors.push({
|
|
3615
|
+
path: `${path}.autonomousThreshold`,
|
|
3616
|
+
message: "autonomousThreshold (Autonomous Limit) must be <= maxTransactionAmount (Hard Limit)"
|
|
3617
|
+
});
|
|
3582
3618
|
}
|
|
3583
3619
|
if (l.maxRequestsPerHour !== void 0 && typeof l.maxRequestsPerHour !== "number") {
|
|
3584
|
-
errors.push({
|
|
3620
|
+
errors.push({
|
|
3621
|
+
path: `${path}.maxRequestsPerHour`,
|
|
3622
|
+
message: "maxRequestsPerHour must be a number"
|
|
3623
|
+
});
|
|
3585
3624
|
}
|
|
3586
3625
|
if (l.currency !== void 0 && typeof l.currency !== "string") {
|
|
3587
3626
|
errors.push({ path: `${path}.currency`, message: "currency must be a string" });
|
|
@@ -3596,7 +3635,10 @@ function validateRiskThresholds(thresholds, path) {
|
|
|
3596
3635
|
const t = thresholds;
|
|
3597
3636
|
for (const range of ["autoAllow", "requireApproval", "autoBlock"]) {
|
|
3598
3637
|
if (!t[range] || typeof t[range] !== "object") {
|
|
3599
|
-
errors.push({
|
|
3638
|
+
errors.push({
|
|
3639
|
+
path: `${path}.${range}`,
|
|
3640
|
+
message: `${range} is required and must be an object with min and max`
|
|
3641
|
+
});
|
|
3600
3642
|
continue;
|
|
3601
3643
|
}
|
|
3602
3644
|
const r = t[range];
|
|
@@ -3692,7 +3734,7 @@ function verifyLocal(evaluator, context) {
|
|
|
3692
3734
|
return evaluator.evaluate(context);
|
|
3693
3735
|
}
|
|
3694
3736
|
|
|
3695
|
-
// src/
|
|
3737
|
+
// src/trust-levels.ts
|
|
3696
3738
|
function getTrustLevel(score) {
|
|
3697
3739
|
if (score >= 80) return "PLATINUM";
|
|
3698
3740
|
if (score >= 60) return "GOLD";
|
|
@@ -3701,7 +3743,7 @@ function getTrustLevel(score) {
|
|
|
3701
3743
|
}
|
|
3702
3744
|
|
|
3703
3745
|
// src/version.ts
|
|
3704
|
-
var SDK_VERSION = "
|
|
3746
|
+
var SDK_VERSION = "5.0.0";
|
|
3705
3747
|
|
|
3706
3748
|
// src/http.ts
|
|
3707
3749
|
var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
|
|
@@ -3731,11 +3773,6 @@ function getCachedWellKnownUrls(apiBaseUrl) {
|
|
|
3731
3773
|
// src/verify.ts
|
|
3732
3774
|
var DEFAULT_CONFIG = {
|
|
3733
3775
|
apiBaseUrl: "https://astrasync.ai/api",
|
|
3734
|
-
// v2.3.9 (defect #30): default for unconfigured callers is `'none'` (no
|
|
3735
|
-
// access). Pre-rename this defaulted to `'guidance'`, which combined with
|
|
3736
|
-
// a route gated at `'guidance'` to silently let unverified traffic
|
|
3737
|
-
// through (`hasMinimumAccess('guidance', 'guidance') === true`).
|
|
3738
|
-
defaultAccessLevel: "none",
|
|
3739
3776
|
// minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
|
|
3740
3777
|
// cacheTtl deliberately unset. When undefined, cacheResult applies the 60s
|
|
3741
3778
|
// default; the caller's explicit value is honoured for cacheable results.
|
|
@@ -3896,13 +3933,6 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
3896
3933
|
// policy is not evaluated (we never reached the gate).
|
|
3897
3934
|
identityVerified: false,
|
|
3898
3935
|
policyAllowed: false,
|
|
3899
|
-
// v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
|
|
3900
|
-
// Adapters additionally short-circuit on `!identityVerified ||
|
|
3901
|
-
// !policyAllowed` before the gate check, but the access level still has
|
|
3902
|
-
// to be honest at the data layer so downstream consumers (SDK adapters
|
|
3903
|
-
// in other languages, custom integrations) inherit the correct
|
|
3904
|
-
// semantics.
|
|
3905
|
-
accessLevel: "none",
|
|
3906
3936
|
guidance,
|
|
3907
3937
|
denialReasons: reason ? [reason] : ["No valid agent credentials provided"],
|
|
3908
3938
|
// Round-10 (#47, O5): on API-error fallback, surface a typed failure so
|
|
@@ -3925,6 +3955,11 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
3925
3955
|
// 4.0.0: typed marker so adapters render the misconfig envelope (503 +
|
|
3926
3956
|
// MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.
|
|
3927
3957
|
...isMisconfig && { misconfigured: true },
|
|
3958
|
+
// 4.6.0: a transient api_error is retryable — mark it so consumers surface
|
|
3959
|
+
// "temporarily unavailable, retry" (recommendation 'error') instead of
|
|
3960
|
+
// coercing the absent recommendation to a policy 'deny'. Misconfig is
|
|
3961
|
+
// deterministic and intentionally NOT marked retryable.
|
|
3962
|
+
...isApiError && { retryable: true },
|
|
3928
3963
|
correlationId: options.correlationId,
|
|
3929
3964
|
attemptId: options.attemptId,
|
|
3930
3965
|
verifiedAt: /* @__PURE__ */ new Date()
|
|
@@ -3991,7 +4026,6 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
3991
4026
|
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
3992
4027
|
access: {
|
|
3993
4028
|
allowed: false,
|
|
3994
|
-
accessLevel: "none",
|
|
3995
4029
|
reason: "endpoint_deactivated",
|
|
3996
4030
|
failures: [
|
|
3997
4031
|
{
|
|
@@ -4054,7 +4088,7 @@ async function verify(config, request, options) {
|
|
|
4054
4088
|
if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
|
|
4055
4089
|
deprecationWarningShown = true;
|
|
4056
4090
|
console.warn(
|
|
4057
|
-
"[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access
|
|
4091
|
+
"[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access decisions (verified ID + runtime challenge + PDLSS + trust score). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side."
|
|
4058
4092
|
);
|
|
4059
4093
|
}
|
|
4060
4094
|
if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {
|
|
@@ -4100,14 +4134,6 @@ async function verify(config, request, options) {
|
|
|
4100
4134
|
const result2 = {
|
|
4101
4135
|
identityVerified: idVerifiedFromBackend,
|
|
4102
4136
|
policyAllowed: false,
|
|
4103
|
-
// v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
|
|
4104
|
-
// Pre-rename this hardcoded `'guidance'`, which conflated with the
|
|
4105
|
-
// colocated `guidance: {...}` help-payload object below and let
|
|
4106
|
-
// denied requests pass any route gated at `'guidance'` because
|
|
4107
|
-
// `hasMinimumAccess('guidance', 'guidance') === true`. Adapters now
|
|
4108
|
-
// ALSO short-circuit on `!identityVerified || !policyAllowed` before
|
|
4109
|
-
// the gate check — belt-and-braces.
|
|
4110
|
-
accessLevel: "none",
|
|
4111
4137
|
// 3.6.0: the server now emits top-level denialReasons on every deny
|
|
4112
4138
|
// path — prefer it verbatim; the failure-message reconstruction remains
|
|
4113
4139
|
// as the fallback for older backends.
|
|
@@ -4156,7 +4182,6 @@ async function verify(config, request, options) {
|
|
|
4156
4182
|
trustScore: apiResponse.organization.trustScore
|
|
4157
4183
|
} : void 0;
|
|
4158
4184
|
const verificationContext = apiResponse.verificationContext;
|
|
4159
|
-
const accessLevel = apiResponse.access?.accessLevel ?? "standard";
|
|
4160
4185
|
const result = {
|
|
4161
4186
|
// 4.5.0 (probe F1): read idVerified from verificationContext with the
|
|
4162
4187
|
// SAME absent⇒false default as the deny branch. The previous `!== false`
|
|
@@ -4168,7 +4193,6 @@ async function verify(config, request, options) {
|
|
|
4168
4193
|
// this load-bearing must never be defaulted on.
|
|
4169
4194
|
identityVerified: apiResponse.verificationContext?.idVerified === true,
|
|
4170
4195
|
policyAllowed: true,
|
|
4171
|
-
accessLevel,
|
|
4172
4196
|
agent,
|
|
4173
4197
|
developer,
|
|
4174
4198
|
organization,
|
|
@@ -4195,7 +4219,6 @@ async function verify(config, request, options) {
|
|
|
4195
4219
|
};
|
|
4196
4220
|
if (result.recommendation === "deny") {
|
|
4197
4221
|
result.policyAllowed = false;
|
|
4198
|
-
result.accessLevel = "none";
|
|
4199
4222
|
result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Access denied by AstraSync recommendation"];
|
|
4200
4223
|
result.guidance = result.runtimeChallenge ? {
|
|
4201
4224
|
message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
|
|
@@ -4308,7 +4331,6 @@ function toGatewayConfig(config) {
|
|
|
4308
4331
|
return {
|
|
4309
4332
|
apiBaseUrl: config.apiBaseUrl || "https://api.astrasync.ai",
|
|
4310
4333
|
apiKey: config.apiKey,
|
|
4311
|
-
defaultAccessLevel: config.defaultAccessLevel,
|
|
4312
4334
|
minTrustScore: config.minTrustScore,
|
|
4313
4335
|
minTrustScoreForFull: config.minTrustScoreForFull,
|
|
4314
4336
|
cacheTtl: config.cacheTtl,
|
|
@@ -4336,7 +4358,7 @@ function toDecision(result) {
|
|
|
4336
4358
|
if (result.identityVerified && result.policyAllowed) {
|
|
4337
4359
|
return {
|
|
4338
4360
|
recommendation: "ALLOW",
|
|
4339
|
-
reason: `Verified
|
|
4361
|
+
reason: result.agent?.trustScore ? `Verified (trust score ${result.agent.trustScore})` : "Verified",
|
|
4340
4362
|
trustScore: result.agent?.trustScore,
|
|
4341
4363
|
sessionId: "sessionId" in result ? result.sessionId : void 0
|
|
4342
4364
|
};
|
|
@@ -259,9 +259,9 @@ var LocalEvaluator = class {
|
|
|
259
259
|
if (scopeBlock) {
|
|
260
260
|
return { recommendation: "DENY", reason: scopeBlock };
|
|
261
261
|
}
|
|
262
|
-
const
|
|
263
|
-
if (
|
|
264
|
-
return
|
|
262
|
+
const limitDecision = this.checkLimits(context);
|
|
263
|
+
if (limitDecision) {
|
|
264
|
+
return limitDecision;
|
|
265
265
|
}
|
|
266
266
|
if (context.purpose === "sub_agent.spawn" && this.policy.selfInstantiation) {
|
|
267
267
|
if (!this.policy.selfInstantiation.allowed) {
|
|
@@ -326,9 +326,21 @@ var LocalEvaluator = class {
|
|
|
326
326
|
checkLimits(context) {
|
|
327
327
|
const limits = this.policy.limits;
|
|
328
328
|
if (!limits) return null;
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
329
|
+
const value = context.transactionValue;
|
|
330
|
+
if (value !== void 0 && value > 0 && (limits.autonomousThreshold !== void 0 || limits.maxTransactionAmount !== void 0)) {
|
|
331
|
+
const autonomousThreshold = limits.autonomousThreshold ?? 0;
|
|
332
|
+
const hardLimit = limits.maxTransactionAmount ?? limits.autonomousThreshold ?? 0;
|
|
333
|
+
if (value > autonomousThreshold) {
|
|
334
|
+
if (value >= hardLimit) {
|
|
335
|
+
return {
|
|
336
|
+
recommendation: "DENY",
|
|
337
|
+
reason: `Transaction value ${value} at or above Hard Limit ${hardLimit}`
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
recommendation: "MANUAL_REVIEW",
|
|
342
|
+
reason: `Transaction value ${value} is in the human-approval band (${autonomousThreshold}, ${hardLimit})`
|
|
343
|
+
};
|
|
332
344
|
}
|
|
333
345
|
}
|
|
334
346
|
if (limits.maxRequestsPerHour !== void 0) {
|
|
@@ -341,7 +353,10 @@ var LocalEvaluator = class {
|
|
|
341
353
|
} else {
|
|
342
354
|
entry.count++;
|
|
343
355
|
if (entry.count > limits.maxRequestsPerHour) {
|
|
344
|
-
return
|
|
356
|
+
return {
|
|
357
|
+
recommendation: "DENY",
|
|
358
|
+
reason: `Rate limit exceeded: ${entry.count}/${limits.maxRequestsPerHour} requests per hour`
|
|
359
|
+
};
|
|
345
360
|
}
|
|
346
361
|
}
|
|
347
362
|
}
|
|
@@ -3550,10 +3565,16 @@ function validatePurpose(purpose, path) {
|
|
|
3550
3565
|
errors.push({ path: `${path}.targets`, message: "targets must be an array of strings" });
|
|
3551
3566
|
}
|
|
3552
3567
|
if (p.blockedPatterns !== void 0 && !isStringArray(p.blockedPatterns)) {
|
|
3553
|
-
errors.push({
|
|
3568
|
+
errors.push({
|
|
3569
|
+
path: `${path}.blockedPatterns`,
|
|
3570
|
+
message: "blockedPatterns must be an array of strings"
|
|
3571
|
+
});
|
|
3554
3572
|
}
|
|
3555
3573
|
if (p.requiresApproval !== void 0 && typeof p.requiresApproval !== "boolean") {
|
|
3556
|
-
errors.push({
|
|
3574
|
+
errors.push({
|
|
3575
|
+
path: `${path}.requiresApproval`,
|
|
3576
|
+
message: "requiresApproval must be a boolean"
|
|
3577
|
+
});
|
|
3557
3578
|
}
|
|
3558
3579
|
return errors;
|
|
3559
3580
|
}
|
|
@@ -3576,11 +3597,29 @@ function validateLimits(limits, path) {
|
|
|
3576
3597
|
return [{ path, message: "limits must be an object" }];
|
|
3577
3598
|
}
|
|
3578
3599
|
const l = limits;
|
|
3600
|
+
if (l.autonomousThreshold !== void 0 && typeof l.autonomousThreshold !== "number") {
|
|
3601
|
+
errors.push({
|
|
3602
|
+
path: `${path}.autonomousThreshold`,
|
|
3603
|
+
message: "autonomousThreshold must be a number"
|
|
3604
|
+
});
|
|
3605
|
+
}
|
|
3579
3606
|
if (l.maxTransactionAmount !== void 0 && typeof l.maxTransactionAmount !== "number") {
|
|
3580
|
-
errors.push({
|
|
3607
|
+
errors.push({
|
|
3608
|
+
path: `${path}.maxTransactionAmount`,
|
|
3609
|
+
message: "maxTransactionAmount must be a number"
|
|
3610
|
+
});
|
|
3611
|
+
}
|
|
3612
|
+
if (typeof l.autonomousThreshold === "number" && typeof l.maxTransactionAmount === "number" && l.autonomousThreshold > l.maxTransactionAmount) {
|
|
3613
|
+
errors.push({
|
|
3614
|
+
path: `${path}.autonomousThreshold`,
|
|
3615
|
+
message: "autonomousThreshold (Autonomous Limit) must be <= maxTransactionAmount (Hard Limit)"
|
|
3616
|
+
});
|
|
3581
3617
|
}
|
|
3582
3618
|
if (l.maxRequestsPerHour !== void 0 && typeof l.maxRequestsPerHour !== "number") {
|
|
3583
|
-
errors.push({
|
|
3619
|
+
errors.push({
|
|
3620
|
+
path: `${path}.maxRequestsPerHour`,
|
|
3621
|
+
message: "maxRequestsPerHour must be a number"
|
|
3622
|
+
});
|
|
3584
3623
|
}
|
|
3585
3624
|
if (l.currency !== void 0 && typeof l.currency !== "string") {
|
|
3586
3625
|
errors.push({ path: `${path}.currency`, message: "currency must be a string" });
|
|
@@ -3595,7 +3634,10 @@ function validateRiskThresholds(thresholds, path) {
|
|
|
3595
3634
|
const t = thresholds;
|
|
3596
3635
|
for (const range of ["autoAllow", "requireApproval", "autoBlock"]) {
|
|
3597
3636
|
if (!t[range] || typeof t[range] !== "object") {
|
|
3598
|
-
errors.push({
|
|
3637
|
+
errors.push({
|
|
3638
|
+
path: `${path}.${range}`,
|
|
3639
|
+
message: `${range} is required and must be an object with min and max`
|
|
3640
|
+
});
|
|
3599
3641
|
continue;
|
|
3600
3642
|
}
|
|
3601
3643
|
const r = t[range];
|
|
@@ -3691,7 +3733,7 @@ function verifyLocal(evaluator, context) {
|
|
|
3691
3733
|
return evaluator.evaluate(context);
|
|
3692
3734
|
}
|
|
3693
3735
|
|
|
3694
|
-
// src/
|
|
3736
|
+
// src/trust-levels.ts
|
|
3695
3737
|
function getTrustLevel(score) {
|
|
3696
3738
|
if (score >= 80) return "PLATINUM";
|
|
3697
3739
|
if (score >= 60) return "GOLD";
|
|
@@ -3700,7 +3742,7 @@ function getTrustLevel(score) {
|
|
|
3700
3742
|
}
|
|
3701
3743
|
|
|
3702
3744
|
// src/version.ts
|
|
3703
|
-
var SDK_VERSION = "
|
|
3745
|
+
var SDK_VERSION = "5.0.0";
|
|
3704
3746
|
|
|
3705
3747
|
// src/http.ts
|
|
3706
3748
|
var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
|
|
@@ -3730,11 +3772,6 @@ function getCachedWellKnownUrls(apiBaseUrl) {
|
|
|
3730
3772
|
// src/verify.ts
|
|
3731
3773
|
var DEFAULT_CONFIG = {
|
|
3732
3774
|
apiBaseUrl: "https://astrasync.ai/api",
|
|
3733
|
-
// v2.3.9 (defect #30): default for unconfigured callers is `'none'` (no
|
|
3734
|
-
// access). Pre-rename this defaulted to `'guidance'`, which combined with
|
|
3735
|
-
// a route gated at `'guidance'` to silently let unverified traffic
|
|
3736
|
-
// through (`hasMinimumAccess('guidance', 'guidance') === true`).
|
|
3737
|
-
defaultAccessLevel: "none",
|
|
3738
3775
|
// minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
|
|
3739
3776
|
// cacheTtl deliberately unset. When undefined, cacheResult applies the 60s
|
|
3740
3777
|
// default; the caller's explicit value is honoured for cacheable results.
|
|
@@ -3895,13 +3932,6 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
3895
3932
|
// policy is not evaluated (we never reached the gate).
|
|
3896
3933
|
identityVerified: false,
|
|
3897
3934
|
policyAllowed: false,
|
|
3898
|
-
// v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
|
|
3899
|
-
// Adapters additionally short-circuit on `!identityVerified ||
|
|
3900
|
-
// !policyAllowed` before the gate check, but the access level still has
|
|
3901
|
-
// to be honest at the data layer so downstream consumers (SDK adapters
|
|
3902
|
-
// in other languages, custom integrations) inherit the correct
|
|
3903
|
-
// semantics.
|
|
3904
|
-
accessLevel: "none",
|
|
3905
3935
|
guidance,
|
|
3906
3936
|
denialReasons: reason ? [reason] : ["No valid agent credentials provided"],
|
|
3907
3937
|
// Round-10 (#47, O5): on API-error fallback, surface a typed failure so
|
|
@@ -3924,6 +3954,11 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
3924
3954
|
// 4.0.0: typed marker so adapters render the misconfig envelope (503 +
|
|
3925
3955
|
// MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.
|
|
3926
3956
|
...isMisconfig && { misconfigured: true },
|
|
3957
|
+
// 4.6.0: a transient api_error is retryable — mark it so consumers surface
|
|
3958
|
+
// "temporarily unavailable, retry" (recommendation 'error') instead of
|
|
3959
|
+
// coercing the absent recommendation to a policy 'deny'. Misconfig is
|
|
3960
|
+
// deterministic and intentionally NOT marked retryable.
|
|
3961
|
+
...isApiError && { retryable: true },
|
|
3927
3962
|
correlationId: options.correlationId,
|
|
3928
3963
|
attemptId: options.attemptId,
|
|
3929
3964
|
verifiedAt: /* @__PURE__ */ new Date()
|
|
@@ -3990,7 +4025,6 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
3990
4025
|
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
3991
4026
|
access: {
|
|
3992
4027
|
allowed: false,
|
|
3993
|
-
accessLevel: "none",
|
|
3994
4028
|
reason: "endpoint_deactivated",
|
|
3995
4029
|
failures: [
|
|
3996
4030
|
{
|
|
@@ -4053,7 +4087,7 @@ async function verify(config, request, options) {
|
|
|
4053
4087
|
if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
|
|
4054
4088
|
deprecationWarningShown = true;
|
|
4055
4089
|
console.warn(
|
|
4056
|
-
"[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access
|
|
4090
|
+
"[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access decisions (verified ID + runtime challenge + PDLSS + trust score). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side."
|
|
4057
4091
|
);
|
|
4058
4092
|
}
|
|
4059
4093
|
if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {
|
|
@@ -4099,14 +4133,6 @@ async function verify(config, request, options) {
|
|
|
4099
4133
|
const result2 = {
|
|
4100
4134
|
identityVerified: idVerifiedFromBackend,
|
|
4101
4135
|
policyAllowed: false,
|
|
4102
|
-
// v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
|
|
4103
|
-
// Pre-rename this hardcoded `'guidance'`, which conflated with the
|
|
4104
|
-
// colocated `guidance: {...}` help-payload object below and let
|
|
4105
|
-
// denied requests pass any route gated at `'guidance'` because
|
|
4106
|
-
// `hasMinimumAccess('guidance', 'guidance') === true`. Adapters now
|
|
4107
|
-
// ALSO short-circuit on `!identityVerified || !policyAllowed` before
|
|
4108
|
-
// the gate check — belt-and-braces.
|
|
4109
|
-
accessLevel: "none",
|
|
4110
4136
|
// 3.6.0: the server now emits top-level denialReasons on every deny
|
|
4111
4137
|
// path — prefer it verbatim; the failure-message reconstruction remains
|
|
4112
4138
|
// as the fallback for older backends.
|
|
@@ -4155,7 +4181,6 @@ async function verify(config, request, options) {
|
|
|
4155
4181
|
trustScore: apiResponse.organization.trustScore
|
|
4156
4182
|
} : void 0;
|
|
4157
4183
|
const verificationContext = apiResponse.verificationContext;
|
|
4158
|
-
const accessLevel = apiResponse.access?.accessLevel ?? "standard";
|
|
4159
4184
|
const result = {
|
|
4160
4185
|
// 4.5.0 (probe F1): read idVerified from verificationContext with the
|
|
4161
4186
|
// SAME absent⇒false default as the deny branch. The previous `!== false`
|
|
@@ -4167,7 +4192,6 @@ async function verify(config, request, options) {
|
|
|
4167
4192
|
// this load-bearing must never be defaulted on.
|
|
4168
4193
|
identityVerified: apiResponse.verificationContext?.idVerified === true,
|
|
4169
4194
|
policyAllowed: true,
|
|
4170
|
-
accessLevel,
|
|
4171
4195
|
agent,
|
|
4172
4196
|
developer,
|
|
4173
4197
|
organization,
|
|
@@ -4194,7 +4218,6 @@ async function verify(config, request, options) {
|
|
|
4194
4218
|
};
|
|
4195
4219
|
if (result.recommendation === "deny") {
|
|
4196
4220
|
result.policyAllowed = false;
|
|
4197
|
-
result.accessLevel = "none";
|
|
4198
4221
|
result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Access denied by AstraSync recommendation"];
|
|
4199
4222
|
result.guidance = result.runtimeChallenge ? {
|
|
4200
4223
|
message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
|
|
@@ -4307,7 +4330,6 @@ function toGatewayConfig(config) {
|
|
|
4307
4330
|
return {
|
|
4308
4331
|
apiBaseUrl: config.apiBaseUrl || "https://api.astrasync.ai",
|
|
4309
4332
|
apiKey: config.apiKey,
|
|
4310
|
-
defaultAccessLevel: config.defaultAccessLevel,
|
|
4311
4333
|
minTrustScore: config.minTrustScore,
|
|
4312
4334
|
minTrustScoreForFull: config.minTrustScoreForFull,
|
|
4313
4335
|
cacheTtl: config.cacheTtl,
|
|
@@ -4335,7 +4357,7 @@ function toDecision(result) {
|
|
|
4335
4357
|
if (result.identityVerified && result.policyAllowed) {
|
|
4336
4358
|
return {
|
|
4337
4359
|
recommendation: "ALLOW",
|
|
4338
|
-
reason: `Verified
|
|
4360
|
+
reason: result.agent?.trustScore ? `Verified (trust score ${result.agent.trustScore})` : "Verified",
|
|
4339
4361
|
trustScore: result.agent?.trustScore,
|
|
4340
4362
|
sessionId: "sessionId" in result ? result.sessionId : void 0
|
|
4341
4363
|
};
|