agent-comms 3.16.0 → 3.17.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/test/port-discovery.unit.test.js +55 -13
- package/dist/bridges/user/web/test/port-discovery.unit.test.js.map +1 -1
- package/dist/core/bridge.d.ts +1 -0
- package/dist/core/bridge.d.ts.map +1 -1
- package/dist/core/bridge.js +12 -2
- package/dist/core/bridge.js.map +1 -1
- package/dist/core/gateway-trust-actions.d.ts +18 -0
- package/dist/core/gateway-trust-actions.d.ts.map +1 -0
- package/dist/core/gateway-trust-actions.js +70 -0
- package/dist/core/gateway-trust-actions.js.map +1 -0
- package/dist/core/hub-session.d.ts +18 -2
- package/dist/core/hub-session.d.ts.map +1 -1
- package/dist/core/hub-session.js +67 -47
- package/dist/core/hub-session.js.map +1 -1
- package/dist/core/mesh-store.d.ts +6 -0
- package/dist/core/mesh-store.d.ts.map +1 -1
- package/dist/core/mesh-store.js +12 -0
- package/dist/core/mesh-store.js.map +1 -1
- package/dist/core/tool.d.ts +3 -3
- package/dist/core/tool.d.ts.map +1 -1
- package/dist/core/tool.js +4 -48
- package/dist/core/tool.js.map +1 -1
- package/dist/core/types.d.ts +4 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +4 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/wire-mesh-transport.d.ts +1 -1
- package/dist/core/wire-mesh-transport.d.ts.map +1 -1
- package/dist/core/wire-mesh-transport.js +3 -1
- package/dist/core/wire-mesh-transport.js.map +1 -1
- package/dist/test/gateway-trust-tool.test.js +98 -1
- package/dist/test/gateway-trust-tool.test.js.map +1 -1
- package/dist/test/hub-mode-session.integration.test.js +23 -0
- package/dist/test/hub-mode-session.integration.test.js.map +1 -1
- package/dist/test/hub-room-domain-verb-trust-bypass.integration.test.d.ts +7 -0
- package/dist/test/hub-room-domain-verb-trust-bypass.integration.test.d.ts.map +1 -0
- package/dist/test/hub-room-domain-verb-trust-bypass.integration.test.js +93 -0
- package/dist/test/hub-room-domain-verb-trust-bypass.integration.test.js.map +1 -0
- package/dist/test/hub-session-dispatch.test.d.ts +5 -0
- package/dist/test/hub-session-dispatch.test.d.ts.map +1 -0
- package/dist/test/hub-session-dispatch.test.js +223 -0
- package/dist/test/hub-session-dispatch.test.js.map +1 -0
- package/dist/test/test-transport.d.ts +6 -0
- package/dist/test/test-transport.d.ts.map +1 -1
- package/dist/test/test-transport.js +12 -2
- package/dist/test/test-transport.js.map +1 -1
- package/package.json +1 -1
|
@@ -73,6 +73,29 @@ describe("connectToHub", () => {
|
|
|
73
73
|
await transportA.shutdown();
|
|
74
74
|
await transportB.shutdown();
|
|
75
75
|
});
|
|
76
|
+
it("discovers a peer via gossip when that peer is trusted only as a principal, not as a bare device (agent-comms#192's own directory-merge widening)", async () => {
|
|
77
|
+
const hub = await realHubOverWs();
|
|
78
|
+
cleanups.push(hub.close);
|
|
79
|
+
const eventsA = recordingEvents();
|
|
80
|
+
const eventsB = recordingEvents();
|
|
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
|
+
// B trusts A's device as a PRINCIPAL (addPrincipal), never on the bare-device allowlist (add) -- proving connect()'s own directory-merge filter now accepts isTrustedForDirectory (bare-device OR principal), not only the original bare-device isTrusted. A trusts nothing at all: whether B's own gossip surfaces here has nothing to do with what A trusts, only with what B's own incoming filter accepts.
|
|
86
|
+
const gatewayTrustA = new GatewayTrust();
|
|
87
|
+
const gatewayTrustB = new GatewayTrust();
|
|
88
|
+
gatewayTrustB.addPrincipal(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);
|
|
91
|
+
await transportA.hub.connect(hub.url);
|
|
92
|
+
await transportB.hub.connect(hub.url);
|
|
93
|
+
await waitForCondition(() => transportB.hub.peers().includes(deviceA));
|
|
94
|
+
// The bare-device allowlist is untouched by this widening: A was never added() to gatewayTrustB, only addPrincipal()'d, so isTrusted(deviceA) itself must still read false even though isTrustedForDirectory let the gossip through.
|
|
95
|
+
expect(gatewayTrustB.isTrusted(deviceA)).toBe(false);
|
|
96
|
+
await transportA.shutdown();
|
|
97
|
+
await transportB.shutdown();
|
|
98
|
+
});
|
|
76
99
|
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 () => {
|
|
77
100
|
const hub = await realHubOverWs();
|
|
78
101
|
cleanups.push(hub.close);
|
|
@@ -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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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end proof of agent-comms#192 over a real wire-mesh relay hub (the same domain logic the production mesh.exadev.io Durable Object runs, served over local WebSockets via hub-helpers.ts): a real room.join from a device the receiving gateway's own GatewayTrust does NOT trust reaches the deliberate human-approval flow instead of being rejected outright by the coarse bare-device gateway allowlist. Under the pre-#192 code, the owner's own consume() would answer this request with an immediate unauthorized outcome, and owner.listPendingRoomJoins() would never show it at all.
|
|
3
|
+
*
|
|
4
|
+
* Only a hub connection between owner and requester is ever established, deliberately never a direct local peer connection: hub mode carries no legacy full-state-sync (room-join-admission.test.ts's own header comment explains why that path makes "a room I've never heard of" untestable over an ordinary two-peer local mesh), so this is the one topology where the requester genuinely has never heard of the owner's room before sending a real wire-level room.join for it.
|
|
5
|
+
*/
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=hub-room-domain-verb-trust-bypass.integration.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub-room-domain-verb-trust-bypass.integration.test.d.ts","sourceRoot":"","sources":["../../src/test/hub-room-domain-verb-trust-bypass.integration.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end proof of agent-comms#192 over a real wire-mesh relay hub (the same domain logic the production mesh.exadev.io Durable Object runs, served over local WebSockets via hub-helpers.ts): a real room.join from a device the receiving gateway's own GatewayTrust does NOT trust reaches the deliberate human-approval flow instead of being rejected outright by the coarse bare-device gateway allowlist. Under the pre-#192 code, the owner's own consume() would answer this request with an immediate unauthorized outcome, and owner.listPendingRoomJoins() would never show it at all.
|
|
3
|
+
*
|
|
4
|
+
* Only a hub connection between owner and requester is ever established, deliberately never a direct local peer connection: hub mode carries no legacy full-state-sync (room-join-admission.test.ts's own header comment explains why that path makes "a room I've never heard of" untestable over an ordinary two-peer local mesh), so this is the one topology where the requester genuinely has never heard of the owner's room before sending a real wire-level room.join for it.
|
|
5
|
+
*/
|
|
6
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
7
|
+
import { MeshStore } from "../core/mesh-store.js";
|
|
8
|
+
import { wireTestTransportWithHub } from "./test-transport.js";
|
|
9
|
+
import { realHubOverWs, waitForCondition } from "./hub-helpers.js";
|
|
10
|
+
const cleanups = [];
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
for (const close of cleanups.splice(0)) {
|
|
13
|
+
await close();
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
/** Wires up an owner and a requester MeshStore, each connected to the same real hub, with the requester trusting the owner's device (the outbound leg WireMeshTransport.sendRoomRequest needs before it will even attempt routing via the hub) but the owner trusting nothing at all -- the absence that is the whole point of every test in this file. Deliberately never calls MeshStore.init(): that method's own local-mesh coordinator election (connectToCoordinator/becomeCoordinator against the real, well-known port 19876) has nothing to do with hub mode and risks colliding with an unrelated coordinator already running on the machine -- hub-mode-session.integration.test.ts's own raw-WireMeshTransport tests never call it either, for the same reason. */
|
|
17
|
+
async function connectedOwnerAndRequester(hubUrl) {
|
|
18
|
+
const owner = new MeshStore();
|
|
19
|
+
const { transport: ownerTransport } = await wireTestTransportWithHub(owner);
|
|
20
|
+
await owner.registerAgent({
|
|
21
|
+
name: "owner",
|
|
22
|
+
harness: "test",
|
|
23
|
+
cwd: "/test/owner",
|
|
24
|
+
pid: process.pid,
|
|
25
|
+
visibility: "visible",
|
|
26
|
+
tags: [],
|
|
27
|
+
});
|
|
28
|
+
const requester = new MeshStore();
|
|
29
|
+
const { transport: requesterTransport } = await wireTestTransportWithHub(requester);
|
|
30
|
+
await requester.registerAgent({
|
|
31
|
+
name: "requester",
|
|
32
|
+
harness: "test",
|
|
33
|
+
cwd: "/test/requester",
|
|
34
|
+
pid: process.pid,
|
|
35
|
+
visibility: "visible",
|
|
36
|
+
tags: [],
|
|
37
|
+
});
|
|
38
|
+
requester.gatewayTrust.add(owner.peerId);
|
|
39
|
+
expect(owner.gatewayTrust.hasAny()).toBe(false);
|
|
40
|
+
await ownerTransport.connectHub?.(hubUrl);
|
|
41
|
+
await requesterTransport.connectHub?.(hubUrl);
|
|
42
|
+
await waitForCondition(() => ownerTransport.hub.isConnected && requesterTransport.hub.isConnected);
|
|
43
|
+
return { owner, requester };
|
|
44
|
+
}
|
|
45
|
+
describe("hub-relayed room.join versus the gateway trust boundary", () => {
|
|
46
|
+
it("reaches the owner's human-approval flow, and grants membership on acceptance, even though the owner's gateway does not trust the requester's device at all", async () => {
|
|
47
|
+
const hub = await realHubOverWs();
|
|
48
|
+
cleanups.push(hub.close);
|
|
49
|
+
const { owner, requester } = await connectedOwnerAndRequester(hub.url);
|
|
50
|
+
const room = await owner.createRoom({
|
|
51
|
+
name: "general",
|
|
52
|
+
type: "public",
|
|
53
|
+
owner: owner.peerId,
|
|
54
|
+
description: "",
|
|
55
|
+
});
|
|
56
|
+
expect(await requester.getRoom(room.id)).toBeUndefined();
|
|
57
|
+
const joinPromise = requester.joinRoom(room.id, requester.peerId);
|
|
58
|
+
await waitForCondition(() => owner
|
|
59
|
+
.listPendingRoomJoins()
|
|
60
|
+
.some((pending) => pending.roomPath === room.id &&
|
|
61
|
+
pending.requesterId === requester.peerId));
|
|
62
|
+
owner.acceptRoomJoin(room.id, requester.peerId);
|
|
63
|
+
const joined = await joinPromise;
|
|
64
|
+
expect(joined.id).toBe(room.id);
|
|
65
|
+
expect(joined.members.includes(requester.peerId)).toBe(true);
|
|
66
|
+
// hubPeersKnown (peers()) stays "gateway-trusted hub peers" even after a real, successful room-domain admission: the requester's own device was never on the owner's bare-device allowlist, only its capability token was ever verified, so it must never surface as a "known" hub peer just because a room-domain request from it happened to succeed.
|
|
67
|
+
expect(owner.gatewayTrust.hasAny()).toBe(false);
|
|
68
|
+
await requester.shutdown();
|
|
69
|
+
await owner.shutdown();
|
|
70
|
+
});
|
|
71
|
+
it("still lets the owner reject the same untrusted-gateway request through the ordinary human-decision outcome, not a gateway-level error", async () => {
|
|
72
|
+
const hub = await realHubOverWs();
|
|
73
|
+
cleanups.push(hub.close);
|
|
74
|
+
const { owner, requester } = await connectedOwnerAndRequester(hub.url);
|
|
75
|
+
const room = await owner.createRoom({
|
|
76
|
+
name: "private-room",
|
|
77
|
+
type: "public",
|
|
78
|
+
owner: owner.peerId,
|
|
79
|
+
description: "",
|
|
80
|
+
});
|
|
81
|
+
const joinPromise = requester.joinRoom(room.id, requester.peerId);
|
|
82
|
+
await waitForCondition(() => owner
|
|
83
|
+
.listPendingRoomJoins()
|
|
84
|
+
.some((pending) => pending.roomPath === room.id &&
|
|
85
|
+
pending.requesterId === requester.peerId));
|
|
86
|
+
owner.rejectRoomJoin(room.id, requester.peerId, "not today");
|
|
87
|
+
await expect(joinPromise).rejects.toThrow();
|
|
88
|
+
expect(await requester.getRoom(room.id)).toBeUndefined();
|
|
89
|
+
await requester.shutdown();
|
|
90
|
+
await owner.shutdown();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=hub-room-domain-verb-trust-bypass.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub-room-domain-verb-trust-bypass.integration.test.js","sourceRoot":"","sources":["../../src/test/hub-room-domain-verb-trust-bypass.integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for dispatchHubRequest (agent-comms#192): the per-request trust decision hub-session.ts's own consume() loop delegates to, exercised directly against fake requests and fake deps rather than a real hub connection, mirroring hub-forwarding.test.ts's own fake-object approach for the sibling gateway-trust gates. hub-mode-session.integration.test.ts already proves the legacy FRAME_VERB gate end to end over a real hub; this file is what actually exercises the fix itself, that a real room-domain verb (room.send, room.join, room.notify, ...) is no longer rejected by the coarse per-device isTrusted allowlist at all, and the edge case that gate's removal would otherwise expose: a request with no fromDevice at all still has to be refused before ever reaching a room-verb handler, since resolveHandle/verifyRoomToken would call deviceIdFromHex on a non-hex placeholder and throw synchronously rather than answering with an ordinary unauthorized outcome.
|
|
3
|
+
*/
|
|
4
|
+
export {};
|
|
5
|
+
//# sourceMappingURL=hub-session-dispatch.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub-session-dispatch.test.d.ts","sourceRoot":"","sources":["../../src/test/hub-session-dispatch.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for dispatchHubRequest (agent-comms#192): the per-request trust decision hub-session.ts's own consume() loop delegates to, exercised directly against fake requests and fake deps rather than a real hub connection, mirroring hub-forwarding.test.ts's own fake-object approach for the sibling gateway-trust gates. hub-mode-session.integration.test.ts already proves the legacy FRAME_VERB gate end to end over a real hub; this file is what actually exercises the fix itself, that a real room-domain verb (room.send, room.join, room.notify, ...) is no longer rejected by the coarse per-device isTrusted allowlist at all, and the edge case that gate's removal would otherwise expose: a request with no fromDevice at all still has to be refused before ever reaching a room-verb handler, since resolveHandle/verifyRoomToken would call deviceIdFromHex on a non-hex placeholder and throw synchronously rather than answering with an ordinary unauthorized outcome.
|
|
3
|
+
*/
|
|
4
|
+
import { describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { deviceIdToHex } from "wire-mesh-core/domain/device-id";
|
|
6
|
+
import { dispatchHubRequest } from "../core/hub-session.js";
|
|
7
|
+
import { FRAME_VERB } from "../core/wire-mesh-transport.js";
|
|
8
|
+
const DEVICE_ID_HEX_LENGTH = 64;
|
|
9
|
+
const SENDER_HEX = "a".repeat(DEVICE_ID_HEX_LENGTH);
|
|
10
|
+
const OWN_HEX = "b".repeat(DEVICE_ID_HEX_LENGTH);
|
|
11
|
+
const OTHER_LOCAL_PEER_HEX = "c".repeat(DEVICE_ID_HEX_LENGTH);
|
|
12
|
+
function deviceIdBytes(hex) {
|
|
13
|
+
const bytes = new Uint8Array(new ArrayBuffer(hex.length / 2));
|
|
14
|
+
for (let i = 0; i < bytes.length; i += 1) {
|
|
15
|
+
bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
16
|
+
}
|
|
17
|
+
// A fixture device-id: the real DeviceId type wire-mesh-core mints only through its own deviceIdFromHex/generateIdentity is structurally just a Uint8Array of the right length, and every dispatchHubRequest call site only ever round-trips this value back through deviceIdToHex, so a plain byte array is a faithful stand-in for a test fixture with no cast needed.
|
|
18
|
+
return bytes;
|
|
19
|
+
}
|
|
20
|
+
function fakeOnKnownPeer() {
|
|
21
|
+
return vi.fn();
|
|
22
|
+
}
|
|
23
|
+
function noopEvents() {
|
|
24
|
+
return {
|
|
25
|
+
onMessage: () => undefined,
|
|
26
|
+
onPeerConnected: () => undefined,
|
|
27
|
+
onPeerDisconnected: () => undefined,
|
|
28
|
+
onIntroduction: () => undefined,
|
|
29
|
+
onConnectionRequest: () => undefined,
|
|
30
|
+
onPeerList: () => undefined,
|
|
31
|
+
onPeerJoined: () => undefined,
|
|
32
|
+
onBecomeCoordinator: () => undefined,
|
|
33
|
+
onRevocationAnnounce: () => undefined,
|
|
34
|
+
onPresenceAdvert: () => undefined,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function fakeRequest(options) {
|
|
38
|
+
const responses = [];
|
|
39
|
+
const scope = { kind: "room", path: "owner/room" };
|
|
40
|
+
const request = {
|
|
41
|
+
requestId: 1,
|
|
42
|
+
command: { verb: options.verb ?? "room:member", params: {} },
|
|
43
|
+
scope,
|
|
44
|
+
...(options.fromDevice !== undefined
|
|
45
|
+
? { fromDevice: deviceIdBytes(options.fromDevice) }
|
|
46
|
+
: {}),
|
|
47
|
+
...(options.toDevice !== undefined
|
|
48
|
+
? { toDevice: deviceIdBytes(options.toDevice) }
|
|
49
|
+
: {}),
|
|
50
|
+
respond: async (outcome) => {
|
|
51
|
+
responses.push(outcome);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
return { request, responses };
|
|
55
|
+
}
|
|
56
|
+
function fakeDeps(overrides = {}) {
|
|
57
|
+
const messages = [];
|
|
58
|
+
const events = {
|
|
59
|
+
...noopEvents(),
|
|
60
|
+
messages,
|
|
61
|
+
onMessage: (_handle, message) => {
|
|
62
|
+
messages.push(message);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
isTrusted: () => false,
|
|
67
|
+
events,
|
|
68
|
+
handleRoomRequest: vi.fn().mockResolvedValue(undefined),
|
|
69
|
+
forwardToLocalPeer: () => undefined,
|
|
70
|
+
...overrides,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
describe("dispatchHubRequest", () => {
|
|
74
|
+
it("drops a FRAME_VERB request with no fromDevice, responding ok, without ever calling onMessage", async () => {
|
|
75
|
+
const { request, responses } = fakeRequest({ verb: FRAME_VERB });
|
|
76
|
+
const deps = fakeDeps();
|
|
77
|
+
const onKnownPeer = fakeOnKnownPeer();
|
|
78
|
+
await dispatchHubRequest(request, OWN_HEX, deps, onKnownPeer);
|
|
79
|
+
expect(responses).toEqual([{ result: "ok" }]);
|
|
80
|
+
expect(deps.events.messages).toEqual([]);
|
|
81
|
+
expect(onKnownPeer).not.toHaveBeenCalled();
|
|
82
|
+
});
|
|
83
|
+
it("refuses a room-domain verb with no fromDevice with an ordinary unauthorized outcome, never dispatching to handleRoomRequest", async () => {
|
|
84
|
+
const { request, responses } = fakeRequest({ verb: "room:member" });
|
|
85
|
+
const deps = fakeDeps();
|
|
86
|
+
const onKnownPeer = fakeOnKnownPeer();
|
|
87
|
+
await dispatchHubRequest(request, OWN_HEX, deps, onKnownPeer);
|
|
88
|
+
expect(responses).toEqual([{ result: "error", code: "unauthorized" }]);
|
|
89
|
+
expect(deps.handleRoomRequest).not.toHaveBeenCalled();
|
|
90
|
+
expect(onKnownPeer).not.toHaveBeenCalled();
|
|
91
|
+
});
|
|
92
|
+
it("drops a FRAME_VERB request from an untrusted device, responding ok, without calling onMessage", async () => {
|
|
93
|
+
const { request, responses } = fakeRequest({
|
|
94
|
+
verb: FRAME_VERB,
|
|
95
|
+
fromDevice: SENDER_HEX,
|
|
96
|
+
});
|
|
97
|
+
const deps = fakeDeps({ isTrusted: () => false });
|
|
98
|
+
const onKnownPeer = fakeOnKnownPeer();
|
|
99
|
+
await dispatchHubRequest(request, OWN_HEX, deps, onKnownPeer);
|
|
100
|
+
expect(responses).toEqual([{ result: "ok" }]);
|
|
101
|
+
expect(deps.events.messages).toEqual([]);
|
|
102
|
+
expect(onKnownPeer).not.toHaveBeenCalled();
|
|
103
|
+
});
|
|
104
|
+
it("delivers a FRAME_VERB request from a trusted device to onMessage and records it as a known hub peer", async () => {
|
|
105
|
+
const message = {
|
|
106
|
+
method: "peer_joined",
|
|
107
|
+
peer: { id: "hi", port: 0, startedAt: "2026-01-01T00:00:00.000Z" },
|
|
108
|
+
};
|
|
109
|
+
const { request, responses } = fakeRequest({
|
|
110
|
+
verb: FRAME_VERB,
|
|
111
|
+
fromDevice: SENDER_HEX,
|
|
112
|
+
});
|
|
113
|
+
request.command.params = { message };
|
|
114
|
+
const deps = fakeDeps({ isTrusted: (hex) => hex === SENDER_HEX });
|
|
115
|
+
const onKnownPeer = fakeOnKnownPeer();
|
|
116
|
+
await dispatchHubRequest(request, OWN_HEX, deps, onKnownPeer);
|
|
117
|
+
expect(responses).toEqual([{ result: "ok" }]);
|
|
118
|
+
expect(deps.events.messages).toEqual([message]);
|
|
119
|
+
expect(onKnownPeer).toHaveBeenCalledWith(SENDER_HEX);
|
|
120
|
+
});
|
|
121
|
+
it("never delivers a state_sync or state_update from a trusted device to onMessage (agent-comms#169)", async () => {
|
|
122
|
+
const { request, responses } = fakeRequest({
|
|
123
|
+
verb: FRAME_VERB,
|
|
124
|
+
fromDevice: SENDER_HEX,
|
|
125
|
+
});
|
|
126
|
+
request.command.params = {
|
|
127
|
+
message: {
|
|
128
|
+
method: "state_update",
|
|
129
|
+
patch: { type: "agent_offline", agentId: "spoofed" },
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
const deps = fakeDeps({ isTrusted: () => true });
|
|
133
|
+
await dispatchHubRequest(request, OWN_HEX, deps, fakeOnKnownPeer());
|
|
134
|
+
expect(responses).toEqual([{ result: "ok" }]);
|
|
135
|
+
expect(deps.events.messages).toEqual([]);
|
|
136
|
+
});
|
|
137
|
+
it("dispatches a room-domain verb from an UNTRUSTED but identified device straight to handleRoomRequest, never rejecting it as unauthorized (the actual agent-comms#192 fix)", async () => {
|
|
138
|
+
const { request, responses } = fakeRequest({
|
|
139
|
+
verb: "room:member",
|
|
140
|
+
fromDevice: SENDER_HEX,
|
|
141
|
+
});
|
|
142
|
+
const handleRoomRequest = vi
|
|
143
|
+
.fn()
|
|
144
|
+
.mockImplementation(async (req) => {
|
|
145
|
+
await req.respond({ result: "ok" });
|
|
146
|
+
});
|
|
147
|
+
const deps = fakeDeps({ isTrusted: () => false, handleRoomRequest });
|
|
148
|
+
const onKnownPeer = fakeOnKnownPeer();
|
|
149
|
+
await dispatchHubRequest(request, OWN_HEX, deps, onKnownPeer);
|
|
150
|
+
expect(handleRoomRequest).toHaveBeenCalledTimes(1);
|
|
151
|
+
const [dispatchedRequest, dispatchedHandle] = handleRoomRequest.mock.calls[0] ?? [];
|
|
152
|
+
expect(dispatchedRequest).toBe(request);
|
|
153
|
+
expect(dispatchedHandle).toEqual({ id: SENDER_HEX });
|
|
154
|
+
expect(responses).toEqual([{ result: "ok" }]);
|
|
155
|
+
// hubPeersKnown stays "gateway-trusted hub peers": a room-domain sender's own capability token hasn't been verified yet at this point (that happens inside handleRoomRequest), so an untrusted sender reaching this branch must not be recorded as known just because it presented a syntactically valid device-id.
|
|
156
|
+
expect(onKnownPeer).not.toHaveBeenCalled();
|
|
157
|
+
});
|
|
158
|
+
it("still records a TRUSTED room-domain sender as a known hub peer", async () => {
|
|
159
|
+
const { request } = fakeRequest({
|
|
160
|
+
verb: "room:member",
|
|
161
|
+
fromDevice: SENDER_HEX,
|
|
162
|
+
});
|
|
163
|
+
const deps = fakeDeps({ isTrusted: () => true });
|
|
164
|
+
const onKnownPeer = fakeOnKnownPeer();
|
|
165
|
+
await dispatchHubRequest(request, OWN_HEX, deps, onKnownPeer);
|
|
166
|
+
expect(onKnownPeer).toHaveBeenCalledWith(SENDER_HEX);
|
|
167
|
+
});
|
|
168
|
+
it("forwards a room-domain verb addressed to a different local device via forwardToLocalPeer, stamping on-behalf-of with the true sender", async () => {
|
|
169
|
+
const { request } = fakeRequest({
|
|
170
|
+
verb: "room:member",
|
|
171
|
+
fromDevice: SENDER_HEX,
|
|
172
|
+
toDevice: OTHER_LOCAL_PEER_HEX,
|
|
173
|
+
});
|
|
174
|
+
request.command.params = { verb: "room.send", text: "hi" };
|
|
175
|
+
const outcome = { result: "ok" };
|
|
176
|
+
const forwardToLocalPeer = vi
|
|
177
|
+
.fn()
|
|
178
|
+
.mockReturnValue(Promise.resolve(outcome));
|
|
179
|
+
const handleRoomRequest = vi.fn().mockResolvedValue(undefined);
|
|
180
|
+
const deps = fakeDeps({
|
|
181
|
+
isTrusted: () => false,
|
|
182
|
+
forwardToLocalPeer,
|
|
183
|
+
handleRoomRequest,
|
|
184
|
+
});
|
|
185
|
+
await dispatchHubRequest(request, OWN_HEX, deps, fakeOnKnownPeer());
|
|
186
|
+
expect(forwardToLocalPeer).toHaveBeenCalledTimes(1);
|
|
187
|
+
const [toDeviceArg, commandArg] = forwardToLocalPeer.mock.calls[0] ?? [];
|
|
188
|
+
expect(toDeviceArg).toBe(OTHER_LOCAL_PEER_HEX);
|
|
189
|
+
expect(commandArg).toMatchObject({
|
|
190
|
+
params: { verb: "room.send", text: "hi", "on-behalf-of": SENDER_HEX },
|
|
191
|
+
});
|
|
192
|
+
expect(handleRoomRequest).not.toHaveBeenCalled();
|
|
193
|
+
});
|
|
194
|
+
it("falls back to handleRoomRequest when forwardToLocalPeer finds no local session for the addressed device", async () => {
|
|
195
|
+
const { request } = fakeRequest({
|
|
196
|
+
verb: "room:member",
|
|
197
|
+
fromDevice: SENDER_HEX,
|
|
198
|
+
toDevice: OTHER_LOCAL_PEER_HEX,
|
|
199
|
+
});
|
|
200
|
+
const handleRoomRequest = vi.fn().mockResolvedValue(undefined);
|
|
201
|
+
const deps = fakeDeps({
|
|
202
|
+
isTrusted: () => false,
|
|
203
|
+
forwardToLocalPeer: () => undefined,
|
|
204
|
+
handleRoomRequest,
|
|
205
|
+
});
|
|
206
|
+
await dispatchHubRequest(request, OWN_HEX, deps, fakeOnKnownPeer());
|
|
207
|
+
expect(handleRoomRequest).toHaveBeenCalledTimes(1);
|
|
208
|
+
});
|
|
209
|
+
it("uses deviceIdToHex(request.fromDevice) as the resolved handle id for a room-domain verb addressed to this side's own device", async () => {
|
|
210
|
+
const { request } = fakeRequest({
|
|
211
|
+
verb: "room:member",
|
|
212
|
+
fromDevice: SENDER_HEX,
|
|
213
|
+
toDevice: OWN_HEX,
|
|
214
|
+
});
|
|
215
|
+
const handleRoomRequest = vi.fn().mockResolvedValue(undefined);
|
|
216
|
+
const deps = fakeDeps({ isTrusted: () => true, handleRoomRequest });
|
|
217
|
+
await dispatchHubRequest(request, OWN_HEX, deps, fakeOnKnownPeer());
|
|
218
|
+
expect(handleRoomRequest).toHaveBeenCalledTimes(1);
|
|
219
|
+
const [, handleArg] = handleRoomRequest.mock.calls[0] ?? [];
|
|
220
|
+
expect(handleArg).toEqual({ id: deviceIdToHex(deviceIdBytes(SENDER_HEX)) });
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
//# sourceMappingURL=hub-session-dispatch.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub-session-dispatch.test.js","sourceRoot":"","sources":["../../src/test/hub-session-dispatch.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/** Wires a real WireMeshTransport plus a persisted identity slot onto a freshly constructed MeshStore -- the same setTransport()/setIdentity() calls every production bridge makes immediately after construction (via createBridgeMesh). MeshStore has no default transport or identity, so every test that constructs one needs this (or an equivalent explicit wiring) before init(), createRoom(), or any other transport- or identity-using method runs. */
|
|
2
|
+
import { WireMeshTransport } from "../core/wire-mesh-transport.js";
|
|
2
3
|
import type { IdentitySlot } from "../core/identity-store.js";
|
|
3
4
|
import type { UserIdentityOptions } from "../core/user-identity.js";
|
|
4
5
|
import type { MeshStore } from "../core/mesh-store.js";
|
|
5
6
|
/** Wires store onto a fresh WireMeshTransport and a persisted identity slot, returning the slot so a test can inspect (or reuse) the persisted room tokens directly via loadRoomTokens(). Defaults to a throwaway temp-dir slot per call -- pass an explicit slot when a test needs the same identity to survive across more than one wireTestTransport call (e.g. simulating a restart). pendingConnectionTimeoutMs overrides WireMeshTransport's own default 5-minute connect_request expiry -- a test proving that expiry behaviour needs it far shorter than any real approval window. presenceReadvertiseIntervalMs likewise overrides the default 20s presence re-advertisement cadence -- a test proving that behaviour needs it far shorter too, or a test that doesn't care about presence at all wants it long enough to never fire spuriously mid-test. Wires getSelfAgentAdvert (`() => store.selfAgentAdvert`) the same way createBridgeMesh does -- a test relying on gossip carrying the registered agent/self extension (e.g. remote-directory-merge coverage, agent-comms#155) needs this wired exactly like production does. */
|
|
6
7
|
export declare function wireTestTransport(store: MeshStore, slot?: Readonly<IdentitySlot>, pendingConnectionTimeoutMs?: number, presenceReadvertiseIntervalMs?: number, userIdentityOptions?: Readonly<UserIdentityOptions>): Promise<IdentitySlot>;
|
|
8
|
+
/** Same wiring as wireTestTransport, but also returns the constructed WireMeshTransport instance itself -- needed by any test that has to reach transport.hub directly (connectHub, hub.peers(), hub.isConnected), since MeshStore exposes no public hub-connect wrapper outside CoordinatorGateway's own becomeCoordinator flow (agent-comms#192's own hub-mode room-verb-gating tests are the first to need this, alongside the real room verb handlers store.roomVerbHandlers already wires in). */
|
|
9
|
+
export declare function wireTestTransportWithHub(store: MeshStore, slot?: Readonly<IdentitySlot>, pendingConnectionTimeoutMs?: number, presenceReadvertiseIntervalMs?: number, userIdentityOptions?: Readonly<UserIdentityOptions>): Promise<{
|
|
10
|
+
slot: IdentitySlot;
|
|
11
|
+
transport: WireMeshTransport;
|
|
12
|
+
}>;
|
|
7
13
|
/**
|
|
8
14
|
* Polls condition() until it returns true or timeoutMs elapses, rather than a fixed sleep() before a single check. A real TLS handshake plus the peer_list -\> connectToPeer -\> state_sync -\> handlePeerConnected round trip genuinely takes variable, load-dependent wall-clock time -- comfortably inside a fixed sleep on a fast local machine, not reliably so under a throttled CI runner. Throws with a descriptive message on timeout rather than letting the caller's own assertion fail with a less specific one.
|
|
9
15
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-transport.d.ts","sourceRoot":"","sources":["../../src/test/test-transport.ts"],"names":[],"mappings":"AAAA,icAAic;
|
|
1
|
+
{"version":3,"file":"test-transport.d.ts","sourceRoot":"","sources":["../../src/test/test-transport.ts"],"names":[],"mappings":"AAAA,icAAic;AAKjc,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAMnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAG9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AA4DvD,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,EACtC,mBAAmB,CAAC,EAAE,QAAQ,CAAC,mBAAmB,CAAC,GAClD,OAAO,CAAC,YAAY,CAAC,CASvB;AAED,ueAAue;AACve,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,SAAS,EAChB,IAAI,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC7B,0BAA0B,CAAC,EAAE,MAAM,EACnC,6BAA6B,CAAC,EAAE,MAAM,EACtC,mBAAmB,CAAC,EAAE,QAAQ,CAAC,mBAAmB,CAAC,GAClD,OAAO,CAAC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,SAAS,EAAE,iBAAiB,CAAA;CAAE,CAAC,CAQ/D;AAMD;;GAEG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,OAAO,EACxB,WAAW,EAAE,MAAM,EACnB,SAAS,SAA8B,GACtC,OAAO,CAAC,IAAI,CAAC,CAYf"}
|
|
@@ -14,7 +14,7 @@ import { nanoid } from "../core/nanoid.js";
|
|
|
14
14
|
/** Short enough to keep generated test identity slots readable, long enough that two concurrent test runs won't collide on the same throwaway cwd. */
|
|
15
15
|
const TEST_IDENTITY_CWD_ID_LENGTH = 8;
|
|
16
16
|
/** Wires store onto a fresh WireMeshTransport and a persisted identity slot, returning the slot so a test can inspect (or reuse) the persisted room tokens directly via loadRoomTokens(). Defaults to a throwaway temp-dir slot per call -- pass an explicit slot when a test needs the same identity to survive across more than one wireTestTransport call (e.g. simulating a restart). pendingConnectionTimeoutMs overrides WireMeshTransport's own default 5-minute connect_request expiry -- a test proving that expiry behaviour needs it far shorter than any real approval window. presenceReadvertiseIntervalMs likewise overrides the default 20s presence re-advertisement cadence -- a test proving that behaviour needs it far shorter too, or a test that doesn't care about presence at all wants it long enough to never fire spuriously mid-test. Wires getSelfAgentAdvert (`() => store.selfAgentAdvert`) the same way createBridgeMesh does -- a test relying on gossip carrying the registered agent/self extension (e.g. remote-directory-merge coverage, agent-comms#155) needs this wired exactly like production does. */
|
|
17
|
-
|
|
17
|
+
async function wireTransportInternal(store, slot, pendingConnectionTimeoutMs, presenceReadvertiseIntervalMs, userIdentityOptions) {
|
|
18
18
|
const resolvedSlot = slot ?? {
|
|
19
19
|
harness: "test",
|
|
20
20
|
cwd: nanoid(TEST_IDENTITY_CWD_ID_LENGTH),
|
|
@@ -30,7 +30,8 @@ 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
|
-
|
|
33
|
+
const transport = new WireMeshTransport(store.events, identity, store.roomVerbHandlers, pendingConnectionTimeoutMs, () => store.selfStatus, presenceReadvertiseIntervalMs, undefined, dataStorage, () => store.selfAgentAdvert, store.gatewayTrust);
|
|
34
|
+
store.setTransport(transport);
|
|
34
35
|
store.setIdentity({
|
|
35
36
|
identity: await toIdentityPort(identity),
|
|
36
37
|
clock: createSystemClock(),
|
|
@@ -44,8 +45,17 @@ export async function wireTestTransport(store, slot, pendingConnectionTimeoutMs,
|
|
|
44
45
|
store.onError = (e) => {
|
|
45
46
|
console.error(`[transport error, peerId=${store.peerId}]`, e.message);
|
|
46
47
|
};
|
|
48
|
+
return { slot: resolvedSlot, transport };
|
|
49
|
+
}
|
|
50
|
+
/** Wires store onto a fresh WireMeshTransport and a persisted identity slot, returning the slot so a test can inspect (or reuse) the persisted room tokens directly via loadRoomTokens(). Defaults to a throwaway temp-dir slot per call -- pass an explicit slot when a test needs the same identity to survive across more than one wireTestTransport call (e.g. simulating a restart). pendingConnectionTimeoutMs overrides WireMeshTransport's own default 5-minute connect_request expiry -- a test proving that expiry behaviour needs it far shorter than any real approval window. presenceReadvertiseIntervalMs likewise overrides the default 20s presence re-advertisement cadence -- a test proving that behaviour needs it far shorter too, or a test that doesn't care about presence at all wants it long enough to never fire spuriously mid-test. Wires getSelfAgentAdvert (`() => store.selfAgentAdvert`) the same way createBridgeMesh does -- a test relying on gossip carrying the registered agent/self extension (e.g. remote-directory-merge coverage, agent-comms#155) needs this wired exactly like production does. */
|
|
51
|
+
export async function wireTestTransport(store, slot, pendingConnectionTimeoutMs, presenceReadvertiseIntervalMs, userIdentityOptions) {
|
|
52
|
+
const { slot: resolvedSlot } = await wireTransportInternal(store, slot, pendingConnectionTimeoutMs, presenceReadvertiseIntervalMs, userIdentityOptions);
|
|
47
53
|
return resolvedSlot;
|
|
48
54
|
}
|
|
55
|
+
/** Same wiring as wireTestTransport, but also returns the constructed WireMeshTransport instance itself -- needed by any test that has to reach transport.hub directly (connectHub, hub.peers(), hub.isConnected), since MeshStore exposes no public hub-connect wrapper outside CoordinatorGateway's own becomeCoordinator flow (agent-comms#192's own hub-mode room-verb-gating tests are the first to need this, alongside the real room verb handlers store.roomVerbHandlers already wires in). */
|
|
56
|
+
export async function wireTestTransportWithHub(store, slot, pendingConnectionTimeoutMs, presenceReadvertiseIntervalMs, userIdentityOptions) {
|
|
57
|
+
return wireTransportInternal(store, slot, pendingConnectionTimeoutMs, presenceReadvertiseIntervalMs, userIdentityOptions);
|
|
58
|
+
}
|
|
49
59
|
// Generous on purpose: waitFor returns the instant its condition holds, so a long ceiling costs nothing on the happy path (a local run settles in well under a second) and only matters for the worst case -- a loaded CI runner working through a real, sequential chain of TLS handshakes (each one genuine X.509 certificate work, not instant) for the accept-flow's second connection direction, confirmed to need meaningfully more than 5s on at least one real CI run.
|
|
50
60
|
const DEFAULT_WAIT_FOR_TIMEOUT_MS = 20_000;
|
|
51
61
|
const WAIT_FOR_POLL_INTERVAL_MS = 20;
|
|
@@ -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;AAEpE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,sJAAsJ;AACtJ,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAEtC,klCAAklC;AACllC,
|
|
1
|
+
{"version":3,"file":"test-transport.js","sourceRoot":"","sources":["../../src/test/test-transport.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-comms",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.1",
|
|
4
4
|
"description": "Cross-harness communication mesh for LLM agents — rooms, DMs, presence, and real-time push delivery over TCP",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
|