@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
@@ -344,7 +344,10 @@ var LocalEvaluator = class {
344
344
  }
345
345
  const depth = context.metadata?.subAgentDepth || 0;
346
346
  if (this.policy.selfInstantiation.maxDepth !== void 0 && depth >= this.policy.selfInstantiation.maxDepth) {
347
- return { recommendation: "DENY", reason: `Sub-agent depth ${depth} exceeds max depth ${this.policy.selfInstantiation.maxDepth}` };
347
+ return {
348
+ recommendation: "DENY",
349
+ reason: `Sub-agent depth ${depth} exceeds max depth ${this.policy.selfInstantiation.maxDepth}`
350
+ };
348
351
  }
349
352
  }
350
353
  if (purposeRule.requiresApproval) {
@@ -425,7 +428,10 @@ var LocalEvaluator = class {
425
428
  return { recommendation: "DENY", reason: `Risk score ${riskScore} exceeds block threshold` };
426
429
  }
427
430
  if (riskScore >= thresholds.requireApproval.min) {
428
- return { recommendation: "MANUAL_REVIEW", reason: `Risk score ${riskScore} requires approval` };
431
+ return {
432
+ recommendation: "MANUAL_REVIEW",
433
+ reason: `Risk score ${riskScore} requires approval`
434
+ };
429
435
  }
430
436
  return null;
431
437
  }
@@ -490,6 +496,10 @@ var LocalEvaluator = class {
490
496
  */
491
497
  matchGlob(value, pattern) {
492
498
  if (pattern === value) return true;
499
+ const starCount = (pattern.match(/\*/g) ?? []).length;
500
+ if (starCount > 8) {
501
+ return false;
502
+ }
493
503
  const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
494
504
  try {
495
505
  return new RegExp(`^${regexStr}$`, "i").test(value);
@@ -3293,7 +3303,14 @@ function getTrustLevel(score) {
3293
3303
  }
3294
3304
 
3295
3305
  // src/version.ts
3296
- var SDK_VERSION = "2.4.12";
3306
+ var SDK_VERSION = "2.4.13";
3307
+
3308
+ // src/well-known.ts
3309
+ var CACHE_TTL_MS = 60 * 60 * 1e3;
3310
+ var cache = /* @__PURE__ */ new Map();
3311
+ function getCachedWellKnownUrls(apiBaseUrl) {
3312
+ return cache.get(apiBaseUrl)?.data;
3313
+ }
3297
3314
 
3298
3315
  // src/verify.ts
3299
3316
  var DEFAULT_CONFIG = {
@@ -3312,22 +3329,27 @@ var DEFAULT_CONFIG = {
3312
3329
  };
3313
3330
  var initCheckPerformed = false;
3314
3331
  var deprecationWarningShown = false;
3315
- async function performInitCheck(apiBaseUrl, debug) {
3332
+ async function performInitCheck(apiBaseUrl, debug, strictInit) {
3316
3333
  initCheckPerformed = true;
3317
3334
  try {
3318
3335
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
3319
3336
  const response = await fetch(probeUrl, { method: "HEAD" });
3320
3337
  const contentType = response.headers.get("content-type") ?? "";
3321
3338
  if (contentType.startsWith("text/html")) {
3322
- console.warn(
3323
- `[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.`
3324
- );
3339
+ 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).`;
3340
+ if (strictInit) {
3341
+ throw new Error(`${message} (strictInit=true)`);
3342
+ }
3343
+ console.warn(`${message} Set disableInitChecks: true on GatewayConfig to silence.`);
3325
3344
  } else if (debug) {
3326
3345
  console.log(
3327
3346
  `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
3328
3347
  );
3329
3348
  }
3330
3349
  } catch (err) {
3350
+ if (strictInit) {
3351
+ throw err;
3352
+ }
3331
3353
  if (debug) {
3332
3354
  console.log(`[VerificationGateway] init check failed (non-blocking): ${String(err)}`);
3333
3355
  }
@@ -3351,7 +3373,23 @@ function getCacheKey(request) {
3351
3373
  request.counterpartyType || "",
3352
3374
  request.isSubAgentRequest ? "1" : "0",
3353
3375
  request.parentAgentId || "",
3354
- request.subAgentDepth ?? ""
3376
+ request.subAgentDepth ?? "",
3377
+ // Audit F-A1-07: previously-missing dimensions that DO affect the
3378
+ // backend verdict. Without these, two requests with different
3379
+ // durations (e.g. 60s vs 86400s) collided on the same cache key and
3380
+ // the shorter-duration allow served the longer-duration request.
3381
+ request.durationRequired ?? "",
3382
+ request.invocationProtocol || "",
3383
+ request.enableRuntimeChallenge ? "1" : "0",
3384
+ // callerMetadata fields contribute to risk model; include the ones
3385
+ // backend reads. sourceIp/userAgent/forwardedFor change per-request
3386
+ // so their inclusion effectively forces a re-check for any varying
3387
+ // client (the right behavior — IP-driven anomaly scoring shouldn't
3388
+ // be cached across IPs).
3389
+ request.callerMetadata?.sourceIp || "",
3390
+ request.callerMetadata?.userAgent || "",
3391
+ request.callerMetadata?.forwardedFor || "",
3392
+ request.callerMetadata?.agentCardUrl || ""
3355
3393
  ].join("|");
3356
3394
  }
3357
3395
  function getCachedResult(request) {
@@ -3375,21 +3413,22 @@ function cacheResult(request, result, configuredTtl) {
3375
3413
  expiresAt: Date.now() + ttlSeconds * 1e3
3376
3414
  });
3377
3415
  }
3378
- function createGuidanceResponse(config, reason, options = {}) {
3416
+ function createGuidanceResponse(_config, reason, options = {}) {
3379
3417
  const source = options.source ?? "no_credentials";
3380
3418
  const isApiError = source === "api_error";
3419
+ const urls = options.urls;
3381
3420
  const guidance = isApiError ? {
3382
3421
  message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
3383
- registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
3384
- documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
3422
+ registrationUrl: urls?.registrationUrl ?? "",
3423
+ documentationUrl: urls?.documentationUrl ?? "",
3385
3424
  steps: [
3386
3425
  "Retry the request with exponential backoff",
3387
3426
  "If failures persist, share the correlationId with support"
3388
3427
  ]
3389
3428
  } : {
3390
3429
  message: "This service verifies AI agents before granting access. Please register your agent with AstraSync.",
3391
- registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
3392
- documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
3430
+ registrationUrl: urls?.registrationUrl ?? "",
3431
+ documentationUrl: urls?.documentationUrl ?? "",
3393
3432
  steps: [
3394
3433
  "Register for an AstraSync account",
3395
3434
  "Create and register your agent",
@@ -3431,7 +3470,7 @@ async function callVerifyAccessAPI(config, request) {
3431
3470
  const { credentials, ...requestData } = request;
3432
3471
  const body = {
3433
3472
  ...credentials.astraId && { agentId: credentials.astraId },
3434
- purpose: requestData.purpose || "general"
3473
+ ...requestData.purpose && { purpose: requestData.purpose }
3435
3474
  };
3436
3475
  if (requestData.action) body.action = requestData.action;
3437
3476
  if (requestData.resourceType) body.resourceType = requestData.resourceType;
@@ -3465,12 +3504,8 @@ async function callVerifyAccessAPI(config, request) {
3465
3504
  "Content-Type": "application/json",
3466
3505
  ...config.customHeaders
3467
3506
  };
3468
- if (credentials.authorizationHeader) {
3469
- headers["Authorization"] = credentials.authorizationHeader;
3470
- } else if (config.apiKey) {
3471
- headers["Authorization"] = `Bearer ${config.apiKey}`;
3472
- }
3473
3507
  if (config.apiKey) {
3508
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
3474
3509
  headers["X-API-Key"] = config.apiKey;
3475
3510
  }
3476
3511
  try {
@@ -3515,8 +3550,13 @@ async function callVerifyAccessAPI(config, request) {
3515
3550
  }
3516
3551
  async function verify(config, request) {
3517
3552
  const mergedConfig = { ...DEFAULT_CONFIG, ...config };
3553
+ const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
3518
3554
  if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
3519
- void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug);
3555
+ if (mergedConfig.strictInit) {
3556
+ await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
3557
+ } else {
3558
+ void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
3559
+ }
3520
3560
  }
3521
3561
  if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
3522
3562
  deprecationWarningShown = true;
@@ -3547,7 +3587,8 @@ async function verify(config, request) {
3547
3587
  if (!apiResponse.success) {
3548
3588
  return createGuidanceResponse(mergedConfig, apiResponse.error, {
3549
3589
  source: "api_error",
3550
- correlationId: apiResponse.correlationId
3590
+ correlationId: apiResponse.correlationId,
3591
+ urls
3551
3592
  });
3552
3593
  }
3553
3594
  if (!apiResponse.access?.allowed) {
@@ -3570,8 +3611,8 @@ async function verify(config, request) {
3570
3611
  requiresApproval: apiResponse.access?.requiresApproval,
3571
3612
  guidance: {
3572
3613
  message: apiResponse.access?.reason || "Access denied by PDLSS policy",
3573
- registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/register`,
3574
- documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
3614
+ registrationUrl: urls?.registrationUrl ?? "",
3615
+ documentationUrl: urls?.documentationUrl ?? ""
3575
3616
  },
3576
3617
  verifiedAt: /* @__PURE__ */ new Date(),
3577
3618
  // Extract sessionId so decisions can be recorded for denials too
@@ -3640,13 +3681,15 @@ async function verify(config, request) {
3640
3681
  result.denialReasons = result.recommendationReasons || [
3641
3682
  "Access denied by AstraSync recommendation"
3642
3683
  ];
3643
- if (result.runtimeChallenge) {
3644
- result.guidance = {
3645
- message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
3646
- registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/register`,
3647
- documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/runtime-challenge`
3648
- };
3649
- }
3684
+ result.guidance = result.runtimeChallenge ? {
3685
+ message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
3686
+ registrationUrl: urls?.registrationUrl ?? "",
3687
+ documentationUrl: urls?.documentationUrl ?? ""
3688
+ } : {
3689
+ message: result.recommendationReasons?.[0] || "Access denied by AstraSync recommendation",
3690
+ registrationUrl: urls?.registrationUrl ?? "",
3691
+ documentationUrl: urls?.documentationUrl ?? ""
3692
+ };
3650
3693
  } else if (result.recommendation === "step_up_required") {
3651
3694
  result.requiresStepUp = true;
3652
3695
  if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
@@ -3672,6 +3715,35 @@ import { parseDictionary } from "structured-headers";
3672
3715
  // src/transport/rfc9421-verify.ts
3673
3716
  import { httpbis } from "http-message-signatures";
3674
3717
 
3718
+ // src/transport/nonce-store.ts
3719
+ var InMemoryNonceStore = class {
3720
+ constructor(capacity = 1e4) {
3721
+ this.entries = /* @__PURE__ */ new Map();
3722
+ this.lastSweepMs = 0;
3723
+ this.capacity = capacity;
3724
+ }
3725
+ seen(key, expiresAtMs) {
3726
+ const nowMs = Date.now();
3727
+ if (nowMs - this.lastSweepMs > 1e3) {
3728
+ for (const [k, exp] of this.entries) {
3729
+ if (exp <= nowMs) this.entries.delete(k);
3730
+ }
3731
+ this.lastSweepMs = nowMs;
3732
+ }
3733
+ const existing = this.entries.get(key);
3734
+ if (existing !== void 0 && existing > nowMs) {
3735
+ return true;
3736
+ }
3737
+ if (this.entries.size >= this.capacity) {
3738
+ const oldest = this.entries.keys().next().value;
3739
+ if (oldest !== void 0) this.entries.delete(oldest);
3740
+ }
3741
+ this.entries.set(key, expiresAtMs);
3742
+ return false;
3743
+ }
3744
+ };
3745
+ var defaultNonceStore = new InMemoryNonceStore();
3746
+
3675
3747
  // src/transport/vi.ts
3676
3748
  import { splitSdJwt, decodeSdJwtSync } from "@sd-jwt/decode";
3677
3749
  import { createHash } from "crypto";