@astrasyncai/verification-gateway 3.11.1 → 4.0.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 (99) 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 +106 -10
  6. package/dist/adapters/express.js.map +1 -1
  7. package/dist/adapters/express.mjs +106 -10
  8. package/dist/adapters/express.mjs.map +1 -1
  9. package/dist/adapters/mcp.d.mts +1 -1
  10. package/dist/adapters/mcp.d.ts +1 -1
  11. package/dist/adapters/mcp.js +111 -10
  12. package/dist/adapters/mcp.js.map +1 -1
  13. package/dist/adapters/mcp.mjs +111 -10
  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 +107 -10
  18. package/dist/adapters/nextjs.js.map +1 -1
  19. package/dist/adapters/nextjs.mjs +107 -10
  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 +92 -10
  24. package/dist/adapters/sdk.js.map +1 -1
  25. package/dist/adapters/sdk.mjs +92 -10
  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/bin/astrasync-claude-hook.js +92 -10
  30. package/dist/bin/astrasync-codex-hook.js +92 -10
  31. package/dist/bin/astrasync-guard.js +92 -10
  32. package/dist/bin/astrasync.js +93 -10
  33. package/dist/browser/background.js +92 -10
  34. package/dist/browser/background.js.map +1 -1
  35. package/dist/browser/background.mjs +92 -10
  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/claude-code/claude-code-adapter.d.mts +2 -2
  40. package/dist/claude-code/claude-code-adapter.d.ts +2 -2
  41. package/dist/cli/index.d.mts +2 -2
  42. package/dist/cli/index.d.ts +2 -2
  43. package/dist/codex/index.d.mts +2 -2
  44. package/dist/codex/index.d.ts +2 -2
  45. package/dist/codex/index.js +92 -10
  46. package/dist/codex/index.js.map +1 -1
  47. package/dist/codex/index.mjs +92 -10
  48. package/dist/codex/index.mjs.map +1 -1
  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 +92 -10
  54. package/dist/cursor/extension.js.map +1 -1
  55. package/dist/cursor/extension.mjs +92 -10
  56. package/dist/cursor/extension.mjs.map +1 -1
  57. package/dist/edge-config.d.mts +1 -1
  58. package/dist/edge-config.d.ts +1 -1
  59. package/dist/{express-DCXa1oqj.d.mts → express-BZajRs4i.d.mts} +1 -1
  60. package/dist/{express-ClNtDhhc.d.ts → express-CjCUB1k7.d.ts} +1 -1
  61. package/dist/gateway/gateway.d.mts +2 -2
  62. package/dist/gateway/gateway.d.ts +2 -2
  63. package/dist/gateway/gateway.js +92 -10
  64. package/dist/gateway/gateway.js.map +1 -1
  65. package/dist/gateway/gateway.mjs +92 -10
  66. package/dist/gateway/gateway.mjs.map +1 -1
  67. package/dist/git-trigger/git-hooks.d.mts +2 -2
  68. package/dist/git-trigger/git-hooks.d.ts +2 -2
  69. package/dist/{index-BrNKDmiR.d.mts → index-B0cyMZDL.d.mts} +1 -1
  70. package/dist/{index-Dr_XiN65.d.mts → index-BRYteOqO.d.mts} +1 -1
  71. package/dist/{index-CfHurO1P.d.ts → index-BZQdVqNw.d.ts} +1 -1
  72. package/dist/{index-D2ztkumS.d.ts → index-adgKhujR.d.ts} +1 -1
  73. package/dist/index.d.mts +9 -9
  74. package/dist/index.d.ts +9 -9
  75. package/dist/index.js +160 -10
  76. package/dist/index.js.map +1 -1
  77. package/dist/index.mjs +159 -10
  78. package/dist/index.mjs.map +1 -1
  79. package/dist/local-evaluator/evaluator.d.mts +2 -2
  80. package/dist/local-evaluator/evaluator.d.ts +2 -2
  81. package/dist/{nextjs-CEBVBsdi.d.ts → nextjs-D_iFf5k-.d.ts} +1 -1
  82. package/dist/{nextjs-DcQIk6Zj.d.mts → nextjs-DeUTnOBd.d.mts} +1 -1
  83. package/dist/{sdk-H0JCLW2y.d.ts → sdk-BM3mwEAq.d.ts} +1 -1
  84. package/dist/{sdk-CZkbSOeO.d.mts → sdk-_il1Q41f.d.mts} +1 -1
  85. package/dist/transport/index.d.mts +2 -2
  86. package/dist/transport/index.d.ts +2 -2
  87. package/dist/{types-sy3tq8lp.d.mts → types-BcDf9Kk0.d.mts} +118 -1
  88. package/dist/{types-DhFPiZ3t.d.ts → types-CHKCgDFC.d.ts} +1 -1
  89. package/dist/{types-cQVCMeNV.d.mts → types-DfnP7JiM.d.mts} +1 -1
  90. package/dist/{types-9tns4wyl.d.ts → types-fTQD448H.d.ts} +118 -1
  91. package/dist/ui/index.d.mts +1 -1
  92. package/dist/ui/index.d.ts +1 -1
  93. package/dist/verify.d.mts +15 -2
  94. package/dist/verify.d.ts +15 -2
  95. package/dist/verify.js +117 -10
  96. package/dist/verify.js.map +1 -1
  97. package/dist/verify.mjs +115 -10
  98. package/dist/verify.mjs.map +1 -1
  99. package/package.json +1 -1
@@ -7,7 +7,7 @@ function getTrustLevel(score) {
7
7
  }
8
8
 
9
9
  // src/version.ts
10
- var SDK_VERSION = "3.11.1";
10
+ var SDK_VERSION = "4.0.0";
11
11
 
12
12
  // src/well-known.ts
13
13
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -85,7 +85,7 @@ var DEFAULT_CONFIG = {
85
85
  };
86
86
  var initCheckPerformed = false;
87
87
  var deprecationWarningShown = false;
88
- async function performInitCheck(apiBaseUrl, debug, strictInit) {
88
+ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
89
89
  initCheckPerformed = true;
90
90
  try {
91
91
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
@@ -102,6 +102,28 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
102
102
  `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
103
103
  );
104
104
  }
105
+ if (apiKey) {
106
+ const selfCheck = await fetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
107
+ headers: { Authorization: `Bearer ${apiKey}` }
108
+ });
109
+ if (selfCheck.status === 401) {
110
+ const body = await selfCheck.json().catch(() => ({}));
111
+ const message = `[VerificationGateway] the configured AstraSync API key was REJECTED at startup (${body.code ?? "api_key_invalid"}: ${body.message ?? "invalid key"}). Every inbound agent will be turned away until the key is rotated` + (body.remediation?.manageUrl ? ` at ${body.remediation.manageUrl}` : "") + `.`;
112
+ if (strictInit) {
113
+ throw new Error(`${message} (strictInit=true)`);
114
+ }
115
+ console.error(message);
116
+ } else if (selfCheck.ok) {
117
+ const body = await selfCheck.json().catch(() => ({}));
118
+ if (typeof body.daysToExpiry === "number" && body.daysToExpiry <= 7) {
119
+ console.warn(
120
+ `[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`
121
+ );
122
+ } else if (debug) {
123
+ console.log("[VerificationGateway] API key self-check passed");
124
+ }
125
+ }
126
+ }
105
127
  } catch (err) {
106
128
  if (strictInit) {
107
129
  throw err;
@@ -213,8 +235,17 @@ function extractCredentials(headers, query) {
213
235
  function createGuidanceResponse(_config, reason, options = {}) {
214
236
  const source = options.source ?? "no_credentials";
215
237
  const isApiError = source === "api_error";
238
+ const isMisconfig = source === "merchant_misconfig";
216
239
  const urls = options.urls;
217
- const guidance = isApiError ? {
240
+ const guidance = isMisconfig ? {
241
+ message: "This site's AstraSync integration is misconfigured (its API key was revoked, expired, or rotated). Your identity and the AstraSync platform are fine \u2014 contact the site operator. Retrying will not help.",
242
+ registrationUrl: urls?.registrationUrl ?? "",
243
+ documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? "",
244
+ steps: [
245
+ "Report the failure to the site operator \u2014 their AstraSync API key needs rotating",
246
+ "Do not retry: the failure is deterministic until the operator updates their key"
247
+ ]
248
+ } : isApiError ? {
218
249
  message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
219
250
  registrationUrl: urls?.registrationUrl ?? "",
220
251
  documentationUrl: urls?.documentationUrl ?? "",
@@ -252,14 +283,24 @@ function createGuidanceResponse(_config, reason, options = {}) {
252
283
  // partners (and their custom onDenied handlers) can branch on
253
284
  // dimension. Without this, the synthesised stub was indistinguishable
254
285
  // from a real policy deny.
255
- failures: isApiError ? [
286
+ failures: isMisconfig ? [
287
+ {
288
+ dimension: "verify_access.merchant_misconfigured",
289
+ message: reason ?? "The integration API key was rejected by AstraSync",
290
+ guidance: guidance.message
291
+ }
292
+ ] : isApiError ? [
256
293
  {
257
294
  dimension: "verify_access.api_error",
258
295
  message: reason ?? "Verification temporarily unavailable",
259
296
  guidance: guidance.message
260
297
  }
261
298
  ] : void 0,
299
+ // 4.0.0: typed marker so adapters render the misconfig envelope (503 +
300
+ // MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.
301
+ ...isMisconfig && { misconfigured: true },
262
302
  correlationId: options.correlationId,
303
+ attemptId: options.attemptId,
263
304
  verifiedAt: /* @__PURE__ */ new Date()
264
305
  };
265
306
  }
@@ -289,6 +330,8 @@ async function callVerifyAccessAPI(config, request) {
289
330
  body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
290
331
  if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;
291
332
  if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
333
+ if (requestData.attemptId) body.attemptId = requestData.attemptId;
334
+ if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;
292
335
  body.sdkVersion = SDK_VERSION;
293
336
  if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
294
337
  const meta = {
@@ -310,12 +353,16 @@ async function callVerifyAccessAPI(config, request) {
310
353
  const response = await fetch(`${config.apiBaseUrl}/agents/verify-access`, {
311
354
  method: "POST",
312
355
  headers,
313
- body: JSON.stringify(body)
356
+ body: JSON.stringify(body),
357
+ signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 1e4)
314
358
  });
315
359
  const data = await response.json();
316
360
  if (response.status === 410) {
317
361
  return {
318
362
  success: true,
363
+ // 3.12.0 (Trust Record): keep the server-echoed attempt handle even on
364
+ // the synthesised 410 deny shape (echoed on every branch).
365
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
319
366
  access: {
320
367
  allowed: false,
321
368
  accessLevel: "none",
@@ -331,10 +378,22 @@ async function callVerifyAccessAPI(config, request) {
331
378
  };
332
379
  }
333
380
  if (!response.ok) {
381
+ if (response.status === 401) {
382
+ return {
383
+ success: false,
384
+ error: data.message || data.error || "Integration API key rejected",
385
+ misconfig: true,
386
+ misconfigCode: typeof data?.code === "string" ? data.code : void 0,
387
+ remediation: data?.remediation && typeof data.remediation === "object" ? data.remediation : void 0,
388
+ correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
389
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
390
+ };
391
+ }
334
392
  return {
335
393
  success: false,
336
394
  error: data.message || data.error || `API returned ${response.status}`,
337
- correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0
395
+ correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
396
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
338
397
  };
339
398
  }
340
399
  return data;
@@ -351,9 +410,19 @@ async function verify(config, request, options) {
351
410
  const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
352
411
  if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
353
412
  if (mergedConfig.strictInit) {
354
- await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
413
+ await performInitCheck(
414
+ mergedConfig.apiBaseUrl,
415
+ mergedConfig.debug,
416
+ true,
417
+ mergedConfig.apiKey
418
+ );
355
419
  } else {
356
- void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
420
+ void performInitCheck(
421
+ mergedConfig.apiBaseUrl,
422
+ mergedConfig.debug,
423
+ false,
424
+ mergedConfig.apiKey
425
+ );
357
426
  }
358
427
  }
359
428
  if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
@@ -368,7 +437,13 @@ async function verify(config, request, options) {
368
437
  if (mergedConfig.debug) {
369
438
  console.log("[VerificationGateway] Returning cached result");
370
439
  }
371
- return cached;
440
+ const hit = { ...cached };
441
+ if (request.attemptId) {
442
+ hit.attemptId = request.attemptId;
443
+ } else {
444
+ delete hit.attemptId;
445
+ }
446
+ return hit;
372
447
  }
373
448
  }
374
449
  const enrichedRequest = { ...request };
@@ -386,8 +461,10 @@ async function verify(config, request, options) {
386
461
  const serverDenialReasons = Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0 ? rawServerDenialReasons : void 0;
387
462
  if (!apiResponse.success) {
388
463
  return createGuidanceResponse(mergedConfig, apiResponse.error, {
389
- source: "api_error",
464
+ source: apiResponse.misconfig ? "merchant_misconfig" : "api_error",
390
465
  correlationId: apiResponse.correlationId,
466
+ attemptId: apiResponse.attemptId,
467
+ remediation: apiResponse.remediation,
391
468
  urls
392
469
  });
393
470
  }
@@ -423,6 +500,9 @@ async function verify(config, request, options) {
423
500
  // Anonymous traffic has no session → correlationId is the per-attempt
424
501
  // linking key (the sessionId-equivalent for anonymous callers).
425
502
  correlationId: apiResponse.correlationId,
503
+ // 3.12.0 (Trust Record): server echoes the attempt-chain handle on
504
+ // every branch — denials included (the funnel outlives one deny).
505
+ attemptId: apiResponse.attemptId,
426
506
  recommendation: apiResponse.recommendation,
427
507
  recommendationReasons: apiResponse.recommendationReasons,
428
508
  stepUpApproval: apiResponse.stepUpApproval,
@@ -474,6 +554,8 @@ async function verify(config, request, options) {
474
554
  // v2.3.10 (defect #34, round-4): anonymous responses surface correlationId
475
555
  // (no session row exists for unverified callers).
476
556
  correlationId: apiResponse.correlationId,
557
+ // 3.12.0 (Trust Record): server-echoed attempt-chain handle.
558
+ attemptId: apiResponse.attemptId,
477
559
  runtimeChallenge: apiResponse.runtimeChallenge,
478
560
  tokenGuidance: apiResponse.tokenGuidance,
479
561
  recommendation: apiResponse.recommendation,
@@ -736,6 +818,24 @@ function dedupeFailures(result) {
736
818
  }
737
819
  function defaultMcpDenied(result, req, res) {
738
820
  const id = req.body?.id ?? null;
821
+ if (result.misconfigured) {
822
+ res.setHeader("X-Astra-Gateway-Mode", "enforced");
823
+ res.status(503).json({
824
+ jsonrpc: "2.0",
825
+ id,
826
+ error: {
827
+ // -32002 → merchant verification misconfigured (see -32000/-32001 below)
828
+ code: -32002,
829
+ message: result.denialReasons?.[0] ?? "This server's AstraSync integration is misconfigured",
830
+ data: {
831
+ guidance: result.guidance,
832
+ failures: result.failures,
833
+ correlationId: result.correlationId
834
+ }
835
+ }
836
+ });
837
+ return;
838
+ }
739
839
  const status = !result.identityVerified ? 401 : 403;
740
840
  res.setHeader("X-Astra-Gateway-Mode", "enforced");
741
841
  res.status(status).json({
@@ -745,6 +845,7 @@ function defaultMcpDenied(result, req, res) {
745
845
  // JSON-RPC error codes:
746
846
  // -32000 → unauthorized (no identity resolved)
747
847
  // -32001 → insufficient access (identity OK, policy denied)
848
+ // -32002 → merchant verification misconfigured (handled above)
748
849
  code: !result.identityVerified ? -32e3 : -32001,
749
850
  message: result.denialReasons?.[0] ?? "Access denied",
750
851
  data: {