@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
@@ -18,7 +18,14 @@ function hasMinimumAccess(actual, required) {
18
18
  }
19
19
 
20
20
  // src/version.ts
21
- var SDK_VERSION = "2.4.12";
21
+ var SDK_VERSION = "2.4.13";
22
+
23
+ // src/well-known.ts
24
+ var CACHE_TTL_MS = 60 * 60 * 1e3;
25
+ var cache = /* @__PURE__ */ new Map();
26
+ function getCachedWellKnownUrls(apiBaseUrl) {
27
+ return cache.get(apiBaseUrl)?.data;
28
+ }
22
29
 
23
30
  // src/verify.ts
24
31
  var DEFAULT_CONFIG = {
@@ -37,22 +44,27 @@ var DEFAULT_CONFIG = {
37
44
  };
38
45
  var initCheckPerformed = false;
39
46
  var deprecationWarningShown = false;
40
- async function performInitCheck(apiBaseUrl, debug) {
47
+ async function performInitCheck(apiBaseUrl, debug, strictInit) {
41
48
  initCheckPerformed = true;
42
49
  try {
43
50
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
44
51
  const response = await fetch(probeUrl, { method: "HEAD" });
45
52
  const contentType = response.headers.get("content-type") ?? "";
46
53
  if (contentType.startsWith("text/html")) {
47
- console.warn(
48
- `[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.`
49
- );
54
+ 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).`;
55
+ if (strictInit) {
56
+ throw new Error(`${message} (strictInit=true)`);
57
+ }
58
+ console.warn(`${message} Set disableInitChecks: true on GatewayConfig to silence.`);
50
59
  } else if (debug) {
51
60
  console.log(
52
61
  `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
53
62
  );
54
63
  }
55
64
  } catch (err) {
65
+ if (strictInit) {
66
+ throw err;
67
+ }
56
68
  if (debug) {
57
69
  console.log(`[VerificationGateway] init check failed (non-blocking): ${String(err)}`);
58
70
  }
@@ -76,7 +88,23 @@ function getCacheKey(request) {
76
88
  request.counterpartyType || "",
77
89
  request.isSubAgentRequest ? "1" : "0",
78
90
  request.parentAgentId || "",
79
- request.subAgentDepth ?? ""
91
+ request.subAgentDepth ?? "",
92
+ // Audit F-A1-07: previously-missing dimensions that DO affect the
93
+ // backend verdict. Without these, two requests with different
94
+ // durations (e.g. 60s vs 86400s) collided on the same cache key and
95
+ // the shorter-duration allow served the longer-duration request.
96
+ request.durationRequired ?? "",
97
+ request.invocationProtocol || "",
98
+ request.enableRuntimeChallenge ? "1" : "0",
99
+ // callerMetadata fields contribute to risk model; include the ones
100
+ // backend reads. sourceIp/userAgent/forwardedFor change per-request
101
+ // so their inclusion effectively forces a re-check for any varying
102
+ // client (the right behavior — IP-driven anomaly scoring shouldn't
103
+ // be cached across IPs).
104
+ request.callerMetadata?.sourceIp || "",
105
+ request.callerMetadata?.userAgent || "",
106
+ request.callerMetadata?.forwardedFor || "",
107
+ request.callerMetadata?.agentCardUrl || ""
80
108
  ].join("|");
81
109
  }
82
110
  function getCachedResult(request) {
@@ -100,21 +128,22 @@ function cacheResult(request, result, configuredTtl) {
100
128
  expiresAt: Date.now() + ttlSeconds * 1e3
101
129
  });
102
130
  }
103
- function createGuidanceResponse(config, reason, options = {}) {
131
+ function createGuidanceResponse(_config, reason, options = {}) {
104
132
  const source = options.source ?? "no_credentials";
105
133
  const isApiError = source === "api_error";
134
+ const urls = options.urls;
106
135
  const guidance = isApiError ? {
107
136
  message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
108
- registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
109
- documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
137
+ registrationUrl: urls?.registrationUrl ?? "",
138
+ documentationUrl: urls?.documentationUrl ?? "",
110
139
  steps: [
111
140
  "Retry the request with exponential backoff",
112
141
  "If failures persist, share the correlationId with support"
113
142
  ]
114
143
  } : {
115
144
  message: "This service verifies AI agents before granting access. Please register your agent with AstraSync.",
116
- registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/register`,
117
- documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
145
+ registrationUrl: urls?.registrationUrl ?? "",
146
+ documentationUrl: urls?.documentationUrl ?? "",
118
147
  steps: [
119
148
  "Register for an AstraSync account",
120
149
  "Create and register your agent",
@@ -156,7 +185,7 @@ async function callVerifyAccessAPI(config, request) {
156
185
  const { credentials, ...requestData } = request;
157
186
  const body = {
158
187
  ...credentials.astraId && { agentId: credentials.astraId },
159
- purpose: requestData.purpose || "general"
188
+ ...requestData.purpose && { purpose: requestData.purpose }
160
189
  };
161
190
  if (requestData.action) body.action = requestData.action;
162
191
  if (requestData.resourceType) body.resourceType = requestData.resourceType;
@@ -190,12 +219,8 @@ async function callVerifyAccessAPI(config, request) {
190
219
  "Content-Type": "application/json",
191
220
  ...config.customHeaders
192
221
  };
193
- if (credentials.authorizationHeader) {
194
- headers["Authorization"] = credentials.authorizationHeader;
195
- } else if (config.apiKey) {
196
- headers["Authorization"] = `Bearer ${config.apiKey}`;
197
- }
198
222
  if (config.apiKey) {
223
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
199
224
  headers["X-API-Key"] = config.apiKey;
200
225
  }
201
226
  try {
@@ -240,8 +265,13 @@ async function callVerifyAccessAPI(config, request) {
240
265
  }
241
266
  async function verify(config, request) {
242
267
  const mergedConfig = { ...DEFAULT_CONFIG, ...config };
268
+ const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
243
269
  if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
244
- void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug);
270
+ if (mergedConfig.strictInit) {
271
+ await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
272
+ } else {
273
+ void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
274
+ }
245
275
  }
246
276
  if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
247
277
  deprecationWarningShown = true;
@@ -272,7 +302,8 @@ async function verify(config, request) {
272
302
  if (!apiResponse.success) {
273
303
  return createGuidanceResponse(mergedConfig, apiResponse.error, {
274
304
  source: "api_error",
275
- correlationId: apiResponse.correlationId
305
+ correlationId: apiResponse.correlationId,
306
+ urls
276
307
  });
277
308
  }
278
309
  if (!apiResponse.access?.allowed) {
@@ -295,8 +326,8 @@ async function verify(config, request) {
295
326
  requiresApproval: apiResponse.access?.requiresApproval,
296
327
  guidance: {
297
328
  message: apiResponse.access?.reason || "Access denied by PDLSS policy",
298
- registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/register`,
299
- documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
329
+ registrationUrl: urls?.registrationUrl ?? "",
330
+ documentationUrl: urls?.documentationUrl ?? ""
300
331
  },
301
332
  verifiedAt: /* @__PURE__ */ new Date(),
302
333
  // Extract sessionId so decisions can be recorded for denials too
@@ -365,13 +396,15 @@ async function verify(config, request) {
365
396
  result.denialReasons = result.recommendationReasons || [
366
397
  "Access denied by AstraSync recommendation"
367
398
  ];
368
- if (result.runtimeChallenge) {
369
- result.guidance = {
370
- message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
371
- registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/register`,
372
- documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/runtime-challenge`
373
- };
374
- }
399
+ result.guidance = result.runtimeChallenge ? {
400
+ message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
401
+ registrationUrl: urls?.registrationUrl ?? "",
402
+ documentationUrl: urls?.documentationUrl ?? ""
403
+ } : {
404
+ message: result.recommendationReasons?.[0] || "Access denied by AstraSync recommendation",
405
+ registrationUrl: urls?.registrationUrl ?? "",
406
+ documentationUrl: urls?.documentationUrl ?? ""
407
+ };
375
408
  } else if (result.recommendation === "step_up_required") {
376
409
  result.requiresStepUp = true;
377
410
  if (ACCESS_LEVEL_HIERARCHY[result.accessLevel] > ACCESS_LEVEL_HIERARCHY["read-only"]) {
@@ -501,6 +534,18 @@ function performCounterpartyPreCheck(routeConfig, astraCreds, purpose) {
501
534
  }
502
535
 
503
536
  // src/adapters/nextjs.ts
537
+ function escapeHtml(value) {
538
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
539
+ }
540
+ function sanitizeUrl(value, fallback) {
541
+ if (typeof value !== "string" || value.length === 0) return escapeHtml(fallback);
542
+ const trimmed = value.trim();
543
+ if (/^javascript:|^data:|^vbscript:/i.test(trimmed)) return escapeHtml(fallback);
544
+ if (/^https?:\/\//i.test(trimmed) || trimmed.startsWith("/")) {
545
+ return escapeHtml(trimmed);
546
+ }
547
+ return escapeHtml(fallback);
548
+ }
504
549
  function extractCredentialsFromNextRequest(request) {
505
550
  const credentials = {};
506
551
  const astraId = request.headers.get("x-astra-id") || request.headers.get("X-Astra-Id");
@@ -572,10 +617,18 @@ function extractPurpose(request) {
572
617
  }
573
618
  }
574
619
  function generateCommerceShieldHtml(result, options) {
575
- const title = options.commerceShield?.title || "AstraSync Agent Verification";
576
- const message = options.commerceShield?.message || result.guidance?.message || "This site verifies AI agents before granting access. We noticed you're visiting without AstraSync credentials.";
577
- const registrationUrl = result.guidance?.registrationUrl || "https://astrasync.ai/register";
578
- const docsUrl = result.guidance?.documentationUrl || "https://astrasync.ai/docs/agent-access";
620
+ const title = escapeHtml(options.commerceShield?.title || "AstraSync Agent Verification");
621
+ const message = escapeHtml(
622
+ options.commerceShield?.message || result.guidance?.message || "This site verifies AI agents before granting access. We noticed you're visiting without AstraSync credentials."
623
+ );
624
+ const registrationUrl = sanitizeUrl(
625
+ result.guidance?.registrationUrl,
626
+ "https://astrasync.ai/register"
627
+ );
628
+ const docsUrl = sanitizeUrl(
629
+ result.guidance?.documentationUrl,
630
+ "https://astrasync.ai/docs/agent-access"
631
+ );
579
632
  const allowGuest = options.commerceShield?.allowGuestAccess ?? true;
580
633
  return `
581
634
  <!DOCTYPE html>
@@ -697,7 +750,7 @@ function generateCommerceShieldHtml(result, options) {
697
750
  <div class="shield-steps">
698
751
  <h3>To get verified access:</h3>
699
752
  <ol>
700
- <li>Register at <a href="${registrationUrl}">astrasync.ai/register</a></li>
753
+ <li>Register at <a href="${registrationUrl}">astrasync.ai/agents/register</a></li>
701
754
  <li>Create and register your agent</li>
702
755
  <li>Add your ASTRA-ID to request headers</li>
703
756
  <li>Refresh this page</li>
@@ -785,7 +838,7 @@ function createMiddleware(options) {
785
838
  denialReasons: preCheckFailures.map((f) => f.message),
786
839
  guidance: {
787
840
  message: "Request exceeds counterparty-defined PDLSS limits.",
788
- registrationUrl: `${config.apiBaseUrl?.replace("/api", "")}/register`,
841
+ registrationUrl: `${config.apiBaseUrl?.replace("/api", "")}/agents/register`,
789
842
  documentationUrl: `${config.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
790
843
  },
791
844
  verifiedAt: /* @__PURE__ */ new Date()