@astrasyncai/verification-gateway 2.4.12 → 2.5.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.
Files changed (91) hide show
  1. package/dist/adapter-interface/interface.d.mts +2 -2
  2. package/dist/adapter-interface/interface.d.ts +2 -2
  3. package/dist/adapters/express.d.mts +2 -2
  4. package/dist/adapters/express.d.ts +2 -2
  5. package/dist/adapters/express.js +224 -42
  6. package/dist/adapters/express.js.map +1 -1
  7. package/dist/adapters/express.mjs +224 -42
  8. package/dist/adapters/express.mjs.map +1 -1
  9. package/dist/adapters/mcp.d.mts +101 -57
  10. package/dist/adapters/mcp.d.ts +101 -57
  11. package/dist/adapters/mcp.js +215 -44
  12. package/dist/adapters/mcp.js.map +1 -1
  13. package/dist/adapters/mcp.mjs +215 -44
  14. package/dist/adapters/mcp.mjs.map +1 -1
  15. package/dist/adapters/nextjs.d.mts +2 -2
  16. package/dist/adapters/nextjs.d.ts +2 -2
  17. package/dist/adapters/nextjs.js +87 -34
  18. package/dist/adapters/nextjs.js.map +1 -1
  19. package/dist/adapters/nextjs.mjs +87 -34
  20. package/dist/adapters/nextjs.mjs.map +1 -1
  21. package/dist/adapters/sdk.d.mts +2 -2
  22. package/dist/adapters/sdk.d.ts +2 -2
  23. package/dist/adapters/sdk.js +61 -28
  24. package/dist/adapters/sdk.js.map +1 -1
  25. package/dist/adapters/sdk.mjs +61 -28
  26. package/dist/adapters/sdk.mjs.map +1 -1
  27. package/dist/agent/index.d.mts +2 -2
  28. package/dist/agent/index.d.ts +2 -2
  29. package/dist/agent/index.js +29 -0
  30. package/dist/agent/index.js.map +1 -1
  31. package/dist/agent/index.mjs +29 -0
  32. package/dist/agent/index.mjs.map +1 -1
  33. package/dist/browser/background.js +102 -30
  34. package/dist/browser/background.js.map +1 -1
  35. package/dist/browser/background.mjs +102 -30
  36. package/dist/browser/background.mjs.map +1 -1
  37. package/dist/browser/browser-adapter.d.mts +2 -2
  38. package/dist/browser/browser-adapter.d.ts +2 -2
  39. package/dist/cli/index.d.mts +2 -2
  40. package/dist/cli/index.d.ts +2 -2
  41. package/dist/cursor/cursor-adapter.d.mts +2 -2
  42. package/dist/cursor/cursor-adapter.d.ts +2 -2
  43. package/dist/cursor/extension.d.mts +2 -2
  44. package/dist/cursor/extension.d.ts +2 -2
  45. package/dist/cursor/extension.js +102 -30
  46. package/dist/cursor/extension.js.map +1 -1
  47. package/dist/cursor/extension.mjs +102 -30
  48. package/dist/cursor/extension.mjs.map +1 -1
  49. package/dist/{express-C1ePFB7n.d.ts → express-CrfwoNAR.d.ts} +1 -1
  50. package/dist/{express-4WStX3PV.d.mts → express-ienhAXps.d.mts} +1 -1
  51. package/dist/gateway/gateway.d.mts +2 -2
  52. package/dist/gateway/gateway.d.ts +2 -2
  53. package/dist/gateway/gateway.js +102 -30
  54. package/dist/gateway/gateway.js.map +1 -1
  55. package/dist/gateway/gateway.mjs +102 -30
  56. package/dist/gateway/gateway.mjs.map +1 -1
  57. package/dist/git-trigger/git-hooks.d.mts +2 -2
  58. package/dist/git-trigger/git-hooks.d.ts +2 -2
  59. package/dist/{index-ChPX4WHl.d.mts → index-B5e2IDWU.d.mts} +1 -1
  60. package/dist/{index-CzJMCgEy.d.ts → index-CCdZxvAr.d.ts} +71 -6
  61. package/dist/{index-D8IEntil.d.mts → index-CEg_WG6y.d.mts} +71 -6
  62. package/dist/{index-Cjm-zBeZ.d.ts → index-DC5f8eoQ.d.ts} +1 -1
  63. package/dist/index.d.mts +39 -9
  64. package/dist/index.d.ts +39 -9
  65. package/dist/index.js +500 -94
  66. package/dist/index.js.map +1 -1
  67. package/dist/index.mjs +497 -94
  68. package/dist/index.mjs.map +1 -1
  69. package/dist/local-evaluator/evaluator.d.mts +2 -2
  70. package/dist/local-evaluator/evaluator.d.ts +2 -2
  71. package/dist/local-evaluator/evaluator.js +12 -2
  72. package/dist/local-evaluator/evaluator.js.map +1 -1
  73. package/dist/local-evaluator/evaluator.mjs +12 -2
  74. package/dist/local-evaluator/evaluator.mjs.map +1 -1
  75. package/dist/{nextjs-BIORS__0.d.ts → nextjs-66R1KW8e.d.ts} +1 -1
  76. package/dist/{nextjs-CjzHdaXA.d.mts → nextjs-DSpisQst.d.mts} +1 -1
  77. package/dist/{sdk-Chhz-FcT.d.mts → sdk-5U_CBRpr.d.mts} +1 -1
  78. package/dist/{sdk-CqTEQAc6.d.ts → sdk-Bm8np66n.d.ts} +1 -1
  79. package/dist/transport/index.d.mts +2 -2
  80. package/dist/transport/index.d.ts +2 -2
  81. package/dist/transport/index.js +146 -28
  82. package/dist/transport/index.js.map +1 -1
  83. package/dist/transport/index.mjs +146 -28
  84. package/dist/transport/index.mjs.map +1 -1
  85. package/dist/{types-L15pYd2c.d.mts → types-B3USs-Kx.d.mts} +42 -1
  86. package/dist/{types-L15pYd2c.d.ts → types-B3USs-Kx.d.ts} +42 -1
  87. package/dist/{types-DNK2BgIf.d.mts → types-CgDCUfo8.d.mts} +1 -1
  88. package/dist/{types-DoWIuzfj.d.ts → types-R5N4ET6x.d.ts} +1 -1
  89. package/dist/ui/index.d.mts +1 -1
  90. package/dist/ui/index.d.ts +1 -1
  91. package/package.json +1 -1
@@ -80,7 +80,10 @@ var LocalEvaluator = class {
80
80
  }
81
81
  const depth = context.metadata?.subAgentDepth || 0;
82
82
  if (this.policy.selfInstantiation.maxDepth !== void 0 && depth >= this.policy.selfInstantiation.maxDepth) {
83
- return { recommendation: "DENY", reason: `Sub-agent depth ${depth} exceeds max depth ${this.policy.selfInstantiation.maxDepth}` };
83
+ return {
84
+ recommendation: "DENY",
85
+ reason: `Sub-agent depth ${depth} exceeds max depth ${this.policy.selfInstantiation.maxDepth}`
86
+ };
84
87
  }
85
88
  }
86
89
  if (purposeRule.requiresApproval) {
@@ -161,7 +164,10 @@ var LocalEvaluator = class {
161
164
  return { recommendation: "DENY", reason: `Risk score ${riskScore} exceeds block threshold` };
162
165
  }
163
166
  if (riskScore >= thresholds.requireApproval.min) {
164
- return { recommendation: "MANUAL_REVIEW", reason: `Risk score ${riskScore} requires approval` };
167
+ return {
168
+ recommendation: "MANUAL_REVIEW",
169
+ reason: `Risk score ${riskScore} requires approval`
170
+ };
165
171
  }
166
172
  return null;
167
173
  }
@@ -226,6 +232,10 @@ var LocalEvaluator = class {
226
232
  */
227
233
  matchGlob(value, pattern) {
228
234
  if (pattern === value) return true;
235
+ const starCount = (pattern.match(/\*/g) ?? []).length;
236
+ if (starCount > 8) {
237
+ return false;
238
+ }
229
239
  const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
230
240
  try {
231
241
  return new RegExp(`^${regexStr}$`, "i").test(value);
@@ -3029,7 +3039,14 @@ function getTrustLevel(score) {
3029
3039
  }
3030
3040
 
3031
3041
  // src/version.ts
3032
- var SDK_VERSION = "2.4.12";
3042
+ var SDK_VERSION = "2.4.13";
3043
+
3044
+ // src/well-known.ts
3045
+ var CACHE_TTL_MS = 60 * 60 * 1e3;
3046
+ var cache = /* @__PURE__ */ new Map();
3047
+ function getCachedWellKnownUrls(apiBaseUrl) {
3048
+ return cache.get(apiBaseUrl)?.data;
3049
+ }
3033
3050
 
3034
3051
  // src/verify.ts
3035
3052
  var DEFAULT_CONFIG = {
@@ -3048,22 +3065,27 @@ var DEFAULT_CONFIG = {
3048
3065
  };
3049
3066
  var initCheckPerformed = false;
3050
3067
  var deprecationWarningShown = false;
3051
- async function performInitCheck(apiBaseUrl, debug) {
3068
+ async function performInitCheck(apiBaseUrl, debug, strictInit) {
3052
3069
  initCheckPerformed = true;
3053
3070
  try {
3054
3071
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
3055
3072
  const response = await fetch(probeUrl, { method: "HEAD" });
3056
3073
  const contentType = response.headers.get("content-type") ?? "";
3057
3074
  if (contentType.startsWith("text/html")) {
3058
- console.warn(
3059
- `[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). Set disableInitChecks: true on GatewayConfig to silence this warning.`
3060
- );
3075
+ 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).`;
3076
+ if (strictInit) {
3077
+ throw new Error(`${message} (strictInit=true)`);
3078
+ }
3079
+ console.warn(`${message} Set disableInitChecks: true on GatewayConfig to silence.`);
3061
3080
  } else if (debug) {
3062
3081
  console.log(
3063
3082
  `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
3064
3083
  );
3065
3084
  }
3066
3085
  } catch (err) {
3086
+ if (strictInit) {
3087
+ throw err;
3088
+ }
3067
3089
  if (debug) {
3068
3090
  console.log(`[VerificationGateway] init check failed (non-blocking): ${String(err)}`);
3069
3091
  }
@@ -3087,7 +3109,23 @@ function getCacheKey(request) {
3087
3109
  request.counterpartyType || "",
3088
3110
  request.isSubAgentRequest ? "1" : "0",
3089
3111
  request.parentAgentId || "",
3090
- request.subAgentDepth ?? ""
3112
+ request.subAgentDepth ?? "",
3113
+ // Audit F-A1-07: previously-missing dimensions that DO affect the
3114
+ // backend verdict. Without these, two requests with different
3115
+ // durations (e.g. 60s vs 86400s) collided on the same cache key and
3116
+ // the shorter-duration allow served the longer-duration request.
3117
+ request.durationRequired ?? "",
3118
+ request.invocationProtocol || "",
3119
+ request.enableRuntimeChallenge ? "1" : "0",
3120
+ // callerMetadata fields contribute to risk model; include the ones
3121
+ // backend reads. sourceIp/userAgent/forwardedFor change per-request
3122
+ // so their inclusion effectively forces a re-check for any varying
3123
+ // client (the right behavior — IP-driven anomaly scoring shouldn't
3124
+ // be cached across IPs).
3125
+ request.callerMetadata?.sourceIp || "",
3126
+ request.callerMetadata?.userAgent || "",
3127
+ request.callerMetadata?.forwardedFor || "",
3128
+ request.callerMetadata?.agentCardUrl || ""
3091
3129
  ].join("|");
3092
3130
  }
3093
3131
  function getCachedResult(request) {
@@ -3111,21 +3149,22 @@ function cacheResult(request, result, configuredTtl) {
3111
3149
  expiresAt: Date.now() + ttlSeconds * 1e3
3112
3150
  });
3113
3151
  }
3114
- function createGuidanceResponse(config, reason, options = {}) {
3152
+ function createGuidanceResponse(_config, reason, options = {}) {
3115
3153
  const source = options.source ?? "no_credentials";
3116
3154
  const isApiError = source === "api_error";
3155
+ const urls = options.urls;
3117
3156
  const guidance = isApiError ? {
3118
3157
  message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
3119
- registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
3120
- documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
3158
+ registrationUrl: urls?.registrationUrl ?? "",
3159
+ documentationUrl: urls?.documentationUrl ?? "",
3121
3160
  steps: [
3122
3161
  "Retry the request with exponential backoff",
3123
3162
  "If failures persist, share the correlationId with support"
3124
3163
  ]
3125
3164
  } : {
3126
3165
  message: "This service verifies AI agents before granting access. Please register your agent with AstraSync.",
3127
- registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
3128
- documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
3166
+ registrationUrl: urls?.registrationUrl ?? "",
3167
+ documentationUrl: urls?.documentationUrl ?? "",
3129
3168
  steps: [
3130
3169
  "Register for an AstraSync account",
3131
3170
  "Create and register your agent",
@@ -3167,7 +3206,7 @@ async function callVerifyAccessAPI(config, request) {
3167
3206
  const { credentials, ...requestData } = request;
3168
3207
  const body = {
3169
3208
  ...credentials.astraId && { agentId: credentials.astraId },
3170
- purpose: requestData.purpose || "general"
3209
+ ...requestData.purpose && { purpose: requestData.purpose }
3171
3210
  };
3172
3211
  if (requestData.action) body.action = requestData.action;
3173
3212
  if (requestData.resourceType) body.resourceType = requestData.resourceType;
@@ -3201,12 +3240,8 @@ async function callVerifyAccessAPI(config, request) {
3201
3240
  "Content-Type": "application/json",
3202
3241
  ...config.customHeaders
3203
3242
  };
3204
- if (credentials.authorizationHeader) {
3205
- headers["Authorization"] = credentials.authorizationHeader;
3206
- } else if (config.apiKey) {
3207
- headers["Authorization"] = `Bearer ${config.apiKey}`;
3208
- }
3209
3243
  if (config.apiKey) {
3244
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
3210
3245
  headers["X-API-Key"] = config.apiKey;
3211
3246
  }
3212
3247
  try {
@@ -3251,8 +3286,13 @@ async function callVerifyAccessAPI(config, request) {
3251
3286
  }
3252
3287
  async function verify(config, request) {
3253
3288
  const mergedConfig = { ...DEFAULT_CONFIG, ...config };
3289
+ const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
3254
3290
  if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
3255
- void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug);
3291
+ if (mergedConfig.strictInit) {
3292
+ await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
3293
+ } else {
3294
+ void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
3295
+ }
3256
3296
  }
3257
3297
  if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
3258
3298
  deprecationWarningShown = true;
@@ -3283,7 +3323,8 @@ async function verify(config, request) {
3283
3323
  if (!apiResponse.success) {
3284
3324
  return createGuidanceResponse(mergedConfig, apiResponse.error, {
3285
3325
  source: "api_error",
3286
- correlationId: apiResponse.correlationId
3326
+ correlationId: apiResponse.correlationId,
3327
+ urls
3287
3328
  });
3288
3329
  }
3289
3330
  if (!apiResponse.access?.allowed) {
@@ -3306,8 +3347,8 @@ async function verify(config, request) {
3306
3347
  requiresApproval: apiResponse.access?.requiresApproval,
3307
3348
  guidance: {
3308
3349
  message: apiResponse.access?.reason || "Access denied by PDLSS policy",
3309
- registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/register`,
3310
- documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
3350
+ registrationUrl: urls?.registrationUrl ?? "",
3351
+ documentationUrl: urls?.documentationUrl ?? ""
3311
3352
  },
3312
3353
  verifiedAt: /* @__PURE__ */ new Date(),
3313
3354
  // Extract sessionId so decisions can be recorded for denials too
@@ -3376,13 +3417,15 @@ async function verify(config, request) {
3376
3417
  result.denialReasons = result.recommendationReasons || [
3377
3418
  "Access denied by AstraSync recommendation"
3378
3419
  ];
3379
- if (result.runtimeChallenge) {
3380
- result.guidance = {
3381
- message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
3382
- registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/register`,
3383
- documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/runtime-challenge`
3384
- };
3385
- }
3420
+ result.guidance = result.runtimeChallenge ? {
3421
+ message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
3422
+ registrationUrl: urls?.registrationUrl ?? "",
3423
+ documentationUrl: urls?.documentationUrl ?? ""
3424
+ } : {
3425
+ message: result.recommendationReasons?.[0] || "Access denied by AstraSync recommendation",
3426
+ registrationUrl: urls?.registrationUrl ?? "",
3427
+ documentationUrl: urls?.documentationUrl ?? ""
3428
+ };
3386
3429
  } else if (result.recommendation === "step_up_required") {
3387
3430
  result.requiresStepUp = true;
3388
3431
  if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
@@ -3408,6 +3451,35 @@ import { parseDictionary } from "structured-headers";
3408
3451
  // src/transport/rfc9421-verify.ts
3409
3452
  import { httpbis } from "http-message-signatures";
3410
3453
 
3454
+ // src/transport/nonce-store.ts
3455
+ var InMemoryNonceStore = class {
3456
+ constructor(capacity = 1e4) {
3457
+ this.entries = /* @__PURE__ */ new Map();
3458
+ this.lastSweepMs = 0;
3459
+ this.capacity = capacity;
3460
+ }
3461
+ seen(key, expiresAtMs) {
3462
+ const nowMs = Date.now();
3463
+ if (nowMs - this.lastSweepMs > 1e3) {
3464
+ for (const [k, exp] of this.entries) {
3465
+ if (exp <= nowMs) this.entries.delete(k);
3466
+ }
3467
+ this.lastSweepMs = nowMs;
3468
+ }
3469
+ const existing = this.entries.get(key);
3470
+ if (existing !== void 0 && existing > nowMs) {
3471
+ return true;
3472
+ }
3473
+ if (this.entries.size >= this.capacity) {
3474
+ const oldest = this.entries.keys().next().value;
3475
+ if (oldest !== void 0) this.entries.delete(oldest);
3476
+ }
3477
+ this.entries.set(key, expiresAtMs);
3478
+ return false;
3479
+ }
3480
+ };
3481
+ var defaultNonceStore = new InMemoryNonceStore();
3482
+
3411
3483
  // src/transport/vi.ts
3412
3484
  import { splitSdJwt, decodeSdJwtSync } from "@sd-jwt/decode";
3413
3485
  import { createHash } from "crypto";