agent-comms 2.31.1 → 3.0.1
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/dist/bridges/user/web/dist/mesh-worker.js +1 -1
- package/dist/bridges/user/web/frontend/mesh-worker.d.ts +93 -0
- package/dist/bridges/user/web/frontend/mesh-worker.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/mesh-worker.js +39 -59
- package/dist/bridges/user/web/frontend/mesh-worker.js.map +1 -1
- package/dist/core/agent-registry.d.ts +1 -3
- package/dist/core/agent-registry.d.ts.map +1 -1
- package/dist/core/agent-registry.js +0 -5
- package/dist/core/agent-registry.js.map +1 -1
- package/dist/core/bridge.d.ts +0 -3
- package/dist/core/bridge.d.ts.map +1 -1
- package/dist/core/bridge.js +0 -23
- package/dist/core/bridge.js.map +1 -1
- package/dist/core/comms-store.d.ts +1 -1
- package/dist/core/comms-store.js +1 -1
- package/dist/core/delivery-engine.d.ts +1 -5
- package/dist/core/delivery-engine.d.ts.map +1 -1
- package/dist/core/delivery-engine.js +0 -12
- package/dist/core/delivery-engine.js.map +1 -1
- package/dist/core/index.d.ts +0 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +0 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/mesh-store.d.ts +1 -15
- package/dist/core/mesh-store.d.ts.map +1 -1
- package/dist/core/mesh-store.js +2 -52
- package/dist/core/mesh-store.js.map +1 -1
- package/dist/core/room-lifecycle.d.ts +1 -4
- package/dist/core/room-lifecycle.d.ts.map +1 -1
- package/dist/core/room-lifecycle.js +0 -12
- package/dist/core/room-lifecycle.js.map +1 -1
- package/dist/core/room-messaging.d.ts +1 -3
- package/dist/core/room-messaging.d.ts.map +1 -1
- package/dist/core/room-messaging.js +0 -4
- package/dist/core/room-messaging.js.map +1 -1
- package/dist/core/room-router.d.ts.map +1 -1
- package/dist/core/room-router.js +2 -11
- package/dist/core/room-router.js.map +1 -1
- package/dist/core/tool.d.ts +1 -20
- package/dist/core/tool.d.ts.map +1 -1
- package/dist/core/tool.js +1 -108
- package/dist/core/tool.js.map +1 -1
- package/dist/core/types.d.ts +0 -54
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +0 -29
- package/dist/core/types.js.map +1 -1
- package/dist/core/wire-protocol.d.ts +0 -33
- package/dist/core/wire-protocol.d.ts.map +1 -1
- package/dist/core/wire-protocol.js.map +1 -1
- package/dist/test/agent-registry.test.js +1 -40
- package/dist/test/agent-registry.test.js.map +1 -1
- package/dist/test/delivery-engine-directed-notify.test.js +0 -39
- package/dist/test/delivery-engine-directed-notify.test.js.map +1 -1
- package/dist/test/delivery-engine.test.js +1 -18
- package/dist/test/delivery-engine.test.js.map +1 -1
- package/dist/test/mesh-store-orchestration.test.js +2 -56
- package/dist/test/mesh-store-orchestration.test.js.map +1 -1
- package/dist/test/room-lifecycle-membership.test.js +0 -30
- package/dist/test/room-lifecycle-membership.test.js.map +1 -1
- package/dist/test/room-lifecycle-remote.test.js +2 -9
- package/dist/test/room-lifecycle-remote.test.js.map +1 -1
- package/dist/test/room-lifecycle.test.js +0 -49
- package/dist/test/room-lifecycle.test.js.map +1 -1
- package/dist/test/room-messaging-durable-send.test.js +0 -1
- package/dist/test/room-messaging-durable-send.test.js.map +1 -1
- package/dist/test/room-messaging.test.js +0 -13
- package/dist/test/room-messaging.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/core/federation-bridge.d.ts +0 -32
- package/dist/core/federation-bridge.d.ts.map +0 -1
- package/dist/core/federation-bridge.js +0 -112
- package/dist/core/federation-bridge.js.map +0 -1
- package/dist/core/federation.d.ts +0 -125
- package/dist/core/federation.d.ts.map +0 -1
- package/dist/core/federation.js +0 -523
- package/dist/core/federation.js.map +0 -1
- package/dist/test/federation-bridge.test.d.ts +0 -2
- package/dist/test/federation-bridge.test.d.ts.map +0 -1
- package/dist/test/federation-bridge.test.js +0 -260
- package/dist/test/federation-bridge.test.js.map +0 -1
- package/dist/test/federation.integration.test.d.ts +0 -16
- package/dist/test/federation.integration.test.d.ts.map +0 -1
- package/dist/test/federation.integration.test.js +0 -210
- package/dist/test/federation.integration.test.js.map +0 -1
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Direct, DI-based unit tests for FederationBridge -- it was previously exercised only indirectly through end-to-end federation.integration.test.ts scenarios, leaving many individual branches, the fed:-prefix startsWith-vs-endsWith distinction, and getVisibleAgents/getFederatedRoomMemberships' filtering unobserved. FederationBridgeDeps is a narrow, injectable surface built exactly for this: a fake deps object with vi.fn() collaborators lets every branch be asserted on directly.
|
|
3
|
-
*
|
|
4
|
-
* Three mutants Stryker raises are true equivalents, not gaps -- documented here rather than chased with a contrived test, matching stale-agent-checker.test.ts's and agent-registry.test.ts's own precedent for the identical pattern: `onAgentGone`'s `this.deps.agents.set(localId, agent)`, and `onRoomJoin`/`onRoomLeave`'s two `this.deps.rooms.set(roomId, room)` calls, each re-set the same key to the exact same object reference the map's own `.get()` already returned. `bump`/`recordMemberOp`/`refreshMembership` all mutate that object in place (bump does `entity.version += 1`; recordMemberOp writes into `room.memberJoins`/`memberLeaves`; refreshMembership reassigns `room.members`/`invited`), so the map already holds the fully up-to-date object before the redundant `.set()` call -- no test can observe removing it.
|
|
5
|
-
*/
|
|
6
|
-
import { describe, expect, it, vi } from "vitest";
|
|
7
|
-
import { FederationBridge, } from "../core/federation-bridge.js";
|
|
8
|
-
function agent(overrides = {}) {
|
|
9
|
-
return {
|
|
10
|
-
id: "local-agent",
|
|
11
|
-
version: 1,
|
|
12
|
-
name: "agent-name",
|
|
13
|
-
harness: "pi",
|
|
14
|
-
cwd: "/tmp",
|
|
15
|
-
pid: 111,
|
|
16
|
-
startedAt: "2026-01-01T00:00:00.000Z",
|
|
17
|
-
visibility: "visible",
|
|
18
|
-
status: "active",
|
|
19
|
-
tags: [],
|
|
20
|
-
subscribedRooms: [],
|
|
21
|
-
...overrides,
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
function room(overrides = {}) {
|
|
25
|
-
return {
|
|
26
|
-
id: "room-1",
|
|
27
|
-
version: 1,
|
|
28
|
-
name: "room-name",
|
|
29
|
-
type: "public",
|
|
30
|
-
owner: "owner-device",
|
|
31
|
-
createdAt: "2026-01-01T00:00:00.000Z",
|
|
32
|
-
description: "",
|
|
33
|
-
members: [],
|
|
34
|
-
invited: [],
|
|
35
|
-
memberJoins: {},
|
|
36
|
-
memberLeaves: {},
|
|
37
|
-
invitedJoins: {},
|
|
38
|
-
invitedLeaves: {},
|
|
39
|
-
...overrides,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
function message(overrides = {}) {
|
|
43
|
-
return {
|
|
44
|
-
id: "msg-1",
|
|
45
|
-
from: "sender",
|
|
46
|
-
room: "room-1",
|
|
47
|
-
content: "hi",
|
|
48
|
-
timestamp: "2026-01-01T00:00:00.000Z",
|
|
49
|
-
readBy: [],
|
|
50
|
-
...overrides,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function makeHarness() {
|
|
54
|
-
const bump = vi.fn();
|
|
55
|
-
const recordMemberOp = vi.fn();
|
|
56
|
-
const refreshMembership = vi.fn();
|
|
57
|
-
const broadcastPatch = vi.fn().mockResolvedValue(undefined);
|
|
58
|
-
const deliverToRoom = vi.fn().mockResolvedValue(undefined);
|
|
59
|
-
const deliverRoomMessageToMember = vi.fn().mockResolvedValue(undefined);
|
|
60
|
-
const deps = {
|
|
61
|
-
agents: new Map(),
|
|
62
|
-
rooms: new Map(),
|
|
63
|
-
messages: new Map(),
|
|
64
|
-
deliveryEngine: {
|
|
65
|
-
bump,
|
|
66
|
-
recordMemberOp,
|
|
67
|
-
refreshMembership,
|
|
68
|
-
broadcastPatch,
|
|
69
|
-
deliverToRoom,
|
|
70
|
-
deliverRoomMessageToMember,
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
|
-
return {
|
|
74
|
-
deps,
|
|
75
|
-
bridge: new FederationBridge(deps),
|
|
76
|
-
bump,
|
|
77
|
-
recordMemberOp,
|
|
78
|
-
refreshMembership,
|
|
79
|
-
broadcastPatch,
|
|
80
|
-
deliverToRoom,
|
|
81
|
-
deliverRoomMessageToMember,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
describe("FederationBridge — onAgentVisible", () => {
|
|
85
|
-
it("stores the remote agent under a fed:<id>@<harness> key, tagged federated, and broadcasts it", async () => {
|
|
86
|
-
const h = makeHarness();
|
|
87
|
-
const remote = agent({ id: "remote-id", harness: "codex", tags: ["x"] });
|
|
88
|
-
await h.bridge.onAgentVisible(remote);
|
|
89
|
-
const stored = h.deps.agents.get("fed:remote-id@codex");
|
|
90
|
-
expect(stored).toBeDefined();
|
|
91
|
-
expect(stored?.id).toBe("fed:remote-id@codex");
|
|
92
|
-
expect(stored?.tags).toEqual(["x", "federated"]);
|
|
93
|
-
expect(h.broadcastPatch).toHaveBeenCalledWith({
|
|
94
|
-
type: "agent_upsert",
|
|
95
|
-
agent: stored,
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
describe("FederationBridge — onAgentGone", () => {
|
|
100
|
-
it("marks the matching fed:-prefixed local agent offline and broadcasts it", async () => {
|
|
101
|
-
const h = makeHarness();
|
|
102
|
-
h.deps.agents.set("fed:remote-id@codex", agent({ id: "fed:remote-id@codex", status: "active" }));
|
|
103
|
-
await h.bridge.onAgentGone("remote-id");
|
|
104
|
-
expect(h.deps.agents.get("fed:remote-id@codex")?.status).toBe("offline");
|
|
105
|
-
expect(h.broadcastPatch).toHaveBeenCalledWith({
|
|
106
|
-
type: "agent_offline",
|
|
107
|
-
agentId: "fed:remote-id@codex",
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
it("does nothing when no local agent matches the fed:<id>@ prefix", async () => {
|
|
111
|
-
const h = makeHarness();
|
|
112
|
-
await h.bridge.onAgentGone("no-such-remote");
|
|
113
|
-
expect(h.broadcastPatch).not.toHaveBeenCalled();
|
|
114
|
-
});
|
|
115
|
-
it("requires the prefix to actually match at the start, not merely appear at the end", async () => {
|
|
116
|
-
const h = makeHarness();
|
|
117
|
-
// Ends with "fed:remote-id@" but does not start with it -- must not match.
|
|
118
|
-
h.deps.agents.set("xfed:remote-id@", agent({ id: "xfed:remote-id@", status: "active" }));
|
|
119
|
-
await h.bridge.onAgentGone("remote-id");
|
|
120
|
-
expect(h.deps.agents.get("xfed:remote-id@")?.status).toBe("active");
|
|
121
|
-
expect(h.broadcastPatch).not.toHaveBeenCalled();
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
describe("FederationBridge — onRoomMessage", () => {
|
|
125
|
-
it("stores the message and delivers it to every local room member", async () => {
|
|
126
|
-
const h = makeHarness();
|
|
127
|
-
h.deps.rooms.set("room-1", room({ id: "room-1", federated: true, members: ["a", "b"] }));
|
|
128
|
-
const msg = message();
|
|
129
|
-
await h.bridge.onRoomMessage("room-1", msg);
|
|
130
|
-
expect(h.deps.messages.get("room-1")).toEqual([msg]);
|
|
131
|
-
expect(h.deliverRoomMessageToMember).toHaveBeenCalledWith("room-1", "a", msg);
|
|
132
|
-
expect(h.deliverRoomMessageToMember).toHaveBeenCalledWith("room-1", "b", msg);
|
|
133
|
-
});
|
|
134
|
-
it("skips fed:-prefixed shadow members -- they have no addressable mesh device of their own, federation.ts's own link forwarding is what reaches the real remote participant", async () => {
|
|
135
|
-
const h = makeHarness();
|
|
136
|
-
h.deps.rooms.set("room-1", room({
|
|
137
|
-
id: "room-1",
|
|
138
|
-
federated: true,
|
|
139
|
-
members: ["a", "fed:remote-agent"],
|
|
140
|
-
}));
|
|
141
|
-
const msg = message();
|
|
142
|
-
await h.bridge.onRoomMessage("room-1", msg);
|
|
143
|
-
expect(h.deliverRoomMessageToMember).toHaveBeenCalledWith("room-1", "a", msg);
|
|
144
|
-
expect(h.deliverRoomMessageToMember).not.toHaveBeenCalledWith("room-1", "fed:remote-agent", msg);
|
|
145
|
-
});
|
|
146
|
-
it("does nothing for a room that isn't federated", async () => {
|
|
147
|
-
const h = makeHarness();
|
|
148
|
-
h.deps.rooms.set("room-1", room({ id: "room-1", federated: false }));
|
|
149
|
-
await h.bridge.onRoomMessage("room-1", message());
|
|
150
|
-
expect(h.deps.messages.get("room-1")).toBeUndefined();
|
|
151
|
-
expect(h.deliverRoomMessageToMember).not.toHaveBeenCalled();
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
describe("FederationBridge — onRoomJoin", () => {
|
|
155
|
-
it("adds a fed:-prefixed shadow member, records the join, and broadcasts the room when the member is new", async () => {
|
|
156
|
-
const h = makeHarness();
|
|
157
|
-
h.deps.rooms.set("room-1", room({ id: "room-1", federated: true, members: [] }));
|
|
158
|
-
await h.bridge.onRoomJoin("room-1", "remote-agent", "Remote Name");
|
|
159
|
-
expect(h.bump).toHaveBeenCalledTimes(1);
|
|
160
|
-
expect(h.recordMemberOp).toHaveBeenCalledWith(expect.anything(), "member", "join", "fed:remote-agent");
|
|
161
|
-
expect(h.refreshMembership).toHaveBeenCalledTimes(1);
|
|
162
|
-
expect(h.broadcastPatch).toHaveBeenCalledWith({
|
|
163
|
-
type: "room_upsert",
|
|
164
|
-
room: expect.anything(),
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
it("skips the join-recording step entirely when the shadow member is already present", async () => {
|
|
168
|
-
const h = makeHarness();
|
|
169
|
-
h.deps.rooms.set("room-1", room({ id: "room-1", federated: true, members: ["fed:remote-agent"] }));
|
|
170
|
-
await h.bridge.onRoomJoin("room-1", "remote-agent", "Remote Name");
|
|
171
|
-
expect(h.bump).not.toHaveBeenCalled();
|
|
172
|
-
expect(h.recordMemberOp).not.toHaveBeenCalled();
|
|
173
|
-
expect(h.broadcastPatch).not.toHaveBeenCalled();
|
|
174
|
-
});
|
|
175
|
-
it("always notifies local members of the join, even when the shadow member already existed", async () => {
|
|
176
|
-
const h = makeHarness();
|
|
177
|
-
h.deps.rooms.set("room-1", room({ id: "room-1", federated: true, members: ["fed:remote-agent"] }));
|
|
178
|
-
await h.bridge.onRoomJoin("room-1", "remote-agent", "Remote Name");
|
|
179
|
-
expect(h.deliverToRoom).toHaveBeenCalledWith("room-1", { type: "member_joined", room: "room-1", agent: "fed:remote-agent" }, "fed:remote-agent");
|
|
180
|
-
});
|
|
181
|
-
it("does nothing at all for a room that isn't federated", async () => {
|
|
182
|
-
const h = makeHarness();
|
|
183
|
-
h.deps.rooms.set("room-1", room({ id: "room-1", federated: false }));
|
|
184
|
-
await h.bridge.onRoomJoin("room-1", "remote-agent", "Remote Name");
|
|
185
|
-
expect(h.bump).not.toHaveBeenCalled();
|
|
186
|
-
expect(h.deliverToRoom).not.toHaveBeenCalled();
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
describe("FederationBridge — onRoomLeave", () => {
|
|
190
|
-
it("records the leave, bumps and broadcasts the room, and notifies local members", async () => {
|
|
191
|
-
const h = makeHarness();
|
|
192
|
-
h.deps.rooms.set("room-1", room({ id: "room-1", federated: true, members: ["fed:remote-agent"] }));
|
|
193
|
-
await h.bridge.onRoomLeave("room-1", "remote-agent");
|
|
194
|
-
expect(h.bump).toHaveBeenCalledTimes(1);
|
|
195
|
-
expect(h.recordMemberOp).toHaveBeenCalledWith(expect.anything(), "member", "leave", "fed:remote-agent");
|
|
196
|
-
expect(h.refreshMembership).toHaveBeenCalledTimes(1);
|
|
197
|
-
expect(h.broadcastPatch).toHaveBeenCalledWith({
|
|
198
|
-
type: "room_upsert",
|
|
199
|
-
room: expect.anything(),
|
|
200
|
-
});
|
|
201
|
-
expect(h.deliverToRoom).toHaveBeenCalledWith("room-1", {
|
|
202
|
-
type: "member_left",
|
|
203
|
-
room: "room-1",
|
|
204
|
-
agent: "fed:remote-agent",
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
it("does nothing at all for a room that isn't federated", async () => {
|
|
208
|
-
const h = makeHarness();
|
|
209
|
-
h.deps.rooms.set("room-1", room({ id: "room-1", federated: false }));
|
|
210
|
-
await h.bridge.onRoomLeave("room-1", "remote-agent");
|
|
211
|
-
expect(h.bump).not.toHaveBeenCalled();
|
|
212
|
-
expect(h.deliverToRoom).not.toHaveBeenCalled();
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
describe("FederationBridge — getVisibleAgents", () => {
|
|
216
|
-
it("includes a visible, non-federated agent", () => {
|
|
217
|
-
const h = makeHarness();
|
|
218
|
-
const a = agent({ id: "local-a", visibility: "visible" });
|
|
219
|
-
h.deps.agents.set(a.id, a);
|
|
220
|
-
expect(h.bridge.getVisibleAgents()).toEqual([a]);
|
|
221
|
-
});
|
|
222
|
-
it("excludes an agent that isn't visible", () => {
|
|
223
|
-
const h = makeHarness();
|
|
224
|
-
h.deps.agents.set("hidden-a", agent({ id: "hidden-a", visibility: "hidden" }));
|
|
225
|
-
expect(h.bridge.getVisibleAgents()).toEqual([]);
|
|
226
|
-
});
|
|
227
|
-
it("excludes an already-federated-in agent even when visible", () => {
|
|
228
|
-
const h = makeHarness();
|
|
229
|
-
h.deps.agents.set("fed:remote@codex", agent({ id: "fed:remote@codex", visibility: "visible" }));
|
|
230
|
-
expect(h.bridge.getVisibleAgents()).toEqual([]);
|
|
231
|
-
});
|
|
232
|
-
it("requires the fed: prefix to be at the start, not merely present at the end", () => {
|
|
233
|
-
const h = makeHarness();
|
|
234
|
-
// Ends with "fed:" but does not start with it -- must be included.
|
|
235
|
-
const a = agent({ id: "xxxfed:", visibility: "visible" });
|
|
236
|
-
h.deps.agents.set(a.id, a);
|
|
237
|
-
expect(h.bridge.getVisibleAgents()).toEqual([a]);
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
describe("FederationBridge — getFederatedRoomMemberships", () => {
|
|
241
|
-
it("includes only federated rooms, with fed:-prefixed members filtered out", () => {
|
|
242
|
-
const h = makeHarness();
|
|
243
|
-
h.deps.rooms.set("fed-room", room({
|
|
244
|
-
id: "fed-room",
|
|
245
|
-
federated: true,
|
|
246
|
-
members: ["local-a", "fed:remote-b"],
|
|
247
|
-
}));
|
|
248
|
-
h.deps.rooms.set("plain-room", room({ id: "plain-room", federated: false, members: ["local-c"] }));
|
|
249
|
-
const result = h.bridge.getFederatedRoomMemberships();
|
|
250
|
-
expect(result.get("fed-room")).toEqual(["local-a"]);
|
|
251
|
-
expect(result.has("plain-room")).toBe(false);
|
|
252
|
-
});
|
|
253
|
-
it("requires the fed: prefix to be at the start, not merely present at the end, when filtering members", () => {
|
|
254
|
-
const h = makeHarness();
|
|
255
|
-
h.deps.rooms.set("fed-room", room({ id: "fed-room", federated: true, members: ["xxxfed:"] }));
|
|
256
|
-
const result = h.bridge.getFederatedRoomMemberships();
|
|
257
|
-
expect(result.get("fed-room")).toEqual(["xxxfed:"]);
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
//# sourceMappingURL=federation-bridge.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"federation-bridge.test.js","sourceRoot":"","sources":["../../src/test/federation-bridge.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Federation integration test — verifies that two MeshStore instances on different "machines" (simulated via separate TCP meshes) can federate through coordinator-to-coordinator TLS links, and that an inbound link presenting an untrusted certificate is rejected outright.
|
|
3
|
-
*
|
|
4
|
-
* Tests:
|
|
5
|
-
* 0. An inbound connection with no pinned fingerprint is rejected
|
|
6
|
-
* 1. Establish federation link between two meshes once both fingerprints are trusted
|
|
7
|
-
* 2. Agent presence propagates across federation
|
|
8
|
-
* 3. Messages in federated rooms propagate across federation
|
|
9
|
-
* 4. Non-federated rooms are isolated (messages never cross)
|
|
10
|
-
* 5. Federation link listing
|
|
11
|
-
* 6. Disconnect federation link
|
|
12
|
-
*
|
|
13
|
-
* Run: node dist/test/federation.integration.test.js
|
|
14
|
-
*/
|
|
15
|
-
export {};
|
|
16
|
-
//# sourceMappingURL=federation.integration.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"federation.integration.test.d.ts","sourceRoot":"","sources":["../../src/test/federation.integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Federation integration test — verifies that two MeshStore instances on different "machines" (simulated via separate TCP meshes) can federate through coordinator-to-coordinator TLS links, and that an inbound link presenting an untrusted certificate is rejected outright.
|
|
3
|
-
*
|
|
4
|
-
* Tests:
|
|
5
|
-
* 0. An inbound connection with no pinned fingerprint is rejected
|
|
6
|
-
* 1. Establish federation link between two meshes once both fingerprints are trusted
|
|
7
|
-
* 2. Agent presence propagates across federation
|
|
8
|
-
* 3. Messages in federated rooms propagate across federation
|
|
9
|
-
* 4. Non-federated rooms are isolated (messages never cross)
|
|
10
|
-
* 5. Federation link listing
|
|
11
|
-
* 6. Disconnect federation link
|
|
12
|
-
*
|
|
13
|
-
* Run: node dist/test/federation.integration.test.js
|
|
14
|
-
*/
|
|
15
|
-
import { MeshStore } from "../core/mesh-store.js";
|
|
16
|
-
import * as net from "node:net";
|
|
17
|
-
import { test, expect } from "vitest";
|
|
18
|
-
import { wireTestTransport } from "./test-transport.js";
|
|
19
|
-
// Use high ports to avoid collisions with real meshes
|
|
20
|
-
const MESH_A_PORT = 28876;
|
|
21
|
-
const MESH_B_PORT = 28877;
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
// Timing constants — settle windows for asynchronous mesh/federation propagation. There is no "operation complete" signal for these steps, so the test waits a fixed budget rather than polling.
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
/** Milliseconds to wait after a mesh-setup step (creating a mesh, starting the federation listener) for local state to settle. */
|
|
26
|
-
const MESH_SETUP_SETTLE_MS = 100;
|
|
27
|
-
/** Milliseconds to wait for a freshly established federation link to settle before exercising it. */
|
|
28
|
-
const FED_LINK_SETTLE_MS = 200;
|
|
29
|
-
/** Milliseconds to wait for a federated room (or a join against its mirror) to propagate across the federation link. */
|
|
30
|
-
const FED_ROOM_SETTLE_MS = 200;
|
|
31
|
-
/** Milliseconds to wait for a room message to propagate across an established federation link. */
|
|
32
|
-
const FED_MESSAGE_PROPAGATION_MS = 500;
|
|
33
|
-
/** Milliseconds to wait for a non-federated (local-only) room to settle after creation. */
|
|
34
|
-
const LOCAL_ROOM_SETTLE_MS = 100;
|
|
35
|
-
/** Milliseconds to wait for a local-only message to settle, confirming it does not leak across federation. */
|
|
36
|
-
const LOCAL_MESSAGE_SETTLE_MS = 100;
|
|
37
|
-
/** Milliseconds to wait for a federation link disconnect to propagate. */
|
|
38
|
-
const FED_DISCONNECT_SETTLE_MS = 200;
|
|
39
|
-
async function sleep(ms) {
|
|
40
|
-
await new Promise((resolve) => {
|
|
41
|
-
setTimeout(resolve, ms);
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
// ---------------------------------------------------------------------------
|
|
45
|
-
// Helpers
|
|
46
|
-
// ---------------------------------------------------------------------------
|
|
47
|
-
async function createMesh(name, coordinatorPort) {
|
|
48
|
-
const store = new MeshStore(coordinatorPort);
|
|
49
|
-
await wireTestTransport(store);
|
|
50
|
-
const deliveries = [];
|
|
51
|
-
store.onDelivery = (_agentId, event) => {
|
|
52
|
-
deliveries.push(event);
|
|
53
|
-
};
|
|
54
|
-
await store.init();
|
|
55
|
-
await store.registerAgent({
|
|
56
|
-
name,
|
|
57
|
-
harness: "test",
|
|
58
|
-
cwd: `/test/${name}`,
|
|
59
|
-
pid: process.pid,
|
|
60
|
-
visibility: "visible",
|
|
61
|
-
tags: [],
|
|
62
|
-
});
|
|
63
|
-
return { store, deliveries };
|
|
64
|
-
}
|
|
65
|
-
/** Find a free port on localhost. */
|
|
66
|
-
async function findFreePort() {
|
|
67
|
-
return await new Promise((resolve, reject) => {
|
|
68
|
-
const server = net.createServer();
|
|
69
|
-
server.listen(0, "127.0.0.1", () => {
|
|
70
|
-
const addr = server.address();
|
|
71
|
-
if (typeof addr === "object" && addr !== null) {
|
|
72
|
-
const port = addr.port;
|
|
73
|
-
server.close(() => resolve(port));
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
server.close(() => reject(new Error("Failed to get port")));
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
server.on("error", reject);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
// ---------------------------------------------------------------------------
|
|
83
|
-
// Test runner
|
|
84
|
-
// ---------------------------------------------------------------------------
|
|
85
|
-
async function main() {
|
|
86
|
-
console.log("=== Federation Integration Tests ===\n");
|
|
87
|
-
console.log("Creating mesh A (coordinator)...");
|
|
88
|
-
const a = await createMesh("mesh-a-agent", MESH_A_PORT);
|
|
89
|
-
await sleep(MESH_SETUP_SETTLE_MS);
|
|
90
|
-
console.log("Creating mesh B (coordinator)...");
|
|
91
|
-
const b = await createMesh("mesh-b-agent", MESH_B_PORT);
|
|
92
|
-
await sleep(MESH_SETUP_SETTLE_MS);
|
|
93
|
-
const fedPort = await findFreePort();
|
|
94
|
-
console.log(`Using federation port ${String(fedPort)}`);
|
|
95
|
-
// Start A's real production federation listener (fedListen -> FederationManager.listen -> handleInbound, the same path a deployed coordinator uses — not a hand-rolled test-only TLS server).
|
|
96
|
-
await a.store.fedListen("127.0.0.1", fedPort);
|
|
97
|
-
await sleep(MESH_SETUP_SETTLE_MS);
|
|
98
|
-
// --- Test 0: untrusted inbound connection is rejected ---
|
|
99
|
-
console.log("\nTest 0: untrusted connection is rejected...");
|
|
100
|
-
await expect(b.store.fedConnect("127.0.0.1", fedPort), "Connecting before either side has pinned the other's fingerprint should be rejected").rejects.toThrow(/rejected|not in the trusted-fingerprint allowlist/i);
|
|
101
|
-
expect(b.store.fedLinks().length, "B should have no federation links after a rejected attempt").toBe(0);
|
|
102
|
-
console.log(" Rejected as expected — no link was created.");
|
|
103
|
-
// --- Pin fingerprints on both sides, mirroring what an operator does out of band ---
|
|
104
|
-
console.log("\nPinning fingerprints on both sides...");
|
|
105
|
-
const fingerprintA = a.store.getFederationFingerprint();
|
|
106
|
-
const fingerprintB = b.store.getFederationFingerprint();
|
|
107
|
-
expect(fingerprintA.length > 0, "A should report its own fingerprint").toBeTruthy();
|
|
108
|
-
expect(fingerprintB.length > 0, "B should report its own fingerprint").toBeTruthy();
|
|
109
|
-
await a.store.fedTrust(fingerprintB);
|
|
110
|
-
await b.store.fedTrust(fingerprintA);
|
|
111
|
-
expect(a.store.fedTrustedFingerprints()).toEqual([fingerprintB]);
|
|
112
|
-
expect(b.store.fedTrustedFingerprints()).toEqual([fingerprintA]);
|
|
113
|
-
// --- Test 1: Establish federation link now that both sides trust each other ---
|
|
114
|
-
console.log("\nTest 1: Establish federation link...");
|
|
115
|
-
const linkId = await b.store.fedConnect("127.0.0.1", fedPort);
|
|
116
|
-
console.log(` Link established: ${linkId}`);
|
|
117
|
-
expect(linkId, "Should return a link ID").toBeTruthy();
|
|
118
|
-
const linksB = b.store.fedLinks();
|
|
119
|
-
expect(linksB.length, "B should have 1 federation link").toBe(1);
|
|
120
|
-
const link = linksB[0];
|
|
121
|
-
expect(link, "Link should exist").toBeTruthy();
|
|
122
|
-
if (link === undefined)
|
|
123
|
-
throw new Error("Link should exist");
|
|
124
|
-
expect(link.remoteMeshId.length > 0, "Remote mesh ID should be present").toBeTruthy();
|
|
125
|
-
await sleep(FED_LINK_SETTLE_MS);
|
|
126
|
-
// --- Test 2: Agent presence propagates ---
|
|
127
|
-
console.log("Test 2: Agent presence propagates...");
|
|
128
|
-
const agentsB = await b.store.listAgents(b.store.peerId);
|
|
129
|
-
console.log(` B sees ${String(agentsB.length)} agent(s)`);
|
|
130
|
-
const fedAgentsB = agentsB.filter((ag) => ag.tags.includes("federated"));
|
|
131
|
-
expect(fedAgentsB.length >= 1, "B should see at least 1 federated agent from A").toBeTruthy();
|
|
132
|
-
const agentsA = await a.store.listAgents(a.store.peerId);
|
|
133
|
-
console.log(` A sees ${String(agentsA.length)} agent(s)`);
|
|
134
|
-
const fedAgentsA = agentsA.filter((ag) => ag.tags.includes("federated"));
|
|
135
|
-
expect(fedAgentsA.length >= 1, "A should see at least 1 federated agent from B").toBeTruthy();
|
|
136
|
-
// --- Test 3: Federated room messages propagate ---
|
|
137
|
-
console.log("Test 3: Federated room messages propagate...");
|
|
138
|
-
const fedRoomId = `fed-room-${String(Date.now())}`;
|
|
139
|
-
const fedRoom = await a.store.createRoom({
|
|
140
|
-
name: fedRoomId,
|
|
141
|
-
type: "public",
|
|
142
|
-
owner: a.store.peerId,
|
|
143
|
-
description: "Federated test room",
|
|
144
|
-
federated: true,
|
|
145
|
-
});
|
|
146
|
-
console.log(` Created federated room: ${fedRoom.id}`);
|
|
147
|
-
await sleep(FED_ROOM_SETTLE_MS);
|
|
148
|
-
// Federation matches a room across the two separate meshes by literal id equality (handleFedRoomMessage/Join/Leave all key off the incoming roomId string directly) -- an owner-rooted path only coincides on both sides when both sides construct it from the same owner, so B's mirror of A's room is created with A's own peerId as owner, not B's.
|
|
149
|
-
const fedRoomB = await b.store.createRoom({
|
|
150
|
-
name: fedRoomId,
|
|
151
|
-
type: "public",
|
|
152
|
-
owner: a.store.peerId,
|
|
153
|
-
description: "Federated test room",
|
|
154
|
-
federated: true,
|
|
155
|
-
});
|
|
156
|
-
console.log(` Created matching federated room on B: ${fedRoomB.id}`);
|
|
157
|
-
// createRoom's default members is [owner] -- since owner is A's peerId (to make the id match), B's own local agent must explicitly join its mirror for handleFedRoomMessage's local-delivery loop to reach it.
|
|
158
|
-
await b.store.joinRoom(fedRoomB.id, b.store.peerId);
|
|
159
|
-
await sleep(FED_ROOM_SETTLE_MS);
|
|
160
|
-
a.deliveries.length = 0;
|
|
161
|
-
b.deliveries.length = 0;
|
|
162
|
-
const msg = await a.store.sendRoomMessage(fedRoom.id, a.store.peerId, "Hello from mesh A!");
|
|
163
|
-
console.log(` A sent: "${msg.content}"`);
|
|
164
|
-
await sleep(FED_MESSAGE_PROPAGATION_MS);
|
|
165
|
-
const fedMsgs = b.deliveries.filter((e) => e.type === "room_message" && e.message.content === "Hello from mesh A!");
|
|
166
|
-
console.log(` B received ${String(fedMsgs.length)} federated message(s)`);
|
|
167
|
-
expect(fedMsgs.length >= 1, "B should receive the federated room message").toBeTruthy();
|
|
168
|
-
// --- Test 4: Non-federated rooms are isolated ---
|
|
169
|
-
console.log("Test 4: Non-federated rooms are isolated...");
|
|
170
|
-
const localRoomId = `local-room-${String(Date.now())}`;
|
|
171
|
-
console.log(` Creating non-federated room: ${localRoomId}`);
|
|
172
|
-
const localRoom = await a.store.createRoom({
|
|
173
|
-
name: localRoomId,
|
|
174
|
-
type: "public",
|
|
175
|
-
owner: a.store.peerId,
|
|
176
|
-
description: "Local-only room",
|
|
177
|
-
// federated defaults to false
|
|
178
|
-
});
|
|
179
|
-
console.log(` Created non-federated room: ${localRoom.id}, federated=${String(localRoom.federated)}`);
|
|
180
|
-
await sleep(LOCAL_ROOM_SETTLE_MS);
|
|
181
|
-
b.deliveries.length = 0;
|
|
182
|
-
console.log(" Sending message in non-federated room...");
|
|
183
|
-
await a.store.sendRoomMessage(localRoom.id, a.store.peerId, "Secret local message");
|
|
184
|
-
console.log(" Message sent.");
|
|
185
|
-
await sleep(LOCAL_MESSAGE_SETTLE_MS);
|
|
186
|
-
const leakedMsgs = b.deliveries.filter((e) => e.type === "room_message" && e.message.content === "Secret local message");
|
|
187
|
-
console.log(` B received ${String(leakedMsgs.length)} leaked message(s)`);
|
|
188
|
-
expect(leakedMsgs.length, "B should NOT receive non-federated room messages").toBe(0);
|
|
189
|
-
// --- Test 5: Federation link listing ---
|
|
190
|
-
console.log("Test 5: Federation link listing...");
|
|
191
|
-
const linksA = a.store.fedLinks();
|
|
192
|
-
expect(linksA.length, "A should have 1 federation link").toBe(1);
|
|
193
|
-
console.log(` A links: ${linksA.map((l) => l.remoteName).join(", ")}`);
|
|
194
|
-
// --- Test 6: Disconnect federation link ---
|
|
195
|
-
console.log("Test 6: Disconnect federation link...");
|
|
196
|
-
await b.store.fedDisconnect(linkId);
|
|
197
|
-
await sleep(FED_DISCONNECT_SETTLE_MS);
|
|
198
|
-
const linksAfter = b.store.fedLinks();
|
|
199
|
-
expect(linksAfter.length, "B should have 0 federation links after disconnect").toBe(0);
|
|
200
|
-
// --- Cleanup ---
|
|
201
|
-
console.log("\nCleaning up...");
|
|
202
|
-
await a.store.fedStopListening();
|
|
203
|
-
await a.store.shutdown();
|
|
204
|
-
await b.store.shutdown();
|
|
205
|
-
console.log("\n✓ All federation tests passed!");
|
|
206
|
-
}
|
|
207
|
-
test("federates two meshes over coordinator-to-coordinator TLS links, propagating presence and room messages while rejecting an untrusted inbound link", async () => {
|
|
208
|
-
await main();
|
|
209
|
-
});
|
|
210
|
-
//# sourceMappingURL=federation.integration.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"federation.integration.test.js","sourceRoot":"","sources":["../../src/test/federation.integration.test.ts"],"names":[],"mappings":"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"}
|