agent-comms 2.18.2 → 2.18.4
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/bundle.js +1 -1
- package/dist/bridges/user/web/frontend/project-tree.js +3 -3
- package/dist/bridges/user/web/frontend/project-tree.js.map +1 -1
- package/dist/bridges/user/web/test/port-discovery.unit.test.js +10 -11
- package/dist/bridges/user/web/test/port-discovery.unit.test.js.map +1 -1
- package/dist/bridges/user/web/test/web-server.integration.test.js +12 -13
- package/dist/bridges/user/web/test/web-server.integration.test.js.map +1 -1
- package/dist/core/identity-store.d.ts.map +1 -1
- package/dist/core/identity-store.js +16 -5
- package/dist/core/identity-store.js.map +1 -1
- package/dist/core/identity.d.ts +6 -5
- package/dist/core/identity.d.ts.map +1 -1
- package/dist/core/identity.js +13 -11
- package/dist/core/identity.js.map +1 -1
- package/dist/core/test/bridge.unit.test.js +11 -12
- package/dist/core/test/bridge.unit.test.js.map +1 -1
- package/dist/core/test/identity.unit.test.js +21 -22
- package/dist/core/test/identity.unit.test.js.map +1 -1
- package/dist/test/approval.integration.test.js +52 -45
- package/dist/test/approval.integration.test.js.map +1 -1
- package/dist/test/become-coordinator-actual-port.integration.test.d.ts +0 -2
- package/dist/test/become-coordinator-actual-port.integration.test.d.ts.map +1 -1
- package/dist/test/become-coordinator-actual-port.integration.test.js +14 -39
- package/dist/test/become-coordinator-actual-port.integration.test.js.map +1 -1
- package/dist/test/bridge-mesh.test.js +9 -10
- package/dist/test/bridge-mesh.test.js.map +1 -1
- package/dist/test/broadcast-window.integration.test.js +4 -7
- package/dist/test/broadcast-window.integration.test.js.map +1 -1
- package/dist/test/coordinator-socket-error.integration.test.js +3 -4
- package/dist/test/coordinator-socket-error.integration.test.js.map +1 -1
- package/dist/test/create-room-mints-owner-grant.test.js +9 -8
- package/dist/test/create-room-mints-owner-grant.test.js.map +1 -1
- package/dist/test/create-room-name-sanitisation.test.js +6 -7
- package/dist/test/create-room-name-sanitisation.test.js.map +1 -1
- package/dist/test/dm-admission.integration.test.js +10 -11
- package/dist/test/dm-admission.integration.test.js.map +1 -1
- package/dist/test/federation.integration.test.js +21 -20
- package/dist/test/federation.integration.test.js.map +1 -1
- package/dist/test/filestore.test.js +16 -17
- package/dist/test/filestore.test.js.map +1 -1
- package/dist/test/handshake.test.js +26 -27
- package/dist/test/handshake.test.js.map +1 -1
- package/dist/test/identity-cert.test.js +3 -4
- package/dist/test/identity-cert.test.js.map +1 -1
- package/dist/test/identity-device-id.test.js +6 -7
- package/dist/test/identity-device-id.test.js.map +1 -1
- package/dist/test/identity-restart.integration.test.js +9 -10
- package/dist/test/identity-restart.integration.test.js.map +1 -1
- package/dist/test/identity-store.test.js +36 -21
- package/dist/test/identity-store.test.js.map +1 -1
- package/dist/test/listener-policy.integration.test.js +63 -56
- package/dist/test/listener-policy.integration.test.js.map +1 -1
- package/dist/test/mcp-registry-retry.test.js +10 -11
- package/dist/test/mcp-registry-retry.test.js.map +1 -1
- package/dist/test/mesh-e2e.integration.test.js +26 -19
- package/dist/test/mesh-e2e.integration.test.js.map +1 -1
- package/dist/test/presence-readvertise.integration.test.js +5 -6
- package/dist/test/presence-readvertise.integration.test.js.map +1 -1
- package/dist/test/random-id.test.js +3 -4
- package/dist/test/random-id.test.js.map +1 -1
- package/dist/test/room-admission-tool-actions.test.js +20 -15
- package/dist/test/room-admission-tool-actions.test.js.map +1 -1
- package/dist/test/room-destroy-revocation.integration.test.js +3 -4
- package/dist/test/room-destroy-revocation.integration.test.js.map +1 -1
- package/dist/test/room-invite-directed.integration.test.js +13 -12
- package/dist/test/room-invite-directed.integration.test.js.map +1 -1
- package/dist/test/room-join-admission.test.js +31 -24
- package/dist/test/room-join-admission.test.js.map +1 -1
- package/dist/test/room-kick-revocation.integration.test.js +5 -6
- package/dist/test/room-kick-revocation.integration.test.js.map +1 -1
- package/dist/test/room-leave-revocation.integration.test.js +10 -9
- package/dist/test/room-leave-revocation.integration.test.js.map +1 -1
- package/dist/test/room-path.test.js +16 -17
- package/dist/test/room-path.test.js.map +1 -1
- package/dist/test/room-read-directed.integration.test.js +14 -11
- package/dist/test/room-read-directed.integration.test.js.map +1 -1
- package/dist/test/room-router.test.js +27 -29
- package/dist/test/room-router.test.js.map +1 -1
- package/dist/test/room-send-directed.integration.test.js +11 -12
- package/dist/test/room-send-directed.integration.test.js.map +1 -1
- package/dist/test/room-send-retry-queue.test.js +10 -11
- package/dist/test/room-send-retry-queue.test.js.map +1 -1
- package/dist/test/room-send-retry.integration.test.js +5 -8
- package/dist/test/room-send-retry.integration.test.js.map +1 -1
- package/dist/test/room-state-sync.integration.test.js +18 -15
- package/dist/test/room-state-sync.integration.test.js.map +1 -1
- package/dist/test/room-token-store.test.js +21 -22
- package/dist/test/room-token-store.test.js.map +1 -1
- package/dist/test/room-token-verification.test.js +19 -20
- package/dist/test/room-token-verification.test.js.map +1 -1
- package/dist/test/state-sync-convergence.test.js +25 -26
- package/dist/test/state-sync-convergence.test.js.map +1 -1
- package/dist/test/visibility.integration.test.js +48 -49
- package/dist/test/visibility.integration.test.js.map +1 -1
- package/dist/test/wire-mesh-identity.test.js +7 -8
- package/dist/test/wire-mesh-identity.test.js.map +1 -1
- package/package.json +4 -4
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
import * as fs from "node:fs";
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
|
-
import
|
|
10
|
-
import { describe, it } from "node:test";
|
|
9
|
+
import { describe, it, expect } from "vitest";
|
|
11
10
|
import { deviceIdFromHex, deviceIdToHex, } from "wire-mesh-core/domain/device-id";
|
|
12
11
|
import { createSystemClock } from "wire-mesh-core/adapters/system-clock";
|
|
13
12
|
import { createRevocationView } from "wire-mesh-core/domain/revocation-view";
|
|
@@ -49,23 +48,25 @@ describe("handleRoomJoin (owner side)", () => {
|
|
|
49
48
|
description: "",
|
|
50
49
|
});
|
|
51
50
|
const handler = store.roomVerbHandlers["room.join"];
|
|
52
|
-
|
|
51
|
+
expect(handler, "expected a registered room.join handler").toBeTruthy();
|
|
52
|
+
if (handler === undefined)
|
|
53
|
+
throw new Error("expected a registered room.join handler");
|
|
53
54
|
const handle = { id: REQUESTER_ID };
|
|
54
55
|
const { request } = fakeRequest(room.id);
|
|
55
56
|
const outcomePromise = handler(request, handle);
|
|
56
|
-
|
|
57
|
+
expect(store.listPendingRoomJoins()).toEqual([
|
|
57
58
|
{ roomPath: room.id, requesterId: REQUESTER_ID },
|
|
58
59
|
]);
|
|
59
60
|
store.acceptRoomJoin(room.id, REQUESTER_ID);
|
|
60
61
|
const outcome = await outcomePromise;
|
|
61
|
-
|
|
62
|
+
expect(outcome.result).toBe("ok");
|
|
62
63
|
if (outcome.result !== "ok")
|
|
63
64
|
return;
|
|
64
|
-
|
|
65
|
+
expect(store.listPendingRoomJoins()).toEqual([]);
|
|
65
66
|
const token = outcome["granted-token"];
|
|
66
|
-
|
|
67
|
+
expect(token, "expected a granted-token in the outcome").toBeDefined();
|
|
67
68
|
const roomAfterJoin = await store.getRoom(room.id);
|
|
68
|
-
|
|
69
|
+
expect(roomAfterJoin?.members.includes(REQUESTER_ID)).toBeTruthy();
|
|
69
70
|
});
|
|
70
71
|
it("denies the request without minting anything on rejection", async () => {
|
|
71
72
|
const store = new MeshStore();
|
|
@@ -85,15 +86,17 @@ describe("handleRoomJoin (owner side)", () => {
|
|
|
85
86
|
description: "",
|
|
86
87
|
});
|
|
87
88
|
const handler = store.roomVerbHandlers["room.join"];
|
|
88
|
-
|
|
89
|
+
expect(handler).toBeTruthy();
|
|
90
|
+
if (handler === undefined)
|
|
91
|
+
throw new Error("expected a room.join handler to be registered");
|
|
89
92
|
const handle = { id: REQUESTER_ID };
|
|
90
93
|
const { request } = fakeRequest(room.id);
|
|
91
94
|
const outcomePromise = handler(request, handle);
|
|
92
95
|
store.rejectRoomJoin(room.id, REQUESTER_ID);
|
|
93
96
|
const outcome = await outcomePromise;
|
|
94
|
-
|
|
97
|
+
expect(outcome.result).toBe("error");
|
|
95
98
|
const roomAfterReject = await store.getRoom(room.id);
|
|
96
|
-
|
|
99
|
+
expect(roomAfterReject?.members.includes(REQUESTER_ID)).toBe(false);
|
|
97
100
|
});
|
|
98
101
|
it("refuses a DM path naming neither of its own device as a participant, with no pending entry created", async () => {
|
|
99
102
|
const store = new MeshStore();
|
|
@@ -101,12 +104,14 @@ describe("handleRoomJoin (owner side)", () => {
|
|
|
101
104
|
// Neither "c"x64 nor "d"x64 is this store's own peerId, so this DM path names a conversation the store has no part in -- the dm-admission integration tests cover the genuinely-a-participant case end to end.
|
|
102
105
|
const dmPath = `${deviceIdToHex(deviceIdFromHex("c".repeat(64)))}+${deviceIdToHex(deviceIdFromHex("d".repeat(64)))}`;
|
|
103
106
|
const handler = store.roomVerbHandlers["room.join"];
|
|
104
|
-
|
|
107
|
+
expect(handler).toBeTruthy();
|
|
108
|
+
if (handler === undefined)
|
|
109
|
+
throw new Error("expected a room.join handler to be registered");
|
|
105
110
|
const handle = { id: REQUESTER_ID };
|
|
106
111
|
const { request } = fakeRequest(dmPath);
|
|
107
112
|
const outcome = await handler(request, handle);
|
|
108
|
-
|
|
109
|
-
|
|
113
|
+
expect(outcome.result).toBe("error");
|
|
114
|
+
expect(store.listPendingRoomJoins()).toEqual([]);
|
|
110
115
|
});
|
|
111
116
|
it("refuses a named room this store doesn't own", async () => {
|
|
112
117
|
const store = new MeshStore();
|
|
@@ -114,12 +119,14 @@ describe("handleRoomJoin (owner side)", () => {
|
|
|
114
119
|
const someoneElse = "e".repeat(64);
|
|
115
120
|
const roomPath = ownerNamedRoomPath(someoneElse, "general");
|
|
116
121
|
const handler = store.roomVerbHandlers["room.join"];
|
|
117
|
-
|
|
122
|
+
expect(handler).toBeTruthy();
|
|
123
|
+
if (handler === undefined)
|
|
124
|
+
throw new Error("expected a room.join handler to be registered");
|
|
118
125
|
const handle = { id: REQUESTER_ID };
|
|
119
126
|
const { request } = fakeRequest(roomPath);
|
|
120
127
|
const outcome = await handler(request, handle);
|
|
121
|
-
|
|
122
|
-
|
|
128
|
+
expect(outcome.result).toBe("error");
|
|
129
|
+
expect(store.listPendingRoomJoins()).toEqual([]);
|
|
123
130
|
});
|
|
124
131
|
});
|
|
125
132
|
describe("joinRoom (requester side, remote path)", () => {
|
|
@@ -152,7 +159,7 @@ describe("joinRoom (requester side, remote path)", () => {
|
|
|
152
159
|
expires: Date.now() + 60_000,
|
|
153
160
|
delegationsRemaining: 0,
|
|
154
161
|
});
|
|
155
|
-
|
|
162
|
+
expect(grantedTokenVerdict.ok, "expected the fixture token to mint successfully").toBeTruthy();
|
|
156
163
|
if (!grantedTokenVerdict.ok)
|
|
157
164
|
return;
|
|
158
165
|
const grantedToken = grantedTokenVerdict.token;
|
|
@@ -173,7 +180,7 @@ describe("joinRoom (requester side, remote path)", () => {
|
|
|
173
180
|
broadcastRevocation: async () => { },
|
|
174
181
|
sendRoomRequest: async (_memberId, command, scope) => {
|
|
175
182
|
capturedRoomPath = scope.path;
|
|
176
|
-
|
|
183
|
+
expect(command.params).toEqual({ verb: "room.join" });
|
|
177
184
|
return {
|
|
178
185
|
result: "ok",
|
|
179
186
|
"granted-token": grantedToken,
|
|
@@ -187,13 +194,13 @@ describe("joinRoom (requester side, remote path)", () => {
|
|
|
187
194
|
unref: () => { },
|
|
188
195
|
};
|
|
189
196
|
store.setTransport(fakeTransport);
|
|
190
|
-
|
|
197
|
+
expect(await store.getRoom(roomPath)).toBe(undefined);
|
|
191
198
|
const joined = await store.joinRoom(roomPath, store.peerId);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
199
|
+
expect(joined.id).toBe(roomPath);
|
|
200
|
+
expect(capturedRoomPath).toBe(roomPath);
|
|
201
|
+
expect(joined.members.includes(store.peerId)).toBeTruthy();
|
|
195
202
|
const tokens = loadRoomTokens(slot);
|
|
196
|
-
|
|
203
|
+
expect(tokens[roomPath], "expected the granted token to be persisted").toBeDefined();
|
|
197
204
|
});
|
|
198
205
|
});
|
|
199
206
|
//# sourceMappingURL=room-join-admission.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"room-join-admission.test.js","sourceRoot":"","sources":["../../src/test/room-join-admission.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,
|
|
1
|
+
{"version":3,"file":"room-join-admission.test.js","sourceRoot":"","sources":["../../src/test/room-join-admission.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Three real peers: owner (mints and later revokes A's grant), A (the member being kicked), and B (a fellow member who never talks to A about the kick directly -- B's own rejection of A's post-kick message is what proves the revocation-announce genuinely propagated over the wire, not merely that owner's own local view updated).
|
|
5
5
|
*/
|
|
6
|
-
import
|
|
7
|
-
import { test } from "node:test";
|
|
6
|
+
import { test, expect } from "vitest";
|
|
8
7
|
import { MeshStore } from "../core/mesh-store.js";
|
|
9
8
|
import { waitFor, wireTestTransport } from "./test-transport.js";
|
|
10
9
|
let nextPort = 21_110;
|
|
@@ -35,7 +34,7 @@ async function joinAndAccept(owner, member, roomId) {
|
|
|
35
34
|
owner.acceptRoomJoin(roomId, member.peerId);
|
|
36
35
|
await joinPromise;
|
|
37
36
|
}
|
|
38
|
-
|
|
37
|
+
test("kicking a member revokes their room:member token for every peer, not just the owner", async () => {
|
|
39
38
|
const port = freshPort();
|
|
40
39
|
const owner = await makeRegisteredStore(port, "owner");
|
|
41
40
|
const memberA = await makeRegisteredStore(port, "member-a");
|
|
@@ -66,9 +65,9 @@ void test("kicking a member revokes their room:member token for every peer, not
|
|
|
66
65
|
// Settles the revocation-announce this kick just broadcast: B's own drain loop processes it asynchronously off the wire, with no observable side effect from outside B's own store to wait on affirmatively.
|
|
67
66
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
68
67
|
// sendRoomMessage (not used here) re-checks this store's own local CRDT room.members list, which the kick's own legacy room_upsert patch has by now also reached A through -- that would mask exactly what this test needs to isolate. sendRoomMessageDirected instead only ever consults A's own persisted bearer token (never revoked by kickFromRoom, which revokes the OWNER's own record of having issued it, not A's own copy), so it genuinely simulates a still-token-holding A trying to reach B directly -- the real scenario a token-side revocation exists to stop, independent of whatever A's own CRDT view happens to already know. B's own handleRoomSend rejects it with "unauthorized" (the announced revocation now verifies as revoked on B's own independent check), which sendRoomMessageDirected surfaces as a thrown error rather than swallowing it the way the fan-out path does.
|
|
69
|
-
await
|
|
70
|
-
|
|
71
|
-
event.message.content === "after the kick"),
|
|
68
|
+
await expect(memberA.sendRoomMessageDirected(room.id, memberB.peerId, "after the kick"), "B must reject a room.send sent under a token its owner already revoked").rejects.toThrow(/unauthorized/);
|
|
69
|
+
expect(bDeliveries.some((event) => event.type === "room_message" &&
|
|
70
|
+
event.message.content === "after the kick"), "B must not have delivered a message sent under a revoked token").toBe(false);
|
|
72
71
|
}
|
|
73
72
|
finally {
|
|
74
73
|
await memberB.shutdown();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"room-kick-revocation.integration.test.js","sourceRoot":"","sources":["../../src/test/room-kick-revocation.integration.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"room-kick-revocation.integration.test.js","sourceRoot":"","sources":["../../src/test/room-kick-revocation.integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Integration tests for room.leave's real wire-level path (P3.8): a member leaving, or a target declining an invite it never joined, both tell the room's own owner over a real, wire-authenticated room.leave -- the owner revokes the sender's own grant for real (the same revocation machinery kickFromRoom already uses) and notifies accordingly (member_left for a real leave, invite_declined for a decline), rather than each mutating a local Room record nobody else reads.
|
|
3
3
|
*/
|
|
4
|
-
import
|
|
5
|
-
import { test } from "node:test";
|
|
4
|
+
import { test, expect } from "vitest";
|
|
6
5
|
import { MeshStore } from "../core/mesh-store.js";
|
|
7
6
|
import { loadRoomTokens } from "../core/identity-store.js";
|
|
8
7
|
import { waitFor, wireTestTransport } from "./test-transport.js";
|
|
@@ -33,7 +32,7 @@ async function joinAndAccept(owner, member, roomId) {
|
|
|
33
32
|
owner.acceptRoomJoin(roomId, member.peerId);
|
|
34
33
|
await joinPromise;
|
|
35
34
|
}
|
|
36
|
-
|
|
35
|
+
test("a member leaving revokes its own grant and notifies the other members", async () => {
|
|
37
36
|
const port = freshPort();
|
|
38
37
|
const { store: owner } = await makeRegisteredStore(port, "owner");
|
|
39
38
|
const { store: memberA, slot: aSlot } = await makeRegisteredStore(port, "member-a");
|
|
@@ -56,8 +55,8 @@ void test("a member leaving revokes its own grant and notifies the other members
|
|
|
56
55
|
await memberA.leaveRoom(room.id, memberA.peerId);
|
|
57
56
|
await waitFor(() => ownerDeliveries.some((event) => event.type === "member_left" && event.agent === memberA.peerId), "owner is notified that A left");
|
|
58
57
|
// A's own local token is gone, and A can no longer act as a member.
|
|
59
|
-
|
|
60
|
-
await
|
|
58
|
+
expect(loadRoomTokens(aSlot)[room.id]).toBe(undefined);
|
|
59
|
+
await expect(memberA.sendRoomMessageDirected(room.id, owner.peerId, "still here?")).rejects.toMatchObject({ code: "NOT_A_MEMBER" });
|
|
61
60
|
}
|
|
62
61
|
finally {
|
|
63
62
|
await memberB.shutdown();
|
|
@@ -65,7 +64,7 @@ void test("a member leaving revokes its own grant and notifies the other members
|
|
|
65
64
|
await owner.shutdown();
|
|
66
65
|
}
|
|
67
66
|
});
|
|
68
|
-
|
|
67
|
+
test("declining an invite before ever joining revokes the pushed grant and notifies the owner", async () => {
|
|
69
68
|
const port = freshPort();
|
|
70
69
|
const { store: owner } = await makeRegisteredStore(port, "owner");
|
|
71
70
|
const { store: target, slot: targetSlot } = await makeRegisteredStore(port, "target");
|
|
@@ -86,9 +85,11 @@ void test("declining an invite before ever joining revokes the pushed grant and
|
|
|
86
85
|
await target.declineInvite(room.id, target.peerId, "not right now");
|
|
87
86
|
await waitFor(() => ownerDeliveries.some((event) => event.type === "invite_declined" && event.agent === target.peerId), "owner is notified of the decline");
|
|
88
87
|
const declined = ownerDeliveries.find((event) => event.type === "invite_declined");
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
expect(declined).toBeTruthy();
|
|
89
|
+
if (declined === undefined)
|
|
90
|
+
throw new Error("expected an invite_declined delivery event");
|
|
91
|
+
expect(declined.reason).toBe("not right now");
|
|
92
|
+
expect(loadRoomTokens(targetSlot)[room.id]).toBe(undefined);
|
|
92
93
|
}
|
|
93
94
|
finally {
|
|
94
95
|
await target.shutdown();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"room-leave-revocation.integration.test.js","sourceRoot":"","sources":["../../src/test/room-leave-revocation.integration.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"room-leave-revocation.integration.test.js","sourceRoot":"","sources":["../../src/test/room-leave-revocation.integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,31 +1,30 @@
|
|
|
1
|
-
import { test } from "
|
|
2
|
-
import assert from "node:assert/strict";
|
|
1
|
+
import { test, expect } from "vitest";
|
|
3
2
|
import { dmRoomPath, ownerNamedRoomPath, parseRoomPath, slugRoomName, } from "../core/room-path.js";
|
|
4
3
|
const OWNER = "1".repeat(64);
|
|
5
4
|
const OTHER = "2".repeat(64);
|
|
6
5
|
test("ownerNamedRoomPath joins the owner and local name with a slash", () => {
|
|
7
|
-
|
|
6
|
+
expect(ownerNamedRoomPath(OWNER, "general")).toBe(`${OWNER}/general`);
|
|
8
7
|
});
|
|
9
8
|
test("ownerNamedRoomPath rejects an owner that isn't 64-character lowercase hex", () => {
|
|
10
|
-
|
|
9
|
+
expect(() => ownerNamedRoomPath("not-hex", "general")).toThrow();
|
|
11
10
|
});
|
|
12
11
|
test("ownerNamedRoomPath rejects a local name outside [A-Za-z0-9_-]+", () => {
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
expect(() => ownerNamedRoomPath(OWNER, "has spaces")).toThrow();
|
|
13
|
+
expect(() => ownerNamedRoomPath(OWNER, "has.dots")).toThrow();
|
|
15
14
|
});
|
|
16
15
|
test("dmRoomPath joins the bytewise-ascending sorted pair with a plus", () => {
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
expect(dmRoomPath(OWNER, OTHER)).toBe(`${OWNER}+${OTHER}`);
|
|
17
|
+
expect(dmRoomPath(OTHER, OWNER)).toBe(`${OWNER}+${OTHER}`);
|
|
19
18
|
});
|
|
20
19
|
test("dmRoomPath refuses to name the same device twice", () => {
|
|
21
|
-
|
|
20
|
+
expect(() => dmRoomPath(OWNER, OWNER)).toThrow();
|
|
22
21
|
});
|
|
23
22
|
test("dmRoomPath rejects a participant that isn't 64-character lowercase hex", () => {
|
|
24
|
-
|
|
23
|
+
expect(() => dmRoomPath("not-hex", OTHER)).toThrow();
|
|
25
24
|
});
|
|
26
25
|
test("parseRoomPath recognises an owner-named path", () => {
|
|
27
26
|
const parsed = parseRoomPath(`${OWNER}/general`);
|
|
28
|
-
|
|
27
|
+
expect(parsed).toEqual({
|
|
29
28
|
kind: "owner-named",
|
|
30
29
|
owner: OWNER,
|
|
31
30
|
localName: "general",
|
|
@@ -33,22 +32,22 @@ test("parseRoomPath recognises an owner-named path", () => {
|
|
|
33
32
|
});
|
|
34
33
|
test("parseRoomPath recognises a DM path", () => {
|
|
35
34
|
const parsed = parseRoomPath(`${OWNER}+${OTHER}`);
|
|
36
|
-
|
|
35
|
+
expect(parsed).toEqual({
|
|
37
36
|
kind: "dm",
|
|
38
37
|
participants: [OWNER, OTHER],
|
|
39
38
|
});
|
|
40
39
|
});
|
|
41
40
|
test("parseRoomPath rejects a path shaped like neither", () => {
|
|
42
|
-
|
|
41
|
+
expect(() => parseRoomPath("just-a-name")).toThrow();
|
|
43
42
|
});
|
|
44
43
|
test("slugRoomName replaces every character outside [A-Za-z0-9_-] with a hyphen", () => {
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
expect(slugRoomName("documents.js")).toBe("documents-js");
|
|
45
|
+
expect(slugRoomName("my project")).toBe("my-project");
|
|
47
46
|
});
|
|
48
47
|
test("slugRoomName leaves an already-valid name unchanged", () => {
|
|
49
|
-
|
|
48
|
+
expect(slugRoomName("agent-comms_2")).toBe("agent-comms_2");
|
|
50
49
|
});
|
|
51
50
|
test("slugRoomName rejects a name with nothing left to slug", () => {
|
|
52
|
-
|
|
51
|
+
expect(() => slugRoomName("...")).toThrow();
|
|
53
52
|
});
|
|
54
53
|
//# sourceMappingURL=room-path.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"room-path.test.js","sourceRoot":"","sources":["../../src/test/room-path.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"room-path.test.js","sourceRoot":"","sources":["../../src/test/room-path.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Membership is set up by minting and persisting the member's own token directly, matching room-send-directed.integration.test.ts's own reasoning: the legacy full-state-sync makes a real room.join round trip structurally unreachable in a two-peer test here, and it's irrelevant to what this file tests.
|
|
5
5
|
*/
|
|
6
|
-
import
|
|
7
|
-
import { test } from "node:test";
|
|
6
|
+
import { test, expect } from "vitest";
|
|
8
7
|
import { mintCapabilityToken } from "wire-mesh-core/domain/tokens";
|
|
9
8
|
import { createSystemClock } from "wire-mesh-core/adapters/system-clock";
|
|
10
9
|
import { deviceIdFromHex } from "wire-mesh-core/domain/device-id";
|
|
@@ -57,12 +56,12 @@ async function grantMembership(ownerSlot, bearerSlot, roomPath, bearerDeviceHex)
|
|
|
57
56
|
expires: clock.now() + 60_000,
|
|
58
57
|
delegationsRemaining: 0,
|
|
59
58
|
});
|
|
60
|
-
|
|
59
|
+
expect(verdict.ok, "expected the fixture grant to mint successfully").toBeTruthy();
|
|
61
60
|
if (!verdict.ok)
|
|
62
61
|
return;
|
|
63
62
|
saveRoomToken(bearerSlot, roomPath, verdict.token);
|
|
64
63
|
}
|
|
65
|
-
|
|
64
|
+
test("reading a directed room.send notifies only its own author via room.read", async () => {
|
|
66
65
|
const { owner, ownerSlot, member, memberSlot } = await makeConnectedPair(freshPort());
|
|
67
66
|
try {
|
|
68
67
|
const room = await owner.createRoom({
|
|
@@ -87,20 +86,24 @@ void test("reading a directed room.send notifies only its own author via room.re
|
|
|
87
86
|
// fireLocalDelivery's own auto-mark-read timer fires markRead for member, which should reach owner as a directed room.read -- no explicit action needed here.
|
|
88
87
|
await waitFor(() => ownerDeliveries.some((event) => event.type === "delivery_status" && event.status === "read"), "owner receives the read receipt");
|
|
89
88
|
const readReceipt = ownerDeliveries.find((event) => event.type === "delivery_status" && event.status === "read");
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
expect(readReceipt).toBeTruthy();
|
|
90
|
+
if (readReceipt === undefined)
|
|
91
|
+
throw new Error("expected a read-receipt delivery event");
|
|
92
|
+
expect(readReceipt.agent).toBe(member.peerId);
|
|
93
|
+
expect(readReceipt.room).toBe(room.id);
|
|
93
94
|
const ownerHistory = await owner.readRoomMessages(room.id);
|
|
94
95
|
const sent = ownerHistory.find((m) => m.content === "hello there");
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
expect(sent).toBeTruthy();
|
|
97
|
+
if (sent === undefined)
|
|
98
|
+
throw new Error("expected to find the sent message");
|
|
99
|
+
expect(sent.readBy.includes(member.peerId)).toBeTruthy();
|
|
97
100
|
}
|
|
98
101
|
finally {
|
|
99
102
|
await member.shutdown();
|
|
100
103
|
await owner.shutdown();
|
|
101
104
|
}
|
|
102
105
|
});
|
|
103
|
-
|
|
106
|
+
test("reading a message from a peer with no room:member token for it does nothing beyond the local readBy update", async () => {
|
|
104
107
|
const { owner, ownerSlot, member, memberSlot } = await makeConnectedPair(freshPort());
|
|
105
108
|
try {
|
|
106
109
|
const room = await owner.createRoom({
|
|
@@ -122,7 +125,7 @@ void test("reading a message from a peer with no room:member token for it does n
|
|
|
122
125
|
await waitFor(() => memberDeliveries.some((event) => event.type === "room_message"), "member receives the directed room.send");
|
|
123
126
|
// Give the auto-mark-read timer a real chance to fire and (incorrectly) notify owner before asserting it never did.
|
|
124
127
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
125
|
-
|
|
128
|
+
expect(ownerDeliveries.some((event) => event.type === "delivery_status")).toBe(false);
|
|
126
129
|
}
|
|
127
130
|
finally {
|
|
128
131
|
await member.shutdown();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"room-read-directed.integration.test.js","sourceRoot":"","sources":["../../src/test/room-read-directed.integration.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"room-read-directed.integration.test.js","sourceRoot":"","sources":["../../src/test/room-read-directed.integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
import { describe, it,
|
|
2
|
-
import assert from "node:assert/strict";
|
|
1
|
+
import { describe, it, vi, expect } from "vitest";
|
|
3
2
|
import { FRAME_VERB, buildCommand } from "../core/wire-mesh-transport.js";
|
|
4
3
|
import { createRoomRouter } from "../core/room-router.js";
|
|
5
4
|
const TEST_HANDLE = { id: "a".repeat(64) };
|
|
6
5
|
function fakeEvents() {
|
|
7
6
|
return {
|
|
8
|
-
onMessage:
|
|
9
|
-
onIntroduction:
|
|
10
|
-
onConnectionRequest:
|
|
11
|
-
onPeerConnected:
|
|
12
|
-
onPeerDisconnected:
|
|
13
|
-
onPeerList:
|
|
14
|
-
onPeerJoined:
|
|
15
|
-
onBecomeCoordinator:
|
|
16
|
-
onError:
|
|
17
|
-
onRevocationAnnounce:
|
|
18
|
-
onPresenceAdvert:
|
|
7
|
+
onMessage: vi.fn(),
|
|
8
|
+
onIntroduction: vi.fn(),
|
|
9
|
+
onConnectionRequest: vi.fn(),
|
|
10
|
+
onPeerConnected: vi.fn(),
|
|
11
|
+
onPeerDisconnected: vi.fn(),
|
|
12
|
+
onPeerList: vi.fn(),
|
|
13
|
+
onPeerJoined: vi.fn(),
|
|
14
|
+
onBecomeCoordinator: vi.fn(),
|
|
15
|
+
onError: vi.fn(),
|
|
16
|
+
onRevocationAnnounce: vi.fn(),
|
|
17
|
+
onPresenceAdvert: vi.fn(),
|
|
19
18
|
};
|
|
20
19
|
}
|
|
21
20
|
function fakeRequest(command, token) {
|
|
@@ -37,8 +36,9 @@ describe("createRoomRouter", () => {
|
|
|
37
36
|
const router = createRoomRouter({ events });
|
|
38
37
|
const { request, responses } = fakeRequest(buildCommand({ method: "peer_list", peers: [] }));
|
|
39
38
|
await router.handleRequest(request, TEST_HANDLE);
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
expect(events.onPeerList.mock.calls
|
|
40
|
+
.length).toBe(1);
|
|
41
|
+
expect(responses).toEqual([{ result: "ok" }]);
|
|
42
42
|
});
|
|
43
43
|
it("routes an otherwise-well-formed FRAME_VERB payload with no recognised case to the onMessage catch-all", async () => {
|
|
44
44
|
const events = fakeEvents();
|
|
@@ -49,8 +49,9 @@ describe("createRoomRouter", () => {
|
|
|
49
49
|
params: { message: { method: "not-a-real-method" } },
|
|
50
50
|
});
|
|
51
51
|
await router.handleRequest(request, TEST_HANDLE);
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
expect(events.onMessage.mock.calls
|
|
53
|
+
.length).toBe(1);
|
|
54
|
+
expect(responses).toEqual([{ result: "ok" }]);
|
|
54
55
|
});
|
|
55
56
|
it("responds ok without routing anything for a FRAME_VERB payload with no message field at all", async () => {
|
|
56
57
|
const events = fakeEvents();
|
|
@@ -60,8 +61,9 @@ describe("createRoomRouter", () => {
|
|
|
60
61
|
params: {},
|
|
61
62
|
});
|
|
62
63
|
await router.handleRequest(request, TEST_HANDLE);
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
expect(events.onMessage.mock.calls
|
|
65
|
+
.length).toBe(0);
|
|
66
|
+
expect(responses).toEqual([{ result: "ok" }]);
|
|
65
67
|
});
|
|
66
68
|
it("dispatches a registered room verb to its own handler", async () => {
|
|
67
69
|
const events = fakeEvents();
|
|
@@ -80,8 +82,8 @@ describe("createRoomRouter", () => {
|
|
|
80
82
|
params: { verb: "room.send", text: "hi" },
|
|
81
83
|
});
|
|
82
84
|
await router.handleRequest(request, TEST_HANDLE);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
expect(handled).toEqual([{ verb: "room.send", text: "hi" }]);
|
|
86
|
+
expect(responses).toEqual([{ result: "ok" }]);
|
|
85
87
|
});
|
|
86
88
|
it("refuses an unregistered room verb with unsupported_verb", async () => {
|
|
87
89
|
const events = fakeEvents();
|
|
@@ -91,8 +93,8 @@ describe("createRoomRouter", () => {
|
|
|
91
93
|
params: { verb: "room.send", text: "hi" },
|
|
92
94
|
});
|
|
93
95
|
await router.handleRequest(request, TEST_HANDLE);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
expect(responses.length).toBe(1);
|
|
97
|
+
expect(responses[0]).toEqual({
|
|
96
98
|
result: "error",
|
|
97
99
|
code: "unsupported_verb",
|
|
98
100
|
});
|
|
@@ -105,9 +107,7 @@ describe("createRoomRouter", () => {
|
|
|
105
107
|
params: { verb: "exec.list" },
|
|
106
108
|
});
|
|
107
109
|
await router.handleRequest(request, TEST_HANDLE);
|
|
108
|
-
|
|
109
|
-
{ result: "error", code: "unsupported_verb" },
|
|
110
|
-
]);
|
|
110
|
+
expect(responses).toEqual([{ result: "error", code: "unsupported_verb" }]);
|
|
111
111
|
});
|
|
112
112
|
it("refuses a params object with no verb field at all", async () => {
|
|
113
113
|
const events = fakeEvents();
|
|
@@ -117,9 +117,7 @@ describe("createRoomRouter", () => {
|
|
|
117
117
|
params: {},
|
|
118
118
|
});
|
|
119
119
|
await router.handleRequest(request, TEST_HANDLE);
|
|
120
|
-
|
|
121
|
-
{ result: "error", code: "unsupported_verb" },
|
|
122
|
-
]);
|
|
120
|
+
expect(responses).toEqual([{ result: "error", code: "unsupported_verb" }]);
|
|
123
121
|
});
|
|
124
122
|
});
|
|
125
123
|
//# sourceMappingURL=room-router.test.js.map
|