@astrasyncai/verification-gateway 3.12.0 → 4.1.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 (134) hide show
  1. package/README.md +106 -29
  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 +482 -22
  7. package/dist/adapters/express.js.map +1 -1
  8. package/dist/adapters/express.mjs +482 -22
  9. package/dist/adapters/express.mjs.map +1 -1
  10. package/dist/adapters/http-pdlss.d.mts +3 -3
  11. package/dist/adapters/http-pdlss.d.ts +3 -3
  12. package/dist/adapters/http-pdlss.js.map +1 -1
  13. package/dist/adapters/http-pdlss.mjs.map +1 -1
  14. package/dist/adapters/mcp.d.mts +56 -36
  15. package/dist/adapters/mcp.d.ts +56 -36
  16. package/dist/adapters/mcp.js +309 -10
  17. package/dist/adapters/mcp.js.map +1 -1
  18. package/dist/adapters/mcp.mjs +309 -10
  19. package/dist/adapters/mcp.mjs.map +1 -1
  20. package/dist/adapters/nextjs.d.mts +2 -2
  21. package/dist/adapters/nextjs.d.ts +2 -2
  22. package/dist/adapters/nextjs.js +518 -25
  23. package/dist/adapters/nextjs.js.map +1 -1
  24. package/dist/adapters/nextjs.mjs +518 -25
  25. package/dist/adapters/nextjs.mjs.map +1 -1
  26. package/dist/adapters/sdk.d.mts +2 -2
  27. package/dist/adapters/sdk.d.ts +2 -2
  28. package/dist/adapters/sdk.js +72 -9
  29. package/dist/adapters/sdk.js.map +1 -1
  30. package/dist/adapters/sdk.mjs +72 -9
  31. package/dist/adapters/sdk.mjs.map +1 -1
  32. package/dist/agent/index.d.mts +2 -2
  33. package/dist/agent/index.d.ts +2 -2
  34. package/dist/agent/index.js.map +1 -1
  35. package/dist/agent/index.mjs.map +1 -1
  36. package/dist/bin/astrasync-claude-hook.js +83 -20
  37. package/dist/bin/astrasync-codex-hook.js +83 -20
  38. package/dist/bin/astrasync-guard.js +83 -20
  39. package/dist/bin/astrasync.js +150 -33
  40. package/dist/browser/background.js +83 -20
  41. package/dist/browser/background.js.map +1 -1
  42. package/dist/browser/background.mjs +83 -20
  43. package/dist/browser/background.mjs.map +1 -1
  44. package/dist/browser/browser-adapter.d.mts +2 -2
  45. package/dist/browser/browser-adapter.d.ts +2 -2
  46. package/dist/claude-code/claude-code-adapter.d.mts +2 -2
  47. package/dist/claude-code/claude-code-adapter.d.ts +2 -2
  48. package/dist/cli/index.d.mts +2 -2
  49. package/dist/cli/index.d.ts +2 -2
  50. package/dist/codex/index.d.mts +3 -3
  51. package/dist/codex/index.d.ts +3 -3
  52. package/dist/codex/index.js +83 -20
  53. package/dist/codex/index.js.map +1 -1
  54. package/dist/codex/index.mjs +83 -20
  55. package/dist/codex/index.mjs.map +1 -1
  56. package/dist/cursor/cursor-adapter.d.mts +2 -2
  57. package/dist/cursor/cursor-adapter.d.ts +2 -2
  58. package/dist/cursor/extension.d.mts +2 -2
  59. package/dist/cursor/extension.d.ts +2 -2
  60. package/dist/cursor/extension.js +83 -20
  61. package/dist/cursor/extension.js.map +1 -1
  62. package/dist/cursor/extension.mjs +83 -20
  63. package/dist/cursor/extension.mjs.map +1 -1
  64. package/dist/edge-config.d.mts +22 -7
  65. package/dist/edge-config.d.ts +22 -7
  66. package/dist/edge-config.js.map +1 -1
  67. package/dist/edge-config.mjs.map +1 -1
  68. package/dist/edge-core/index.d.mts +425 -0
  69. package/dist/edge-core/index.d.ts +425 -0
  70. package/dist/edge-core/index.js +1482 -0
  71. package/dist/edge-core/index.js.map +1 -0
  72. package/dist/edge-core/index.mjs +1437 -0
  73. package/dist/edge-core/index.mjs.map +1 -0
  74. package/dist/{express-B39o89gf.d.mts → express-BVd1_3FE.d.ts} +9 -7
  75. package/dist/{express-BuxKNO_q.d.ts → express-D_4hTn5Z.d.mts} +9 -7
  76. package/dist/gateway/gateway.d.mts +2 -2
  77. package/dist/gateway/gateway.d.ts +2 -2
  78. package/dist/gateway/gateway.js +83 -20
  79. package/dist/gateway/gateway.js.map +1 -1
  80. package/dist/gateway/gateway.mjs +83 -20
  81. package/dist/gateway/gateway.mjs.map +1 -1
  82. package/dist/git-trigger/git-hooks.d.mts +2 -2
  83. package/dist/git-trigger/git-hooks.d.ts +2 -2
  84. package/dist/{index-CLHdqs2M.d.ts → index-B0YHu_SP.d.ts} +30 -27
  85. package/dist/{index-DME3w3lf.d.mts → index-BPEBlOsE.d.mts} +30 -27
  86. package/dist/{index-CqydB4ks.d.mts → index-DQb5-_1X.d.mts} +1 -1
  87. package/dist/{index-BG62SXso.d.ts → index-T1aBoUcc.d.ts} +1 -1
  88. package/dist/index.d.mts +11 -11
  89. package/dist/index.d.ts +11 -11
  90. package/dist/index.js +595 -272
  91. package/dist/index.js.map +1 -1
  92. package/dist/index.mjs +592 -272
  93. package/dist/index.mjs.map +1 -1
  94. package/dist/local-evaluator/evaluator.d.mts +2 -2
  95. package/dist/local-evaluator/evaluator.d.ts +2 -2
  96. package/dist/metadata-capture.d.mts +63 -4
  97. package/dist/metadata-capture.d.ts +63 -4
  98. package/dist/metadata-capture.js +67 -0
  99. package/dist/metadata-capture.js.map +1 -1
  100. package/dist/metadata-capture.mjs +64 -0
  101. package/dist/metadata-capture.mjs.map +1 -1
  102. package/dist/{nextjs-D74W7wt-.d.mts → nextjs-WyeVr2Kp.d.mts} +3 -3
  103. package/dist/{nextjs-Ddlw_J1J.d.ts → nextjs-w7RTbP1P.d.ts} +3 -3
  104. package/dist/platform-signatures.d.mts +5 -6
  105. package/dist/platform-signatures.d.ts +5 -6
  106. package/dist/platform-signatures.js.map +1 -1
  107. package/dist/platform-signatures.mjs.map +1 -1
  108. package/dist/registration/index.d.mts +10 -11
  109. package/dist/registration/index.d.ts +10 -11
  110. package/dist/registration/index.js.map +1 -1
  111. package/dist/registration/index.mjs.map +1 -1
  112. package/dist/{sdk-CT7gdkfR.d.ts → sdk-CbTNIkAa.d.mts} +4 -4
  113. package/dist/{sdk-Bn6bj7kt.d.mts → sdk-QeX0Z8Ho.d.ts} +4 -4
  114. package/dist/transport/index.d.mts +2 -2
  115. package/dist/transport/index.d.ts +2 -2
  116. package/dist/transport/index.js.map +1 -1
  117. package/dist/transport/index.mjs.map +1 -1
  118. package/dist/{types-DHu7m9HI.d.ts → types-BLUx92FJ.d.ts} +1 -1
  119. package/dist/{types-Djw4GLtz.d.mts → types-DqfPU5Bl.d.mts} +1 -1
  120. package/dist/{types-BntuzEEn.d.mts → types-r850cOt0.d.mts} +121 -88
  121. package/dist/{types-SDu4Llbe.d.ts → types-sMxBT-nM.d.ts} +121 -88
  122. package/dist/ui/index.d.mts +11 -7
  123. package/dist/ui/index.d.ts +11 -7
  124. package/dist/ui/index.js +13 -9
  125. package/dist/ui/index.js.map +1 -1
  126. package/dist/ui/index.mjs +10 -8
  127. package/dist/ui/index.mjs.map +1 -1
  128. package/dist/verify.d.mts +11 -8
  129. package/dist/verify.d.ts +11 -8
  130. package/dist/verify.js +76 -8
  131. package/dist/verify.js.map +1 -1
  132. package/dist/verify.mjs +75 -8
  133. package/dist/verify.mjs.map +1 -1
  134. package/package.json +8 -2
@@ -5000,7 +5000,7 @@ var SDK_VERSION;
5000
5000
  var init_version = __esm({
5001
5001
  "src/version.ts"() {
5002
5002
  "use strict";
5003
- SDK_VERSION = "3.12.0";
5003
+ SDK_VERSION = "4.1.0";
5004
5004
  }
5005
5005
  });
5006
5006
 
@@ -5018,7 +5018,7 @@ var init_well_known = __esm({
5018
5018
  });
5019
5019
 
5020
5020
  // src/verify.ts
5021
- async function performInitCheck(apiBaseUrl, debug, strictInit) {
5021
+ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
5022
5022
  initCheckPerformed = true;
5023
5023
  try {
5024
5024
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
@@ -5035,6 +5035,28 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
5035
5035
  `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
5036
5036
  );
5037
5037
  }
5038
+ if (apiKey) {
5039
+ const selfCheck = await fetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
5040
+ headers: { Authorization: `Bearer ${apiKey}` }
5041
+ });
5042
+ if (selfCheck.status === 401) {
5043
+ const body = await selfCheck.json().catch(() => ({}));
5044
+ 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}` : "") + `.`;
5045
+ if (strictInit) {
5046
+ throw new Error(`${message} (strictInit=true)`);
5047
+ }
5048
+ console.error(message);
5049
+ } else if (selfCheck.ok) {
5050
+ const body = await selfCheck.json().catch(() => ({}));
5051
+ if (typeof body.daysToExpiry === "number" && body.daysToExpiry <= 7) {
5052
+ console.warn(
5053
+ `[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`
5054
+ );
5055
+ } else if (debug) {
5056
+ console.log("[VerificationGateway] API key self-check passed");
5057
+ }
5058
+ }
5059
+ }
5038
5060
  } catch (err) {
5039
5061
  if (strictInit) {
5040
5062
  throw err;
@@ -5110,8 +5132,17 @@ function cacheResult(request2, result, configuredTtl, counterpartyId) {
5110
5132
  function createGuidanceResponse(_config, reason, options = {}) {
5111
5133
  const source = options.source ?? "no_credentials";
5112
5134
  const isApiError = source === "api_error";
5135
+ const isMisconfig = source === "merchant_misconfig";
5113
5136
  const urls = options.urls;
5114
- const guidance = isApiError ? {
5137
+ const guidance = isMisconfig ? {
5138
+ 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.",
5139
+ registrationUrl: urls?.registrationUrl ?? "",
5140
+ documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? "",
5141
+ steps: [
5142
+ "Report the failure to the site operator \u2014 their AstraSync API key needs rotating",
5143
+ "Do not retry: the failure is deterministic until the operator updates their key"
5144
+ ]
5145
+ } : isApiError ? {
5115
5146
  message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
5116
5147
  registrationUrl: urls?.registrationUrl ?? "",
5117
5148
  documentationUrl: urls?.documentationUrl ?? "",
@@ -5149,13 +5180,22 @@ function createGuidanceResponse(_config, reason, options = {}) {
5149
5180
  // partners (and their custom onDenied handlers) can branch on
5150
5181
  // dimension. Without this, the synthesised stub was indistinguishable
5151
5182
  // from a real policy deny.
5152
- failures: isApiError ? [
5183
+ failures: isMisconfig ? [
5184
+ {
5185
+ dimension: "verify_access.merchant_misconfigured",
5186
+ message: reason ?? "The integration API key was rejected by AstraSync",
5187
+ guidance: guidance.message
5188
+ }
5189
+ ] : isApiError ? [
5153
5190
  {
5154
5191
  dimension: "verify_access.api_error",
5155
5192
  message: reason ?? "Verification temporarily unavailable",
5156
5193
  guidance: guidance.message
5157
5194
  }
5158
5195
  ] : void 0,
5196
+ // 4.0.0: typed marker so adapters render the misconfig envelope (503 +
5197
+ // MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.
5198
+ ...isMisconfig && { misconfigured: true },
5159
5199
  correlationId: options.correlationId,
5160
5200
  attemptId: options.attemptId,
5161
5201
  verifiedAt: /* @__PURE__ */ new Date()
@@ -5210,7 +5250,8 @@ async function callVerifyAccessAPI(config, request2) {
5210
5250
  const response = await fetch(`${config.apiBaseUrl}/agents/verify-access`, {
5211
5251
  method: "POST",
5212
5252
  headers,
5213
- body: JSON.stringify(body)
5253
+ body: JSON.stringify(body),
5254
+ signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 1e4)
5214
5255
  });
5215
5256
  const data = await response.json();
5216
5257
  if (response.status === 410) {
@@ -5234,6 +5275,17 @@ async function callVerifyAccessAPI(config, request2) {
5234
5275
  };
5235
5276
  }
5236
5277
  if (!response.ok) {
5278
+ if (response.status === 401) {
5279
+ return {
5280
+ success: false,
5281
+ error: data.message || data.error || "Integration API key rejected",
5282
+ misconfig: true,
5283
+ misconfigCode: typeof data?.code === "string" ? data.code : void 0,
5284
+ remediation: data?.remediation && typeof data.remediation === "object" ? data.remediation : void 0,
5285
+ correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
5286
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
5287
+ };
5288
+ }
5237
5289
  return {
5238
5290
  success: false,
5239
5291
  error: data.message || data.error || `API returned ${response.status}`,
@@ -5255,9 +5307,19 @@ async function verify(config, request2, options) {
5255
5307
  const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
5256
5308
  if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
5257
5309
  if (mergedConfig.strictInit) {
5258
- await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
5310
+ await performInitCheck(
5311
+ mergedConfig.apiBaseUrl,
5312
+ mergedConfig.debug,
5313
+ true,
5314
+ mergedConfig.apiKey
5315
+ );
5259
5316
  } else {
5260
- void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
5317
+ void performInitCheck(
5318
+ mergedConfig.apiBaseUrl,
5319
+ mergedConfig.debug,
5320
+ false,
5321
+ mergedConfig.apiKey
5322
+ );
5261
5323
  }
5262
5324
  }
5263
5325
  if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
@@ -5296,9 +5358,10 @@ async function verify(config, request2, options) {
5296
5358
  const serverDenialReasons = Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0 ? rawServerDenialReasons : void 0;
5297
5359
  if (!apiResponse.success) {
5298
5360
  return createGuidanceResponse(mergedConfig, apiResponse.error, {
5299
- source: "api_error",
5361
+ source: apiResponse.misconfig ? "merchant_misconfig" : "api_error",
5300
5362
  correlationId: apiResponse.correlationId,
5301
5363
  attemptId: apiResponse.attemptId,
5364
+ remediation: apiResponse.remediation,
5302
5365
  urls
5303
5366
  });
5304
5367
  }
@@ -5504,6 +5567,82 @@ var init_metadata_capture = __esm({
5504
5567
  }
5505
5568
  });
5506
5569
 
5570
+ // src/edge-config.ts
5571
+ var DEFAULT_EDGE_CONFIG, DEFAULT_TTL_MS, DEFAULT_MAX_STALE_MS;
5572
+ var init_edge_config = __esm({
5573
+ "src/edge-config.ts"() {
5574
+ "use strict";
5575
+ DEFAULT_EDGE_CONFIG = Object.freeze({
5576
+ version: 1,
5577
+ mode: "observe",
5578
+ depth: "classify",
5579
+ pathRules: [],
5580
+ sampling: Object.freeze({ anonymousBeaconRate: 0.1 }),
5581
+ failurePosture: "open"
5582
+ });
5583
+ DEFAULT_TTL_MS = 60 * 1e3;
5584
+ DEFAULT_MAX_STALE_MS = 24 * 60 * 60 * 1e3;
5585
+ }
5586
+ });
5587
+
5588
+ // src/platform-signatures.ts
5589
+ var init_platform_signatures = __esm({
5590
+ "src/platform-signatures.ts"() {
5591
+ "use strict";
5592
+ }
5593
+ });
5594
+
5595
+ // src/edge-core/request.ts
5596
+ var init_request = __esm({
5597
+ "src/edge-core/request.ts"() {
5598
+ "use strict";
5599
+ init_metadata_capture();
5600
+ }
5601
+ });
5602
+
5603
+ // src/edge-core/detect.ts
5604
+ var init_detect = __esm({
5605
+ "src/edge-core/detect.ts"() {
5606
+ "use strict";
5607
+ init_request();
5608
+ }
5609
+ });
5610
+
5611
+ // src/edge-core/classify.ts
5612
+ var init_classify = __esm({
5613
+ "src/edge-core/classify.ts"() {
5614
+ "use strict";
5615
+ init_edge_config();
5616
+ init_metadata_capture();
5617
+ init_platform_signatures();
5618
+ init_verify();
5619
+ init_detect();
5620
+ init_request();
5621
+ }
5622
+ });
5623
+
5624
+ // src/edge-core/events.ts
5625
+ var init_events = __esm({
5626
+ "src/edge-core/events.ts"() {
5627
+ "use strict";
5628
+ init_verify();
5629
+ init_request();
5630
+ }
5631
+ });
5632
+
5633
+ // src/adapters/anonymous-beacon.ts
5634
+ var init_anonymous_beacon = __esm({
5635
+ "src/adapters/anonymous-beacon.ts"() {
5636
+ "use strict";
5637
+ init_classify();
5638
+ init_events();
5639
+ init_edge_config();
5640
+ init_metadata_capture();
5641
+ init_platform_signatures();
5642
+ init_verify();
5643
+ }
5644
+ });
5645
+
5507
5646
  // src/adapters/express.ts
5508
5647
  var DEFAULT_ROUTES_REFRESH_MS;
5509
5648
  var init_express = __esm({
@@ -5517,6 +5656,7 @@ var init_express = __esm({
5517
5656
  init_pdlss_pre_check();
5518
5657
  init_well_known();
5519
5658
  init_metadata_capture();
5659
+ init_anonymous_beacon();
5520
5660
  DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1e3;
5521
5661
  }
5522
5662
  });
@@ -5531,6 +5671,7 @@ var init_nextjs = __esm({
5531
5671
  init_http();
5532
5672
  init_pdlss_pre_check();
5533
5673
  init_metadata_capture();
5674
+ init_anonymous_beacon();
5534
5675
  init_http_pdlss();
5535
5676
  init_approval_gate();
5536
5677
  DEFAULT_ROUTES_REFRESH_MS2 = 5 * 60 * 1e3;
@@ -5844,6 +5985,7 @@ var init_mcp2 = __esm({
5844
5985
  "src/adapters/mcp.ts"() {
5845
5986
  "use strict";
5846
5987
  init_verify();
5988
+ init_metadata_capture();
5847
5989
  init_approval_gate();
5848
5990
  init_stepup_poll();
5849
5991
  init_well_known();
@@ -5920,31 +6062,6 @@ var init_agent = __esm({
5920
6062
  }
5921
6063
  });
5922
6064
 
5923
- // src/edge-config.ts
5924
- var DEFAULT_EDGE_CONFIG, DEFAULT_TTL_MS, DEFAULT_MAX_STALE_MS;
5925
- var init_edge_config = __esm({
5926
- "src/edge-config.ts"() {
5927
- "use strict";
5928
- DEFAULT_EDGE_CONFIG = Object.freeze({
5929
- version: 1,
5930
- mode: "observe",
5931
- depth: "classify",
5932
- pathRules: [],
5933
- sampling: Object.freeze({ anonymousBeaconRate: 0.1 }),
5934
- failurePosture: "open"
5935
- });
5936
- DEFAULT_TTL_MS = 60 * 1e3;
5937
- DEFAULT_MAX_STALE_MS = 24 * 60 * 60 * 1e3;
5938
- }
5939
- });
5940
-
5941
- // src/platform-signatures.ts
5942
- var init_platform_signatures = __esm({
5943
- "src/platform-signatures.ts"() {
5944
- "use strict";
5945
- }
5946
- });
5947
-
5948
6065
  // src/index.ts
5949
6066
  var init_src = __esm({
5950
6067
  "src/index.ts"() {
@@ -3938,7 +3938,7 @@ function getTrustLevel(score) {
3938
3938
  }
3939
3939
 
3940
3940
  // src/version.ts
3941
- var SDK_VERSION = "3.12.0";
3941
+ var SDK_VERSION = "4.1.0";
3942
3942
 
3943
3943
  // src/well-known.ts
3944
3944
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -3964,7 +3964,7 @@ var DEFAULT_CONFIG = {
3964
3964
  };
3965
3965
  var initCheckPerformed = false;
3966
3966
  var deprecationWarningShown = false;
3967
- async function performInitCheck(apiBaseUrl, debug, strictInit) {
3967
+ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
3968
3968
  initCheckPerformed = true;
3969
3969
  try {
3970
3970
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
@@ -3981,6 +3981,28 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
3981
3981
  `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
3982
3982
  );
3983
3983
  }
3984
+ if (apiKey) {
3985
+ const selfCheck = await fetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
3986
+ headers: { Authorization: `Bearer ${apiKey}` }
3987
+ });
3988
+ if (selfCheck.status === 401) {
3989
+ const body = await selfCheck.json().catch(() => ({}));
3990
+ 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}` : "") + `.`;
3991
+ if (strictInit) {
3992
+ throw new Error(`${message} (strictInit=true)`);
3993
+ }
3994
+ console.error(message);
3995
+ } else if (selfCheck.ok) {
3996
+ const body = await selfCheck.json().catch(() => ({}));
3997
+ if (typeof body.daysToExpiry === "number" && body.daysToExpiry <= 7) {
3998
+ console.warn(
3999
+ `[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`
4000
+ );
4001
+ } else if (debug) {
4002
+ console.log("[VerificationGateway] API key self-check passed");
4003
+ }
4004
+ }
4005
+ }
3984
4006
  } catch (err) {
3985
4007
  if (strictInit) {
3986
4008
  throw err;
@@ -4058,8 +4080,17 @@ function cacheResult(request, result, configuredTtl, counterpartyId) {
4058
4080
  function createGuidanceResponse(_config, reason, options = {}) {
4059
4081
  const source = options.source ?? "no_credentials";
4060
4082
  const isApiError = source === "api_error";
4083
+ const isMisconfig = source === "merchant_misconfig";
4061
4084
  const urls = options.urls;
4062
- const guidance = isApiError ? {
4085
+ const guidance = isMisconfig ? {
4086
+ 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.",
4087
+ registrationUrl: urls?.registrationUrl ?? "",
4088
+ documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? "",
4089
+ steps: [
4090
+ "Report the failure to the site operator \u2014 their AstraSync API key needs rotating",
4091
+ "Do not retry: the failure is deterministic until the operator updates their key"
4092
+ ]
4093
+ } : isApiError ? {
4063
4094
  message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
4064
4095
  registrationUrl: urls?.registrationUrl ?? "",
4065
4096
  documentationUrl: urls?.documentationUrl ?? "",
@@ -4097,13 +4128,22 @@ function createGuidanceResponse(_config, reason, options = {}) {
4097
4128
  // partners (and their custom onDenied handlers) can branch on
4098
4129
  // dimension. Without this, the synthesised stub was indistinguishable
4099
4130
  // from a real policy deny.
4100
- failures: isApiError ? [
4131
+ failures: isMisconfig ? [
4132
+ {
4133
+ dimension: "verify_access.merchant_misconfigured",
4134
+ message: reason ?? "The integration API key was rejected by AstraSync",
4135
+ guidance: guidance.message
4136
+ }
4137
+ ] : isApiError ? [
4101
4138
  {
4102
4139
  dimension: "verify_access.api_error",
4103
4140
  message: reason ?? "Verification temporarily unavailable",
4104
4141
  guidance: guidance.message
4105
4142
  }
4106
4143
  ] : void 0,
4144
+ // 4.0.0: typed marker so adapters render the misconfig envelope (503 +
4145
+ // MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.
4146
+ ...isMisconfig && { misconfigured: true },
4107
4147
  correlationId: options.correlationId,
4108
4148
  attemptId: options.attemptId,
4109
4149
  verifiedAt: /* @__PURE__ */ new Date()
@@ -4158,7 +4198,8 @@ async function callVerifyAccessAPI(config, request) {
4158
4198
  const response = await fetch(`${config.apiBaseUrl}/agents/verify-access`, {
4159
4199
  method: "POST",
4160
4200
  headers,
4161
- body: JSON.stringify(body)
4201
+ body: JSON.stringify(body),
4202
+ signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 1e4)
4162
4203
  });
4163
4204
  const data = await response.json();
4164
4205
  if (response.status === 410) {
@@ -4182,6 +4223,17 @@ async function callVerifyAccessAPI(config, request) {
4182
4223
  };
4183
4224
  }
4184
4225
  if (!response.ok) {
4226
+ if (response.status === 401) {
4227
+ return {
4228
+ success: false,
4229
+ error: data.message || data.error || "Integration API key rejected",
4230
+ misconfig: true,
4231
+ misconfigCode: typeof data?.code === "string" ? data.code : void 0,
4232
+ remediation: data?.remediation && typeof data.remediation === "object" ? data.remediation : void 0,
4233
+ correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
4234
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
4235
+ };
4236
+ }
4185
4237
  return {
4186
4238
  success: false,
4187
4239
  error: data.message || data.error || `API returned ${response.status}`,
@@ -4203,9 +4255,19 @@ async function verify(config, request, options) {
4203
4255
  const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
4204
4256
  if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
4205
4257
  if (mergedConfig.strictInit) {
4206
- await performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, true);
4258
+ await performInitCheck(
4259
+ mergedConfig.apiBaseUrl,
4260
+ mergedConfig.debug,
4261
+ true,
4262
+ mergedConfig.apiKey
4263
+ );
4207
4264
  } else {
4208
- void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug, false);
4265
+ void performInitCheck(
4266
+ mergedConfig.apiBaseUrl,
4267
+ mergedConfig.debug,
4268
+ false,
4269
+ mergedConfig.apiKey
4270
+ );
4209
4271
  }
4210
4272
  }
4211
4273
  if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
@@ -4244,9 +4306,10 @@ async function verify(config, request, options) {
4244
4306
  const serverDenialReasons = Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0 ? rawServerDenialReasons : void 0;
4245
4307
  if (!apiResponse.success) {
4246
4308
  return createGuidanceResponse(mergedConfig, apiResponse.error, {
4247
- source: "api_error",
4309
+ source: apiResponse.misconfig ? "merchant_misconfig" : "api_error",
4248
4310
  correlationId: apiResponse.correlationId,
4249
4311
  attemptId: apiResponse.attemptId,
4312
+ remediation: apiResponse.remediation,
4250
4313
  urls
4251
4314
  });
4252
4315
  }
@@ -4376,6 +4439,18 @@ var FALLBACK_MAX_WAIT_MS = 5 * 60 * 1e3;
4376
4439
  // src/metadata-capture.ts
4377
4440
  var MAX_TOTAL_BYTES = 16 * 1024;
4378
4441
 
4442
+ // src/edge-config.ts
4443
+ var DEFAULT_EDGE_CONFIG = Object.freeze({
4444
+ version: 1,
4445
+ mode: "observe",
4446
+ depth: "classify",
4447
+ pathRules: [],
4448
+ sampling: Object.freeze({ anonymousBeaconRate: 0.1 }),
4449
+ failurePosture: "open"
4450
+ });
4451
+ var DEFAULT_TTL_MS = 60 * 1e3;
4452
+ var DEFAULT_MAX_STALE_MS = 24 * 60 * 60 * 1e3;
4453
+
4379
4454
  // src/adapters/express.ts
4380
4455
  var DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1e3;
4381
4456
 
@@ -4444,18 +4519,6 @@ var import_node_crypto4 = require("crypto");
4444
4519
  // src/transport/registry/visa.ts
4445
4520
  var import_jose = require("jose");
4446
4521
 
4447
- // src/edge-config.ts
4448
- var DEFAULT_EDGE_CONFIG = Object.freeze({
4449
- version: 1,
4450
- mode: "observe",
4451
- depth: "classify",
4452
- pathRules: [],
4453
- sampling: Object.freeze({ anonymousBeaconRate: 0.1 }),
4454
- failurePosture: "open"
4455
- });
4456
- var DEFAULT_TTL_MS = 60 * 1e3;
4457
- var DEFAULT_MAX_STALE_MS = 24 * 60 * 60 * 1e3;
4458
-
4459
4522
  // src/gateway/modes/online.ts
4460
4523
  function toGatewayConfig(config) {
4461
4524
  return {