@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
@@ -65,7 +65,7 @@ function getTrustLevel(score) {
65
65
  }
66
66
 
67
67
  // src/version.ts
68
- var SDK_VERSION = "3.11.1";
68
+ var SDK_VERSION = "4.0.0";
69
69
 
70
70
  // src/well-known.ts
71
71
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -143,7 +143,7 @@ var DEFAULT_CONFIG = {
143
143
  };
144
144
  var initCheckPerformed = false;
145
145
  var deprecationWarningShown = false;
146
- async function performInitCheck(apiBaseUrl, debug, strictInit) {
146
+ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
147
147
  initCheckPerformed = true;
148
148
  try {
149
149
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
@@ -160,6 +160,28 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
160
160
  `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
161
161
  );
162
162
  }
163
+ if (apiKey) {
164
+ const selfCheck = await fetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
165
+ headers: { Authorization: `Bearer ${apiKey}` }
166
+ });
167
+ if (selfCheck.status === 401) {
168
+ const body = await selfCheck.json().catch(() => ({}));
169
+ 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}` : "") + `.`;
170
+ if (strictInit) {
171
+ throw new Error(`${message} (strictInit=true)`);
172
+ }
173
+ console.error(message);
174
+ } else if (selfCheck.ok) {
175
+ const body = await selfCheck.json().catch(() => ({}));
176
+ if (typeof body.daysToExpiry === "number" && body.daysToExpiry <= 7) {
177
+ console.warn(
178
+ `[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`
179
+ );
180
+ } else if (debug) {
181
+ console.log("[VerificationGateway] API key self-check passed");
182
+ }
183
+ }
184
+ }
163
185
  } catch (err) {
164
186
  if (strictInit) {
165
187
  throw err;
@@ -271,8 +293,17 @@ function extractCredentials(headers, query) {
271
293
  function createGuidanceResponse(_config, reason, options = {}) {
272
294
  const source = options.source ?? "no_credentials";
273
295
  const isApiError = source === "api_error";
296
+ const isMisconfig = source === "merchant_misconfig";
274
297
  const urls = options.urls;
275
- const guidance = isApiError ? {
298
+ const guidance = isMisconfig ? {
299
+ 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.",
300
+ registrationUrl: urls?.registrationUrl ?? "",
301
+ documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? "",
302
+ steps: [
303
+ "Report the failure to the site operator \u2014 their AstraSync API key needs rotating",
304
+ "Do not retry: the failure is deterministic until the operator updates their key"
305
+ ]
306
+ } : isApiError ? {
276
307
  message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
277
308
  registrationUrl: urls?.registrationUrl ?? "",
278
309
  documentationUrl: urls?.documentationUrl ?? "",
@@ -310,14 +341,24 @@ function createGuidanceResponse(_config, reason, options = {}) {
310
341
  // partners (and their custom onDenied handlers) can branch on
311
342
  // dimension. Without this, the synthesised stub was indistinguishable
312
343
  // from a real policy deny.
313
- failures: isApiError ? [
344
+ failures: isMisconfig ? [
345
+ {
346
+ dimension: "verify_access.merchant_misconfigured",
347
+ message: reason ?? "The integration API key was rejected by AstraSync",
348
+ guidance: guidance.message
349
+ }
350
+ ] : isApiError ? [
314
351
  {
315
352
  dimension: "verify_access.api_error",
316
353
  message: reason ?? "Verification temporarily unavailable",
317
354
  guidance: guidance.message
318
355
  }
319
356
  ] : void 0,
357
+ // 4.0.0: typed marker so adapters render the misconfig envelope (503 +
358
+ // MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.
359
+ ...isMisconfig && { misconfigured: true },
320
360
  correlationId: options.correlationId,
361
+ attemptId: options.attemptId,
321
362
  verifiedAt: /* @__PURE__ */ new Date()
322
363
  };
323
364
  }
@@ -347,6 +388,8 @@ async function callVerifyAccessAPI(config, request) {
347
388
  body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
348
389
  if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;
349
390
  if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
391
+ if (requestData.attemptId) body.attemptId = requestData.attemptId;
392
+ if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;
350
393
  body.sdkVersion = SDK_VERSION;
351
394
  if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
352
395
  const meta = {
@@ -368,12 +411,16 @@ async function callVerifyAccessAPI(config, request) {
368
411
  const response = await fetch(`${config.apiBaseUrl}/agents/verify-access`, {
369
412
  method: "POST",
370
413
  headers,
371
- body: JSON.stringify(body)
414
+ body: JSON.stringify(body),
415
+ signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 1e4)
372
416
  });
373
417
  const data = await response.json();
374
418
  if (response.status === 410) {
375
419
  return {
376
420
  success: true,
421
+ // 3.12.0 (Trust Record): keep the server-echoed attempt handle even on
422
+ // the synthesised 410 deny shape (echoed on every branch).
423
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
377
424
  access: {
378
425
  allowed: false,
379
426
  accessLevel: "none",
@@ -389,10 +436,22 @@ async function callVerifyAccessAPI(config, request) {
389
436
  };
390
437
  }
391
438
  if (!response.ok) {
439
+ if (response.status === 401) {
440
+ return {
441
+ success: false,
442
+ error: data.message || data.error || "Integration API key rejected",
443
+ misconfig: true,
444
+ misconfigCode: typeof data?.code === "string" ? data.code : void 0,
445
+ remediation: data?.remediation && typeof data.remediation === "object" ? data.remediation : void 0,
446
+ correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
447
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
448
+ };
449
+ }
392
450
  return {
393
451
  success: false,
394
452
  error: data.message || data.error || `API returned ${response.status}`,
395
- correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0
453
+ correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
454
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
396
455
  };
397
456
  }
398
457
  return data;
@@ -409,9 +468,19 @@ async function verify(config, request, options) {
409
468
  const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
410
469
  if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
411
470
  if (mergedConfig.strictInit) {
412
- await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
471
+ await performInitCheck(
472
+ mergedConfig.apiBaseUrl,
473
+ mergedConfig.debug,
474
+ true,
475
+ mergedConfig.apiKey
476
+ );
413
477
  } else {
414
- void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
478
+ void performInitCheck(
479
+ mergedConfig.apiBaseUrl,
480
+ mergedConfig.debug,
481
+ false,
482
+ mergedConfig.apiKey
483
+ );
415
484
  }
416
485
  }
417
486
  if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
@@ -426,7 +495,13 @@ async function verify(config, request, options) {
426
495
  if (mergedConfig.debug) {
427
496
  console.log("[VerificationGateway] Returning cached result");
428
497
  }
429
- return cached;
498
+ const hit = { ...cached };
499
+ if (request.attemptId) {
500
+ hit.attemptId = request.attemptId;
501
+ } else {
502
+ delete hit.attemptId;
503
+ }
504
+ return hit;
430
505
  }
431
506
  }
432
507
  const enrichedRequest = { ...request };
@@ -444,8 +519,10 @@ async function verify(config, request, options) {
444
519
  const serverDenialReasons = Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0 ? rawServerDenialReasons : void 0;
445
520
  if (!apiResponse.success) {
446
521
  return createGuidanceResponse(mergedConfig, apiResponse.error, {
447
- source: "api_error",
522
+ source: apiResponse.misconfig ? "merchant_misconfig" : "api_error",
448
523
  correlationId: apiResponse.correlationId,
524
+ attemptId: apiResponse.attemptId,
525
+ remediation: apiResponse.remediation,
449
526
  urls
450
527
  });
451
528
  }
@@ -481,6 +558,9 @@ async function verify(config, request, options) {
481
558
  // Anonymous traffic has no session → correlationId is the per-attempt
482
559
  // linking key (the sessionId-equivalent for anonymous callers).
483
560
  correlationId: apiResponse.correlationId,
561
+ // 3.12.0 (Trust Record): server echoes the attempt-chain handle on
562
+ // every branch — denials included (the funnel outlives one deny).
563
+ attemptId: apiResponse.attemptId,
484
564
  recommendation: apiResponse.recommendation,
485
565
  recommendationReasons: apiResponse.recommendationReasons,
486
566
  stepUpApproval: apiResponse.stepUpApproval,
@@ -532,6 +612,8 @@ async function verify(config, request, options) {
532
612
  // v2.3.10 (defect #34, round-4): anonymous responses surface correlationId
533
613
  // (no session row exists for unverified callers).
534
614
  correlationId: apiResponse.correlationId,
615
+ // 3.12.0 (Trust Record): server-echoed attempt-chain handle.
616
+ attemptId: apiResponse.attemptId,
535
617
  runtimeChallenge: apiResponse.runtimeChallenge,
536
618
  tokenGuidance: apiResponse.tokenGuidance,
537
619
  recommendation: apiResponse.recommendation,
@@ -997,6 +1079,20 @@ function dedupeFailures(result) {
997
1079
  }
998
1080
  }
999
1081
  function defaultOnDenied(result, _req, res) {
1082
+ if (result.misconfigured) {
1083
+ res.setHeader("X-Astra-Gateway-Mode", "enforced");
1084
+ res.status(503).json({
1085
+ success: false,
1086
+ error: {
1087
+ code: "MERCHANT_VERIFICATION_MISCONFIGURED",
1088
+ message: result.denialReasons?.[0] || "This site's AstraSync integration is misconfigured",
1089
+ guidance: result.guidance,
1090
+ failures: result.failures,
1091
+ correlationId: result.correlationId
1092
+ }
1093
+ });
1094
+ return;
1095
+ }
1000
1096
  const statusCode = !result.identityVerified ? 401 : 403;
1001
1097
  res.setHeader("X-Astra-Gateway-Mode", "enforced");
1002
1098
  res.status(statusCode).json({