agent-comms 3.12.0 → 3.13.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 (74) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +1 -1
  4. package/dist/core/bridge-mesh.d.ts.map +1 -1
  5. package/dist/core/bridge-mesh.js +1 -1
  6. package/dist/core/bridge-mesh.js.map +1 -1
  7. package/dist/core/bridge.d.ts +4 -0
  8. package/dist/core/bridge.d.ts.map +1 -1
  9. package/dist/core/bridge.js +15 -0
  10. package/dist/core/bridge.js.map +1 -1
  11. package/dist/core/gateway-trust.d.ts +25 -0
  12. package/dist/core/gateway-trust.d.ts.map +1 -0
  13. package/dist/core/gateway-trust.js +26 -0
  14. package/dist/core/gateway-trust.js.map +1 -0
  15. package/dist/core/hub-forwarding.d.ts +7 -5
  16. package/dist/core/hub-forwarding.d.ts.map +1 -1
  17. package/dist/core/hub-forwarding.js +13 -6
  18. package/dist/core/hub-forwarding.js.map +1 -1
  19. package/dist/core/hub-session.d.ts +5 -1
  20. package/dist/core/hub-session.d.ts.map +1 -1
  21. package/dist/core/hub-session.js +20 -5
  22. package/dist/core/hub-session.js.map +1 -1
  23. package/dist/core/listener-registry.d.ts +25 -0
  24. package/dist/core/listener-registry.d.ts.map +1 -0
  25. package/dist/core/listener-registry.js +52 -0
  26. package/dist/core/listener-registry.js.map +1 -0
  27. package/dist/core/mesh-store.d.ts +9 -0
  28. package/dist/core/mesh-store.d.ts.map +1 -1
  29. package/dist/core/mesh-store.js +18 -0
  30. package/dist/core/mesh-store.js.map +1 -1
  31. package/dist/core/tool.d.ts +6 -0
  32. package/dist/core/tool.d.ts.map +1 -1
  33. package/dist/core/tool.js +51 -0
  34. package/dist/core/tool.js.map +1 -1
  35. package/dist/core/types.d.ts +16 -0
  36. package/dist/core/types.d.ts.map +1 -1
  37. package/dist/core/types.js +9 -0
  38. package/dist/core/types.js.map +1 -1
  39. package/dist/core/wire-mesh-transport.d.ts +6 -5
  40. package/dist/core/wire-mesh-transport.d.ts.map +1 -1
  41. package/dist/core/wire-mesh-transport.js +21 -44
  42. package/dist/core/wire-mesh-transport.js.map +1 -1
  43. package/dist/test/gateway-forwarding.integration.test.d.ts +2 -0
  44. package/dist/test/gateway-forwarding.integration.test.d.ts.map +1 -1
  45. package/dist/test/gateway-forwarding.integration.test.js +11 -0
  46. package/dist/test/gateway-forwarding.integration.test.js.map +1 -1
  47. package/dist/test/gateway-trust-tool.test.d.ts +2 -0
  48. package/dist/test/gateway-trust-tool.test.d.ts.map +1 -0
  49. package/dist/test/gateway-trust-tool.test.js +120 -0
  50. package/dist/test/gateway-trust-tool.test.js.map +1 -0
  51. package/dist/test/gateway-trust.integration.test.d.ts +5 -0
  52. package/dist/test/gateway-trust.integration.test.d.ts.map +1 -0
  53. package/dist/test/gateway-trust.integration.test.js +143 -0
  54. package/dist/test/gateway-trust.integration.test.js.map +1 -0
  55. package/dist/test/gateway-trust.test.d.ts +2 -0
  56. package/dist/test/gateway-trust.test.d.ts.map +1 -0
  57. package/dist/test/gateway-trust.test.js +60 -0
  58. package/dist/test/gateway-trust.test.js.map +1 -0
  59. package/dist/test/hub-forwarding.test.d.ts +2 -0
  60. package/dist/test/hub-forwarding.test.d.ts.map +1 -0
  61. package/dist/test/hub-forwarding.test.js +62 -0
  62. package/dist/test/hub-forwarding.test.js.map +1 -0
  63. package/dist/test/hub-mode-session.integration.test.js +25 -10
  64. package/dist/test/hub-mode-session.integration.test.js.map +1 -1
  65. package/dist/test/test-transport.d.ts.map +1 -1
  66. package/dist/test/test-transport.js +1 -1
  67. package/dist/test/test-transport.js.map +1 -1
  68. package/dist/test/wire-mesh-transport-gateway-trust.test.d.ts +2 -0
  69. package/dist/test/wire-mesh-transport-gateway-trust.test.d.ts.map +1 -0
  70. package/dist/test/wire-mesh-transport-gateway-trust.test.js +50 -0
  71. package/dist/test/wire-mesh-transport-gateway-trust.test.js.map +1 -0
  72. package/dist/test/wire-mesh-transport.test.js +1 -11
  73. package/dist/test/wire-mesh-transport.test.js.map +1 -1
  74. package/package.json +1 -1
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Integration tests for the gateway allowlist's own deny-by-default posture (agent-comms#156), the trust-boundary leg of the cross-machine mesh epic (#153) on top of #155's own (now trust-gated) forwarding. Same two-independent-local-meshes-over-a-real-hub harness as gateway-forwarding.integration.test.ts, but every scenario here proves the ABSENCE of forwarding/merge/routing before any trust is established, complementing that file's own coverage of the PRESENT-trust happy path.
3
+ */
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { MeshStore } from "../core/mesh-store.js";
6
+ import { realHubOverWs } from "./hub-helpers.js";
7
+ import { wireTestTransport } from "./test-transport.js";
8
+ let nextPort = 22_500;
9
+ function freshPort() {
10
+ nextPort += 1;
11
+ return nextPort;
12
+ }
13
+ /** Short enough that a gossip re-advertisement fires within a test's own poll budget, matching gateway-forwarding.integration.test.ts's own choice. */
14
+ const FAST_GOSSIP_INTERVAL_MS = 50;
15
+ const POLL_ATTEMPTS = 100;
16
+ const POLL_INTERVAL_MS = 50;
17
+ const sleep = async (ms) => new Promise((resolve) => {
18
+ setTimeout(resolve, ms);
19
+ });
20
+ async function waitFor(what, check) {
21
+ for (let i = 0; i < POLL_ATTEMPTS; i++) {
22
+ if (await check())
23
+ return;
24
+ await sleep(POLL_INTERVAL_MS);
25
+ }
26
+ expect(false, `timed out waiting for ${what}`).toBeTruthy();
27
+ }
28
+ const cleanups = [];
29
+ afterEach(async () => {
30
+ for (const close of cleanups.splice(0)) {
31
+ await close();
32
+ }
33
+ });
34
+ describe("gateway trust -- deny by default", () => {
35
+ it("never merges a remote agent's directory entry when this side hasn't trusted it, even once a trusted control agent proves propagation had time", async () => {
36
+ const hub = await realHubOverWs();
37
+ cleanups.push(hub.close);
38
+ const a1 = new MeshStore(freshPort(), hub.url);
39
+ await wireTestTransport(a1, undefined, undefined, FAST_GOSSIP_INTERVAL_MS);
40
+ await a1.init();
41
+ cleanups.push(async () => a1.shutdown());
42
+ await a1.registerAgent({
43
+ name: "untrusted-a1",
44
+ harness: "test",
45
+ cwd: "/test/a1",
46
+ pid: process.pid,
47
+ visibility: "visible",
48
+ tags: [],
49
+ });
50
+ const b1 = new MeshStore(freshPort(), hub.url);
51
+ await wireTestTransport(b1, undefined, undefined, FAST_GOSSIP_INTERVAL_MS);
52
+ await b1.init();
53
+ cleanups.push(async () => b1.shutdown());
54
+ const c1 = new MeshStore(freshPort(), hub.url);
55
+ await wireTestTransport(c1, undefined, undefined, FAST_GOSSIP_INTERVAL_MS);
56
+ await c1.init();
57
+ cleanups.push(async () => c1.shutdown());
58
+ await c1.registerAgent({
59
+ name: "trusted-control-c1",
60
+ harness: "test",
61
+ cwd: "/test/c1",
62
+ pid: process.pid,
63
+ visibility: "visible",
64
+ tags: [],
65
+ });
66
+ // a1 needs at least one trusted device to forward at all (the outbound gate); c1 fills that role so a1's own gossip reaches the hub, without ever trusting b1 specifically. b1 trusts c1 (proving propagation genuinely had time) but never trusts a1.
67
+ a1.addTrustedGateway(c1.peerId);
68
+ c1.addTrustedGateway(a1.peerId);
69
+ b1.addTrustedGateway(c1.peerId);
70
+ c1.addTrustedGateway(b1.peerId);
71
+ await waitFor("b1 to see the trusted control agent c1", async () => {
72
+ const agents = await b1.listAgents(b1.peerId);
73
+ return agents.some((agent) => agent.id === c1.peerId);
74
+ });
75
+ const agents = await b1.listAgents(b1.peerId);
76
+ expect(agents.some((agent) => agent.id === a1.peerId)).toBe(false);
77
+ });
78
+ it("never advertises anything onto the hub while this side has trusted nobody, even for a peer another side would have accepted", async () => {
79
+ const hub = await realHubOverWs();
80
+ cleanups.push(hub.close);
81
+ const a1 = new MeshStore(freshPort(), hub.url);
82
+ await wireTestTransport(a1, undefined, undefined, FAST_GOSSIP_INTERVAL_MS);
83
+ await a1.init();
84
+ cleanups.push(async () => a1.shutdown());
85
+ await a1.registerAgent({
86
+ name: "never-advertised-a1",
87
+ harness: "test",
88
+ cwd: "/test/a1",
89
+ pid: process.pid,
90
+ visibility: "visible",
91
+ tags: [],
92
+ });
93
+ // a1 trusts nobody at all -- the outbound gate (hasAny) should withhold every advertisement.
94
+ const b1 = new MeshStore(freshPort(), hub.url);
95
+ await wireTestTransport(b1, undefined, undefined, FAST_GOSSIP_INTERVAL_MS);
96
+ await b1.init();
97
+ cleanups.push(async () => b1.shutdown());
98
+ b1.addTrustedGateway(a1.peerId);
99
+ const c1 = new MeshStore(freshPort(), hub.url);
100
+ await wireTestTransport(c1, undefined, undefined, FAST_GOSSIP_INTERVAL_MS);
101
+ await c1.init();
102
+ cleanups.push(async () => c1.shutdown());
103
+ await c1.registerAgent({
104
+ name: "trusted-control-c1",
105
+ harness: "test",
106
+ cwd: "/test/c1",
107
+ pid: process.pid,
108
+ visibility: "visible",
109
+ tags: [],
110
+ });
111
+ b1.addTrustedGateway(c1.peerId);
112
+ c1.addTrustedGateway(b1.peerId);
113
+ await waitFor("b1 to see c1, proving gossip had time to reach it", async () => {
114
+ const agents = await b1.listAgents(b1.peerId);
115
+ return agents.some((agent) => agent.id === c1.peerId);
116
+ });
117
+ const agents = await b1.listAgents(b1.peerId);
118
+ expect(agents.some((agent) => agent.id === a1.peerId)).toBe(false);
119
+ });
120
+ it("refuses to route a request to an untrusted remote device, without ever reaching the hub", async () => {
121
+ const hub = await realHubOverWs();
122
+ cleanups.push(hub.close);
123
+ const a1 = new MeshStore(freshPort(), hub.url);
124
+ await wireTestTransport(a1, undefined, undefined, FAST_GOSSIP_INTERVAL_MS);
125
+ await a1.init();
126
+ cleanups.push(async () => a1.shutdown());
127
+ await a1.registerAgent({
128
+ name: "a1-gateway",
129
+ harness: "test",
130
+ cwd: "/test/a1",
131
+ pid: process.pid,
132
+ visibility: "visible",
133
+ tags: [],
134
+ });
135
+ const b1 = new MeshStore(freshPort(), hub.url);
136
+ await wireTestTransport(b1, undefined, undefined, FAST_GOSSIP_INTERVAL_MS);
137
+ await b1.init();
138
+ cleanups.push(async () => b1.shutdown());
139
+ // b1 never trusts a1 -- requestDmAccess must be refused fast, not hang out sendRoomRequest's own hub timeout.
140
+ await expect(b1.requestDmAccess(a1.peerId)).rejects.toThrow(/unauthorized/);
141
+ });
142
+ });
143
+ //# sourceMappingURL=gateway-trust.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-trust.integration.test.js","sourceRoot":"","sources":["../../src/test/gateway-trust.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gateway-trust.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-trust.test.d.ts","sourceRoot":"","sources":["../../src/test/gateway-trust.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Direct unit tests for GatewayTrust -- the cross-machine trust boundary's own allowlist (agent-comms#156), tested standalone against no real transport or hub socket, mirroring coordinator-gateway.test.ts's own approach for the sibling gateway-lifecycle class.
3
+ */
4
+ import { describe, expect, it } from "vitest";
5
+ import { GatewayTrust } from "../core/gateway-trust.js";
6
+ describe("GatewayTrust", () => {
7
+ it("trusts nobody by default", () => {
8
+ const trust = new GatewayTrust();
9
+ expect(trust.hasAny()).toBe(false);
10
+ expect(trust.isTrusted("aabbcc")).toBe(false);
11
+ expect(trust.list()).toEqual([]);
12
+ });
13
+ it("trusts a device once added", () => {
14
+ const trust = new GatewayTrust();
15
+ trust.add("AABBCC");
16
+ expect(trust.isTrusted("aabbcc")).toBe(true);
17
+ expect(trust.hasAny()).toBe(true);
18
+ expect(trust.list()).toEqual(["aabbcc"]);
19
+ });
20
+ it("normalises hex case so add and isTrusted agree regardless of casing", () => {
21
+ const trust = new GatewayTrust();
22
+ trust.add("AaBbCc");
23
+ expect(trust.isTrusted("aabbcc")).toBe(true);
24
+ expect(trust.isTrusted("AABBCC")).toBe(true);
25
+ });
26
+ it("is idempotent: adding the same device twice keeps it listed once", () => {
27
+ const trust = new GatewayTrust();
28
+ trust.add("aabbcc");
29
+ trust.add("AABBCC");
30
+ expect(trust.list()).toEqual(["aabbcc"]);
31
+ });
32
+ it("stops trusting a device once removed", () => {
33
+ const trust = new GatewayTrust();
34
+ trust.add("aabbcc");
35
+ trust.remove("AABBCC");
36
+ expect(trust.isTrusted("aabbcc")).toBe(false);
37
+ expect(trust.list()).toEqual([]);
38
+ });
39
+ it("removing a device that was never trusted is a safe no-op", () => {
40
+ const trust = new GatewayTrust();
41
+ expect(() => {
42
+ trust.remove("aabbcc");
43
+ }).not.toThrow();
44
+ expect(trust.list()).toEqual([]);
45
+ });
46
+ it("hasAny reflects removal down to empty", () => {
47
+ const trust = new GatewayTrust();
48
+ trust.add("aabbcc");
49
+ trust.remove("aabbcc");
50
+ expect(trust.hasAny()).toBe(false);
51
+ });
52
+ it("lists every currently trusted device once each device-id is trusted, unaffected by another device's own trust/untrust", () => {
53
+ const trust = new GatewayTrust();
54
+ trust.add("aabbcc");
55
+ trust.add("ddeeff");
56
+ trust.remove("aabbcc");
57
+ expect(trust.list()).toEqual(["ddeeff"]);
58
+ });
59
+ });
60
+ //# sourceMappingURL=gateway-trust.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-trust.test.js","sourceRoot":"","sources":["../../src/test/gateway-trust.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=hub-forwarding.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hub-forwarding.test.d.ts","sourceRoot":"","sources":["../../src/test/hub-forwarding.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,62 @@
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, pushHubCatchUp } from "../core/hub-forwarding.js";
6
+ const DEVICE_ID_HEX_LENGTH = 64;
7
+ const DEVICE_A_HEX = "a".repeat(DEVICE_ID_HEX_LENGTH);
8
+ function deviceIdBytes(hex) {
9
+ const bytes = new Uint8Array(new ArrayBuffer(hex.length / 2));
10
+ for (let i = 0; i < bytes.length; i += 1) {
11
+ bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
12
+ }
13
+ return bytes;
14
+ }
15
+ function advert() {
16
+ return { addresses: [], "snapshot-seconds": 1 };
17
+ }
18
+ function entry(hex) {
19
+ return {
20
+ device: deviceIdBytes(hex),
21
+ advert: { ...advert(), "agent/self": {} },
22
+ };
23
+ }
24
+ function fakeHub() {
25
+ return {
26
+ isConnected: true,
27
+ advertiseDevices: vi.fn().mockResolvedValue(undefined),
28
+ };
29
+ }
30
+ describe("forwardAdvertsToHub -- gateway-trust gate", () => {
31
+ it("does not advertise anything when no remote gateway is trusted", () => {
32
+ const hub = fakeHub();
33
+ forwardAdvertsToHub(hub, [entry(DEVICE_A_HEX)], undefined, () => false);
34
+ expect(hub.advertiseDevices).not.toHaveBeenCalled();
35
+ });
36
+ it("advertises once at least one remote gateway is trusted", () => {
37
+ const hub = fakeHub();
38
+ forwardAdvertsToHub(hub, [entry(DEVICE_A_HEX)], undefined, () => true);
39
+ expect(hub.advertiseDevices).toHaveBeenCalledTimes(1);
40
+ });
41
+ it("still does nothing when not connected, even when trusted", () => {
42
+ const hub = fakeHub();
43
+ hub.isConnected = false;
44
+ forwardAdvertsToHub(hub, [entry(DEVICE_A_HEX)], undefined, () => true);
45
+ expect(hub.advertiseDevices).not.toHaveBeenCalled();
46
+ });
47
+ });
48
+ describe("pushHubCatchUp -- gateway-trust gate", () => {
49
+ it("does not push the catch-up when no remote gateway is trusted", () => {
50
+ const hub = fakeHub();
51
+ const knownDevices = new Map([[DEVICE_A_HEX, entry(DEVICE_A_HEX).advert]]);
52
+ pushHubCatchUp(hub, knownDevices, undefined, () => false);
53
+ expect(hub.advertiseDevices).not.toHaveBeenCalled();
54
+ });
55
+ it("pushes the catch-up once at least one remote gateway is trusted", () => {
56
+ const hub = fakeHub();
57
+ const knownDevices = new Map([[DEVICE_A_HEX, entry(DEVICE_A_HEX).advert]]);
58
+ pushHubCatchUp(hub, knownDevices, undefined, () => true);
59
+ expect(hub.advertiseDevices).toHaveBeenCalledTimes(1);
60
+ });
61
+ });
62
+ //# sourceMappingURL=hub-forwarding.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hub-forwarding.test.js","sourceRoot":"","sources":["../../src/test/hub-forwarding.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhF,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAChC,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAEtD,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,MAAM;IACb,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,kBAAkB,EAAE,CAAC,EAA2B,CAAC;AAC3E,CAAC;AAED,SAAS,KAAK,CAAC,GAAW;IACxB,OAAO;QACL,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC;QAC1B,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE;KAC1C,CAAC;AACJ,CAAC;AAED,SAAS,OAAO;IAMd,OAAO;QACL,WAAW,EAAE,IAAI;QACjB,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;KACvD,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,2CAA2C,EAAE,GAAG,EAAE;IACzD,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QAEtB,mBAAmB,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;QAExE,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QAEtB,mBAAmB,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAEvE,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,WAAW,GAAG,KAAK,CAAC;QAExB,mBAAmB,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAEvE,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAE3E,cAAc,CAAC,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAE3E,cAAc,CAAC,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAEzD,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,8 +1,10 @@
1
- // Integration: two real agent-comms WireMeshTransports discovering each other and exchanging messages through a real wire-mesh relay hub (createRelayHub -- the same domain logic the production mesh.exadev.io Durable Object runs) served over local WebSockets. This is agent-comms#151's own acceptance shape: the hub connection is a relay, not a coordinator -- no connect_request/introduce approval applies, peers discover each other via the hub's gossip forwarding + catch-up, and messages ride relay pairings (sendManageRequest's own targetDevice routing).
1
+ // Integration: two real agent-comms WireMeshTransports discovering each other and exchanging messages through a real wire-mesh relay hub (createRelayHub -- the same domain logic the production mesh.exadev.io Durable Object runs) served over local WebSockets. This is agent-comms#151's own acceptance shape: the hub connection is a relay, not a coordinator -- no connect_request/introduce approval applies, peers discover each other via the hub's gossip forwarding + catch-up, and messages ride relay pairings (sendManageRequest's own targetDevice routing). Every transport here is constructed with an explicit GatewayTrust mutually trusting the other side's device-id (agent-comms#156's own deny-by-default trust boundary): without it, hub-session.ts's own directory-merge and consume() gates would drop the other side's gossip/messages entirely before any of this file's own assertions could run.
2
2
  import { afterEach, describe, expect, it } from "vitest";
3
3
  import { realHubOverWs, waitForCondition } from "./hub-helpers.js";
4
4
  import { generateIdentity } from "../core/identity.js";
5
+ import { deviceIdToHex } from "wire-mesh-core/domain/device-id";
5
6
  import { WireMeshTransport } from "../core/wire-mesh-transport.js";
7
+ import { GatewayTrust } from "../core/gateway-trust.js";
6
8
  function recordingEvents() {
7
9
  const messages = [];
8
10
  const allMessages = [];
@@ -38,13 +40,20 @@ describe("connectToHub", () => {
38
40
  cleanups.push(hub.close);
39
41
  const eventsA = recordingEvents();
40
42
  const eventsB = recordingEvents();
41
- const transportA = new WireMeshTransport(eventsA, generateIdentity());
42
- const transportB = new WireMeshTransport(eventsB, generateIdentity());
43
+ const identityA = generateIdentity();
44
+ const identityB = generateIdentity();
45
+ const deviceA = deviceIdToHex(Uint8Array.from(identityA.deviceId));
46
+ const deviceB = deviceIdToHex(Uint8Array.from(identityB.deviceId));
47
+ // Gateway trust (agent-comms#156) is deny-all by default: each side's own hub-session directory-merge and consume() gates would otherwise drop the other's gossip/messages entirely, so hub.peers() would never populate and onMessage would never fire. Mutual trust here for both.
48
+ const gatewayTrustA = new GatewayTrust();
49
+ gatewayTrustA.add(deviceB);
50
+ const gatewayTrustB = new GatewayTrust();
51
+ gatewayTrustB.add(deviceA);
52
+ const transportA = new WireMeshTransport(eventsA, identityA, undefined, undefined, undefined, undefined, undefined, undefined, undefined, gatewayTrustA);
53
+ const transportB = new WireMeshTransport(eventsB, identityB, undefined, undefined, undefined, undefined, undefined, undefined, undefined, gatewayTrustB);
43
54
  await transportA.hub.connect(hub.url);
44
55
  await transportB.hub.connect(hub.url);
45
56
  // Discovery: each side's hubPeers should eventually list the other.
46
- const deviceA = await transportA.hub.ownDeviceHex();
47
- const deviceB = await transportB.hub.ownDeviceHex();
48
57
  await waitForCondition(() => {
49
58
  return (transportA.hub.peers().includes(deviceB) &&
50
59
  transportB.hub.peers().includes(deviceA));
@@ -64,17 +73,23 @@ describe("connectToHub", () => {
64
73
  await transportA.shutdown();
65
74
  await transportB.shutdown();
66
75
  });
67
- it("never applies a state_sync or state_update relayed by an unauthenticated hub peer (agent-comms#169 security finding: real per-peer admission lands in #156, but nothing today should let any hub peer patch local mesh state)", async () => {
76
+ it('never applies a state_sync or state_update relayed by a hub peer, even one this side now explicitly trusts (agent-comms#169 security finding: real per-peer admission landed in #156, but gateway trust means "this device\'s traffic is worth acting on", not "this device may directly overwrite this side\'s mesh state")', async () => {
68
77
  const hub = await realHubOverWs();
69
78
  cleanups.push(hub.close);
70
79
  const eventsA = recordingEvents();
71
80
  const eventsB = recordingEvents();
72
- const transportA = new WireMeshTransport(eventsA, generateIdentity());
73
- const transportB = new WireMeshTransport(eventsB, generateIdentity());
81
+ const identityA = generateIdentity();
82
+ const identityB = generateIdentity();
83
+ const deviceA = deviceIdToHex(Uint8Array.from(identityA.deviceId));
84
+ const deviceB = deviceIdToHex(Uint8Array.from(identityB.deviceId));
85
+ const gatewayTrustA = new GatewayTrust();
86
+ gatewayTrustA.add(deviceB);
87
+ const gatewayTrustB = new GatewayTrust();
88
+ gatewayTrustB.add(deviceA);
89
+ const transportA = new WireMeshTransport(eventsA, identityA, undefined, undefined, undefined, undefined, undefined, undefined, undefined, gatewayTrustA);
90
+ const transportB = new WireMeshTransport(eventsB, identityB, undefined, undefined, undefined, undefined, undefined, undefined, undefined, gatewayTrustB);
74
91
  await transportA.hub.connect(hub.url);
75
92
  await transportB.hub.connect(hub.url);
76
- const deviceA = await transportA.hub.ownDeviceHex();
77
- const deviceB = await transportB.hub.ownDeviceHex();
78
93
  await waitForCondition(() => {
79
94
  return (transportA.hub.peers().includes(deviceB) &&
80
95
  transportB.hub.peers().includes(deviceA));
@@ -1 +1 @@
1
- {"version":3,"file":"hub-mode-session.integration.test.js","sourceRoot":"","sources":["../../src/test/hub-mode-session.integration.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hub-mode-session.integration.test.js","sourceRoot":"","sources":["../../src/test/hub-mode-session.integration.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"test-transport.d.ts","sourceRoot":"","sources":["../../src/test/test-transport.ts"],"names":[],"mappings":"AAAA,icAAic;AAWjc,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAI9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAKvD,klCAAklC;AACllC,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,SAAS,EAChB,IAAI,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC7B,0BAA0B,CAAC,EAAE,MAAM,EACnC,6BAA6B,CAAC,EAAE,MAAM,GACrC,OAAO,CAAC,YAAY,CAAC,CA2CvB;AAMD;;GAEG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,OAAO,EACxB,WAAW,EAAE,MAAM,EACnB,SAAS,SAA8B,GACtC,OAAO,CAAC,IAAI,CAAC,CAYf"}
1
+ {"version":3,"file":"test-transport.d.ts","sourceRoot":"","sources":["../../src/test/test-transport.ts"],"names":[],"mappings":"AAAA,icAAic;AAWjc,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAI9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAKvD,klCAAklC;AACllC,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,SAAS,EAChB,IAAI,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC7B,0BAA0B,CAAC,EAAE,MAAM,EACnC,6BAA6B,CAAC,EAAE,MAAM,GACrC,OAAO,CAAC,YAAY,CAAC,CA4CvB;AAMD;;GAEG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,OAAO,EACxB,WAAW,EAAE,MAAM,EACnB,SAAS,SAA8B,GACtC,OAAO,CAAC,IAAI,CAAC,CAYf"}
@@ -30,7 +30,7 @@ export async function wireTestTransport(store, slot, pendingConnectionTimeoutMs,
30
30
  store.peerId = deviceIdToHex(Uint8Array.from(identity.deviceId));
31
31
  // One shared dataStorage instance for both the transport's own data-domain frame responder and the store's own durable-send mint path (P5, agent-comms#50) -- memory-backed, matching every other throwaway test identity here, rather than a real createNodeFsStorage a test would need to clean up afterwards.
32
32
  const dataStorage = createMemoryStorage();
33
- store.setTransport(new WireMeshTransport(store.events, identity, store.roomVerbHandlers, pendingConnectionTimeoutMs, () => store.selfStatus, presenceReadvertiseIntervalMs, undefined, dataStorage, () => store.selfAgentAdvert));
33
+ store.setTransport(new WireMeshTransport(store.events, identity, store.roomVerbHandlers, pendingConnectionTimeoutMs, () => store.selfStatus, presenceReadvertiseIntervalMs, undefined, dataStorage, () => store.selfAgentAdvert, store.gatewayTrust));
34
34
  store.setIdentity({
35
35
  identity: await toIdentityPort(identity),
36
36
  clock: createSystemClock(),
@@ -1 +1 @@
1
- {"version":3,"file":"test-transport.js","sourceRoot":"","sources":["../../src/test/test-transport.ts"],"names":[],"mappings":"AAAA,icAAic;AAEjc,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,sJAAsJ;AACtJ,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAEtC,klCAAklC;AACllC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAgB,EAChB,IAA6B,EAC7B,0BAAmC,EACnC,6BAAsC;IAEtC,MAAM,YAAY,GAAiB,IAAI,IAAI;QACzC,OAAO,EAAE,MAAM;QACf,GAAG,EAAE,MAAM,CAAC,2BAA2B,CAAC;QACxC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,4BAA4B,CAAC,CAAC;KACvE,CAAC;IACF,MAAM,QAAQ,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACpD,qSAAqS;IACrS,MAAM,mBAAmB,GAAG;QAC1B,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iCAAiC,CAAC,CAAC;KAC5E,CAAC;IACF,MAAM,YAAY,GAAG,wBAAwB,CAAC,mBAAmB,CAAC,CAAC;IACnE,yXAAyX;IACzX,KAAK,CAAC,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjE,iTAAiT;IACjT,MAAM,WAAW,GAAG,mBAAmB,EAAE,CAAC;IAC1C,KAAK,CAAC,YAAY,CAChB,IAAI,iBAAiB,CACnB,KAAK,CAAC,MAAM,EACZ,QAAQ,EACR,KAAK,CAAC,gBAAgB,EACtB,0BAA0B,EAC1B,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EACtB,6BAA6B,EAC7B,SAAS,EACT,WAAW,EACX,GAAG,EAAE,CAAC,KAAK,CAAC,eAAe,CAC5B,CACF,CAAC;IACF,KAAK,CAAC,WAAW,CAAC;QAChB,QAAQ,EAAE,MAAM,cAAc,CAAC,QAAQ,CAAC;QACxC,KAAK,EAAE,iBAAiB,EAAE;QAC1B,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE,oBAAoB,EAAE;QAClC,WAAW;QACX,YAAY,EAAE,MAAM,cAAc,CAAC,YAAY,CAAC;QAChD,mBAAmB;KACpB,CAAC,CAAC;IACH,4PAA4P;IAC5P,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,EAAE;QACpB,OAAO,CAAC,KAAK,CAAC,4BAA4B,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACxE,CAAC,CAAC;IACF,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,+cAA+c;AAC/c,MAAM,2BAA2B,GAAG,MAAM,CAAC;AAC3C,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,SAAwB,EACxB,WAAmB,EACnB,SAAS,GAAG,2BAA2B;IAEvC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACxC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;QACpB,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,2BAA2B,MAAM,CAAC,SAAS,CAAC,OAAO,WAAW,EAAE,CACjE,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC5B,UAAU,CAAC,OAAO,EAAE,yBAAyB,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"test-transport.js","sourceRoot":"","sources":["../../src/test/test-transport.ts"],"names":[],"mappings":"AAAA,icAAic;AAEjc,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,sJAAsJ;AACtJ,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAEtC,klCAAklC;AACllC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAgB,EAChB,IAA6B,EAC7B,0BAAmC,EACnC,6BAAsC;IAEtC,MAAM,YAAY,GAAiB,IAAI,IAAI;QACzC,OAAO,EAAE,MAAM;QACf,GAAG,EAAE,MAAM,CAAC,2BAA2B,CAAC;QACxC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,4BAA4B,CAAC,CAAC;KACvE,CAAC;IACF,MAAM,QAAQ,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACpD,qSAAqS;IACrS,MAAM,mBAAmB,GAAG;QAC1B,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iCAAiC,CAAC,CAAC;KAC5E,CAAC;IACF,MAAM,YAAY,GAAG,wBAAwB,CAAC,mBAAmB,CAAC,CAAC;IACnE,yXAAyX;IACzX,KAAK,CAAC,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjE,iTAAiT;IACjT,MAAM,WAAW,GAAG,mBAAmB,EAAE,CAAC;IAC1C,KAAK,CAAC,YAAY,CAChB,IAAI,iBAAiB,CACnB,KAAK,CAAC,MAAM,EACZ,QAAQ,EACR,KAAK,CAAC,gBAAgB,EACtB,0BAA0B,EAC1B,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EACtB,6BAA6B,EAC7B,SAAS,EACT,WAAW,EACX,GAAG,EAAE,CAAC,KAAK,CAAC,eAAe,EAC3B,KAAK,CAAC,YAAY,CACnB,CACF,CAAC;IACF,KAAK,CAAC,WAAW,CAAC;QAChB,QAAQ,EAAE,MAAM,cAAc,CAAC,QAAQ,CAAC;QACxC,KAAK,EAAE,iBAAiB,EAAE;QAC1B,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE,oBAAoB,EAAE;QAClC,WAAW;QACX,YAAY,EAAE,MAAM,cAAc,CAAC,YAAY,CAAC;QAChD,mBAAmB;KACpB,CAAC,CAAC;IACH,4PAA4P;IAC5P,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,EAAE;QACpB,OAAO,CAAC,KAAK,CAAC,4BAA4B,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACxE,CAAC,CAAC;IACF,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,+cAA+c;AAC/c,MAAM,2BAA2B,GAAG,MAAM,CAAC;AAC3C,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,SAAwB,EACxB,WAAmB,EACnB,SAAS,GAAG,2BAA2B;IAEvC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACxC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;QACpB,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,2BAA2B,MAAM,CAAC,SAAS,CAAC,OAAO,WAAW,EAAE,CACjE,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC5B,UAAU,CAAC,OAAO,EAAE,yBAAyB,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=wire-mesh-transport-gateway-trust.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-mesh-transport-gateway-trust.test.d.ts","sourceRoot":"","sources":["../../src/test/wire-mesh-transport-gateway-trust.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * WireMeshTransport.sendRoomRequest's own gateway-trust gate (agent-comms#156) -- split out of wire-mesh-transport.test.ts to stay under this repo's max-lines cap, the same reason wire-mesh-transport-hub.test.ts and wire-mesh-transport-shutdown-unref.test.ts were split.
3
+ */
4
+ import { test, describe, expect } from "vitest";
5
+ import { generateIdentity } from "../core/identity.js";
6
+ import { WireMeshTransport } from "../core/wire-mesh-transport.js";
7
+ import { GatewayTrust } from "../core/gateway-trust.js";
8
+ function noopEvents() {
9
+ return {
10
+ onMessage: () => undefined,
11
+ onPeerConnected: () => undefined,
12
+ onPeerDisconnected: () => undefined,
13
+ onIntroduction: () => undefined,
14
+ onConnectionRequest: () => undefined,
15
+ onPeerList: () => undefined,
16
+ onPeerJoined: () => undefined,
17
+ onBecomeCoordinator: () => undefined,
18
+ onRevocationAnnounce: () => undefined,
19
+ onPresenceAdvert: () => undefined,
20
+ };
21
+ }
22
+ describe("WireMeshTransport.sendRoomRequest -- gateway trust", () => {
23
+ test("resolves unauthorized without ever touching the hub when the target device isn't trusted", async () => {
24
+ const identity = generateIdentity();
25
+ // No GatewayTrust passed -- defaults to a fresh, empty (deny-all) instance.
26
+ const transport = new WireMeshTransport(noopEvents(), identity);
27
+ try {
28
+ const outcome = await transport.sendRoomRequest("nobody-home", { verb: "room.send", params: {} }, { kind: "agent-comms-mesh" });
29
+ expect(outcome).toEqual({ result: "error", code: "unauthorized" });
30
+ }
31
+ finally {
32
+ await transport.shutdown();
33
+ }
34
+ });
35
+ test("falls through to the ordinary not_connected outcome once the target device is trusted", async () => {
36
+ const identity = generateIdentity();
37
+ const gatewayTrust = new GatewayTrust();
38
+ gatewayTrust.add("nobody-home");
39
+ const transport = new WireMeshTransport(noopEvents(), identity, undefined, undefined, undefined, undefined, undefined, undefined, undefined, gatewayTrust);
40
+ try {
41
+ const outcome = await transport.sendRoomRequest("nobody-home", { verb: "room.send", params: {} }, { kind: "agent-comms-mesh" });
42
+ // Trusted, but there is no live local session and this transport was never dialled into a hub -- routeRoomRequestViaHub's own not_connected outcome, unaffected by the trust gate once it's passed.
43
+ expect(outcome).toEqual({ result: "error", code: "not_connected" });
44
+ }
45
+ finally {
46
+ await transport.shutdown();
47
+ }
48
+ });
49
+ });
50
+ //# sourceMappingURL=wire-mesh-transport-gateway-trust.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-mesh-transport-gateway-trust.test.js","sourceRoot":"","sources":["../../src/test/wire-mesh-transport-gateway-trust.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGxD,SAAS,UAAU;IACjB,OAAO;QACL,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS;QAC1B,eAAe,EAAE,GAAG,EAAE,CAAC,SAAS;QAChC,kBAAkB,EAAE,GAAG,EAAE,CAAC,SAAS;QACnC,cAAc,EAAE,GAAG,EAAE,CAAC,SAAS;QAC/B,mBAAmB,EAAE,GAAG,EAAE,CAAC,SAAS;QACpC,UAAU,EAAE,GAAG,EAAE,CAAC,SAAS;QAC3B,YAAY,EAAE,GAAG,EAAE,CAAC,SAAS;QAC7B,mBAAmB,EAAE,GAAG,EAAE,CAAC,SAAS;QACpC,oBAAoB,EAAE,GAAG,EAAE,CAAC,SAAS;QACrC,gBAAgB,EAAE,GAAG,EAAE,CAAC,SAAS;KAClC,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,oDAAoD,EAAE,GAAG,EAAE;IAClE,IAAI,CAAC,0FAA0F,EAAE,KAAK,IAAI,EAAE;QAC1G,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;QACpC,4EAA4E;QAC5E,MAAM,SAAS,GAAG,IAAI,iBAAiB,CAAC,UAAU,EAAE,EAAE,QAAQ,CAAC,CAAC;QAChE,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,eAAe,CAC7C,aAAa,EACb,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,EACjC,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAC7B,CAAC;YACF,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QACrE,CAAC;gBAAS,CAAC;YACT,MAAM,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uFAAuF,EAAE,KAAK,IAAI,EAAE;QACvG,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;QACpC,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;QACxC,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAChC,MAAM,SAAS,GAAG,IAAI,iBAAiB,CACrC,UAAU,EAAE,EACZ,QAAQ,EACR,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,CACb,CAAC;QACF,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,eAAe,CAC7C,aAAa,EACb,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,EACjC,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAC7B,CAAC;YACF,oMAAoM;YACpM,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;QACtE,CAAC;gBAAS,CAAC;YACT,MAAM,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -511,17 +511,7 @@ describe("WireMeshTransport send/sendRoomRequest to an unknown or broken peer",
511
511
  await transport.shutdown();
512
512
  }
513
513
  });
514
- test("sendRoomRequest to a member with no live session resolves not_connected rather than throwing", async () => {
515
- const identity = generateIdentity();
516
- const transport = new WireMeshTransport(noopEvents(), identity);
517
- try {
518
- const outcome = await transport.sendRoomRequest("nobody-home", { verb: "room.send", params: {} }, { kind: "agent-comms-mesh" });
519
- expect(outcome).toEqual({ result: "error", code: "not_connected" });
520
- }
521
- finally {
522
- await transport.shutdown();
523
- }
524
- });
514
+ // sendRoomRequest's own gateway-trust gate (agent-comms#156) has its own dedicated coverage in wire-mesh-transport-gateway-trust.test.ts, split out the same reason wire-mesh-transport-hub.test.ts/wire-mesh-transport-shutdown-unref.test.ts already were.
525
515
  // A test proving send()'s own catch/onError path (a send failing against a session whose remote end just closed) was attempted the same way and hit the identical flakiness as the gossip-failure test above -- watchForDisconnect's own cleanup consistently won the race against a still-tracked-but-broken session. Left as a documented gap for the same reason.
526
516
  });
527
517
  describe("WireMeshTransport pending-connection expiry", () => {