@astrasyncai/verification-gateway 3.7.1 → 3.9.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 (109) hide show
  1. package/README.md +99 -11
  2. package/dist/adapter-interface/interface.d.mts +2 -2
  3. package/dist/adapter-interface/interface.d.ts +2 -2
  4. package/dist/adapters/express.d.mts +2 -2
  5. package/dist/adapters/express.d.ts +2 -2
  6. package/dist/adapters/express.js +2 -1
  7. package/dist/adapters/express.js.map +1 -1
  8. package/dist/adapters/express.mjs +2 -1
  9. package/dist/adapters/express.mjs.map +1 -1
  10. package/dist/adapters/http-pdlss.d.mts +81 -0
  11. package/dist/adapters/http-pdlss.d.ts +81 -0
  12. package/dist/adapters/http-pdlss.js +117 -0
  13. package/dist/adapters/http-pdlss.js.map +1 -0
  14. package/dist/adapters/http-pdlss.mjs +87 -0
  15. package/dist/adapters/http-pdlss.mjs.map +1 -0
  16. package/dist/adapters/mcp.d.mts +1 -1
  17. package/dist/adapters/mcp.d.ts +1 -1
  18. package/dist/adapters/mcp.js +2 -1
  19. package/dist/adapters/mcp.js.map +1 -1
  20. package/dist/adapters/mcp.mjs +2 -1
  21. package/dist/adapters/mcp.mjs.map +1 -1
  22. package/dist/adapters/nextjs.d.mts +2 -2
  23. package/dist/adapters/nextjs.d.ts +2 -2
  24. package/dist/adapters/nextjs.js +2 -1
  25. package/dist/adapters/nextjs.js.map +1 -1
  26. package/dist/adapters/nextjs.mjs +2 -1
  27. package/dist/adapters/nextjs.mjs.map +1 -1
  28. package/dist/adapters/sdk.d.mts +2 -2
  29. package/dist/adapters/sdk.d.ts +2 -2
  30. package/dist/adapters/sdk.js +2 -1
  31. package/dist/adapters/sdk.js.map +1 -1
  32. package/dist/adapters/sdk.mjs +2 -1
  33. package/dist/adapters/sdk.mjs.map +1 -1
  34. package/dist/agent/index.d.mts +2 -2
  35. package/dist/agent/index.d.ts +2 -2
  36. package/dist/bin/astrasync-claude-hook.js +14 -1
  37. package/dist/bin/astrasync-guard.js +14 -1
  38. package/dist/bin/astrasync.js +31 -1
  39. package/dist/browser/background.js +14 -1
  40. package/dist/browser/background.js.map +1 -1
  41. package/dist/browser/background.mjs +14 -1
  42. package/dist/browser/background.mjs.map +1 -1
  43. package/dist/browser/browser-adapter.d.mts +2 -2
  44. package/dist/browser/browser-adapter.d.ts +2 -2
  45. package/dist/claude-code/claude-code-adapter.d.mts +2 -2
  46. package/dist/claude-code/claude-code-adapter.d.ts +2 -2
  47. package/dist/cli/index.d.mts +2 -2
  48. package/dist/cli/index.d.ts +2 -2
  49. package/dist/cursor/cursor-adapter.d.mts +2 -2
  50. package/dist/cursor/cursor-adapter.d.ts +2 -2
  51. package/dist/cursor/extension.d.mts +2 -2
  52. package/dist/cursor/extension.d.ts +2 -2
  53. package/dist/cursor/extension.js +14 -1
  54. package/dist/cursor/extension.js.map +1 -1
  55. package/dist/cursor/extension.mjs +14 -1
  56. package/dist/cursor/extension.mjs.map +1 -1
  57. package/dist/edge-config.d.mts +130 -0
  58. package/dist/edge-config.d.ts +130 -0
  59. package/dist/edge-config.js +162 -0
  60. package/dist/edge-config.js.map +1 -0
  61. package/dist/edge-config.mjs +131 -0
  62. package/dist/edge-config.mjs.map +1 -0
  63. package/dist/{express-BnMO-H3y.d.mts → express-DXUyvv7t.d.mts} +1 -1
  64. package/dist/{express-DQhDzNAt.d.ts → express-sGXhDdd0.d.ts} +1 -1
  65. package/dist/gateway/gateway.d.mts +2 -2
  66. package/dist/gateway/gateway.d.ts +2 -2
  67. package/dist/gateway/gateway.js +14 -1
  68. package/dist/gateway/gateway.js.map +1 -1
  69. package/dist/gateway/gateway.mjs +14 -1
  70. package/dist/gateway/gateway.mjs.map +1 -1
  71. package/dist/git-trigger/git-hooks.d.mts +2 -2
  72. package/dist/git-trigger/git-hooks.d.ts +2 -2
  73. package/dist/{index-D8-dvUFA.d.ts → index-C61VL_OW.d.ts} +1 -1
  74. package/dist/{index-rftma0ln.d.ts → index-CMg-vjEK.d.ts} +1 -1
  75. package/dist/{index-WHKq2v17.d.mts → index-Dalih3EB.d.mts} +1 -1
  76. package/dist/{index-BT_aRn-I.d.mts → index-DmmdehNu.d.mts} +1 -1
  77. package/dist/index.d.mts +26 -82
  78. package/dist/index.d.ts +26 -82
  79. package/dist/index.js +226 -10
  80. package/dist/index.js.map +1 -1
  81. package/dist/index.mjs +215 -10
  82. package/dist/index.mjs.map +1 -1
  83. package/dist/local-evaluator/evaluator.d.mts +2 -2
  84. package/dist/local-evaluator/evaluator.d.ts +2 -2
  85. package/dist/{nextjs-DPj7ZNlq.d.ts → nextjs-DwUW-Nm1.d.ts} +1 -1
  86. package/dist/{nextjs-DFKYhxe6.d.mts → nextjs-F_2pbPIA.d.mts} +1 -1
  87. package/dist/platform-signatures.d.mts +47 -0
  88. package/dist/platform-signatures.d.ts +47 -0
  89. package/dist/platform-signatures.js +89 -0
  90. package/dist/platform-signatures.js.map +1 -0
  91. package/dist/platform-signatures.mjs +63 -0
  92. package/dist/platform-signatures.mjs.map +1 -0
  93. package/dist/{sdk-CAcHgB5x.d.ts → sdk-CfHANs4A.d.ts} +1 -1
  94. package/dist/{sdk-Cy3wAmDt.d.mts → sdk-Clob2-0A.d.mts} +1 -1
  95. package/dist/transport/index.d.mts +2 -2
  96. package/dist/transport/index.d.ts +2 -2
  97. package/dist/{types-CKe8O0lR.d.mts → types-ACMsV07B.d.mts} +112 -9
  98. package/dist/{types-CKe8O0lR.d.ts → types-ACMsV07B.d.ts} +112 -9
  99. package/dist/{types-B-ubjHER.d.mts → types-BtqUvK8v.d.mts} +1 -1
  100. package/dist/{types-Bgn5gxHQ.d.ts → types-DmSDgPpG.d.ts} +1 -1
  101. package/dist/ui/index.d.mts +1 -1
  102. package/dist/ui/index.d.ts +1 -1
  103. package/dist/verify.d.mts +144 -0
  104. package/dist/verify.d.ts +144 -0
  105. package/dist/verify.js +593 -0
  106. package/dist/verify.js.map +1 -0
  107. package/dist/verify.mjs +557 -0
  108. package/dist/verify.mjs.map +1 -0
  109. package/package.json +21 -1
package/dist/verify.js ADDED
@@ -0,0 +1,593 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/verify.ts
21
+ var verify_exports = {};
22
+ __export(verify_exports, {
23
+ clearCache: () => clearCache,
24
+ extractCredentials: () => extractCredentials,
25
+ fetchRoutes: () => fetchRoutes,
26
+ hasCredentials: () => hasCredentials,
27
+ quickVerify: () => quickVerify,
28
+ recordDecision: () => recordDecision,
29
+ reportCounterpartyPreCheckFailure: () => reportCounterpartyPreCheckFailure,
30
+ reportUnregisteredAttempt: () => reportUnregisteredAttempt,
31
+ verify: () => verify,
32
+ verifyAndRecord: () => verifyAndRecord
33
+ });
34
+ module.exports = __toCommonJS(verify_exports);
35
+
36
+ // src/access-levels.ts
37
+ function getTrustLevel(score) {
38
+ if (score >= 80) return "PLATINUM";
39
+ if (score >= 60) return "GOLD";
40
+ if (score >= 40) return "SILVER";
41
+ return "BRONZE";
42
+ }
43
+
44
+ // src/version.ts
45
+ var SDK_VERSION = "3.9.0";
46
+
47
+ // src/well-known.ts
48
+ var CACHE_TTL_MS = 60 * 60 * 1e3;
49
+ var cache = /* @__PURE__ */ new Map();
50
+ function getCachedWellKnownUrls(apiBaseUrl) {
51
+ return cache.get(apiBaseUrl)?.data;
52
+ }
53
+
54
+ // src/verify.ts
55
+ var DEFAULT_CONFIG = {
56
+ apiBaseUrl: "https://astrasync.ai/api",
57
+ // v2.3.9 (defect #30): default for unconfigured callers is `'none'` (no
58
+ // access). Pre-rename this defaulted to `'guidance'`, which combined with
59
+ // a route gated at `'guidance'` to silently let unverified traffic
60
+ // through (`hasMinimumAccess('guidance', 'guidance') === true`).
61
+ defaultAccessLevel: "none",
62
+ // minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
63
+ // cacheTtl deliberately unset. When undefined, cacheResult applies the 60s
64
+ // default; the caller's explicit value is honoured for cacheable results.
65
+ // Denials and step-up escalations are NEVER cached (3.6.0) regardless of
66
+ // cacheTtl. Set cacheTtl: 0 to disable caching entirely.
67
+ debug: false
68
+ };
69
+ var initCheckPerformed = false;
70
+ var deprecationWarningShown = false;
71
+ async function performInitCheck(apiBaseUrl, debug, strictInit) {
72
+ initCheckPerformed = true;
73
+ try {
74
+ const probeUrl = `${apiBaseUrl}/agents/verify-access`;
75
+ const response = await fetch(probeUrl, { method: "HEAD" });
76
+ const contentType = response.headers.get("content-type") ?? "";
77
+ if (contentType.startsWith("text/html")) {
78
+ 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).`;
79
+ if (strictInit) {
80
+ throw new Error(`${message} (strictInit=true)`);
81
+ }
82
+ console.warn(`${message} Set disableInitChecks: true on GatewayConfig to silence.`);
83
+ } else if (debug) {
84
+ console.log(
85
+ `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
86
+ );
87
+ }
88
+ } catch (err) {
89
+ if (strictInit) {
90
+ throw err;
91
+ }
92
+ if (debug) {
93
+ console.log(`[VerificationGateway] init check failed (non-blocking): ${String(err)}`);
94
+ }
95
+ }
96
+ }
97
+ var verificationCache = /* @__PURE__ */ new Map();
98
+ function getCacheKey(request, counterpartyId) {
99
+ const c = request.credentials;
100
+ return [
101
+ c.astraId || "",
102
+ c.apiKey || "",
103
+ c.jwt || "",
104
+ request.purpose || "",
105
+ request.action || "",
106
+ request.resourceType || "",
107
+ request.resource || "",
108
+ request.jurisdiction || "",
109
+ request.transactionValue ?? "",
110
+ request.currency || "",
111
+ // SECURITY (cross-merchant cache leak): the merchant identity is sent via
112
+ // `config.counterpartyId`, NOT on the request, so it was previously absent
113
+ // from the key — two verifies for the SAME agent/purpose/action/value but
114
+ // DIFFERENT merchants collided, and a grant at a permissive merchant (low
115
+ // trust floor) was served for a stricter one. Same bug class as the
116
+ // duration omission (F-A1-07). counterpartyId affects the backend verdict
117
+ // (trust floor / per-route policy), so it MUST key the cache.
118
+ counterpartyId || "",
119
+ request.counterpartyUrl || "",
120
+ request.counterpartyType || "",
121
+ request.isSubAgentRequest ? "1" : "0",
122
+ request.parentAgentId || "",
123
+ request.subAgentDepth ?? "",
124
+ // Audit F-A1-07: previously-missing dimensions that DO affect the
125
+ // backend verdict. Without these, two requests with different
126
+ // durations (e.g. 60s vs 86400s) collided on the same cache key and
127
+ // the shorter-duration allow served the longer-duration request.
128
+ request.durationRequired ?? "",
129
+ request.invocationProtocol || "",
130
+ request.enableRuntimeChallenge ? "1" : "0",
131
+ // callerMetadata fields contribute to risk model; include the ones
132
+ // backend reads. sourceIp/userAgent/forwardedFor change per-request
133
+ // so their inclusion effectively forces a re-check for any varying
134
+ // client (the right behavior — IP-driven anomaly scoring shouldn't
135
+ // be cached across IPs).
136
+ request.callerMetadata?.sourceIp || "",
137
+ request.callerMetadata?.userAgent || "",
138
+ request.callerMetadata?.forwardedFor || "",
139
+ request.callerMetadata?.agentCardUrl || ""
140
+ ].join("|");
141
+ }
142
+ function getCachedResult(request, counterpartyId) {
143
+ const key = getCacheKey(request, counterpartyId);
144
+ const cached = verificationCache.get(key);
145
+ if (cached && cached.expiresAt > Date.now()) {
146
+ return cached.result;
147
+ }
148
+ if (cached) {
149
+ verificationCache.delete(key);
150
+ }
151
+ return null;
152
+ }
153
+ var DEFAULT_CACHE_TTL_SECONDS = 60;
154
+ function cacheResult(request, result, configuredTtl, counterpartyId) {
155
+ const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : DEFAULT_CACHE_TTL_SECONDS;
156
+ const key = getCacheKey(request, counterpartyId);
157
+ verificationCache.set(key, {
158
+ result,
159
+ expiresAt: Date.now() + ttlSeconds * 1e3
160
+ });
161
+ }
162
+ function clearCache() {
163
+ verificationCache.clear();
164
+ }
165
+ function extractCredentials(headers, query) {
166
+ const credentials = {};
167
+ const ASTRA_ID_PATTERN = /^ASTRAE?-[A-Za-z0-9_-]{1,64}$/;
168
+ const astraIdHeader = headers["x-astra-id"] || headers["X-Astra-Id"] || headers["X-ASTRA-ID"] || headers["x-astra-agentid"] || headers["X-Astra-AgentId"] || headers["x-astra-agent-id"] || headers["X-Astra-Agent-Id"] || headers["X-ASTRA-AGENT-ID"];
169
+ if (astraIdHeader) {
170
+ const raw = Array.isArray(astraIdHeader) ? astraIdHeader[0] : typeof astraIdHeader === "string" ? astraIdHeader : void 0;
171
+ if (typeof raw === "string" && ASTRA_ID_PATTERN.test(raw)) {
172
+ credentials.astraId = raw;
173
+ }
174
+ }
175
+ const apiKeyHeader = headers["x-api-key"] || headers["X-Api-Key"] || headers["X-API-KEY"];
176
+ if (apiKeyHeader) {
177
+ credentials.apiKey = Array.isArray(apiKeyHeader) ? apiKeyHeader[0] : apiKeyHeader;
178
+ }
179
+ const authHeader = headers["authorization"] || headers["Authorization"];
180
+ if (authHeader) {
181
+ const authValue = Array.isArray(authHeader) ? authHeader[0] : authHeader;
182
+ if (typeof authValue === "string") {
183
+ credentials.authorizationHeader = authValue;
184
+ if (authValue.startsWith("Bearer ")) {
185
+ credentials.jwt = authValue.slice(7);
186
+ }
187
+ }
188
+ }
189
+ if (query) {
190
+ if (query.astraId && !credentials.astraId) {
191
+ credentials.astraId = query.astraId;
192
+ }
193
+ if (query.apiKey && !credentials.apiKey) {
194
+ credentials.apiKey = query.apiKey;
195
+ }
196
+ }
197
+ return credentials;
198
+ }
199
+ function hasCredentials(credentials) {
200
+ return !!(credentials.astraId || credentials.apiKey || credentials.jwt);
201
+ }
202
+ function createGuidanceResponse(_config, reason, options = {}) {
203
+ const source = options.source ?? "no_credentials";
204
+ const isApiError = source === "api_error";
205
+ const urls = options.urls;
206
+ const guidance = isApiError ? {
207
+ message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
208
+ registrationUrl: urls?.registrationUrl ?? "",
209
+ documentationUrl: urls?.documentationUrl ?? "",
210
+ steps: [
211
+ "Retry the request with exponential backoff",
212
+ "If failures persist, share the correlationId with support"
213
+ ]
214
+ } : {
215
+ message: "This service verifies AI agents before granting access. Please register your agent with AstraSync.",
216
+ registrationUrl: urls?.registrationUrl ?? "",
217
+ documentationUrl: urls?.documentationUrl ?? "",
218
+ steps: [
219
+ "Register for an AstraSync account",
220
+ "Create and register your agent",
221
+ "Add your ASTRA-ID to request headers",
222
+ "Retry your request"
223
+ ]
224
+ };
225
+ return {
226
+ // Round-18 G4: createGuidanceResponse fires for unverified-agent path or
227
+ // API-error fallback. Identity is not verified (no agent resolved);
228
+ // policy is not evaluated (we never reached the gate).
229
+ identityVerified: false,
230
+ policyAllowed: false,
231
+ // v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
232
+ // Adapters additionally short-circuit on `!identityVerified ||
233
+ // !policyAllowed` before the gate check, but the access level still has
234
+ // to be honest at the data layer so downstream consumers (SDK adapters
235
+ // in other languages, custom integrations) inherit the correct
236
+ // semantics.
237
+ accessLevel: "none",
238
+ guidance,
239
+ denialReasons: reason ? [reason] : ["No valid agent credentials provided"],
240
+ // Round-10 (#47, O5): on API-error fallback, surface a typed failure so
241
+ // partners (and their custom onDenied handlers) can branch on
242
+ // dimension. Without this, the synthesised stub was indistinguishable
243
+ // from a real policy deny.
244
+ failures: isApiError ? [
245
+ {
246
+ dimension: "verify_access.api_error",
247
+ message: reason ?? "Verification temporarily unavailable",
248
+ guidance: guidance.message
249
+ }
250
+ ] : void 0,
251
+ correlationId: options.correlationId,
252
+ verifiedAt: /* @__PURE__ */ new Date()
253
+ };
254
+ }
255
+ async function callVerifyAccessAPI(config, request) {
256
+ const { credentials, ...requestData } = request;
257
+ const body = {
258
+ ...credentials.astraId && { agentId: credentials.astraId },
259
+ ...requestData.purpose && { purpose: requestData.purpose }
260
+ };
261
+ if (requestData.action) body.action = requestData.action;
262
+ if (requestData.resourceType) body.resourceType = requestData.resourceType;
263
+ if (requestData.resource) body.resource = requestData.resource;
264
+ if (requestData.jurisdiction) body.jurisdiction = requestData.jurisdiction;
265
+ if (requestData.transactionValue) body.transactionValue = requestData.transactionValue;
266
+ if (requestData.currency) body.currency = requestData.currency;
267
+ if (requestData.isSubAgentRequest) body.isSubAgentRequest = requestData.isSubAgentRequest;
268
+ if (requestData.parentAgentId) body.parentAgentId = requestData.parentAgentId;
269
+ if (requestData.subAgentDepth !== void 0) body.subAgentDepth = requestData.subAgentDepth;
270
+ if (requestData.enableRuntimeChallenge)
271
+ body.enableRuntimeChallenge = requestData.enableRuntimeChallenge;
272
+ if (requestData.createSession) body.createSession = requestData.createSession;
273
+ if (requestData.durationRequired) body.durationRequired = requestData.durationRequired;
274
+ if (requestData.counterpartyType) body.counterpartyType = requestData.counterpartyType;
275
+ if (requestData.counterpartyUrl) body.counterpartyUrl = requestData.counterpartyUrl;
276
+ if (config.counterpartyId) body.counterpartyId = config.counterpartyId;
277
+ if (requestData.runtimeChallengeOptions)
278
+ body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
279
+ if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;
280
+ if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
281
+ body.sdkVersion = SDK_VERSION;
282
+ if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
283
+ const meta = {
284
+ ...requestData.clientIp && { sourceIp: requestData.clientIp },
285
+ ...requestData.userAgent && { userAgent: requestData.userAgent },
286
+ ...requestData.callerMetadata
287
+ };
288
+ if (Object.keys(meta).length > 0) body.callerMetadata = meta;
289
+ }
290
+ const headers = {
291
+ "Content-Type": "application/json",
292
+ ...config.customHeaders
293
+ };
294
+ if (config.apiKey) {
295
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
296
+ headers["X-API-Key"] = config.apiKey;
297
+ }
298
+ try {
299
+ const response = await fetch(`${config.apiBaseUrl}/agents/verify-access`, {
300
+ method: "POST",
301
+ headers,
302
+ body: JSON.stringify(body)
303
+ });
304
+ const data = await response.json();
305
+ if (response.status === 410) {
306
+ return {
307
+ success: true,
308
+ access: {
309
+ allowed: false,
310
+ accessLevel: "none",
311
+ reason: "endpoint_deactivated",
312
+ failures: [
313
+ {
314
+ dimension: "endpoint.deactivated",
315
+ message: typeof data?.message === "string" ? data.message : "Endpoint has been deactivated",
316
+ guidance: typeof data?.guidance === "string" ? data.guidance : "Reactivate via POST /api/endpoints/{id}/reactivate, or update the URL on the calling agent."
317
+ }
318
+ ]
319
+ }
320
+ };
321
+ }
322
+ if (!response.ok) {
323
+ return {
324
+ success: false,
325
+ error: data.message || data.error || `API returned ${response.status}`,
326
+ correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0
327
+ };
328
+ }
329
+ return data;
330
+ } catch (error) {
331
+ const message = error instanceof Error ? error.message : "Unknown error";
332
+ return {
333
+ success: false,
334
+ error: `Failed to call verify-access API: ${message}`
335
+ };
336
+ }
337
+ }
338
+ async function verify(config, request, options) {
339
+ const mergedConfig = { ...DEFAULT_CONFIG, ...config };
340
+ const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
341
+ if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
342
+ if (mergedConfig.strictInit) {
343
+ await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
344
+ } else {
345
+ void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
346
+ }
347
+ }
348
+ if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
349
+ deprecationWarningShown = true;
350
+ console.warn(
351
+ "[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access-level decisions (the SDK reads access.accessLevel from the verify-access response). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side."
352
+ );
353
+ }
354
+ if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {
355
+ const cached = getCachedResult(request, mergedConfig.counterpartyId);
356
+ if (cached) {
357
+ if (mergedConfig.debug) {
358
+ console.log("[VerificationGateway] Returning cached result");
359
+ }
360
+ return cached;
361
+ }
362
+ }
363
+ const enrichedRequest = { ...request };
364
+ if (!enrichedRequest.counterpartyUrl && mergedConfig.counterpartyUrl) {
365
+ enrichedRequest.counterpartyUrl = mergedConfig.counterpartyUrl;
366
+ }
367
+ if (!enrichedRequest.counterpartyType && mergedConfig.counterpartyType) {
368
+ enrichedRequest.counterpartyType = mergedConfig.counterpartyType;
369
+ }
370
+ if (mergedConfig.debug) {
371
+ console.log("[VerificationGateway] Calling verify-access API");
372
+ }
373
+ const apiResponse = await callVerifyAccessAPI(mergedConfig, enrichedRequest);
374
+ const rawServerDenialReasons = apiResponse.denialReasons;
375
+ const serverDenialReasons = Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0 ? rawServerDenialReasons : void 0;
376
+ if (!apiResponse.success) {
377
+ return createGuidanceResponse(mergedConfig, apiResponse.error, {
378
+ source: "api_error",
379
+ correlationId: apiResponse.correlationId,
380
+ urls
381
+ });
382
+ }
383
+ if (!apiResponse.access?.allowed) {
384
+ const aggregatedFailures = apiResponse.access?.failures;
385
+ const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true;
386
+ const result2 = {
387
+ identityVerified: idVerifiedFromBackend,
388
+ policyAllowed: false,
389
+ // v2.3.9 (defect #30): denials grant `'none'`, NEVER a positive band.
390
+ // Pre-rename this hardcoded `'guidance'`, which conflated with the
391
+ // colocated `guidance: {...}` help-payload object below and let
392
+ // denied requests pass any route gated at `'guidance'` because
393
+ // `hasMinimumAccess('guidance', 'guidance') === true`. Adapters now
394
+ // ALSO short-circuit on `!identityVerified || !policyAllowed` before
395
+ // the gate check — belt-and-braces.
396
+ accessLevel: "none",
397
+ // 3.6.0: the server now emits top-level denialReasons on every deny
398
+ // path — prefer it verbatim; the failure-message reconstruction remains
399
+ // as the fallback for older backends.
400
+ denialReasons: serverDenialReasons ?? (aggregatedFailures && aggregatedFailures.length > 0 ? aggregatedFailures.map((f) => f.message) : apiResponse.access?.reason ? [apiResponse.access.reason] : ["Access denied"]),
401
+ failures: aggregatedFailures,
402
+ requiresStepUp: apiResponse.access?.requiresStepUp,
403
+ requiresApproval: apiResponse.access?.requiresApproval,
404
+ guidance: {
405
+ message: apiResponse.access?.reason || "Access denied by PDLSS policy",
406
+ registrationUrl: urls?.registrationUrl ?? "",
407
+ documentationUrl: urls?.documentationUrl ?? ""
408
+ },
409
+ verifiedAt: /* @__PURE__ */ new Date(),
410
+ // Extract sessionId so decisions can be recorded for denials too
411
+ sessionId: apiResponse.sessionId,
412
+ // Anonymous traffic has no session → correlationId is the per-attempt
413
+ // linking key (the sessionId-equivalent for anonymous callers).
414
+ correlationId: apiResponse.correlationId,
415
+ recommendation: apiResponse.recommendation,
416
+ recommendationReasons: apiResponse.recommendationReasons,
417
+ stepUpApproval: apiResponse.stepUpApproval,
418
+ settlement: apiResponse.settlement
419
+ };
420
+ return result2;
421
+ }
422
+ const agent = apiResponse.agent ? {
423
+ astraId: apiResponse.agent.astraId,
424
+ name: apiResponse.agent.name,
425
+ trustScore: apiResponse.agent.trustScore,
426
+ trustLevel: getTrustLevel(apiResponse.agent.trustScore),
427
+ blockchainVerified: apiResponse.agent.blockchainStatus === "verified",
428
+ status: apiResponse.agent.agentStatus
429
+ } : void 0;
430
+ const developer = apiResponse.developer ? {
431
+ astradId: apiResponse.developer.kyaOwnerId,
432
+ name: apiResponse.developer.fullName,
433
+ trustScore: apiResponse.developer.trustScore || 0,
434
+ verified: apiResponse.developer.identityVerified
435
+ } : void 0;
436
+ const organization = apiResponse.organization ? {
437
+ name: apiResponse.organization.name,
438
+ verified: apiResponse.organization.verified,
439
+ trustScore: apiResponse.organization.trustScore
440
+ } : void 0;
441
+ const verificationContext = apiResponse.verificationContext;
442
+ const accessLevel = apiResponse.access?.accessLevel ?? "standard";
443
+ const result = {
444
+ // Round-18 G4: backend allowed access. Identity is verified (we resolved
445
+ // the caller to an agent) and policy passed all gates. Read idVerified
446
+ // from verificationContext for symmetry with the deny branch; default true
447
+ // on success path since `access.allowed === true` implies identity was
448
+ // resolvable (anonymous-allow paths flow through createGuidanceResponse).
449
+ identityVerified: apiResponse.verificationContext?.idVerified !== false,
450
+ policyAllowed: true,
451
+ accessLevel,
452
+ agent,
453
+ developer,
454
+ organization,
455
+ appliedPolicy: apiResponse.access?.appliedPolicy,
456
+ verificationContext,
457
+ requiresStepUp: apiResponse.access?.requiresStepUp,
458
+ requiresApproval: apiResponse.access?.requiresApproval,
459
+ verifiedAt: /* @__PURE__ */ new Date(),
460
+ cacheTtl: mergedConfig.cacheTtl,
461
+ // Handshake Protocol v10 enhanced fields (present when backend returns them)
462
+ sessionId: apiResponse.sessionId,
463
+ // v2.3.10 (defect #34, round-4): anonymous responses surface correlationId
464
+ // (no session row exists for unverified callers).
465
+ correlationId: apiResponse.correlationId,
466
+ runtimeChallenge: apiResponse.runtimeChallenge,
467
+ tokenGuidance: apiResponse.tokenGuidance,
468
+ recommendation: apiResponse.recommendation,
469
+ recommendationReasons: apiResponse.recommendationReasons,
470
+ warningHeader: apiResponse.warningHeader,
471
+ stepUpApproval: apiResponse.stepUpApproval,
472
+ settlement: apiResponse.settlement
473
+ };
474
+ if (result.recommendation === "deny") {
475
+ result.policyAllowed = false;
476
+ result.accessLevel = "none";
477
+ result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Access denied by AstraSync recommendation"];
478
+ result.guidance = result.runtimeChallenge ? {
479
+ message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
480
+ registrationUrl: urls?.registrationUrl ?? "",
481
+ documentationUrl: urls?.documentationUrl ?? ""
482
+ } : {
483
+ message: result.recommendationReasons?.[0] || "Access denied by AstraSync recommendation",
484
+ registrationUrl: urls?.registrationUrl ?? "",
485
+ documentationUrl: urls?.documentationUrl ?? ""
486
+ };
487
+ } else if (result.recommendation === "step_up_required") {
488
+ result.requiresStepUp = true;
489
+ result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Step-up verification required"];
490
+ }
491
+ const escalates = result.requiresStepUp === true || result.requiresApproval === true || result.recommendation === "step_up_required";
492
+ if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny" && !escalates) {
493
+ cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
494
+ }
495
+ return result;
496
+ }
497
+ async function recordDecision(config, sessionId, decision, reason) {
498
+ const headers = { "Content-Type": "application/json" };
499
+ if (config.apiKey) {
500
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
501
+ headers["X-API-Key"] = config.apiKey;
502
+ }
503
+ await fetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
504
+ method: "POST",
505
+ headers,
506
+ body: JSON.stringify({ decision, reason })
507
+ }).catch(() => {
508
+ });
509
+ }
510
+ async function fetchRoutes(config, counterpartyId) {
511
+ if (!counterpartyId) return null;
512
+ const headers = { "Content-Type": "application/json" };
513
+ if (config.apiKey) {
514
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
515
+ headers["X-API-Key"] = config.apiKey;
516
+ }
517
+ try {
518
+ const response = await fetch(
519
+ `${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,
520
+ { method: "GET", headers }
521
+ );
522
+ if (!response.ok) return null;
523
+ const body = await response.json();
524
+ return body.data?.routes ?? [];
525
+ } catch {
526
+ return null;
527
+ }
528
+ }
529
+ async function verifyAndRecord(config, request, options) {
530
+ const mergedConfig = { ...DEFAULT_CONFIG, ...config };
531
+ const result = await verify(mergedConfig, { ...request, createSession: true }, options);
532
+ const sessionId = result.sessionId;
533
+ if (sessionId) {
534
+ if (result.identityVerified && result.policyAllowed) {
535
+ recordDecision(mergedConfig, sessionId, "granted").catch(() => {
536
+ });
537
+ } else {
538
+ recordDecision(mergedConfig, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
539
+ });
540
+ }
541
+ }
542
+ return result;
543
+ }
544
+ async function reportUnregisteredAttempt(config, data) {
545
+ const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
546
+ const { counterpartyUrl, ...rest } = data;
547
+ const body = {
548
+ ...rest,
549
+ ...counterpartyUrl && { counterpartyUrl },
550
+ ...config.counterpartyId && { counterpartyId: config.counterpartyId }
551
+ };
552
+ await fetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {
553
+ method: "POST",
554
+ headers: { "Content-Type": "application/json" },
555
+ body: JSON.stringify(body)
556
+ }).catch(() => {
557
+ });
558
+ }
559
+ async function reportCounterpartyPreCheckFailure(config, data) {
560
+ const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
561
+ await fetch(`${apiBaseUrl}/verification-activity/counterparty-pre-check-failure`, {
562
+ method: "POST",
563
+ headers: { "Content-Type": "application/json" },
564
+ body: JSON.stringify(data)
565
+ }).catch(() => {
566
+ });
567
+ }
568
+ async function quickVerify(config, credentials) {
569
+ const result = await verify(config, {
570
+ credentials,
571
+ purpose: "verification"
572
+ });
573
+ return {
574
+ identityVerified: result.identityVerified,
575
+ policyAllowed: result.policyAllowed,
576
+ accessLevel: result.accessLevel,
577
+ reason: result.denialReasons?.[0]
578
+ };
579
+ }
580
+ // Annotate the CommonJS export names for ESM import in node:
581
+ 0 && (module.exports = {
582
+ clearCache,
583
+ extractCredentials,
584
+ fetchRoutes,
585
+ hasCredentials,
586
+ quickVerify,
587
+ recordDecision,
588
+ reportCounterpartyPreCheckFailure,
589
+ reportUnregisteredAttempt,
590
+ verify,
591
+ verifyAndRecord
592
+ });
593
+ //# sourceMappingURL=verify.js.map