@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
@@ -323,7 +323,10 @@ var LocalEvaluator = class {
323
323
  }
324
324
  const depth = context.metadata?.subAgentDepth || 0;
325
325
  if (this.policy.selfInstantiation.maxDepth !== void 0 && depth >= this.policy.selfInstantiation.maxDepth) {
326
- return { recommendation: "DENY", reason: `Sub-agent depth ${depth} exceeds max depth ${this.policy.selfInstantiation.maxDepth}` };
326
+ return {
327
+ recommendation: "DENY",
328
+ reason: `Sub-agent depth ${depth} exceeds max depth ${this.policy.selfInstantiation.maxDepth}`
329
+ };
327
330
  }
328
331
  }
329
332
  if (purposeRule.requiresApproval) {
@@ -404,7 +407,10 @@ var LocalEvaluator = class {
404
407
  return { recommendation: "DENY", reason: `Risk score ${riskScore} exceeds block threshold` };
405
408
  }
406
409
  if (riskScore >= thresholds.requireApproval.min) {
407
- return { recommendation: "MANUAL_REVIEW", reason: `Risk score ${riskScore} requires approval` };
410
+ return {
411
+ recommendation: "MANUAL_REVIEW",
412
+ reason: `Risk score ${riskScore} requires approval`
413
+ };
408
414
  }
409
415
  return null;
410
416
  }
@@ -469,6 +475,10 @@ var LocalEvaluator = class {
469
475
  */
470
476
  matchGlob(value, pattern) {
471
477
  if (pattern === value) return true;
478
+ const starCount = (pattern.match(/\*/g) ?? []).length;
479
+ if (starCount > 8) {
480
+ return false;
481
+ }
472
482
  const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
473
483
  try {
474
484
  return new RegExp(`^${regexStr}$`, "i").test(value);
@@ -3272,7 +3282,14 @@ function getTrustLevel(score) {
3272
3282
  }
3273
3283
 
3274
3284
  // src/version.ts
3275
- var SDK_VERSION = "2.4.12";
3285
+ var SDK_VERSION = "2.4.13";
3286
+
3287
+ // src/well-known.ts
3288
+ var CACHE_TTL_MS = 60 * 60 * 1e3;
3289
+ var cache = /* @__PURE__ */ new Map();
3290
+ function getCachedWellKnownUrls(apiBaseUrl) {
3291
+ return cache.get(apiBaseUrl)?.data;
3292
+ }
3276
3293
 
3277
3294
  // src/verify.ts
3278
3295
  var DEFAULT_CONFIG = {
@@ -3291,22 +3308,27 @@ var DEFAULT_CONFIG = {
3291
3308
  };
3292
3309
  var initCheckPerformed = false;
3293
3310
  var deprecationWarningShown = false;
3294
- async function performInitCheck(apiBaseUrl, debug) {
3311
+ async function performInitCheck(apiBaseUrl, debug, strictInit) {
3295
3312
  initCheckPerformed = true;
3296
3313
  try {
3297
3314
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
3298
3315
  const response = await fetch(probeUrl, { method: "HEAD" });
3299
3316
  const contentType = response.headers.get("content-type") ?? "";
3300
3317
  if (contentType.startsWith("text/html")) {
3301
- console.warn(
3302
- `[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.`
3303
- );
3318
+ 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).`;
3319
+ if (strictInit) {
3320
+ throw new Error(`${message} (strictInit=true)`);
3321
+ }
3322
+ console.warn(`${message} Set disableInitChecks: true on GatewayConfig to silence.`);
3304
3323
  } else if (debug) {
3305
3324
  console.log(
3306
3325
  `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
3307
3326
  );
3308
3327
  }
3309
3328
  } catch (err) {
3329
+ if (strictInit) {
3330
+ throw err;
3331
+ }
3310
3332
  if (debug) {
3311
3333
  console.log(`[VerificationGateway] init check failed (non-blocking): ${String(err)}`);
3312
3334
  }
@@ -3330,7 +3352,23 @@ function getCacheKey(request) {
3330
3352
  request.counterpartyType || "",
3331
3353
  request.isSubAgentRequest ? "1" : "0",
3332
3354
  request.parentAgentId || "",
3333
- request.subAgentDepth ?? ""
3355
+ request.subAgentDepth ?? "",
3356
+ // Audit F-A1-07: previously-missing dimensions that DO affect the
3357
+ // backend verdict. Without these, two requests with different
3358
+ // durations (e.g. 60s vs 86400s) collided on the same cache key and
3359
+ // the shorter-duration allow served the longer-duration request.
3360
+ request.durationRequired ?? "",
3361
+ request.invocationProtocol || "",
3362
+ request.enableRuntimeChallenge ? "1" : "0",
3363
+ // callerMetadata fields contribute to risk model; include the ones
3364
+ // backend reads. sourceIp/userAgent/forwardedFor change per-request
3365
+ // so their inclusion effectively forces a re-check for any varying
3366
+ // client (the right behavior — IP-driven anomaly scoring shouldn't
3367
+ // be cached across IPs).
3368
+ request.callerMetadata?.sourceIp || "",
3369
+ request.callerMetadata?.userAgent || "",
3370
+ request.callerMetadata?.forwardedFor || "",
3371
+ request.callerMetadata?.agentCardUrl || ""
3334
3372
  ].join("|");
3335
3373
  }
3336
3374
  function getCachedResult(request) {
@@ -3354,21 +3392,22 @@ function cacheResult(request, result, configuredTtl) {
3354
3392
  expiresAt: Date.now() + ttlSeconds * 1e3
3355
3393
  });
3356
3394
  }
3357
- function createGuidanceResponse(config, reason, options = {}) {
3395
+ function createGuidanceResponse(_config, reason, options = {}) {
3358
3396
  const source = options.source ?? "no_credentials";
3359
3397
  const isApiError = source === "api_error";
3398
+ const urls = options.urls;
3360
3399
  const guidance = isApiError ? {
3361
3400
  message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
3362
- registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
3363
- documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
3401
+ registrationUrl: urls?.registrationUrl ?? "",
3402
+ documentationUrl: urls?.documentationUrl ?? "",
3364
3403
  steps: [
3365
3404
  "Retry the request with exponential backoff",
3366
3405
  "If failures persist, share the correlationId with support"
3367
3406
  ]
3368
3407
  } : {
3369
3408
  message: "This service verifies AI agents before granting access. Please register your agent with AstraSync.",
3370
- registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
3371
- documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
3409
+ registrationUrl: urls?.registrationUrl ?? "",
3410
+ documentationUrl: urls?.documentationUrl ?? "",
3372
3411
  steps: [
3373
3412
  "Register for an AstraSync account",
3374
3413
  "Create and register your agent",
@@ -3410,7 +3449,7 @@ async function callVerifyAccessAPI(config, request) {
3410
3449
  const { credentials, ...requestData } = request;
3411
3450
  const body = {
3412
3451
  ...credentials.astraId && { agentId: credentials.astraId },
3413
- purpose: requestData.purpose || "general"
3452
+ ...requestData.purpose && { purpose: requestData.purpose }
3414
3453
  };
3415
3454
  if (requestData.action) body.action = requestData.action;
3416
3455
  if (requestData.resourceType) body.resourceType = requestData.resourceType;
@@ -3444,12 +3483,8 @@ async function callVerifyAccessAPI(config, request) {
3444
3483
  "Content-Type": "application/json",
3445
3484
  ...config.customHeaders
3446
3485
  };
3447
- if (credentials.authorizationHeader) {
3448
- headers["Authorization"] = credentials.authorizationHeader;
3449
- } else if (config.apiKey) {
3450
- headers["Authorization"] = `Bearer ${config.apiKey}`;
3451
- }
3452
3486
  if (config.apiKey) {
3487
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
3453
3488
  headers["X-API-Key"] = config.apiKey;
3454
3489
  }
3455
3490
  try {
@@ -3494,8 +3529,13 @@ async function callVerifyAccessAPI(config, request) {
3494
3529
  }
3495
3530
  async function verify(config, request) {
3496
3531
  const mergedConfig = { ...DEFAULT_CONFIG, ...config };
3532
+ const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
3497
3533
  if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
3498
- void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug);
3534
+ if (mergedConfig.strictInit) {
3535
+ await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
3536
+ } else {
3537
+ void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
3538
+ }
3499
3539
  }
3500
3540
  if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
3501
3541
  deprecationWarningShown = true;
@@ -3526,7 +3566,8 @@ async function verify(config, request) {
3526
3566
  if (!apiResponse.success) {
3527
3567
  return createGuidanceResponse(mergedConfig, apiResponse.error, {
3528
3568
  source: "api_error",
3529
- correlationId: apiResponse.correlationId
3569
+ correlationId: apiResponse.correlationId,
3570
+ urls
3530
3571
  });
3531
3572
  }
3532
3573
  if (!apiResponse.access?.allowed) {
@@ -3549,8 +3590,8 @@ async function verify(config, request) {
3549
3590
  requiresApproval: apiResponse.access?.requiresApproval,
3550
3591
  guidance: {
3551
3592
  message: apiResponse.access?.reason || "Access denied by PDLSS policy",
3552
- registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/register`,
3553
- documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
3593
+ registrationUrl: urls?.registrationUrl ?? "",
3594
+ documentationUrl: urls?.documentationUrl ?? ""
3554
3595
  },
3555
3596
  verifiedAt: /* @__PURE__ */ new Date(),
3556
3597
  // Extract sessionId so decisions can be recorded for denials too
@@ -3619,13 +3660,15 @@ async function verify(config, request) {
3619
3660
  result.denialReasons = result.recommendationReasons || [
3620
3661
  "Access denied by AstraSync recommendation"
3621
3662
  ];
3622
- if (result.runtimeChallenge) {
3623
- result.guidance = {
3624
- message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
3625
- registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/register`,
3626
- documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/runtime-challenge`
3627
- };
3628
- }
3663
+ result.guidance = result.runtimeChallenge ? {
3664
+ message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
3665
+ registrationUrl: urls?.registrationUrl ?? "",
3666
+ documentationUrl: urls?.documentationUrl ?? ""
3667
+ } : {
3668
+ message: result.recommendationReasons?.[0] || "Access denied by AstraSync recommendation",
3669
+ registrationUrl: urls?.registrationUrl ?? "",
3670
+ documentationUrl: urls?.documentationUrl ?? ""
3671
+ };
3629
3672
  } else if (result.recommendation === "step_up_required") {
3630
3673
  result.requiresStepUp = true;
3631
3674
  if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
@@ -3651,6 +3694,35 @@ import { parseDictionary } from "structured-headers";
3651
3694
  // src/transport/rfc9421-verify.ts
3652
3695
  import { httpbis } from "http-message-signatures";
3653
3696
 
3697
+ // src/transport/nonce-store.ts
3698
+ var InMemoryNonceStore = class {
3699
+ constructor(capacity = 1e4) {
3700
+ this.entries = /* @__PURE__ */ new Map();
3701
+ this.lastSweepMs = 0;
3702
+ this.capacity = capacity;
3703
+ }
3704
+ seen(key, expiresAtMs) {
3705
+ const nowMs = Date.now();
3706
+ if (nowMs - this.lastSweepMs > 1e3) {
3707
+ for (const [k, exp] of this.entries) {
3708
+ if (exp <= nowMs) this.entries.delete(k);
3709
+ }
3710
+ this.lastSweepMs = nowMs;
3711
+ }
3712
+ const existing = this.entries.get(key);
3713
+ if (existing !== void 0 && existing > nowMs) {
3714
+ return true;
3715
+ }
3716
+ if (this.entries.size >= this.capacity) {
3717
+ const oldest = this.entries.keys().next().value;
3718
+ if (oldest !== void 0) this.entries.delete(oldest);
3719
+ }
3720
+ this.entries.set(key, expiresAtMs);
3721
+ return false;
3722
+ }
3723
+ };
3724
+ var defaultNonceStore = new InMemoryNonceStore();
3725
+
3654
3726
  // src/transport/vi.ts
3655
3727
  import { splitSdJwt, decodeSdJwtSync } from "@sd-jwt/decode";
3656
3728
  import { createHash } from "crypto";