@astrasyncai/verification-gateway 5.12.0 → 5.14.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 (75) hide show
  1. package/dist/adapters/express.js +63 -19
  2. package/dist/adapters/express.js.map +1 -1
  3. package/dist/adapters/express.mjs +63 -19
  4. package/dist/adapters/express.mjs.map +1 -1
  5. package/dist/adapters/mcp.js +26 -9
  6. package/dist/adapters/mcp.js.map +1 -1
  7. package/dist/adapters/mcp.mjs +26 -9
  8. package/dist/adapters/mcp.mjs.map +1 -1
  9. package/dist/adapters/nextjs.js +63 -19
  10. package/dist/adapters/nextjs.js.map +1 -1
  11. package/dist/adapters/nextjs.mjs +63 -19
  12. package/dist/adapters/nextjs.mjs.map +1 -1
  13. package/dist/adapters/sdk.js +26 -9
  14. package/dist/adapters/sdk.js.map +1 -1
  15. package/dist/adapters/sdk.mjs +26 -9
  16. package/dist/adapters/sdk.mjs.map +1 -1
  17. package/dist/agent/index.js +1 -1
  18. package/dist/agent/index.js.map +1 -1
  19. package/dist/agent/index.mjs +1 -1
  20. package/dist/agent/index.mjs.map +1 -1
  21. package/dist/bin/astrasync-claude-hook.js +53 -18
  22. package/dist/bin/astrasync-codex-hook.js +53 -18
  23. package/dist/bin/astrasync-guard.js +53 -18
  24. package/dist/bin/astrasync.js +54 -19
  25. package/dist/browser/background.js +53 -18
  26. package/dist/browser/background.js.map +1 -1
  27. package/dist/browser/background.mjs +53 -18
  28. package/dist/browser/background.mjs.map +1 -1
  29. package/dist/cli/index.js +1 -1
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/cli/index.mjs +1 -1
  32. package/dist/cli/index.mjs.map +1 -1
  33. package/dist/codex/index.js +53 -18
  34. package/dist/codex/index.js.map +1 -1
  35. package/dist/codex/index.mjs +53 -18
  36. package/dist/codex/index.mjs.map +1 -1
  37. package/dist/cursor/extension.js +53 -18
  38. package/dist/cursor/extension.js.map +1 -1
  39. package/dist/cursor/extension.mjs +53 -18
  40. package/dist/cursor/extension.mjs.map +1 -1
  41. package/dist/edge-config.js +1 -1
  42. package/dist/edge-config.js.map +1 -1
  43. package/dist/edge-config.mjs +1 -1
  44. package/dist/edge-config.mjs.map +1 -1
  45. package/dist/edge-core/index.d.mts +32 -4
  46. package/dist/edge-core/index.d.ts +32 -4
  47. package/dist/edge-core/index.js +53 -18
  48. package/dist/edge-core/index.js.map +1 -1
  49. package/dist/edge-core/index.mjs +53 -18
  50. package/dist/edge-core/index.mjs.map +1 -1
  51. package/dist/gateway/gateway.js +53 -18
  52. package/dist/gateway/gateway.js.map +1 -1
  53. package/dist/gateway/gateway.mjs +53 -18
  54. package/dist/gateway/gateway.mjs.map +1 -1
  55. package/dist/index.d.mts +2 -12
  56. package/dist/index.d.ts +2 -12
  57. package/dist/index.js +63 -19
  58. package/dist/index.js.map +1 -1
  59. package/dist/index.mjs +63 -19
  60. package/dist/index.mjs.map +1 -1
  61. package/dist/registration/index.js +1 -1
  62. package/dist/registration/index.js.map +1 -1
  63. package/dist/registration/index.mjs +1 -1
  64. package/dist/registration/index.mjs.map +1 -1
  65. package/dist/transport/index.js +1 -1
  66. package/dist/transport/index.js.map +1 -1
  67. package/dist/transport/index.mjs +1 -1
  68. package/dist/transport/index.mjs.map +1 -1
  69. package/dist/verify.d.mts +0 -10
  70. package/dist/verify.d.ts +0 -10
  71. package/dist/verify.js +36 -10
  72. package/dist/verify.js.map +1 -1
  73. package/dist/verify.mjs +36 -10
  74. package/dist/verify.mjs.map +1 -1
  75. package/package.json +3 -2
@@ -26,7 +26,7 @@ __export(express_exports, {
26
26
  module.exports = __toCommonJS(express_exports);
27
27
 
28
28
  // src/version.ts
29
- var SDK_VERSION = "5.12.0";
29
+ var SDK_VERSION = "5.14.0";
30
30
 
31
31
  // src/http.ts
32
32
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -236,7 +236,7 @@ var DEFAULT_CONFIG = {
236
236
  };
237
237
  var initCheckPerformed = false;
238
238
  var deprecationWarningShown = false;
239
- async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
239
+ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey, counterparty) {
240
240
  initCheckPerformed = true;
241
241
  try {
242
242
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
@@ -254,7 +254,8 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
254
254
  );
255
255
  }
256
256
  if (apiKey) {
257
- const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
257
+ const q = counterparty?.id ? `?counterpartyId=${encodeURIComponent(counterparty.id)}` : counterparty?.url ? `?counterpartyUrl=${encodeURIComponent(counterparty.url)}` : "";
258
+ const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check${q}`, {
258
259
  headers: { Authorization: `Bearer ${apiKey}` }
259
260
  });
260
261
  if (selfCheck.status === 401) {
@@ -266,6 +267,13 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
266
267
  console.error(message);
267
268
  } else if (selfCheck.ok) {
268
269
  const body = await selfCheck.json().catch(() => ({}));
270
+ if (body.counterparty && body.counterparty.canVerify === false) {
271
+ const message = `[VerificationGateway] the configured AstraSync API key cannot verify for this endpoint (${body.counterparty.message ?? "endpoint not found or owned by another account"}). Every inbound agent will be turned away until the key or counterparty is corrected.`;
272
+ if (strictInit) {
273
+ throw new Error(`${message} (strictInit=true)`);
274
+ }
275
+ console.error(message);
276
+ }
269
277
  if (typeof body.daysToExpiry === "number" && body.daysToExpiry <= 7) {
270
278
  console.warn(
271
279
  `[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`
@@ -404,11 +412,11 @@ function createGuidanceResponse(_config, reason, options = {}) {
404
412
  const isMisconfig = source === "merchant_misconfig";
405
413
  const urls = options.urls;
406
414
  const guidance = isMisconfig ? {
407
- 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.",
415
+ message: "This site's AstraSync integration is misconfigured (its API key was revoked, expired, rotated, or belongs to another account). Your identity and the AstraSync platform are fine \u2014 contact the site operator. Retrying will not help.",
408
416
  registrationUrl: urls?.registrationUrl ?? "",
409
417
  documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? "",
410
418
  steps: [
411
- "Report the failure to the site operator \u2014 their AstraSync API key needs rotating",
419
+ "Report the failure to the site operator \u2014 their AstraSync API key needs replacing",
412
420
  "Do not retry: the failure is deterministic until the operator updates their key"
413
421
  ]
414
422
  } : isApiError ? {
@@ -620,12 +628,13 @@ async function callVerifyAccessAPI(config, request) {
620
628
  };
621
629
  }
622
630
  if (!response.ok) {
623
- if (response.status === 401) {
631
+ const keyMismatch = response.status === 403 && data?.error === "COUNTERPARTY_KEY_MISMATCH";
632
+ if (response.status === 401 || keyMismatch) {
624
633
  return {
625
634
  success: false,
626
635
  error: data.message || data.error || "Integration API key rejected",
627
636
  misconfig: true,
628
- misconfigCode: typeof data?.code === "string" ? data.code : void 0,
637
+ misconfigCode: keyMismatch ? "counterparty_key_mismatch" : typeof data?.code === "string" ? data.code : void 0,
629
638
  remediation: data?.remediation && typeof data.remediation === "object" ? data.remediation : void 0,
630
639
  correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
631
640
  attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
@@ -658,14 +667,22 @@ async function verify(config, request, options) {
658
667
  mergedConfig.apiBaseUrl,
659
668
  mergedConfig.debug,
660
669
  true,
661
- mergedConfig.apiKey
670
+ mergedConfig.apiKey,
671
+ {
672
+ id: mergedConfig.counterpartyId,
673
+ url: mergedConfig.counterpartyUrl ?? request.counterpartyUrl
674
+ }
662
675
  );
663
676
  } else {
664
677
  void performInitCheck(
665
678
  mergedConfig.apiBaseUrl,
666
679
  mergedConfig.debug,
667
680
  false,
668
- mergedConfig.apiKey
681
+ mergedConfig.apiKey,
682
+ {
683
+ id: mergedConfig.counterpartyId,
684
+ url: mergedConfig.counterpartyUrl ?? request.counterpartyUrl
685
+ }
669
686
  );
670
687
  }
671
688
  }
@@ -854,6 +871,7 @@ async function recordDecision(config, sessionId, decision, reason) {
854
871
  }).catch(() => {
855
872
  });
856
873
  }
874
+ var refusedPolicyReads = /* @__PURE__ */ new Set();
857
875
  async function fetchRoutes(config, counterpartyId) {
858
876
  if (!counterpartyId) return null;
859
877
  const headers = { "Content-Type": "application/json" };
@@ -866,7 +884,15 @@ async function fetchRoutes(config, counterpartyId) {
866
884
  `${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,
867
885
  { method: "GET", headers }
868
886
  );
869
- if (!response.ok) return null;
887
+ if (!response.ok) {
888
+ if ((response.status === 401 || response.status === 403 || response.status === 404) && !refusedPolicyReads.has(counterpartyId)) {
889
+ refusedPolicyReads.add(counterpartyId);
890
+ console.error(
891
+ `[VerificationGateway] the configured API key cannot read the route policy for ${counterpartyId} (HTTP ${response.status}). The key belongs to an account that does not own this endpoint, or the counterpartyId is wrong. The gateway is in PASS-THROUGH mode: no agent is being verified.`
892
+ );
893
+ }
894
+ return null;
895
+ }
870
896
  const body = await response.json();
871
897
  return body.data?.routes ?? [];
872
898
  } catch {
@@ -1629,6 +1655,11 @@ async function withBudget(promise, ms) {
1629
1655
  if (timer) clearTimeout(timer);
1630
1656
  }
1631
1657
  }
1658
+ var CONTAINER_ID = (() => {
1659
+ const c = globalThis.crypto;
1660
+ if (c?.randomUUID) return c.randomUUID();
1661
+ return `c-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
1662
+ })();
1632
1663
  var destKeyOf = (d) => `${d.apiBaseUrl}\0${d.apiKey ?? ""}\0${d.counterparty}\0${d.adapter ?? ""}`;
1633
1664
  var BeaconBuffer = class {
1634
1665
  constructor(options = {}) {
@@ -1636,6 +1667,7 @@ var BeaconBuffer = class {
1636
1667
  this.droppedSinceLast = 0;
1637
1668
  this.droppedTotal = 0;
1638
1669
  this.deliveredTotal = 0;
1670
+ this.enqueuedTotal = 0;
1639
1671
  this.backoffUntil = 0;
1640
1672
  this.collapse = /* @__PURE__ */ new Map();
1641
1673
  /** Keys the backend answered 401 for — later batches go unauthenticated. */
@@ -1648,13 +1680,16 @@ var BeaconBuffer = class {
1648
1680
  collapseMaxKeys: options.collapseMaxKeys ?? 1e3,
1649
1681
  requestTimeoutMs: options.requestTimeoutMs ?? 1e4,
1650
1682
  retryBackoffMs: options.retryBackoffMs ?? 1e3,
1683
+ holdRepeats: options.holdRepeats ?? false,
1684
+ containerId: options.containerId ?? CONTAINER_ID,
1651
1685
  now: options.now ?? Date.now
1652
1686
  };
1653
1687
  }
1654
1688
  /**
1655
1689
  * Queue one beacon. With a `collapseKey`, a repeat inside the window is
1656
- * merged into a held aggregate (sent when the window closes) instead of
1657
- * becoming its own item.
1690
+ * merged into this key's item while that item is still queued (not yet in
1691
+ * flight). Once it has left, the repeat becomes a new item, sendable on
1692
+ * this flush — nothing waits for a later invocation (round 27.6).
1658
1693
  */
1659
1694
  enqueue(dest, item, collapseKey) {
1660
1695
  const now = this.opts.now();
@@ -1667,12 +1702,15 @@ var BeaconBuffer = class {
1667
1702
  return;
1668
1703
  }
1669
1704
  }
1670
- const held = this.push(
1671
- dest,
1672
- { ...item, repeatCount: 1 },
1673
- entry.firstSeenAt + this.opts.collapseWindowMs
1674
- );
1675
- entry.held = held;
1705
+ if (this.opts.holdRepeats) {
1706
+ entry.held = this.push(
1707
+ dest,
1708
+ { ...item, repeatCount: 1 },
1709
+ entry.firstSeenAt + this.opts.collapseWindowMs
1710
+ );
1711
+ return;
1712
+ }
1713
+ entry.first = this.push(dest, { ...item, repeatCount: 1 }, now);
1676
1714
  return;
1677
1715
  }
1678
1716
  this.collapse.delete(collapseKey);
@@ -1708,6 +1746,7 @@ var BeaconBuffer = class {
1708
1746
  droppedSinceLast: this.droppedSinceLast,
1709
1747
  droppedTotal: this.droppedTotal,
1710
1748
  deliveredTotal: this.deliveredTotal,
1749
+ enqueuedTotal: this.enqueuedTotal,
1711
1750
  flushing: this.inFlight !== void 0
1712
1751
  };
1713
1752
  }
@@ -1722,6 +1761,7 @@ var BeaconBuffer = class {
1722
1761
  inFlight: false
1723
1762
  };
1724
1763
  this.queue.push(entry);
1764
+ this.enqueuedTotal += 1;
1725
1765
  return entry;
1726
1766
  }
1727
1767
  dropOldest() {
@@ -1767,7 +1807,11 @@ var BeaconBuffer = class {
1767
1807
  droppedSinceLast: reportedDropped,
1768
1808
  queueDepth: this.queue.length,
1769
1809
  adapter: dest.adapter ?? "edge-core",
1770
- version: SDK_VERSION
1810
+ version: SDK_VERSION,
1811
+ containerId: this.opts.containerId,
1812
+ enqueuedTotal: this.enqueuedTotal,
1813
+ deliveredTotal: this.deliveredTotal,
1814
+ droppedTotal: this.droppedTotal
1771
1815
  };
1772
1816
  const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
1773
1817
  const response = await withBudget(