@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
@@ -36,7 +36,7 @@ __export(nextjs_exports, {
36
36
  module.exports = __toCommonJS(nextjs_exports);
37
37
 
38
38
  // src/version.ts
39
- var SDK_VERSION = "5.12.0";
39
+ var SDK_VERSION = "5.14.0";
40
40
 
41
41
  // src/http.ts
42
42
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -194,7 +194,7 @@ var DEFAULT_CONFIG = {
194
194
  };
195
195
  var initCheckPerformed = false;
196
196
  var deprecationWarningShown = false;
197
- async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
197
+ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey, counterparty) {
198
198
  initCheckPerformed = true;
199
199
  try {
200
200
  const probeUrl = `${apiBaseUrl}/agents/verify-access`;
@@ -212,7 +212,8 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
212
212
  );
213
213
  }
214
214
  if (apiKey) {
215
- const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
215
+ const q = counterparty?.id ? `?counterpartyId=${encodeURIComponent(counterparty.id)}` : counterparty?.url ? `?counterpartyUrl=${encodeURIComponent(counterparty.url)}` : "";
216
+ const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check${q}`, {
216
217
  headers: { Authorization: `Bearer ${apiKey}` }
217
218
  });
218
219
  if (selfCheck.status === 401) {
@@ -224,6 +225,13 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
224
225
  console.error(message);
225
226
  } else if (selfCheck.ok) {
226
227
  const body = await selfCheck.json().catch(() => ({}));
228
+ if (body.counterparty && body.counterparty.canVerify === false) {
229
+ 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.`;
230
+ if (strictInit) {
231
+ throw new Error(`${message} (strictInit=true)`);
232
+ }
233
+ console.error(message);
234
+ }
227
235
  if (typeof body.daysToExpiry === "number" && body.daysToExpiry <= 7) {
228
236
  console.warn(
229
237
  `[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`
@@ -362,11 +370,11 @@ function createGuidanceResponse(_config, reason, options = {}) {
362
370
  const isMisconfig = source === "merchant_misconfig";
363
371
  const urls = options.urls;
364
372
  const guidance = isMisconfig ? {
365
- 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.",
373
+ 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.",
366
374
  registrationUrl: urls?.registrationUrl ?? "",
367
375
  documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? "",
368
376
  steps: [
369
- "Report the failure to the site operator \u2014 their AstraSync API key needs rotating",
377
+ "Report the failure to the site operator \u2014 their AstraSync API key needs replacing",
370
378
  "Do not retry: the failure is deterministic until the operator updates their key"
371
379
  ]
372
380
  } : isApiError ? {
@@ -578,12 +586,13 @@ async function callVerifyAccessAPI(config, request) {
578
586
  };
579
587
  }
580
588
  if (!response.ok) {
581
- if (response.status === 401) {
589
+ const keyMismatch = response.status === 403 && data?.error === "COUNTERPARTY_KEY_MISMATCH";
590
+ if (response.status === 401 || keyMismatch) {
582
591
  return {
583
592
  success: false,
584
593
  error: data.message || data.error || "Integration API key rejected",
585
594
  misconfig: true,
586
- misconfigCode: typeof data?.code === "string" ? data.code : void 0,
595
+ misconfigCode: keyMismatch ? "counterparty_key_mismatch" : typeof data?.code === "string" ? data.code : void 0,
587
596
  remediation: data?.remediation && typeof data.remediation === "object" ? data.remediation : void 0,
588
597
  correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
589
598
  attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
@@ -616,14 +625,22 @@ async function verify(config, request, options) {
616
625
  mergedConfig.apiBaseUrl,
617
626
  mergedConfig.debug,
618
627
  true,
619
- mergedConfig.apiKey
628
+ mergedConfig.apiKey,
629
+ {
630
+ id: mergedConfig.counterpartyId,
631
+ url: mergedConfig.counterpartyUrl ?? request.counterpartyUrl
632
+ }
620
633
  );
621
634
  } else {
622
635
  void performInitCheck(
623
636
  mergedConfig.apiBaseUrl,
624
637
  mergedConfig.debug,
625
638
  false,
626
- mergedConfig.apiKey
639
+ mergedConfig.apiKey,
640
+ {
641
+ id: mergedConfig.counterpartyId,
642
+ url: mergedConfig.counterpartyUrl ?? request.counterpartyUrl
643
+ }
627
644
  );
628
645
  }
629
646
  }
@@ -799,6 +816,7 @@ async function verify(config, request, options) {
799
816
  }
800
817
  return result;
801
818
  }
819
+ var refusedPolicyReads = /* @__PURE__ */ new Set();
802
820
  async function fetchRoutes(config, counterpartyId) {
803
821
  if (!counterpartyId) return null;
804
822
  const headers = { "Content-Type": "application/json" };
@@ -811,7 +829,15 @@ async function fetchRoutes(config, counterpartyId) {
811
829
  `${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,
812
830
  { method: "GET", headers }
813
831
  );
814
- if (!response.ok) return null;
832
+ if (!response.ok) {
833
+ if ((response.status === 401 || response.status === 403 || response.status === 404) && !refusedPolicyReads.has(counterpartyId)) {
834
+ refusedPolicyReads.add(counterpartyId);
835
+ console.error(
836
+ `[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.`
837
+ );
838
+ }
839
+ return null;
840
+ }
815
841
  const body = await response.json();
816
842
  return body.data?.routes ?? [];
817
843
  } catch {
@@ -1457,6 +1483,11 @@ async function withBudget(promise, ms) {
1457
1483
  if (timer) clearTimeout(timer);
1458
1484
  }
1459
1485
  }
1486
+ var CONTAINER_ID = (() => {
1487
+ const c = globalThis.crypto;
1488
+ if (c?.randomUUID) return c.randomUUID();
1489
+ return `c-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
1490
+ })();
1460
1491
  var destKeyOf = (d) => `${d.apiBaseUrl}\0${d.apiKey ?? ""}\0${d.counterparty}\0${d.adapter ?? ""}`;
1461
1492
  var BeaconBuffer = class {
1462
1493
  constructor(options = {}) {
@@ -1464,6 +1495,7 @@ var BeaconBuffer = class {
1464
1495
  this.droppedSinceLast = 0;
1465
1496
  this.droppedTotal = 0;
1466
1497
  this.deliveredTotal = 0;
1498
+ this.enqueuedTotal = 0;
1467
1499
  this.backoffUntil = 0;
1468
1500
  this.collapse = /* @__PURE__ */ new Map();
1469
1501
  /** Keys the backend answered 401 for — later batches go unauthenticated. */
@@ -1476,13 +1508,16 @@ var BeaconBuffer = class {
1476
1508
  collapseMaxKeys: options.collapseMaxKeys ?? 1e3,
1477
1509
  requestTimeoutMs: options.requestTimeoutMs ?? 1e4,
1478
1510
  retryBackoffMs: options.retryBackoffMs ?? 1e3,
1511
+ holdRepeats: options.holdRepeats ?? false,
1512
+ containerId: options.containerId ?? CONTAINER_ID,
1479
1513
  now: options.now ?? Date.now
1480
1514
  };
1481
1515
  }
1482
1516
  /**
1483
1517
  * Queue one beacon. With a `collapseKey`, a repeat inside the window is
1484
- * merged into a held aggregate (sent when the window closes) instead of
1485
- * becoming its own item.
1518
+ * merged into this key's item while that item is still queued (not yet in
1519
+ * flight). Once it has left, the repeat becomes a new item, sendable on
1520
+ * this flush — nothing waits for a later invocation (round 27.6).
1486
1521
  */
1487
1522
  enqueue(dest, item, collapseKey) {
1488
1523
  const now = this.opts.now();
@@ -1495,12 +1530,15 @@ var BeaconBuffer = class {
1495
1530
  return;
1496
1531
  }
1497
1532
  }
1498
- const held = this.push(
1499
- dest,
1500
- { ...item, repeatCount: 1 },
1501
- entry.firstSeenAt + this.opts.collapseWindowMs
1502
- );
1503
- entry.held = held;
1533
+ if (this.opts.holdRepeats) {
1534
+ entry.held = this.push(
1535
+ dest,
1536
+ { ...item, repeatCount: 1 },
1537
+ entry.firstSeenAt + this.opts.collapseWindowMs
1538
+ );
1539
+ return;
1540
+ }
1541
+ entry.first = this.push(dest, { ...item, repeatCount: 1 }, now);
1504
1542
  return;
1505
1543
  }
1506
1544
  this.collapse.delete(collapseKey);
@@ -1536,6 +1574,7 @@ var BeaconBuffer = class {
1536
1574
  droppedSinceLast: this.droppedSinceLast,
1537
1575
  droppedTotal: this.droppedTotal,
1538
1576
  deliveredTotal: this.deliveredTotal,
1577
+ enqueuedTotal: this.enqueuedTotal,
1539
1578
  flushing: this.inFlight !== void 0
1540
1579
  };
1541
1580
  }
@@ -1550,6 +1589,7 @@ var BeaconBuffer = class {
1550
1589
  inFlight: false
1551
1590
  };
1552
1591
  this.queue.push(entry);
1592
+ this.enqueuedTotal += 1;
1553
1593
  return entry;
1554
1594
  }
1555
1595
  dropOldest() {
@@ -1595,7 +1635,11 @@ var BeaconBuffer = class {
1595
1635
  droppedSinceLast: reportedDropped,
1596
1636
  queueDepth: this.queue.length,
1597
1637
  adapter: dest.adapter ?? "edge-core",
1598
- version: SDK_VERSION
1638
+ version: SDK_VERSION,
1639
+ containerId: this.opts.containerId,
1640
+ enqueuedTotal: this.enqueuedTotal,
1641
+ deliveredTotal: this.deliveredTotal,
1642
+ droppedTotal: this.droppedTotal
1599
1643
  };
1600
1644
  const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
1601
1645
  const response = await withBudget(