@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
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var SDK_VERSION = "5.12.0";
2
+ var SDK_VERSION = "5.14.0";
3
3
 
4
4
  // src/http.ts
5
5
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -209,7 +209,7 @@ var DEFAULT_CONFIG = {
209
209
  };
210
210
  var initCheckPerformed = false;
211
211
  var deprecationWarningShown = false;
212
- async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
212
+ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey, counterparty) {
213
213
  initCheckPerformed = true;
214
214
  try {
215
215
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
@@ -227,7 +227,8 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
227
227
  );
228
228
  }
229
229
  if (apiKey) {
230
- const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
230
+ const q = counterparty?.id ? `?counterpartyId=${encodeURIComponent(counterparty.id)}` : counterparty?.url ? `?counterpartyUrl=${encodeURIComponent(counterparty.url)}` : "";
231
+ const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check${q}`, {
231
232
  headers: { Authorization: `Bearer ${apiKey}` }
232
233
  });
233
234
  if (selfCheck.status === 401) {
@@ -239,6 +240,13 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
239
240
  console.error(message);
240
241
  } else if (selfCheck.ok) {
241
242
  const body = await selfCheck.json().catch(() => ({}));
243
+ if (body.counterparty && body.counterparty.canVerify === false) {
244
+ 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.`;
245
+ if (strictInit) {
246
+ throw new Error(`${message} (strictInit=true)`);
247
+ }
248
+ console.error(message);
249
+ }
242
250
  if (typeof body.daysToExpiry === "number" && body.daysToExpiry <= 7) {
243
251
  console.warn(
244
252
  `[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`
@@ -377,11 +385,11 @@ function createGuidanceResponse(_config, reason, options = {}) {
377
385
  const isMisconfig = source === "merchant_misconfig";
378
386
  const urls = options.urls;
379
387
  const guidance = isMisconfig ? {
380
- 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.",
388
+ 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.",
381
389
  registrationUrl: urls?.registrationUrl ?? "",
382
390
  documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? "",
383
391
  steps: [
384
- "Report the failure to the site operator \u2014 their AstraSync API key needs rotating",
392
+ "Report the failure to the site operator \u2014 their AstraSync API key needs replacing",
385
393
  "Do not retry: the failure is deterministic until the operator updates their key"
386
394
  ]
387
395
  } : isApiError ? {
@@ -593,12 +601,13 @@ async function callVerifyAccessAPI(config, request) {
593
601
  };
594
602
  }
595
603
  if (!response.ok) {
596
- if (response.status === 401) {
604
+ const keyMismatch = response.status === 403 && data?.error === "COUNTERPARTY_KEY_MISMATCH";
605
+ if (response.status === 401 || keyMismatch) {
597
606
  return {
598
607
  success: false,
599
608
  error: data.message || data.error || "Integration API key rejected",
600
609
  misconfig: true,
601
- misconfigCode: typeof data?.code === "string" ? data.code : void 0,
610
+ misconfigCode: keyMismatch ? "counterparty_key_mismatch" : typeof data?.code === "string" ? data.code : void 0,
602
611
  remediation: data?.remediation && typeof data.remediation === "object" ? data.remediation : void 0,
603
612
  correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
604
613
  attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
@@ -631,14 +640,22 @@ async function verify(config, request, options) {
631
640
  mergedConfig.apiBaseUrl,
632
641
  mergedConfig.debug,
633
642
  true,
634
- mergedConfig.apiKey
643
+ mergedConfig.apiKey,
644
+ {
645
+ id: mergedConfig.counterpartyId,
646
+ url: mergedConfig.counterpartyUrl ?? request.counterpartyUrl
647
+ }
635
648
  );
636
649
  } else {
637
650
  void performInitCheck(
638
651
  mergedConfig.apiBaseUrl,
639
652
  mergedConfig.debug,
640
653
  false,
641
- mergedConfig.apiKey
654
+ mergedConfig.apiKey,
655
+ {
656
+ id: mergedConfig.counterpartyId,
657
+ url: mergedConfig.counterpartyUrl ?? request.counterpartyUrl
658
+ }
642
659
  );
643
660
  }
644
661
  }
@@ -827,6 +844,7 @@ async function recordDecision(config, sessionId, decision, reason) {
827
844
  }).catch(() => {
828
845
  });
829
846
  }
847
+ var refusedPolicyReads = /* @__PURE__ */ new Set();
830
848
  async function fetchRoutes(config, counterpartyId) {
831
849
  if (!counterpartyId) return null;
832
850
  const headers = { "Content-Type": "application/json" };
@@ -839,7 +857,15 @@ async function fetchRoutes(config, counterpartyId) {
839
857
  `${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,
840
858
  { method: "GET", headers }
841
859
  );
842
- if (!response.ok) return null;
860
+ if (!response.ok) {
861
+ if ((response.status === 401 || response.status === 403 || response.status === 404) && !refusedPolicyReads.has(counterpartyId)) {
862
+ refusedPolicyReads.add(counterpartyId);
863
+ console.error(
864
+ `[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.`
865
+ );
866
+ }
867
+ return null;
868
+ }
843
869
  const body = await response.json();
844
870
  return body.data?.routes ?? [];
845
871
  } catch {
@@ -1602,6 +1628,11 @@ async function withBudget(promise, ms) {
1602
1628
  if (timer) clearTimeout(timer);
1603
1629
  }
1604
1630
  }
1631
+ var CONTAINER_ID = (() => {
1632
+ const c = globalThis.crypto;
1633
+ if (c?.randomUUID) return c.randomUUID();
1634
+ return `c-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
1635
+ })();
1605
1636
  var destKeyOf = (d) => `${d.apiBaseUrl}\0${d.apiKey ?? ""}\0${d.counterparty}\0${d.adapter ?? ""}`;
1606
1637
  var BeaconBuffer = class {
1607
1638
  constructor(options = {}) {
@@ -1609,6 +1640,7 @@ var BeaconBuffer = class {
1609
1640
  this.droppedSinceLast = 0;
1610
1641
  this.droppedTotal = 0;
1611
1642
  this.deliveredTotal = 0;
1643
+ this.enqueuedTotal = 0;
1612
1644
  this.backoffUntil = 0;
1613
1645
  this.collapse = /* @__PURE__ */ new Map();
1614
1646
  /** Keys the backend answered 401 for — later batches go unauthenticated. */
@@ -1621,13 +1653,16 @@ var BeaconBuffer = class {
1621
1653
  collapseMaxKeys: options.collapseMaxKeys ?? 1e3,
1622
1654
  requestTimeoutMs: options.requestTimeoutMs ?? 1e4,
1623
1655
  retryBackoffMs: options.retryBackoffMs ?? 1e3,
1656
+ holdRepeats: options.holdRepeats ?? false,
1657
+ containerId: options.containerId ?? CONTAINER_ID,
1624
1658
  now: options.now ?? Date.now
1625
1659
  };
1626
1660
  }
1627
1661
  /**
1628
1662
  * Queue one beacon. With a `collapseKey`, a repeat inside the window is
1629
- * merged into a held aggregate (sent when the window closes) instead of
1630
- * becoming its own item.
1663
+ * merged into this key's item while that item is still queued (not yet in
1664
+ * flight). Once it has left, the repeat becomes a new item, sendable on
1665
+ * this flush — nothing waits for a later invocation (round 27.6).
1631
1666
  */
1632
1667
  enqueue(dest, item, collapseKey) {
1633
1668
  const now = this.opts.now();
@@ -1640,12 +1675,15 @@ var BeaconBuffer = class {
1640
1675
  return;
1641
1676
  }
1642
1677
  }
1643
- const held = this.push(
1644
- dest,
1645
- { ...item, repeatCount: 1 },
1646
- entry.firstSeenAt + this.opts.collapseWindowMs
1647
- );
1648
- entry.held = held;
1678
+ if (this.opts.holdRepeats) {
1679
+ entry.held = this.push(
1680
+ dest,
1681
+ { ...item, repeatCount: 1 },
1682
+ entry.firstSeenAt + this.opts.collapseWindowMs
1683
+ );
1684
+ return;
1685
+ }
1686
+ entry.first = this.push(dest, { ...item, repeatCount: 1 }, now);
1649
1687
  return;
1650
1688
  }
1651
1689
  this.collapse.delete(collapseKey);
@@ -1681,6 +1719,7 @@ var BeaconBuffer = class {
1681
1719
  droppedSinceLast: this.droppedSinceLast,
1682
1720
  droppedTotal: this.droppedTotal,
1683
1721
  deliveredTotal: this.deliveredTotal,
1722
+ enqueuedTotal: this.enqueuedTotal,
1684
1723
  flushing: this.inFlight !== void 0
1685
1724
  };
1686
1725
  }
@@ -1695,6 +1734,7 @@ var BeaconBuffer = class {
1695
1734
  inFlight: false
1696
1735
  };
1697
1736
  this.queue.push(entry);
1737
+ this.enqueuedTotal += 1;
1698
1738
  return entry;
1699
1739
  }
1700
1740
  dropOldest() {
@@ -1740,7 +1780,11 @@ var BeaconBuffer = class {
1740
1780
  droppedSinceLast: reportedDropped,
1741
1781
  queueDepth: this.queue.length,
1742
1782
  adapter: dest.adapter ?? "edge-core",
1743
- version: SDK_VERSION
1783
+ version: SDK_VERSION,
1784
+ containerId: this.opts.containerId,
1785
+ enqueuedTotal: this.enqueuedTotal,
1786
+ deliveredTotal: this.deliveredTotal,
1787
+ droppedTotal: this.droppedTotal
1744
1788
  };
1745
1789
  const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
1746
1790
  const response = await withBudget(