@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
@@ -1,5 +1,5 @@
1
1
  import { Request, Response, RequestHandler } from 'express';
2
- import { a as AccessLevel, G as GatewayConfig, r as VerificationResult } from '../types-sy3tq8lp.mjs';
2
+ import { a as AccessLevel, G as GatewayConfig, w as VerificationResult } from '../types-BcDf9Kk0.mjs';
3
3
  import '../metadata-capture.mjs';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { Request, Response, RequestHandler } from 'express';
2
- import { a as AccessLevel, G as GatewayConfig, r as VerificationResult } from '../types-9tns4wyl.js';
2
+ import { a as AccessLevel, G as GatewayConfig, w as VerificationResult } from '../types-fTQD448H.js';
3
3
  import '../metadata-capture.js';
4
4
 
5
5
  /**
@@ -40,7 +40,7 @@ function getTrustLevel(score) {
40
40
  }
41
41
 
42
42
  // src/version.ts
43
- var SDK_VERSION = "3.11.1";
43
+ var SDK_VERSION = "4.0.0";
44
44
 
45
45
  // src/well-known.ts
46
46
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -118,7 +118,7 @@ var DEFAULT_CONFIG = {
118
118
  };
119
119
  var initCheckPerformed = false;
120
120
  var deprecationWarningShown = false;
121
- async function performInitCheck(apiBaseUrl, debug, strictInit) {
121
+ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
122
122
  initCheckPerformed = true;
123
123
  try {
124
124
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
@@ -135,6 +135,28 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
135
135
  `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
136
136
  );
137
137
  }
138
+ if (apiKey) {
139
+ const selfCheck = await fetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
140
+ headers: { Authorization: `Bearer ${apiKey}` }
141
+ });
142
+ if (selfCheck.status === 401) {
143
+ const body = await selfCheck.json().catch(() => ({}));
144
+ 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}` : "") + `.`;
145
+ if (strictInit) {
146
+ throw new Error(`${message} (strictInit=true)`);
147
+ }
148
+ console.error(message);
149
+ } else if (selfCheck.ok) {
150
+ const body = await selfCheck.json().catch(() => ({}));
151
+ if (typeof body.daysToExpiry === "number" && body.daysToExpiry <= 7) {
152
+ console.warn(
153
+ `[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`
154
+ );
155
+ } else if (debug) {
156
+ console.log("[VerificationGateway] API key self-check passed");
157
+ }
158
+ }
159
+ }
138
160
  } catch (err) {
139
161
  if (strictInit) {
140
162
  throw err;
@@ -246,8 +268,17 @@ function extractCredentials(headers, query) {
246
268
  function createGuidanceResponse(_config, reason, options = {}) {
247
269
  const source = options.source ?? "no_credentials";
248
270
  const isApiError = source === "api_error";
271
+ const isMisconfig = source === "merchant_misconfig";
249
272
  const urls = options.urls;
250
- const guidance = isApiError ? {
273
+ const guidance = isMisconfig ? {
274
+ 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.",
275
+ registrationUrl: urls?.registrationUrl ?? "",
276
+ documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? "",
277
+ steps: [
278
+ "Report the failure to the site operator \u2014 their AstraSync API key needs rotating",
279
+ "Do not retry: the failure is deterministic until the operator updates their key"
280
+ ]
281
+ } : isApiError ? {
251
282
  message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
252
283
  registrationUrl: urls?.registrationUrl ?? "",
253
284
  documentationUrl: urls?.documentationUrl ?? "",
@@ -285,14 +316,24 @@ function createGuidanceResponse(_config, reason, options = {}) {
285
316
  // partners (and their custom onDenied handlers) can branch on
286
317
  // dimension. Without this, the synthesised stub was indistinguishable
287
318
  // from a real policy deny.
288
- failures: isApiError ? [
319
+ failures: isMisconfig ? [
320
+ {
321
+ dimension: "verify_access.merchant_misconfigured",
322
+ message: reason ?? "The integration API key was rejected by AstraSync",
323
+ guidance: guidance.message
324
+ }
325
+ ] : isApiError ? [
289
326
  {
290
327
  dimension: "verify_access.api_error",
291
328
  message: reason ?? "Verification temporarily unavailable",
292
329
  guidance: guidance.message
293
330
  }
294
331
  ] : void 0,
332
+ // 4.0.0: typed marker so adapters render the misconfig envelope (503 +
333
+ // MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.
334
+ ...isMisconfig && { misconfigured: true },
295
335
  correlationId: options.correlationId,
336
+ attemptId: options.attemptId,
296
337
  verifiedAt: /* @__PURE__ */ new Date()
297
338
  };
298
339
  }
@@ -322,6 +363,8 @@ async function callVerifyAccessAPI(config, request) {
322
363
  body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
323
364
  if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;
324
365
  if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
366
+ if (requestData.attemptId) body.attemptId = requestData.attemptId;
367
+ if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;
325
368
  body.sdkVersion = SDK_VERSION;
326
369
  if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
327
370
  const meta = {
@@ -343,12 +386,16 @@ async function callVerifyAccessAPI(config, request) {
343
386
  const response = await fetch(`${config.apiBaseUrl}/agents/verify-access`, {
344
387
  method: "POST",
345
388
  headers,
346
- body: JSON.stringify(body)
389
+ body: JSON.stringify(body),
390
+ signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 1e4)
347
391
  });
348
392
  const data = await response.json();
349
393
  if (response.status === 410) {
350
394
  return {
351
395
  success: true,
396
+ // 3.12.0 (Trust Record): keep the server-echoed attempt handle even on
397
+ // the synthesised 410 deny shape (echoed on every branch).
398
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
352
399
  access: {
353
400
  allowed: false,
354
401
  accessLevel: "none",
@@ -364,10 +411,22 @@ async function callVerifyAccessAPI(config, request) {
364
411
  };
365
412
  }
366
413
  if (!response.ok) {
414
+ if (response.status === 401) {
415
+ return {
416
+ success: false,
417
+ error: data.message || data.error || "Integration API key rejected",
418
+ misconfig: true,
419
+ misconfigCode: typeof data?.code === "string" ? data.code : void 0,
420
+ remediation: data?.remediation && typeof data.remediation === "object" ? data.remediation : void 0,
421
+ correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
422
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
423
+ };
424
+ }
367
425
  return {
368
426
  success: false,
369
427
  error: data.message || data.error || `API returned ${response.status}`,
370
- correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0
428
+ correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
429
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
371
430
  };
372
431
  }
373
432
  return data;
@@ -384,9 +443,19 @@ async function verify(config, request, options) {
384
443
  const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
385
444
  if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
386
445
  if (mergedConfig.strictInit) {
387
- await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
446
+ await performInitCheck(
447
+ mergedConfig.apiBaseUrl,
448
+ mergedConfig.debug,
449
+ true,
450
+ mergedConfig.apiKey
451
+ );
388
452
  } else {
389
- void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
453
+ void performInitCheck(
454
+ mergedConfig.apiBaseUrl,
455
+ mergedConfig.debug,
456
+ false,
457
+ mergedConfig.apiKey
458
+ );
390
459
  }
391
460
  }
392
461
  if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
@@ -401,7 +470,13 @@ async function verify(config, request, options) {
401
470
  if (mergedConfig.debug) {
402
471
  console.log("[VerificationGateway] Returning cached result");
403
472
  }
404
- return cached;
473
+ const hit = { ...cached };
474
+ if (request.attemptId) {
475
+ hit.attemptId = request.attemptId;
476
+ } else {
477
+ delete hit.attemptId;
478
+ }
479
+ return hit;
405
480
  }
406
481
  }
407
482
  const enrichedRequest = { ...request };
@@ -419,8 +494,10 @@ async function verify(config, request, options) {
419
494
  const serverDenialReasons = Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0 ? rawServerDenialReasons : void 0;
420
495
  if (!apiResponse.success) {
421
496
  return createGuidanceResponse(mergedConfig, apiResponse.error, {
422
- source: "api_error",
497
+ source: apiResponse.misconfig ? "merchant_misconfig" : "api_error",
423
498
  correlationId: apiResponse.correlationId,
499
+ attemptId: apiResponse.attemptId,
500
+ remediation: apiResponse.remediation,
424
501
  urls
425
502
  });
426
503
  }
@@ -456,6 +533,9 @@ async function verify(config, request, options) {
456
533
  // Anonymous traffic has no session → correlationId is the per-attempt
457
534
  // linking key (the sessionId-equivalent for anonymous callers).
458
535
  correlationId: apiResponse.correlationId,
536
+ // 3.12.0 (Trust Record): server echoes the attempt-chain handle on
537
+ // every branch — denials included (the funnel outlives one deny).
538
+ attemptId: apiResponse.attemptId,
459
539
  recommendation: apiResponse.recommendation,
460
540
  recommendationReasons: apiResponse.recommendationReasons,
461
541
  stepUpApproval: apiResponse.stepUpApproval,
@@ -507,6 +587,8 @@ async function verify(config, request, options) {
507
587
  // v2.3.10 (defect #34, round-4): anonymous responses surface correlationId
508
588
  // (no session row exists for unverified callers).
509
589
  correlationId: apiResponse.correlationId,
590
+ // 3.12.0 (Trust Record): server-echoed attempt-chain handle.
591
+ attemptId: apiResponse.attemptId,
510
592
  runtimeChallenge: apiResponse.runtimeChallenge,
511
593
  tokenGuidance: apiResponse.tokenGuidance,
512
594
  recommendation: apiResponse.recommendation,
@@ -769,6 +851,24 @@ function dedupeFailures(result) {
769
851
  }
770
852
  function defaultMcpDenied(result, req, res) {
771
853
  const id = req.body?.id ?? null;
854
+ if (result.misconfigured) {
855
+ res.setHeader("X-Astra-Gateway-Mode", "enforced");
856
+ res.status(503).json({
857
+ jsonrpc: "2.0",
858
+ id,
859
+ error: {
860
+ // -32002 → merchant verification misconfigured (see -32000/-32001 below)
861
+ code: -32002,
862
+ message: result.denialReasons?.[0] ?? "This server's AstraSync integration is misconfigured",
863
+ data: {
864
+ guidance: result.guidance,
865
+ failures: result.failures,
866
+ correlationId: result.correlationId
867
+ }
868
+ }
869
+ });
870
+ return;
871
+ }
772
872
  const status = !result.identityVerified ? 401 : 403;
773
873
  res.setHeader("X-Astra-Gateway-Mode", "enforced");
774
874
  res.status(status).json({
@@ -778,6 +878,7 @@ function defaultMcpDenied(result, req, res) {
778
878
  // JSON-RPC error codes:
779
879
  // -32000 → unauthorized (no identity resolved)
780
880
  // -32001 → insufficient access (identity OK, policy denied)
881
+ // -32002 → merchant verification misconfigured (handled above)
781
882
  code: !result.identityVerified ? -32e3 : -32001,
782
883
  message: result.denialReasons?.[0] ?? "Access denied",
783
884
  data: {