agent-comms 5.2.5 → 7.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 (138) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +6 -2
  4. package/dist/bridges/user/controller.d.ts +1 -1
  5. package/dist/bridges/user/controller.d.ts.map +1 -1
  6. package/dist/bridges/user/controller.js +1 -1
  7. package/dist/bridges/user/controller.js.map +1 -1
  8. package/dist/core/bridge-mesh.d.ts +2 -2
  9. package/dist/core/bridge-mesh.d.ts.map +1 -1
  10. package/dist/core/bridge-mesh.js +3 -2
  11. package/dist/core/bridge-mesh.js.map +1 -1
  12. package/dist/core/gateway-trust.d.ts +15 -9
  13. package/dist/core/gateway-trust.d.ts.map +1 -1
  14. package/dist/core/gateway-trust.js +49 -21
  15. package/dist/core/gateway-trust.js.map +1 -1
  16. package/dist/core/gossip-directory.d.ts +1 -1
  17. package/dist/core/gossip-directory.d.ts.map +1 -1
  18. package/dist/core/gossip-directory.js +4 -2
  19. package/dist/core/gossip-directory.js.map +1 -1
  20. package/dist/core/hub-forwarding.d.ts +4 -18
  21. package/dist/core/hub-forwarding.d.ts.map +1 -1
  22. package/dist/core/hub-forwarding.js +2 -41
  23. package/dist/core/hub-forwarding.js.map +1 -1
  24. package/dist/core/hub-link.d.ts +58 -0
  25. package/dist/core/hub-link.d.ts.map +1 -0
  26. package/dist/core/hub-link.js +118 -0
  27. package/dist/core/hub-link.js.map +1 -0
  28. package/dist/core/hub-session.d.ts +14 -15
  29. package/dist/core/hub-session.d.ts.map +1 -1
  30. package/dist/core/hub-session.js +30 -51
  31. package/dist/core/hub-session.js.map +1 -1
  32. package/dist/core/identity-store.d.ts +8 -4
  33. package/dist/core/identity-store.d.ts.map +1 -1
  34. package/dist/core/identity-store.js +29 -15
  35. package/dist/core/identity-store.js.map +1 -1
  36. package/dist/core/mesh-graph.d.ts +1 -1
  37. package/dist/core/mesh-graph.js +1 -1
  38. package/dist/core/mesh-store.d.ts +11 -6
  39. package/dist/core/mesh-store.d.ts.map +1 -1
  40. package/dist/core/mesh-store.js +33 -22
  41. package/dist/core/mesh-store.js.map +1 -1
  42. package/dist/core/peer-lifecycle.d.ts +2 -5
  43. package/dist/core/peer-lifecycle.d.ts.map +1 -1
  44. package/dist/core/peer-lifecycle.js +0 -1
  45. package/dist/core/peer-lifecycle.js.map +1 -1
  46. package/dist/core/room-router.d.ts +2 -2
  47. package/dist/core/room-router.d.ts.map +1 -1
  48. package/dist/core/room-router.js +2 -32
  49. package/dist/core/room-router.js.map +1 -1
  50. package/dist/core/shutdown-signals.d.ts +1 -1
  51. package/dist/core/shutdown-signals.js +1 -1
  52. package/dist/core/transport.d.ts +7 -7
  53. package/dist/core/transport.d.ts.map +1 -1
  54. package/dist/core/wire-mesh-transport.d.ts +7 -3
  55. package/dist/core/wire-mesh-transport.d.ts.map +1 -1
  56. package/dist/core/wire-mesh-transport.js +39 -22
  57. package/dist/core/wire-mesh-transport.js.map +1 -1
  58. package/dist/test/bridge-mesh.integration.test.js +15 -1
  59. package/dist/test/bridge-mesh.integration.test.js.map +1 -1
  60. package/dist/test/chat-controller-mesh-errors.integration.test.js +7 -1
  61. package/dist/test/chat-controller-mesh-errors.integration.test.js.map +1 -1
  62. package/dist/test/coordinator-failover-hub.integration.test.d.ts +5 -0
  63. package/dist/test/coordinator-failover-hub.integration.test.d.ts.map +1 -0
  64. package/dist/test/coordinator-failover-hub.integration.test.js +78 -0
  65. package/dist/test/coordinator-failover-hub.integration.test.js.map +1 -0
  66. package/dist/test/coordinator-failover.integration.test.js +3 -6
  67. package/dist/test/coordinator-failover.integration.test.js.map +1 -1
  68. package/dist/test/coordinator-failover.unit.test.js +0 -7
  69. package/dist/test/coordinator-failover.unit.test.js.map +1 -1
  70. package/dist/test/gateway-trust.integration.test.d.ts +1 -1
  71. package/dist/test/gateway-trust.integration.test.js +26 -2
  72. package/dist/test/gateway-trust.integration.test.js.map +1 -1
  73. package/dist/test/gateway-trust.unit.test.js +43 -5
  74. package/dist/test/gateway-trust.unit.test.js.map +1 -1
  75. package/dist/test/hub-exposure.integration.test.d.ts +5 -0
  76. package/dist/test/hub-exposure.integration.test.d.ts.map +1 -0
  77. package/dist/test/hub-exposure.integration.test.js +121 -0
  78. package/dist/test/hub-exposure.integration.test.js.map +1 -0
  79. package/dist/test/hub-helpers.d.ts +18 -3
  80. package/dist/test/hub-helpers.d.ts.map +1 -1
  81. package/dist/test/hub-helpers.js +24 -3
  82. package/dist/test/hub-helpers.js.map +1 -1
  83. package/dist/test/hub-link.unit.test.d.ts +2 -0
  84. package/dist/test/hub-link.unit.test.d.ts.map +1 -0
  85. package/dist/test/hub-link.unit.test.js +210 -0
  86. package/dist/test/hub-link.unit.test.js.map +1 -0
  87. package/dist/test/hub-peer-per-store.integration.test.d.ts +9 -0
  88. package/dist/test/hub-peer-per-store.integration.test.d.ts.map +1 -0
  89. package/dist/test/hub-peer-per-store.integration.test.js +211 -0
  90. package/dist/test/hub-peer-per-store.integration.test.js.map +1 -0
  91. package/dist/test/hub-room-domain-verb-trust-bypass.integration.test.js +2 -2
  92. package/dist/test/hub-room-domain-verb-trust-bypass.integration.test.js.map +1 -1
  93. package/dist/test/hub-session-close.integration.test.js +1 -1
  94. package/dist/test/hub-session-close.integration.test.js.map +1 -1
  95. package/dist/test/hub-session-dispatch.unit.test.js +1 -66
  96. package/dist/test/hub-session-dispatch.unit.test.js.map +1 -1
  97. package/dist/test/identity-store.integration.test.js +24 -32
  98. package/dist/test/identity-store.integration.test.js.map +1 -1
  99. package/dist/test/mesh-graph-trace.integration.test.js +2 -2
  100. package/dist/test/mesh-graph-trace.integration.test.js.map +1 -1
  101. package/dist/test/mesh-smoke.runner.js +1 -3
  102. package/dist/test/mesh-smoke.runner.js.map +1 -1
  103. package/dist/test/mesh-store-orchestration.unit.test.js +11 -41
  104. package/dist/test/mesh-store-orchestration.unit.test.js.map +1 -1
  105. package/dist/test/peer-lifecycle.unit.test.js +0 -8
  106. package/dist/test/peer-lifecycle.unit.test.js.map +1 -1
  107. package/dist/test/principal-membership-trust.integration.test.js +8 -1
  108. package/dist/test/principal-membership-trust.integration.test.js.map +1 -1
  109. package/dist/test/room-join-by-bare-name.integration.test.js +1 -1
  110. package/dist/test/room-join-by-bare-name.integration.test.js.map +1 -1
  111. package/dist/test/test-transport.d.ts +1 -1
  112. package/dist/test/test-transport.d.ts.map +1 -1
  113. package/dist/test/test-transport.js +1 -1
  114. package/dist/test/test-transport.js.map +1 -1
  115. package/dist/test/wire-mesh-transport-hub.integration.test.d.ts +1 -1
  116. package/dist/test/wire-mesh-transport-hub.integration.test.js +96 -9
  117. package/dist/test/wire-mesh-transport-hub.integration.test.js.map +1 -1
  118. package/package.json +1 -1
  119. package/dist/core/coordinator-gateway.d.ts +0 -25
  120. package/dist/core/coordinator-gateway.d.ts.map +0 -1
  121. package/dist/core/coordinator-gateway.js +0 -34
  122. package/dist/core/coordinator-gateway.js.map +0 -1
  123. package/dist/test/coordinator-gateway.unit.test.d.ts +0 -2
  124. package/dist/test/coordinator-gateway.unit.test.d.ts.map +0 -1
  125. package/dist/test/coordinator-gateway.unit.test.js +0 -88
  126. package/dist/test/coordinator-gateway.unit.test.js.map +0 -1
  127. package/dist/test/gateway-forwarding.integration.test.d.ts +0 -9
  128. package/dist/test/gateway-forwarding.integration.test.d.ts.map +0 -1
  129. package/dist/test/gateway-forwarding.integration.test.js +0 -226
  130. package/dist/test/gateway-forwarding.integration.test.js.map +0 -1
  131. package/dist/test/hub-forwarding.unit.test.d.ts +0 -2
  132. package/dist/test/hub-forwarding.unit.test.d.ts.map +0 -1
  133. package/dist/test/hub-forwarding.unit.test.js +0 -102
  134. package/dist/test/hub-forwarding.unit.test.js.map +0 -1
  135. package/dist/test/hub-todevice-routing.integration.test.d.ts +0 -7
  136. package/dist/test/hub-todevice-routing.integration.test.d.ts.map +0 -1
  137. package/dist/test/hub-todevice-routing.integration.test.js +0 -121
  138. package/dist/test/hub-todevice-routing.integration.test.js.map +0 -1
@@ -1,34 +0,0 @@
1
- /**
2
- * CoordinatorGateway — attaches the cross-machine gateway role to this machine's local coordinator (agent-comms#154, agent-comms#153's first leg). A bridge that becomes the mesh's local coordinator, whether by a fresh bind (MeshStore's own init()) or a takeover (PeerLifecycle's own handleBecomeCoordinator), also becomes the machine's gateway: it dials the hub and holds the connection for as long as it holds the coordinator role. Losing the role, gracefully or by crash, drops the connection; the next coordinator re-dials as part of taking over. Hub-side state is therefore rebuilt from scratch on every takeover -- messages in flight during the gap are lost, the same loss class as a coordinator crash today, now on the data path. Forwarding local agents onto the hub and merging its directory back (agent-comms#155) is deliberately not this class's concern; it owns only the connection lifecycle.
3
- */
4
- export class CoordinatorGateway {
5
- deps;
6
- connected = false;
7
- constructor(deps) {
8
- this.deps = deps;
9
- }
10
- /** Whether this side currently holds the gateway role: it has dialled the hub and has not since lost coordinator status. */
11
- get isConnected() {
12
- return this.connected;
13
- }
14
- /** Dials the hub for this machine's gateway role. Idempotent: a call while already connected is a no-op, since nothing in this codebase's own coordinator-election machinery re-fires "became coordinator" without an intervening onLostCoordinator -- this guard is defensive, not a known double-fire path. Never throws: local coordinator election (the whole reason this side is calling this at all) must not depend on the hub being reachable, so a dial failure is reported via deps.onError and swallowed here, leaving isConnected false so a later onBecameCoordinator call retries rather than being blocked by the earlier failure's own idempotency guard. */
15
- async onBecameCoordinator() {
16
- if (this.connected)
17
- return;
18
- try {
19
- await this.deps.connectHub(this.deps.hubUrl);
20
- this.connected = true;
21
- }
22
- catch (error) {
23
- this.deps.onError?.(error instanceof Error ? error : new Error(String(error)));
24
- }
25
- }
26
- /** Drops this machine's held hub connection. A no-op if this side never became the gateway, or already lost the role -- MeshStore.shutdown() calls this unconditionally regardless of coordinator status, so this guard is what makes that safe rather than a redundant extra close. */
27
- async onLostCoordinator() {
28
- if (!this.connected)
29
- return;
30
- this.connected = false;
31
- await this.deps.disconnectHub();
32
- }
33
- }
34
- //# sourceMappingURL=coordinator-gateway.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"coordinator-gateway.js","sourceRoot":"","sources":["../../src/core/coordinator-gateway.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH,MAAM,OAAO,kBAAkB;IAGA;IAFrB,SAAS,GAAG,KAAK,CAAC;IAE1B,YAA6B,IAAsC;QAAtC,SAAI,GAAJ,IAAI,CAAkC;IAAG,CAAC;IAEvE,4HAA4H;IAC5H,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,6oBAA6oB;IAC7oB,KAAK,CAAC,mBAAmB;QACvB,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CACjB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAC1D,CAAC;QACJ,CAAC;IACH,CAAC;IAED,wRAAwR;IACxR,KAAK,CAAC,iBAAiB;QACrB,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QAC5B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAClC,CAAC;CACF"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=coordinator-gateway.unit.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"coordinator-gateway.unit.test.d.ts","sourceRoot":"","sources":["../../src/test/coordinator-gateway.unit.test.ts"],"names":[],"mappings":""}
@@ -1,88 +0,0 @@
1
- /**
2
- * Direct unit tests for CoordinatorGateway -- the connect-hub-on-become-coordinator / disconnect-hub-on-lose-coordinator wiring (agent-comms#154), tested against injected connectHub/disconnectHub closures rather than a real transport or hub socket, mirroring peer-lifecycle.test.ts's own DI-based approach.
3
- */
4
- import { describe, expect, it, vi } from "vitest";
5
- import { CoordinatorGateway, } from "../core/coordinator-gateway.js";
6
- const HUB_URL = "wss://mesh.example.test/";
7
- function makeHarness() {
8
- const connectHub = vi.fn().mockResolvedValue(undefined);
9
- const disconnectHub = vi.fn().mockResolvedValue(undefined);
10
- const onError = vi.fn();
11
- const deps = {
12
- hubUrl: HUB_URL,
13
- connectHub,
14
- disconnectHub,
15
- onError,
16
- };
17
- return {
18
- gateway: new CoordinatorGateway(deps),
19
- connectHub,
20
- disconnectHub,
21
- onError,
22
- };
23
- }
24
- describe("CoordinatorGateway — onBecameCoordinator", () => {
25
- it("dials the configured hub URL", async () => {
26
- const { gateway, connectHub } = makeHarness();
27
- await gateway.onBecameCoordinator();
28
- expect(connectHub).toHaveBeenCalledWith(HUB_URL);
29
- expect(connectHub).toHaveBeenCalledTimes(1);
30
- });
31
- it("marks isConnected true once dialled", async () => {
32
- const { gateway } = makeHarness();
33
- expect(gateway.isConnected).toBe(false);
34
- await gateway.onBecameCoordinator();
35
- expect(gateway.isConnected).toBe(true);
36
- });
37
- it("is idempotent -- a second call while already connected does not redial", async () => {
38
- const { gateway, connectHub } = makeHarness();
39
- await gateway.onBecameCoordinator();
40
- await gateway.onBecameCoordinator();
41
- expect(connectHub).toHaveBeenCalledTimes(1);
42
- });
43
- it("reports a dial failure via onError rather than throwing -- local coordinator election must not depend on hub reachability", async () => {
44
- const { gateway, connectHub, onError } = makeHarness();
45
- const dialError = new Error("ECONNREFUSED");
46
- connectHub.mockRejectedValueOnce(dialError);
47
- await expect(gateway.onBecameCoordinator()).resolves.toBeUndefined();
48
- expect(onError).toHaveBeenCalledWith(dialError);
49
- });
50
- it("does not mark itself connected after a failed dial, so a later call can retry", async () => {
51
- const { gateway, connectHub } = makeHarness();
52
- connectHub.mockRejectedValueOnce(new Error("ECONNREFUSED"));
53
- await gateway.onBecameCoordinator();
54
- expect(gateway.isConnected).toBe(false);
55
- await gateway.onBecameCoordinator();
56
- expect(gateway.isConnected).toBe(true);
57
- expect(connectHub).toHaveBeenCalledTimes(2);
58
- });
59
- });
60
- describe("CoordinatorGateway — onLostCoordinator", () => {
61
- it("drops the hub connection when one is held", async () => {
62
- const { gateway, disconnectHub } = makeHarness();
63
- await gateway.onBecameCoordinator();
64
- await gateway.onLostCoordinator();
65
- expect(disconnectHub).toHaveBeenCalledTimes(1);
66
- expect(gateway.isConnected).toBe(false);
67
- });
68
- it("is a no-op when this side never became the gateway", async () => {
69
- const { gateway, disconnectHub } = makeHarness();
70
- await gateway.onLostCoordinator();
71
- expect(disconnectHub).not.toHaveBeenCalled();
72
- });
73
- it("is a no-op on a second call after already losing the role", async () => {
74
- const { gateway, disconnectHub } = makeHarness();
75
- await gateway.onBecameCoordinator();
76
- await gateway.onLostCoordinator();
77
- await gateway.onLostCoordinator();
78
- expect(disconnectHub).toHaveBeenCalledTimes(1);
79
- });
80
- it("allows redialling after losing and regaining the role", async () => {
81
- const { gateway, connectHub } = makeHarness();
82
- await gateway.onBecameCoordinator();
83
- await gateway.onLostCoordinator();
84
- await gateway.onBecameCoordinator();
85
- expect(connectHub).toHaveBeenCalledTimes(2);
86
- });
87
- });
88
- //# sourceMappingURL=coordinator-gateway.unit.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"coordinator-gateway.unit.test.js","sourceRoot":"","sources":["../../src/test/coordinator-gateway.unit.test.ts"],"names":[],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- /**
2
- * Integration tests for the gateway actually forwarding between the local mesh and the hub (agent-comms#155), the core leg of the cross-machine mesh epic (#153) on top of #154's own connection-lifecycle-only gateway. Two independent local meshes ("machine A" and "machine B"), each its own coordinator dialling a shared real relay hub (createRelayHub, the same domain logic the production mesh.exadev.io Durable Object runs, served over local WebSockets via hub-helpers.ts) -- neither mesh is ever directly connected to the other, so anything either side learns about the other can only have arrived via the hub.
3
- *
4
- * Machine A's coordinator (a1) additionally has a second, ordinary local peer (a2) -- proving outbound advertisement and the remote-directory merge work for a local peer that is NOT itself the gateway, not just for the gateway's own agent (which #154 already exercised end-to-end before this issue).
5
- *
6
- * Every gateway here explicitly trusts the specific remote device-ids it needs to (agent-comms#156's own gateway allowlist, added after these tests first landed): the allowlist is deny-all by default, so every test below establishes trust before expecting forwarding/merge/routing to happen -- see gateway-trust.integration.test.ts for the deny-by-default behaviour itself (untrusted forwarding/merge/routing all failing) rather than re-proving it per test here.
7
- */
8
- export {};
9
- //# sourceMappingURL=gateway-forwarding.integration.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gateway-forwarding.integration.test.d.ts","sourceRoot":"","sources":["../../src/test/gateway-forwarding.integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -1,226 +0,0 @@
1
- /**
2
- * Integration tests for the gateway actually forwarding between the local mesh and the hub (agent-comms#155), the core leg of the cross-machine mesh epic (#153) on top of #154's own connection-lifecycle-only gateway. Two independent local meshes ("machine A" and "machine B"), each its own coordinator dialling a shared real relay hub (createRelayHub, the same domain logic the production mesh.exadev.io Durable Object runs, served over local WebSockets via hub-helpers.ts) -- neither mesh is ever directly connected to the other, so anything either side learns about the other can only have arrived via the hub.
3
- *
4
- * Machine A's coordinator (a1) additionally has a second, ordinary local peer (a2) -- proving outbound advertisement and the remote-directory merge work for a local peer that is NOT itself the gateway, not just for the gateway's own agent (which #154 already exercised end-to-end before this issue).
5
- *
6
- * Every gateway here explicitly trusts the specific remote device-ids it needs to (agent-comms#156's own gateway allowlist, added after these tests first landed): the allowlist is deny-all by default, so every test below establishes trust before expecting forwarding/merge/routing to happen -- see gateway-trust.integration.test.ts for the deny-by-default behaviour itself (untrusted forwarding/merge/routing all failing) rather than re-proving it per test here.
7
- */
8
- import { afterEach, describe, expect, it } from "vitest";
9
- import { MeshStore } from "../core/mesh-store.js";
10
- import { dmRoomPath } from "../core/room-path.js";
11
- import { realHubOverWs, TeardownStack } from "./hub-helpers.js";
12
- import { wireTestTransport } from "./test-transport.js";
13
- let nextPort = 22_400;
14
- function freshPort() {
15
- nextPort += 1;
16
- return nextPort;
17
- }
18
- /** Short enough that a gossip re-advertisement (which carries the registerAgent'd agent/self extension) fires within a test's own poll budget, unlike the 20s production default. */
19
- const FAST_GOSSIP_INTERVAL_MS = 50;
20
- const POLL_ATTEMPTS = 100;
21
- const POLL_INTERVAL_MS = 50;
22
- const sleep = async (ms) => new Promise((resolve) => {
23
- setTimeout(resolve, ms);
24
- });
25
- /** Polls an async predicate until it holds, matching broadcast-window.integration.test.ts's own established pattern for this -- the shared test-transport.ts waitFor takes a synchronous condition, which can't await a MeshStore's own async listAgents/serialise-derived checks. */
26
- async function waitFor(what, check) {
27
- for (let i = 0; i < POLL_ATTEMPTS; i++) {
28
- if (await check())
29
- return;
30
- await sleep(POLL_INTERVAL_MS);
31
- }
32
- expect(false, `timed out waiting for ${what}`).toBeTruthy();
33
- }
34
- const cleanups = new TeardownStack();
35
- afterEach(async () => {
36
- await cleanups.run();
37
- });
38
- describe("gateway forwarding", () => {
39
- it("advertises a local peer's agent (not just the gateway's own) onto the hub, and a separate machine's gateway merges it into its own knownDevices/listAgents", async () => {
40
- const hub = await realHubOverWs();
41
- cleanups.push(hub.close);
42
- const a1 = new MeshStore({ coordinatorPort: freshPort(), hubUrl: hub.url });
43
- await wireTestTransport(a1, {
44
- presenceReadvertiseIntervalMs: FAST_GOSSIP_INTERVAL_MS,
45
- });
46
- await a1.init();
47
- cleanups.push(async () => a1.shutdown());
48
- const a2 = new MeshStore({
49
- coordinatorPort: a1.coordinatorPort,
50
- hubUrl: hub.url,
51
- });
52
- await wireTestTransport(a2, {
53
- presenceReadvertiseIntervalMs: FAST_GOSSIP_INTERVAL_MS,
54
- });
55
- await a2.init();
56
- cleanups.push(async () => a2.shutdown());
57
- await a2.registerAgent({
58
- name: "a2-local-peer",
59
- harness: "test",
60
- cwd: "/test/a2",
61
- pid: process.pid,
62
- visibility: "visible",
63
- tags: ["from-a2"],
64
- });
65
- const b1 = new MeshStore({ coordinatorPort: freshPort(), hubUrl: hub.url });
66
- await wireTestTransport(b1, {
67
- presenceReadvertiseIntervalMs: FAST_GOSSIP_INTERVAL_MS,
68
- });
69
- await b1.init();
70
- cleanups.push(async () => b1.shutdown());
71
- // Deny-all by default (agent-comms#156): a1 needs at least one trusted device to forward anything at all onto the hub, and b1 needs a2's own device-id specifically trusted to merge a2's directory entry (trust is keyed per device, not per remote machine -- see GatewayTrust's own class doc).
72
- a1.addTrustedGateway(b1.peerId);
73
- b1.addTrustedGateway(a2.peerId);
74
- await waitFor("b1 (a separate machine's gateway) to learn of a2 (a non-gateway local peer on machine A) via the hub", async () => {
75
- const agents = await b1.listAgents(b1.peerId);
76
- return agents.some((agent) => agent.id === a2.peerId);
77
- });
78
- const agents = await b1.listAgents(b1.peerId);
79
- const discovered = agents.find((agent) => agent.id === a2.peerId);
80
- expect(discovered).toMatchObject({
81
- id: a2.peerId,
82
- name: "a2-local-peer",
83
- harness: "test",
84
- cwd: "/test/a2",
85
- visibility: "visible",
86
- tags: ["from-a2"],
87
- });
88
- });
89
- it("never advertises a hidden or ghost agent across the hub", async () => {
90
- const hub = await realHubOverWs();
91
- cleanups.push(hub.close);
92
- const a1 = new MeshStore({ coordinatorPort: freshPort(), hubUrl: hub.url });
93
- await wireTestTransport(a1, {
94
- presenceReadvertiseIntervalMs: FAST_GOSSIP_INTERVAL_MS,
95
- });
96
- await a1.init();
97
- cleanups.push(async () => a1.shutdown());
98
- const aHidden = new MeshStore({
99
- coordinatorPort: a1.coordinatorPort,
100
- hubUrl: hub.url,
101
- });
102
- await wireTestTransport(aHidden, {
103
- presenceReadvertiseIntervalMs: FAST_GOSSIP_INTERVAL_MS,
104
- });
105
- await aHidden.init();
106
- cleanups.push(async () => aHidden.shutdown());
107
- await aHidden.registerAgent({
108
- name: "hidden-peer",
109
- harness: "test",
110
- cwd: "/test/hidden",
111
- pid: process.pid,
112
- visibility: "hidden",
113
- tags: [],
114
- });
115
- const aGhost = new MeshStore({
116
- coordinatorPort: a1.coordinatorPort,
117
- hubUrl: hub.url,
118
- });
119
- await wireTestTransport(aGhost, {
120
- presenceReadvertiseIntervalMs: FAST_GOSSIP_INTERVAL_MS,
121
- });
122
- await aGhost.init();
123
- cleanups.push(async () => aGhost.shutdown());
124
- await aGhost.registerAgent({
125
- name: "ghost-peer",
126
- harness: "test",
127
- cwd: "/test/ghost",
128
- pid: process.pid,
129
- visibility: "ghost",
130
- tags: [],
131
- });
132
- // A visible control peer on the identical mesh, registered after the hidden/ghost ones -- its own arrival on b1's side is the proof gossip genuinely had time to propagate, ruling out "nothing arrived at all" as a false-negative explanation for hidden/ghost never showing up below.
133
- const aVisible = new MeshStore({
134
- coordinatorPort: a1.coordinatorPort,
135
- hubUrl: hub.url,
136
- });
137
- await wireTestTransport(aVisible, {
138
- presenceReadvertiseIntervalMs: FAST_GOSSIP_INTERVAL_MS,
139
- });
140
- await aVisible.init();
141
- cleanups.push(async () => aVisible.shutdown());
142
- await aVisible.registerAgent({
143
- name: "visible-peer",
144
- harness: "test",
145
- cwd: "/test/visible",
146
- pid: process.pid,
147
- visibility: "visible",
148
- tags: [],
149
- });
150
- const b1 = new MeshStore({ coordinatorPort: freshPort(), hubUrl: hub.url });
151
- await wireTestTransport(b1, {
152
- presenceReadvertiseIntervalMs: FAST_GOSSIP_INTERVAL_MS,
153
- });
154
- await b1.init();
155
- cleanups.push(async () => b1.shutdown());
156
- // Deny-all by default (agent-comms#156) -- a1 needs at least one trusted device to forward at all, and b1 needs the visible control peer's own device-id trusted so its arrival can prove gossip had time to propagate. Trusting only aVisible (never aHidden/aGhost) doesn't weaken this test: hidden/ghost are already filtered out at the source (forwardAdvertsToHub's own AGENT_SELF_GOSSIP_KEY eligibility check, upstream of the trust gate), so this proves the trust gate isn't the reason they never arrive.
157
- a1.addTrustedGateway(b1.peerId);
158
- b1.addTrustedGateway(aVisible.peerId);
159
- await waitFor("b1 to see the visible control peer, proving gossip had time to propagate", async () => {
160
- const agents = await b1.listAgents(b1.peerId);
161
- return agents.some((agent) => agent.id === aVisible.peerId);
162
- });
163
- const agents = await b1.listAgents(b1.peerId);
164
- expect(agents.some((agent) => agent.id === aHidden.peerId)).toBe(false);
165
- expect(agents.some((agent) => agent.id === aGhost.peerId)).toBe(false);
166
- });
167
- it("routes a DM to a remote gateway's own agent through the hub's relay pairing, delivered with the true sender attributed", async () => {
168
- const hub = await realHubOverWs();
169
- cleanups.push(hub.close);
170
- const a1 = new MeshStore({ coordinatorPort: freshPort(), hubUrl: hub.url });
171
- await wireTestTransport(a1, {
172
- presenceReadvertiseIntervalMs: FAST_GOSSIP_INTERVAL_MS,
173
- });
174
- await a1.init();
175
- cleanups.push(async () => a1.shutdown());
176
- await a1.registerAgent({
177
- name: "a1-gateway",
178
- harness: "test",
179
- cwd: "/test/a1",
180
- pid: process.pid,
181
- visibility: "visible",
182
- tags: [],
183
- });
184
- const b1 = new MeshStore({ coordinatorPort: freshPort(), hubUrl: hub.url });
185
- await wireTestTransport(b1, {
186
- presenceReadvertiseIntervalMs: FAST_GOSSIP_INTERVAL_MS,
187
- });
188
- await b1.init();
189
- cleanups.push(async () => b1.shutdown());
190
- await b1.registerAgent({
191
- name: "b1-gateway",
192
- harness: "test",
193
- cwd: "/test/b1",
194
- pid: process.pid,
195
- visibility: "visible",
196
- tags: [],
197
- });
198
- // Deny-all by default (agent-comms#156) -- mutual trust: a1 must trust b1 to accept b1's incoming DM request (consume()'s own isTrusted gate on fromDevice), and b1 must trust a1 for sendRoomRequest's own outbound isTrusted gate to route the request (and the later DM) to a1 at all.
199
- a1.addTrustedGateway(b1.peerId);
200
- b1.addTrustedGateway(a1.peerId);
201
- // Two-round DM consent (section 6), exactly like the local-mesh-only dm-admission.integration.test.ts -- b1's own outbound request is what's actually exercised via the new hub-relay fallback, since a1 is not a local peer of b1's own mesh.
202
- const dmPath = dmRoomPath(b1.peerId, a1.peerId);
203
- const requestPromise = b1.requestDmAccess(a1.peerId);
204
- await waitFor("a1 to see b1's pending DM request via the hub", async () => {
205
- await Promise.resolve();
206
- return a1.listPendingRoomJoins().length === 1;
207
- });
208
- const [pending] = a1.listPendingRoomJoins();
209
- expect(pending?.roomPath).toBe(dmPath);
210
- expect(pending?.requesterId).toBe(b1.peerId);
211
- a1.acceptRoomJoin(dmPath, b1.peerId);
212
- await requestPromise;
213
- const message = await b1.sendDm(b1.peerId, a1.peerId, "hello from b1");
214
- await waitFor("a1 to receive the DM via the hub", async () => {
215
- const a1Dms = a1.serialise().dms[dmPath] ?? [];
216
- return a1Dms.some((m) => m.id === message.message.id);
217
- });
218
- const delivered = (a1.serialise().dms[dmPath] ?? []).find((m) => m.id === message.message.id);
219
- expect(delivered).toMatchObject({
220
- from: b1.peerId,
221
- to: a1.peerId,
222
- content: "hello from b1",
223
- });
224
- });
225
- });
226
- //# sourceMappingURL=gateway-forwarding.integration.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gateway-forwarding.integration.test.js","sourceRoot":"","sources":["../../src/test/gateway-forwarding.integration.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=hub-forwarding.unit.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hub-forwarding.unit.test.d.ts","sourceRoot":"","sources":["../../src/test/hub-forwarding.unit.test.ts"],"names":[],"mappings":""}
@@ -1,102 +0,0 @@
1
- /**
2
- * Direct unit tests for forwardAdvertsToHub/pushHubCatchUp's own gateway-trust gate (agent-comms#156) -- previously only exercised indirectly through gateway-forwarding.integration.test.ts's real-hub harness. Uses a fake hub object (isConnected/advertiseDevices) rather than a real HubSession, mirroring gossip-directory.test.ts's own standalone-fixture approach for the sibling gossip-merge function.
3
- */
4
- import { describe, expect, it, vi } from "vitest";
5
- import { forwardAdvertsToHub, makeSendToLocalPeer, pushHubCatchUp, } from "../core/hub-forwarding.js";
6
- import { syntheticAdvert } from "./synthetic-advert.js";
7
- const DEVICE_ID_HEX_LENGTH = 64;
8
- const DEVICE_A_HEX = "a".repeat(DEVICE_ID_HEX_LENGTH);
9
- const DEVICE_B_HEX = "b".repeat(DEVICE_ID_HEX_LENGTH);
10
- function deviceIdBytes(hex) {
11
- const bytes = new Uint8Array(new ArrayBuffer(hex.length / 2));
12
- for (let i = 0; i < bytes.length; i += 1) {
13
- bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
14
- }
15
- return bytes;
16
- }
17
- function entry(hex) {
18
- const device = deviceIdBytes(hex);
19
- return {
20
- device,
21
- advert: syntheticAdvert(device, {
22
- snapshotSeconds: 1,
23
- extensions: { "agent/self": {} },
24
- }),
25
- };
26
- }
27
- function fakeHub(peers = []) {
28
- return {
29
- isConnected: true,
30
- peers: () => peers,
31
- advertiseDevices: vi.fn().mockResolvedValue(undefined),
32
- };
33
- }
34
- describe("forwardAdvertsToHub -- gateway-trust gate", () => {
35
- it("does not advertise anything when no remote gateway is trusted", () => {
36
- const hub = fakeHub();
37
- forwardAdvertsToHub(hub, [entry(DEVICE_A_HEX)], undefined, () => false);
38
- expect(hub.advertiseDevices).not.toHaveBeenCalled();
39
- });
40
- it("advertises once at least one remote gateway is trusted", () => {
41
- const hub = fakeHub();
42
- forwardAdvertsToHub(hub, [entry(DEVICE_A_HEX)], undefined, () => true);
43
- expect(hub.advertiseDevices).toHaveBeenCalledTimes(1);
44
- });
45
- it("still does nothing when not connected, even when trusted", () => {
46
- const hub = fakeHub();
47
- hub.isConnected = false;
48
- forwardAdvertsToHub(hub, [entry(DEVICE_A_HEX)], undefined, () => true);
49
- expect(hub.advertiseDevices).not.toHaveBeenCalled();
50
- });
51
- });
52
- describe("pushHubCatchUp -- gateway-trust gate", () => {
53
- it("does not push the catch-up when no remote gateway is trusted", () => {
54
- const hub = fakeHub();
55
- const knownDevices = new Map([[DEVICE_A_HEX, entry(DEVICE_A_HEX).advert]]);
56
- pushHubCatchUp(hub, knownDevices, undefined, () => false);
57
- expect(hub.advertiseDevices).not.toHaveBeenCalled();
58
- });
59
- it("pushes the catch-up once at least one remote gateway is trusted", () => {
60
- const hub = fakeHub();
61
- const knownDevices = new Map([[DEVICE_A_HEX, entry(DEVICE_A_HEX).advert]]);
62
- pushHubCatchUp(hub, knownDevices, undefined, () => true);
63
- expect(hub.advertiseDevices).toHaveBeenCalledTimes(1);
64
- });
65
- });
66
- describe("pushHubCatchUp -- devices learned from the hub", () => {
67
- it("advertises only the devices this side fronts, never one it learned from the hub", () => {
68
- const hub = fakeHub([DEVICE_B_HEX]);
69
- const knownDevices = new Map([
70
- [DEVICE_A_HEX, entry(DEVICE_A_HEX).advert],
71
- [DEVICE_B_HEX, entry(DEVICE_B_HEX).advert],
72
- ]);
73
- pushHubCatchUp(hub, knownDevices, undefined, () => true);
74
- const advertised = hub.advertiseDevices.mock.calls.flatMap(([entries]) => entries.map((forwarded) => forwarded.advert.device));
75
- expect(advertised).toEqual([entry(DEVICE_A_HEX).advert.device]);
76
- });
77
- it("advertises nothing when every known device was learned from the hub", () => {
78
- const hub = fakeHub([DEVICE_A_HEX]);
79
- const knownDevices = new Map([[DEVICE_A_HEX, entry(DEVICE_A_HEX).advert]]);
80
- pushHubCatchUp(hub, knownDevices, undefined, () => true);
81
- expect(hub.advertiseDevices).not.toHaveBeenCalled();
82
- });
83
- });
84
- describe("makeSendToLocalPeer -- synchronous no-session signal", () => {
85
- const command = { verb: "room:member", params: {} };
86
- const scope = { kind: "room", path: "owner/room" };
87
- it("returns undefined synchronously, never a Promise, when no local session exists for the device", () => {
88
- const send = makeSendToLocalPeer(new Map());
89
- const result = send(DEVICE_A_HEX, command, scope, undefined);
90
- // HubSession branches on `forwarded !== undefined` to decide whether to fall back to local dispatch, so the no-session signal has to be a plain undefined: an async wrapper would return a Promise here (always defined) and silently disable that fallback for every device this gateway doesn't front.
91
- expect(result).toBeUndefined();
92
- });
93
- it("forwards to the local session and returns its own outcome when one exists", async () => {
94
- const outcome = { result: "error", code: "not_connected" };
95
- const sendManageRequest = vi.fn().mockResolvedValue(outcome);
96
- const send = makeSendToLocalPeer(new Map([[DEVICE_A_HEX, { sendManageRequest }]]));
97
- const result = send(DEVICE_A_HEX, command, scope, undefined);
98
- await expect(result).resolves.toBe(outcome);
99
- expect(sendManageRequest).toHaveBeenCalledWith(command, scope, undefined, undefined);
100
- });
101
- });
102
- //# sourceMappingURL=hub-forwarding.unit.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hub-forwarding.unit.test.js","sourceRoot":"","sources":["../../src/test/hub-forwarding.unit.test.ts"],"names":[],"mappings":"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"}
@@ -1,7 +0,0 @@
1
- /**
2
- * Integration test for agent-comms#184: a hub-relayed manage-request explicitly addressed (relay-data's own `to-device` field, surfaced as `IncomingManageRequest.toDevice` since wire-mesh#170, wire-mesh-core 1.48.1) to a NON-gateway local peer must be routed on to that peer's own local mesh session, not dispatched against the gateway's own local state the way gateway-forwarding.integration.test.ts's "routes a DM to a remote gateway's own agent" case already covers for the gateway itself. Also proves the request's true remote origin (b1) survives the forwarding hop intact -- room-router.ts's own "on-behalf-of" mechanism, not just delivery reaching the right recipient.
3
- *
4
- * Same three-party shape as gateway-forwarding.integration.test.ts: machine A has a coordinator (a1, the gateway, dialled to the hub) and a second, ordinary local peer (a2) that is never itself connected to the hub. Machine B (b1) reaches a2 purely through the hub's relay pairing with a1 -- if toDevice routing didn't exist, b1's request would land at a1's own DM state instead of a2's, since a1's hub session has no way to tell the two apart.
5
- */
6
- export {};
7
- //# sourceMappingURL=hub-todevice-routing.integration.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hub-todevice-routing.integration.test.d.ts","sourceRoot":"","sources":["../../src/test/hub-todevice-routing.integration.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}