From cc91e481b872472ae693439439c72ab3fa4097be Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Tue, 15 Sep 2026 11:39:06 +0100 Subject: [PATCH 1/4] test(mesh-store): assert MeshStore's own orchestration logic directly MeshStore's constructor takes no injectable deps (unlike its extracted collaborators), and its own orchestration-level logic -- requireTransport/ requireIdentity's guard errors, the connected getter, init()'s connect-vs- becomeCoordinator-vs-EADDRINUSE branching, the events getter's dispatch table, federation/listener/room-join-approval passthroughs, and shutdown() -- was previously exercised only indirectly through wireTestTransport-based integration tests, which don't isolate MeshStore's own branching from its collaborators' real behaviour. Uses a hand-built fake MeshTransport passed to the real setTransport() for deterministic control over init()'s branches, and reaches the private roomProtocol/connectionApproval/peerLifecycle/deliveryEngine/staleAgentChecker collaborators via a narrow cast to assert a delegating wrapper actually calls through -- TypeScript's private is compile-time only, and this is exactly the kind of whitebox check a one-line pass-through method needs that no public-API-only test can express. Covers every currently-open survivor/timeout this file's mutation score reports except the events getter's onMessage/onPeerConnected dispatch pair sharing a mutant with an already-covered branch, and getFederationFingerprint (no test infrastructure for a real TLS identity certificate exists yet). --- src/test/mesh-store-orchestration.test.ts | 543 ++++++++++++++++++++++ 1 file changed, 543 insertions(+) create mode 100644 src/test/mesh-store-orchestration.test.ts diff --git a/src/test/mesh-store-orchestration.test.ts b/src/test/mesh-store-orchestration.test.ts new file mode 100644 index 00000000..5a2de341 --- /dev/null +++ b/src/test/mesh-store-orchestration.test.ts @@ -0,0 +1,543 @@ +/** + * Direct unit tests for MeshStore's own orchestration logic -- requireTransport/requireIdentity's guard errors, the connected getter, init()'s connect-vs-becomeCoordinator-vs-EADDRINUSE branching, the events getter's dispatch table, federation/listener/room-join-approval passthroughs, and shutdown() -- as opposed to the collaborator-owned behaviour wireTestTransport-based integration tests already cover end-to-end. MeshStore's constructor takes no injectable deps (unlike its collaborators), so these tests use a hand-built fake MeshTransport passed to the real setTransport(), and reach the private roomProtocol/connectionApproval/peerLifecycle/deliveryEngine/agentRegistry collaborators via a narrow, explicitly-justified cast -- TypeScript's `private` is compile-time only, and asserting a delegating wrapper actually calls through to the collaborator that owns the real implementation is exactly the kind of whitebox check no public-API-only test can express for a one-line pass-through. + */ +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { MeshStore } from "../core/mesh-store.js"; +import type { ConnectionHandle, MeshTransport } from "../core/transport.js"; +import type { ManageOutcome } from "wire-mesh-core/domain/mesh-session"; +import type { PeerInfo } from "../core/wire-protocol.js"; + +/** A device-id is a 64-character lowercase hex SHA-256 digest; room-path.ts's assertDeviceIdHex rejects anything shorter. */ +const DEVICE_ID_HEX_LENGTH = 64; +const VALID_DEVICE_ID = "a".repeat(DEVICE_ID_HEX_LENGTH); +/** Arbitrary, distinctive remote port for a connectToRemote test fixture -- no significance beyond "a real-looking port number". */ +const REMOTE_PORT = 4242; + +function fakeTransport(): MeshTransport { + return { + dataPort: 4000, + isCoordinator: false, + hasCoordinatorConnection: false, + startDataServer: vi.fn().mockResolvedValue(undefined), + connectToCoordinator: vi.fn().mockResolvedValue(undefined), + becomeCoordinator: vi.fn().mockResolvedValue(undefined), + connectToPeer: vi.fn().mockResolvedValue(undefined), + send: vi.fn().mockResolvedValue(undefined), + acceptConnection: vi.fn().mockResolvedValue(undefined), + rejectConnection: vi.fn().mockResolvedValue(undefined), + connectToRemote: vi.fn().mockResolvedValue(undefined), + broadcast: vi.fn().mockResolvedValue(undefined), + broadcastRevocation: vi.fn().mockResolvedValue(undefined), + sendRoomRequest: vi.fn().mockResolvedValue({ + result: "error", + code: "not_connected", + } satisfies ManageOutcome), + addListener: vi.fn().mockResolvedValue("listener-1"), + removeListener: vi.fn().mockResolvedValue(undefined), + listListeners: vi.fn().mockReturnValue([]), + shutdown: vi.fn().mockResolvedValue(undefined), + unref: vi.fn<() => void>(), + }; +} + +/** Reaches a private collaborator for a whitebox delegation check -- see the file header for why this cast is justified rather than avoided. Returns `unknown`; each call site casts to the narrow method slice it actually needs. */ +function collaborator(store: MeshStore, name: string): unknown { + return (store as unknown as Record)[name]; +} + +describe("MeshStore — requireTransport/requireIdentity guards", () => { + it("throws a specific error when a transport-using method is called before setTransport()", () => { + const store = new MeshStore(); + expect(() => store.listListeners()).toThrow( + "MeshStore: no transport set; call setTransport() before using the store", + ); + }); + + it("throws a specific error when an identity-using method is called before setIdentity()", async () => { + const store = new MeshStore(); + store.setTransport(fakeTransport()); + await expect( + store.createRoom({ + name: "r", + type: "public", + owner: VALID_DEVICE_ID, + description: "", + }), + ).rejects.toThrow( + "MeshStore: no identity set; call setIdentity() before using the store", + ); + }); +}); + +describe("MeshStore — connected getter", () => { + it("is true when the transport is the coordinator", () => { + const store = new MeshStore(); + const transport = fakeTransport(); + (transport as { isCoordinator: boolean }).isCoordinator = true; + store.setTransport(transport); + expect(store.connected).toBe(true); + }); + + it("is true when the transport has a live coordinator connection", () => { + const store = new MeshStore(); + const transport = fakeTransport(); + ( + transport as { hasCoordinatorConnection: boolean } + ).hasCoordinatorConnection = true; + store.setTransport(transport); + expect(store.connected).toBe(true); + }); + + it("is false when neither is true", () => { + const store = new MeshStore(); + store.setTransport(fakeTransport()); + expect(store.connected).toBe(false); + }); +}); + +describe("MeshStore — init()", () => { + it("starts the data server, records its own peer info, connects to an existing coordinator, and unrefs -- without becoming coordinator", async () => { + const store = new MeshStore(); + const transport = fakeTransport(); + store.setTransport(transport); + + await store.init(); + + expect(transport.startDataServer).toHaveBeenCalledTimes(1); + expect(transport.connectToCoordinator).toHaveBeenCalledTimes(1); + expect(transport.becomeCoordinator).not.toHaveBeenCalled(); + expect(transport.unref).toHaveBeenCalledTimes(1); + }); + + it("falls back to becoming coordinator when no existing coordinator is reachable", async () => { + const store = new MeshStore(); + const transport = fakeTransport(); + vi.mocked(transport.connectToCoordinator).mockRejectedValue( + new Error("ECONNREFUSED"), + ); + store.setTransport(transport); + const staleAgentChecker = collaborator(store, "staleAgentChecker") as { + start: ReturnType; + }; + const startSpy = vi.spyOn(staleAgentChecker, "start"); + + await store.init(); + + expect(transport.becomeCoordinator).toHaveBeenCalledTimes(1); + expect(startSpy).toHaveBeenCalledTimes(1); + expect(transport.unref).toHaveBeenCalledTimes(1); + }); + + it("degrades gracefully (no throw, onError fires) when becomeCoordinator fails with EADDRINUSE", async () => { + const store = new MeshStore(); + const transport = fakeTransport(); + vi.mocked(transport.connectToCoordinator).mockRejectedValue( + new Error("ECONNREFUSED"), + ); + vi.mocked(transport.becomeCoordinator).mockRejectedValue( + new Error("listen EADDRINUSE: address already in use"), + ); + store.setTransport(transport); + const onError = vi.fn<(error: Error) => void>(); + store.onError = onError; + + await expect(store.init()).resolves.toBeUndefined(); + + expect(onError).toHaveBeenCalledTimes(1); + expect(onError.mock.calls[0]?.[0]?.message).toContain( + "could not join or create mesh", + ); + expect(transport.unref).not.toHaveBeenCalled(); + }); + + it("rethrows a becomeCoordinator failure that isn't EADDRINUSE", async () => { + const store = new MeshStore(); + const transport = fakeTransport(); + vi.mocked(transport.connectToCoordinator).mockRejectedValue( + new Error("ECONNREFUSED"), + ); + vi.mocked(transport.becomeCoordinator).mockRejectedValue( + new Error("EPERM: permission denied"), + ); + store.setTransport(transport); + + await expect(store.init()).rejects.toThrow("EPERM"); + }); + + it("is idempotent -- a second call does nothing", async () => { + const store = new MeshStore(); + const transport = fakeTransport(); + store.setTransport(transport); + + await store.init(); + await store.init(); + + expect(transport.startDataServer).toHaveBeenCalledTimes(1); + }); +}); + +describe("MeshStore — events getter dispatch table", () => { + it("dispatches every transport event to the collaborator method that owns it", () => { + const store = new MeshStore(); + store.setTransport(fakeTransport()); + + const peerLifecycle = collaborator(store, "peerLifecycle") as { + handleDataMessage: ReturnType; + handlePeerConnected: ReturnType; + handlePeerDisconnected: ReturnType; + handleIntroduction: ReturnType; + handlePeerList: ReturnType; + handlePeerJoined: ReturnType; + handleBecomeCoordinator: ReturnType; + }; + const connectionApproval = collaborator(store, "connectionApproval") as { + handleConnectionRequest: ReturnType; + }; + const deliveryEngine = collaborator(store, "deliveryEngine") as { + handleRevocationAnnounce: ReturnType; + handlePresenceAdvert: ReturnType; + }; + + const spies = { + handleDataMessage: vi + .spyOn(peerLifecycle, "handleDataMessage") + .mockResolvedValue(undefined), + handlePeerConnected: vi + .spyOn(peerLifecycle, "handlePeerConnected") + .mockResolvedValue(undefined), + handlePeerDisconnected: vi + .spyOn(peerLifecycle, "handlePeerDisconnected") + .mockReturnValue(undefined), + handleIntroduction: vi + .spyOn(peerLifecycle, "handleIntroduction") + .mockResolvedValue(undefined), + handlePeerList: vi + .spyOn(peerLifecycle, "handlePeerList") + .mockReturnValue(undefined), + handlePeerJoined: vi + .spyOn(peerLifecycle, "handlePeerJoined") + .mockReturnValue(undefined), + handleBecomeCoordinator: vi + .spyOn(peerLifecycle, "handleBecomeCoordinator") + .mockResolvedValue(undefined), + handleConnectionRequest: vi + .spyOn(connectionApproval, "handleConnectionRequest") + .mockReturnValue(undefined), + handleRevocationAnnounce: vi + .spyOn(deliveryEngine, "handleRevocationAnnounce") + .mockResolvedValue(undefined), + handlePresenceAdvert: vi + .spyOn(deliveryEngine, "handlePresenceAdvert") + .mockReturnValue(undefined), + }; + + const handle: Readonly = { id: "conn-1" }; + const peer: Readonly = { + id: "peer-1", + port: 1, + startedAt: "2026-01-01T00:00:00.000Z", + }; + + store.events.onMessage(handle, { + method: "state_update", + patch: { type: "room_delete", roomId: "r" }, + }); + expect(spies.handleDataMessage).toHaveBeenCalledWith(handle, { + method: "state_update", + patch: { type: "room_delete", roomId: "r" }, + }); + + store.events.onPeerConnected(handle, peer); + expect(spies.handlePeerConnected).toHaveBeenCalledWith(handle, peer); + + store.events.onPeerDisconnected(handle); + expect(spies.handlePeerDisconnected).toHaveBeenCalledWith(handle); + + store.events.onIntroduction(handle, { peerId: "p", dataPort: 1 }); + expect(spies.handleIntroduction).toHaveBeenCalledWith(handle, { + peerId: "p", + dataPort: 1, + }); + + store.events.onPeerList([peer]); + expect(spies.handlePeerList).toHaveBeenCalledWith([peer]); + + store.events.onPeerJoined(peer); + expect(spies.handlePeerJoined).toHaveBeenCalledWith(peer); + + store.events.onBecomeCoordinator([peer]); + expect(spies.handleBecomeCoordinator).toHaveBeenCalledWith([peer]); + + store.events.onConnectionRequest(handle, { + peerId: "p", + dataPort: 1, + name: "n", + fingerprint: "fp", + }); + expect(spies.handleConnectionRequest).toHaveBeenCalledWith(handle, { + peerId: "p", + dataPort: 1, + name: "n", + fingerprint: "fp", + }); + + const revocationEntry = { + tokenId: new Uint8Array(), + issuer: new Uint8Array(), + revokedAt: 0, + }; + store.events.onRevocationAnnounce(revocationEntry as never); + expect(spies.handleRevocationAnnounce).toHaveBeenCalledWith( + revocationEntry, + ); + + store.events.onPresenceAdvert(handle, "active"); + expect(spies.handlePresenceAdvert).toHaveBeenCalledWith("conn-1", "active"); + }); + + it("forwards a transport-level error to this store's own onError, when one is set", () => { + const store = new MeshStore(); + store.setTransport(fakeTransport()); + const onError = vi.fn<(error: Error) => void>(); + store.onError = onError; + + const error = new Error("transport failure"); + store.events.onError?.(error); + + expect(onError).toHaveBeenCalledWith(error); + }); +}); + +describe("MeshStore — identity delegation", () => { + it("writeIdentity actually persists to the identity cache, readable back by readIdentity", async () => { + const store = new MeshStore(); + await store.writeIdentity("pi", "/tmp", "written-id"); + await expect(store.readIdentity("pi", "/tmp")).resolves.toEqual({ + id: "written-id", + }); + }); +}); + +describe("MeshStore — agent lifecycle delegation", () => { + it("setAgentOffline actually marks the agent offline in listAgents' own view", async () => { + const store = new MeshStore(); + store.setTransport(fakeTransport()); + const agent = await store.registerAgent({ + name: "a", + harness: "pi", + cwd: "/tmp", + pid: 1, + visibility: "visible", + tags: [], + }); + + await store.setAgentOffline(agent.id); + + const listed = await store.listAgents(agent.id); + expect(listed.find((a) => a.id === agent.id)?.status).toBe("offline"); + }); +}); + +describe("MeshStore — addListener policy validation", () => { + it("rejects an invalid policy naming the exact bad value, without ever touching the transport", async () => { + const store = new MeshStore(); + const transport = fakeTransport(); + store.setTransport(transport); + + await expect( + store.addListener("127.0.0.1", 0, "not-a-real-policy"), + ).rejects.toMatchObject({ + message: 'Invalid policy "not-a-real-policy"', + code: "INVALID_POLICY", + }); + expect(transport.addListener).not.toHaveBeenCalled(); + }); + + it.each(["full", "observe", "rooms-only", "gateway"] as const)( + "accepts the valid policy %s and forwards it to the transport", + async (policy) => { + const store = new MeshStore(); + const transport = fakeTransport(); + store.setTransport(transport); + + await store.addListener("127.0.0.1", 0, policy); + + expect(transport.addListener).toHaveBeenCalledWith( + "127.0.0.1", + 0, + policy, + ); + }, + ); +}); + +describe("MeshStore — room-join approval passthroughs", () => { + it("acceptRoomJoin/rejectRoomJoin/listPendingRoomJoins all reach the real RoomProtocol collaborator", () => { + const store = new MeshStore(); + store.setTransport(fakeTransport()); + const roomProtocol = collaborator(store, "roomProtocol") as { + acceptRoomJoin: ReturnType; + rejectRoomJoin: ReturnType; + listPendingRoomJoins: ReturnType; + }; + const acceptSpy = vi + .spyOn(roomProtocol, "acceptRoomJoin") + .mockReturnValue(undefined); + const rejectSpy = vi + .spyOn(roomProtocol, "rejectRoomJoin") + .mockReturnValue(undefined); + const listSpy = vi + .spyOn(roomProtocol, "listPendingRoomJoins") + .mockReturnValue([]); + + store.acceptRoomJoin("room-path", "requester"); + expect(acceptSpy).toHaveBeenCalledWith("room-path", "requester"); + + store.rejectRoomJoin("room-path", "requester", "no thanks"); + expect(rejectSpy).toHaveBeenCalledWith( + "room-path", + "requester", + "no thanks", + ); + + store.listPendingRoomJoins(); + expect(listSpy).toHaveBeenCalledTimes(1); + }); + + it("connectToRemote reaches the real ConnectionApproval collaborator", async () => { + const store = new MeshStore(); + store.setTransport(fakeTransport()); + const connectionApproval = collaborator(store, "connectionApproval") as { + connectToRemote: ReturnType; + }; + const spy = vi + .spyOn(connectionApproval, "connectToRemote") + .mockResolvedValue(undefined); + + await store.connectToRemote("example.test", REMOTE_PORT); + + expect(spy).toHaveBeenCalledWith("example.test", REMOTE_PORT); + }); +}); + +describe("MeshStore — federation passthroughs", () => { + it("forwards fedConnect/fedDisconnect/fedLinks/fedTrust/fedUntrust/fedTrustedFingerprints/fedListen/fedStopListening to the real, public federation manager", async () => { + const store = new MeshStore(); + store.setTransport(fakeTransport()); + + const connectSpy = vi + .spyOn(store.federation, "connect") + .mockResolvedValue("link-1"); + await expect(store.fedConnect("host", 1, "name")).resolves.toBe("link-1"); + expect(connectSpy).toHaveBeenCalledWith("host", 1, "name"); + + const disconnectSpy = vi + .spyOn(store.federation, "disconnect") + .mockResolvedValue(undefined); + await store.fedDisconnect("link-1"); + expect(disconnectSpy).toHaveBeenCalledWith("link-1"); + + const linksSpy = vi + .spyOn(store.federation, "listLinks") + .mockReturnValue([]); + store.fedLinks(); + expect(linksSpy).toHaveBeenCalledTimes(1); + + const trustSpy = vi + .spyOn(store.federation, "addTrustedFingerprint") + .mockReturnValue(undefined); + await store.fedTrust("fingerprint-a"); + expect(trustSpy).toHaveBeenCalledWith("fingerprint-a"); + + const untrustSpy = vi + .spyOn(store.federation, "removeTrustedFingerprint") + .mockReturnValue(undefined); + await store.fedUntrust("fingerprint-a"); + expect(untrustSpy).toHaveBeenCalledWith("fingerprint-a"); + + const listTrustedSpy = vi + .spyOn(store.federation, "listTrustedFingerprints") + .mockReturnValue([]); + store.fedTrustedFingerprints(); + expect(listTrustedSpy).toHaveBeenCalledTimes(1); + + const listenSpy = vi + .spyOn(store.federation, "listen") + .mockResolvedValue(undefined); + await store.fedListen("host", 2); + expect(listenSpy).toHaveBeenCalledWith("host", 2); + + const stopListeningSpy = vi + .spyOn(store.federation, "stopListening") + .mockResolvedValue(undefined); + await store.fedStopListening(); + expect(stopListeningSpy).toHaveBeenCalledTimes(1); + }); +}); + +describe("MeshStore — shutdown()", () => { + let store: MeshStore; + let transport: ReturnType; + + beforeEach(() => { + store = new MeshStore(); + transport = fakeTransport(); + store.setTransport(transport); + }); + + it("stops the stale-agent checker, shuts down federation, and shuts down the transport", async () => { + const staleAgentChecker = collaborator(store, "staleAgentChecker") as { + stop: ReturnType; + }; + const stopSpy = vi.spyOn(staleAgentChecker, "stop"); + const federationShutdownSpy = vi + .spyOn(store.federation, "shutdown") + .mockResolvedValue(undefined); + + await store.shutdown(); + + expect(stopSpy).toHaveBeenCalledTimes(1); + expect(federationShutdownSpy).toHaveBeenCalledTimes(1); + expect(transport.shutdown).toHaveBeenCalledTimes(1); + }); + + it("broadcasts agent_offline for its own self agent when one is registered", async () => { + vi.spyOn(store.federation, "shutdown").mockResolvedValue(undefined); + const agent = await store.registerAgent({ + name: "self", + harness: "pi", + cwd: "/tmp", + pid: 1, + visibility: "visible", + tags: [], + }); + store.peerId = agent.id; + const deliveryEngine = collaborator(store, "deliveryEngine") as { + broadcastPatch: ReturnType; + }; + const broadcastSpy = vi + .spyOn(deliveryEngine, "broadcastPatch") + .mockResolvedValue(undefined); + + await store.shutdown(); + + expect(broadcastSpy).toHaveBeenCalledWith({ + type: "agent_offline", + agentId: agent.id, + }); + }); + + it("does not broadcast agent_offline when no self agent was ever registered", async () => { + vi.spyOn(store.federation, "shutdown").mockResolvedValue(undefined); + const deliveryEngine = collaborator(store, "deliveryEngine") as { + broadcastPatch: ReturnType; + }; + const broadcastSpy = vi + .spyOn(deliveryEngine, "broadcastPatch") + .mockResolvedValue(undefined); + + await store.shutdown(); + + expect(broadcastSpy).not.toHaveBeenCalled(); + }); +}); From bec92a18ceccf1336cdaacbbdf7370738f840fce Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Tue, 15 Sep 2026 12:17:56 +0100 Subject: [PATCH 2/4] test(mesh-store): close four more real gaps a fresh mutation run surfaced Verified against a real run rather than trusting the prior commit's own unverified claim about what remained (which named the wrong survivors entirely -- neither of the two it named was actually still open). The real gaps: constructor wiring for both discovery backends (observable via discovery.advertise's own "Available:" error message), the getOnPatch closure passed to DeliveryEngine (observable via a real broadcastPatch call), ConnectionApproval's queueDelivery closure and MeshStore.deliver()'s own delegation (both observable via drainDelivery picking up the queued event), and shutdown()'s pending-markRead-timer clearing loop. Two survivors remain genuinely open, left for follow-up rather than forced: FederationManager's own meshName string (needs a real two-way federation connection to observe, the kind of setup federation.integration.test.ts already has but doesn't currently assert this specific field against), and a handful of Timeout-classified mutants inside init()'s branches and the events getter that this file's own new tests do correctly fail fast against, but where the whole command-runner suite still doesn't exit within budget for an unrelated reason -- timeouts already count as caught for scoring purposes, so these don't block the threshold, only slow the run. --- src/test/mesh-store-orchestration.test.ts | 85 +++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/test/mesh-store-orchestration.test.ts b/src/test/mesh-store-orchestration.test.ts index 5a2de341..27fbb91c 100644 --- a/src/test/mesh-store-orchestration.test.ts +++ b/src/test/mesh-store-orchestration.test.ts @@ -308,6 +308,71 @@ describe("MeshStore — events getter dispatch table", () => { }); }); +describe("MeshStore — constructor wiring", () => { + it("registers both the mdns and tailscale discovery backends", async () => { + const store = new MeshStore(); + await expect( + store.discovery.advertise("not-a-real-backend", { name: "x", port: 1 }), + ).rejects.toThrow("Available: mdns, tailscale"); + }); + + it("fires onPatch when a broadcasted patch reaches it, via the getOnPatch closure passed to DeliveryEngine", async () => { + const store = new MeshStore(); + store.setTransport(fakeTransport()); + const onPatch = vi.fn<(patch: unknown) => void>(); + store.onPatch = onPatch; + + await store.registerAgent({ + name: "a", + harness: "pi", + cwd: "/tmp", + pid: 1, + visibility: "visible", + tags: [], + }); + + expect(onPatch).toHaveBeenCalledWith( + expect.objectContaining({ type: "agent_upsert" }), + ); + }); + + it("wires ConnectionApproval's queueDelivery closure to the real DeliveryEngine, observable via drainDelivery", async () => { + const store = new MeshStore(); + store.setTransport(fakeTransport()); + + store.events.onConnectionRequest( + { id: "conn-1" }, + { peerId: "remote", dataPort: 1, name: "n", fingerprint: "fp" }, + ); + + const drained = await store.drainDelivery(store.peerId); + expect(drained).toContainEqual( + expect.objectContaining({ + type: "connection_request", + connectionId: "conn-1", + }), + ); + }); + + it("deliver() actually reaches the real DeliveryEngine, observable via drainDelivery", async () => { + const store = new MeshStore(); + store.setTransport(fakeTransport()); + const event = { + type: "connection_request" as const, + connectionId: "c", + peerId: "p", + dataPort: 1, + name: "n", + fingerprint: "fp", + }; + + await store.deliver(store.peerId, event); + + const drained = await store.drainDelivery(store.peerId); + expect(drained).toContainEqual(event); + }); +}); + describe("MeshStore — identity delegation", () => { it("writeIdentity actually persists to the identity cache, readable back by readIdentity", async () => { const store = new MeshStore(); @@ -527,6 +592,26 @@ describe("MeshStore — shutdown()", () => { }); }); + it("clears every pending markRead timer", async () => { + vi.spyOn(store.federation, "shutdown").mockResolvedValue(undefined); + const pending = collaborator(store, "pendingMarkReadTimers") as ReturnType< + typeof setTimeout + >[]; + // Long enough to guarantee it's still pending (never fires) for the duration of this test. + const FAR_FUTURE_DELAY_MS = 1_000_000; + const timer = setTimeout(() => undefined, FAR_FUTURE_DELAY_MS); + pending.push(timer); + const clearTimeoutSpy = vi.spyOn(global, "clearTimeout"); + + try { + await store.shutdown(); + expect(clearTimeoutSpy).toHaveBeenCalledWith(timer); + expect(pending).toHaveLength(0); + } finally { + clearTimeoutSpy.mockRestore(); + } + }); + it("does not broadcast agent_offline when no self agent was ever registered", async () => { vi.spyOn(store.federation, "shutdown").mockResolvedValue(undefined); const deliveryEngine = collaborator(store, "deliveryEngine") as { From 4ffaf9f89201dd06b29b8a119b50613ecbaf1020 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Tue, 15 Sep 2026 12:53:24 +0100 Subject: [PATCH 3/4] test(mesh-store): close two more real gaps, init()'s onError message and isShutDown Verified against a fresh mutation run: the EADDRINUSE-degrade onError message assertion only checked its first half, missing a mutant on the second half's own string literal. shutdown()'s isShutDown = true flip had no assertion at all -- fixed via its one observable effect (fireLocalDelivery's own isShutDown() guard on scheduling further markRead timers) rather than reaching into the private field directly. One survivor remains genuinely open: FederationManager's meshName string, which needs a real two-way federation connection to observe -- left for follow-up rather than forced with a contrived unit test. --- src/test/mesh-store-orchestration.test.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/mesh-store-orchestration.test.ts b/src/test/mesh-store-orchestration.test.ts index 27fbb91c..2e68b28e 100644 --- a/src/test/mesh-store-orchestration.test.ts +++ b/src/test/mesh-store-orchestration.test.ts @@ -147,6 +147,9 @@ describe("MeshStore — init()", () => { expect(onError.mock.calls[0]?.[0]?.message).toContain( "could not join or create mesh", ); + expect(onError.mock.calls[0]?.[0]?.message).toContain( + "Running without mesh — agent-comms will be unavailable.", + ); expect(transport.unref).not.toHaveBeenCalled(); }); @@ -612,6 +615,26 @@ describe("MeshStore — shutdown()", () => { } }); + it("actually sets isShutDown, observable via DeliveryEngine no longer scheduling markRead timers afterward", async () => { + vi.spyOn(store.federation, "shutdown").mockResolvedValue(undefined); + await store.shutdown(); + + const pending = collaborator(store, "pendingMarkReadTimers") as unknown[]; + await store.deliver(store.peerId, { + type: "room_message", + message: { + id: "m", + from: "a", + room: "r", + content: "hi", + timestamp: "2026-01-01T00:00:00.000Z", + readBy: [], + }, + }); + + expect(pending).toHaveLength(0); + }); + it("does not broadcast agent_offline when no self agent was ever registered", async () => { vi.spyOn(store.federation, "shutdown").mockResolvedValue(undefined); const deliveryEngine = collaborator(store, "deliveryEngine") as { From 1314c8c9c2472ffab1b3d6a7b620efcf1cc1bbea Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Tue, 15 Sep 2026 13:28:47 +0100 Subject: [PATCH 4/4] test(mesh-store): fix isShutDown test to actually reach the guarded branch Verified against a fresh mutation run the previous commit's own isShutDown test still survived -- fireLocalDelivery returns before ever reaching the isShutDown-guarded timer push unless onDelivery is set, so the assertion never actually exercised the line it claimed to cover. Fixed by setting store.onDelivery, then confirmed directly: with this.isShutDown = true manually flipped to false in the source, the test now genuinely fails (pending length 1 instead of 0), and passes against the real code -- proof the fix actually distinguishes the two, not just that it was plausible. --- src/test/mesh-store-orchestration.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/mesh-store-orchestration.test.ts b/src/test/mesh-store-orchestration.test.ts index 2e68b28e..3a776495 100644 --- a/src/test/mesh-store-orchestration.test.ts +++ b/src/test/mesh-store-orchestration.test.ts @@ -616,6 +616,8 @@ describe("MeshStore — shutdown()", () => { }); it("actually sets isShutDown, observable via DeliveryEngine no longer scheduling markRead timers afterward", async () => { + // fireLocalDelivery returns before ever reaching the isShutDown-guarded push unless onDelivery is set -- without this, the test would pass for both real code and a mutant, since it never reaches the line under test. + store.onDelivery = vi.fn(); vi.spyOn(store.federation, "shutdown").mockResolvedValue(undefined); await store.shutdown();