@astrasyncai/verification-gateway 2.4.14 → 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.
@@ -20,6 +20,65 @@ function hasMinimumAccess(actual, required) {
20
20
  // src/version.ts
21
21
  var SDK_VERSION = "2.4.13";
22
22
 
23
+ // src/well-known.ts
24
+ var CACHE_TTL_MS = 60 * 60 * 1e3;
25
+ var cache = /* @__PURE__ */ new Map();
26
+ var inflight = /* @__PURE__ */ new Map();
27
+ function wellKnownUrl(apiBaseUrl) {
28
+ const base = apiBaseUrl.replace(/\/api\/?$/, "");
29
+ return `${base}/.well-known/agentic-commerce`;
30
+ }
31
+ async function fetchWellKnown(apiBaseUrl) {
32
+ const url = wellKnownUrl(apiBaseUrl);
33
+ const response = await fetch(url, {
34
+ method: "GET",
35
+ headers: { Accept: "application/json" },
36
+ signal: AbortSignal.timeout(5e3)
37
+ });
38
+ if (!response.ok) {
39
+ throw new Error(
40
+ `AstraSync platform must expose /.well-known/agentic-commerce; got ${response.status} from ${url}. SDK cannot initialise without it.`
41
+ );
42
+ }
43
+ const data = await response.json();
44
+ if (!data.registrationUrl || !data.documentationUrl || !data.verifyAccessUrl) {
45
+ throw new Error(
46
+ `/.well-known/agentic-commerce response missing required fields (registrationUrl, documentationUrl, verifyAccessUrl).`
47
+ );
48
+ }
49
+ return data;
50
+ }
51
+ function prefetchWellKnown(apiBaseUrl) {
52
+ const existing = inflight.get(apiBaseUrl);
53
+ if (existing) return existing;
54
+ const promise = fetchWellKnown(apiBaseUrl).then((data) => {
55
+ cache.set(apiBaseUrl, { data, fetchedAt: Date.now() });
56
+ inflight.delete(apiBaseUrl);
57
+ return data;
58
+ }).catch((err) => {
59
+ inflight.delete(apiBaseUrl);
60
+ throw err;
61
+ });
62
+ inflight.set(apiBaseUrl, promise);
63
+ return promise;
64
+ }
65
+ async function getWellKnownUrls(apiBaseUrl) {
66
+ const entry = cache.get(apiBaseUrl);
67
+ if (entry) {
68
+ if (Date.now() - entry.fetchedAt > CACHE_TTL_MS) {
69
+ prefetchWellKnown(apiBaseUrl).catch(() => {
70
+ });
71
+ }
72
+ return entry.data;
73
+ }
74
+ const pending = inflight.get(apiBaseUrl);
75
+ if (pending) return pending;
76
+ return prefetchWellKnown(apiBaseUrl);
77
+ }
78
+ function getCachedWellKnownUrls(apiBaseUrl) {
79
+ return cache.get(apiBaseUrl)?.data;
80
+ }
81
+
23
82
  // src/verify.ts
24
83
  var DEFAULT_CONFIG = {
25
84
  apiBaseUrl: "https://astrasync.ai/api",
@@ -155,21 +214,22 @@ function extractCredentials(headers, query) {
155
214
  }
156
215
  return credentials;
157
216
  }
158
- function createGuidanceResponse(config, reason, options = {}) {
217
+ function createGuidanceResponse(_config, reason, options = {}) {
159
218
  const source = options.source ?? "no_credentials";
160
219
  const isApiError = source === "api_error";
220
+ const urls = options.urls;
161
221
  const guidance = isApiError ? {
162
222
  message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
163
- registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/agents/register`,
164
- documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
223
+ registrationUrl: urls?.registrationUrl ?? "",
224
+ documentationUrl: urls?.documentationUrl ?? "",
165
225
  steps: [
166
226
  "Retry the request with exponential backoff",
167
227
  "If failures persist, share the correlationId with support"
168
228
  ]
169
229
  } : {
170
230
  message: "This service verifies AI agents before granting access. Please register your agent with AstraSync.",
171
- registrationUrl: `${config.apiBaseUrl.replace("/api", "")}/agents/register`,
172
- documentationUrl: `${config.apiBaseUrl.replace("/api", "")}/docs/agent-access`,
231
+ registrationUrl: urls?.registrationUrl ?? "",
232
+ documentationUrl: urls?.documentationUrl ?? "",
173
233
  steps: [
174
234
  "Register for an AstraSync account",
175
235
  "Create and register your agent",
@@ -211,7 +271,7 @@ async function callVerifyAccessAPI(config, request) {
211
271
  const { credentials, ...requestData } = request;
212
272
  const body = {
213
273
  ...credentials.astraId && { agentId: credentials.astraId },
214
- purpose: requestData.purpose || "general"
274
+ ...requestData.purpose && { purpose: requestData.purpose }
215
275
  };
216
276
  if (requestData.action) body.action = requestData.action;
217
277
  if (requestData.resourceType) body.resourceType = requestData.resourceType;
@@ -291,6 +351,7 @@ async function callVerifyAccessAPI(config, request) {
291
351
  }
292
352
  async function verify(config, request) {
293
353
  const mergedConfig = { ...DEFAULT_CONFIG, ...config };
354
+ const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
294
355
  if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
295
356
  if (mergedConfig.strictInit) {
296
357
  await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
@@ -327,7 +388,8 @@ async function verify(config, request) {
327
388
  if (!apiResponse.success) {
328
389
  return createGuidanceResponse(mergedConfig, apiResponse.error, {
329
390
  source: "api_error",
330
- correlationId: apiResponse.correlationId
391
+ correlationId: apiResponse.correlationId,
392
+ urls
331
393
  });
332
394
  }
333
395
  if (!apiResponse.access?.allowed) {
@@ -350,8 +412,8 @@ async function verify(config, request) {
350
412
  requiresApproval: apiResponse.access?.requiresApproval,
351
413
  guidance: {
352
414
  message: apiResponse.access?.reason || "Access denied by PDLSS policy",
353
- registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/agents/register`,
354
- documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
415
+ registrationUrl: urls?.registrationUrl ?? "",
416
+ documentationUrl: urls?.documentationUrl ?? ""
355
417
  },
356
418
  verifiedAt: /* @__PURE__ */ new Date(),
357
419
  // Extract sessionId so decisions can be recorded for denials too
@@ -422,12 +484,12 @@ async function verify(config, request) {
422
484
  ];
423
485
  result.guidance = result.runtimeChallenge ? {
424
486
  message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
425
- registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/agents/register`,
426
- documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/runtime-challenge`
487
+ registrationUrl: urls?.registrationUrl ?? "",
488
+ documentationUrl: urls?.documentationUrl ?? ""
427
489
  } : {
428
490
  message: result.recommendationReasons?.[0] || "Access denied by AstraSync recommendation",
429
- registrationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/agents/register`,
430
- documentationUrl: `${mergedConfig.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
491
+ registrationUrl: urls?.registrationUrl ?? "",
492
+ documentationUrl: urls?.documentationUrl ?? ""
431
493
  };
432
494
  } else if (result.recommendation === "step_up_required") {
433
495
  result.requiresStepUp = true;
@@ -650,6 +712,9 @@ function dedupeFailures(result) {
650
712
  return true;
651
713
  });
652
714
  }
715
+ if (result.denialReasons && result.denialReasons.length > 1) {
716
+ result.denialReasons = [...new Set(result.denialReasons)];
717
+ }
653
718
  }
654
719
  function defaultOnDenied(result, _req, res) {
655
720
  const statusCode = !result.identityVerified ? 401 : 403;
@@ -681,6 +746,10 @@ function createMiddleware(options) {
681
746
  caseInsensitiveRouteMatch = false,
682
747
  ...config
683
748
  } = options;
749
+ if (config.apiBaseUrl) {
750
+ prefetchWellKnown(config.apiBaseUrl).catch(() => {
751
+ });
752
+ }
684
753
  let cachedRoutes = [];
685
754
  let lastFetchAt = 0;
686
755
  let refreshing = null;
@@ -743,6 +812,7 @@ function createMiddleware(options) {
743
812
  }
744
813
  return next();
745
814
  }
815
+ const wellKnownUrls = config.apiBaseUrl ? await getWellKnownUrls(config.apiBaseUrl).catch(() => void 0) : void 0;
746
816
  const credentials = customExtractCredentials ? customExtractCredentials(req) : defaultExtractCredentials(req);
747
817
  const shouldEnforce = routeConfig.minAccessLevel !== "none";
748
818
  if (routeConfig.minAccessLevel === "none" && (!config.evaluateAlwaysIfCredentialed || !credentials.astraId)) {
@@ -764,8 +834,8 @@ function createMiddleware(options) {
764
834
  denialReasons: preCheckFailures.map((f) => f.message),
765
835
  guidance: {
766
836
  message: "Request exceeds counterparty-defined PDLSS limits.",
767
- registrationUrl: `${config.apiBaseUrl?.replace("/api", "")}/agents/register`,
768
- documentationUrl: `${config.apiBaseUrl?.replace("/api", "")}/docs/pdlss`
837
+ registrationUrl: wellKnownUrls?.registrationUrl ?? "",
838
+ documentationUrl: wellKnownUrls?.documentationUrl ?? ""
769
839
  },
770
840
  verifiedAt: /* @__PURE__ */ new Date()
771
841
  };
@@ -845,6 +915,13 @@ function createMiddleware(options) {
845
915
  };
846
916
  result.failures = [...result.failures ?? [], insufficientFailure];
847
917
  result.denialReasons = [...result.denialReasons ?? [], insufficientFailure.message];
918
+ if (!result.guidance && wellKnownUrls) {
919
+ result.guidance = {
920
+ message: insufficientFailure.message,
921
+ registrationUrl: wellKnownUrls.registrationUrl,
922
+ documentationUrl: wellKnownUrls.documentationUrl
923
+ };
924
+ }
848
925
  if (shouldRecordDecisions && sessionId) {
849
926
  recordDecision(config, sessionId, "denied", insufficientFailure.message).catch(() => {
850
927
  });
@@ -862,6 +939,13 @@ function createMiddleware(options) {
862
939
  };
863
940
  result.failures = [...result.failures ?? [], trustFailure];
864
941
  result.denialReasons = [trustFailure.message];
942
+ if (!result.guidance && wellKnownUrls) {
943
+ result.guidance = {
944
+ message: trustFailure.message,
945
+ registrationUrl: wellKnownUrls.registrationUrl,
946
+ documentationUrl: wellKnownUrls.documentationUrl
947
+ };
948
+ }
865
949
  if (shouldRecordDecisions && sessionId) {
866
950
  recordDecision(config, sessionId, "denied", trustFailure.message).catch(() => {
867
951
  });
@@ -902,6 +986,14 @@ function createMiddleware(options) {
902
986
  verifiedAt: /* @__PURE__ */ new Date(),
903
987
  correlationId
904
988
  };
989
+ const catchUrls = config.apiBaseUrl ? await getWellKnownUrls(config.apiBaseUrl).catch(() => void 0) : void 0;
990
+ if (catchUrls) {
991
+ result.guidance = {
992
+ message: `Middleware threw ${errorClass} \u2014 failing closed`,
993
+ registrationUrl: catchUrls.registrationUrl,
994
+ documentationUrl: catchUrls.documentationUrl
995
+ };
996
+ }
905
997
  dedupeFailures(result);
906
998
  return onDenied(result, req, res);
907
999
  }