dsh-remote-control 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/cordis.patch.yml +4 -0
  2. package/dist/bundle/client.cjs +484 -0
  3. package/dist/bundle/index.js +577 -433
  4. package/package.json +14 -6
  5. package/dist/src/core/clock.d.ts +0 -45
  6. package/dist/src/core/clock.js +0 -83
  7. package/dist/src/core/clock.js.map +0 -1
  8. package/dist/src/core/keys.d.ts +0 -98
  9. package/dist/src/core/keys.js +0 -176
  10. package/dist/src/core/keys.js.map +0 -1
  11. package/dist/src/core/pairing-window.d.ts +0 -95
  12. package/dist/src/core/pairing-window.js +0 -92
  13. package/dist/src/core/pairing-window.js.map +0 -1
  14. package/dist/src/core/runtime.d.ts +0 -104
  15. package/dist/src/core/runtime.js +0 -491
  16. package/dist/src/core/runtime.js.map +0 -1
  17. package/dist/src/core/sleep-policy.d.ts +0 -81
  18. package/dist/src/core/sleep-policy.js +0 -134
  19. package/dist/src/core/sleep-policy.js.map +0 -1
  20. package/dist/src/core/window.d.ts +0 -88
  21. package/dist/src/core/window.js +0 -185
  22. package/dist/src/core/window.js.map +0 -1
  23. package/dist/src/index.d.ts +0 -70
  24. package/dist/src/index.js +0 -882
  25. package/dist/src/index.js.map +0 -1
  26. package/dist/src/platform/carrier-services.d.ts +0 -96
  27. package/dist/src/platform/carrier-services.js +0 -982
  28. package/dist/src/platform/carrier-services.js.map +0 -1
  29. package/dist/src/platform/guard.d.ts +0 -60
  30. package/dist/src/platform/guard.js +0 -124
  31. package/dist/src/platform/guard.js.map +0 -1
  32. package/dist/src/platform/mock-kernel.d.ts +0 -95
  33. package/dist/src/platform/mock-kernel.js +0 -180
  34. package/dist/src/platform/mock-kernel.js.map +0 -1
  35. package/dist/src/platform/qr.d.ts +0 -28
  36. package/dist/src/platform/qr.js +0 -80
  37. package/dist/src/platform/qr.js.map +0 -1
  38. package/dist/src/platform/sleep-posix.d.ts +0 -17
  39. package/dist/src/platform/sleep-posix.js +0 -91
  40. package/dist/src/platform/sleep-posix.js.map +0 -1
  41. package/dist/src/ports/index.d.ts +0 -246
  42. package/dist/src/ports/index.js +0 -2
  43. package/dist/src/ports/index.js.map +0 -1
  44. package/dist/src/shell/config.d.ts +0 -56
  45. package/dist/src/shell/config.js +0 -212
  46. package/dist/src/shell/config.js.map +0 -1
  47. package/dist/src/shell/pairing-text.d.ts +0 -38
  48. package/dist/src/shell/pairing-text.js +0 -22
  49. package/dist/src/shell/pairing-text.js.map +0 -1
  50. package/dist/src/shell/status.d.ts +0 -39
  51. package/dist/src/shell/status.js +0 -119
  52. package/dist/src/shell/status.js.map +0 -1
  53. package/dist/src/transport/relay.d.ts +0 -107
  54. package/dist/src/transport/relay.js +0 -359
  55. package/dist/src/transport/relay.js.map +0 -1
  56. package/dist/tests/carrier-events.test.d.ts +0 -1
  57. package/dist/tests/carrier-events.test.js +0 -88
  58. package/dist/tests/carrier-events.test.js.map +0 -1
  59. package/dist/tests/carrier-services.test.d.ts +0 -1
  60. package/dist/tests/carrier-services.test.js +0 -562
  61. package/dist/tests/carrier-services.test.js.map +0 -1
  62. package/dist/tests/carrier-vocabulary.test.d.ts +0 -1
  63. package/dist/tests/carrier-vocabulary.test.js +0 -149
  64. package/dist/tests/carrier-vocabulary.test.js.map +0 -1
  65. package/dist/tests/clock-probe-timers.test.d.ts +0 -1
  66. package/dist/tests/clock-probe-timers.test.js +0 -73
  67. package/dist/tests/clock-probe-timers.test.js.map +0 -1
  68. package/dist/tests/command-result.test.d.ts +0 -1
  69. package/dist/tests/command-result.test.js +0 -185
  70. package/dist/tests/command-result.test.js.map +0 -1
  71. package/dist/tests/config.test.d.ts +0 -1
  72. package/dist/tests/config.test.js +0 -223
  73. package/dist/tests/config.test.js.map +0 -1
  74. package/dist/tests/guard.test.d.ts +0 -1
  75. package/dist/tests/guard.test.js +0 -175
  76. package/dist/tests/guard.test.js.map +0 -1
  77. package/dist/tests/ids-and-keys.test.d.ts +0 -1
  78. package/dist/tests/ids-and-keys.test.js +0 -211
  79. package/dist/tests/ids-and-keys.test.js.map +0 -1
  80. package/dist/tests/pairing-text.test.d.ts +0 -1
  81. package/dist/tests/pairing-text.test.js +0 -62
  82. package/dist/tests/pairing-text.test.js.map +0 -1
  83. package/dist/tests/pairing-window.test.d.ts +0 -1
  84. package/dist/tests/pairing-window.test.js +0 -165
  85. package/dist/tests/pairing-window.test.js.map +0 -1
  86. package/dist/tests/relay-client.test.d.ts +0 -1
  87. package/dist/tests/relay-client.test.js +0 -557
  88. package/dist/tests/relay-client.test.js.map +0 -1
  89. package/dist/tests/runtime.test.d.ts +0 -1
  90. package/dist/tests/runtime.test.js +0 -963
  91. package/dist/tests/runtime.test.js.map +0 -1
  92. package/dist/tests/sleep.test.d.ts +0 -1
  93. package/dist/tests/sleep.test.js +0 -264
  94. package/dist/tests/sleep.test.js.map +0 -1
  95. package/dist/tests/status.test.d.ts +0 -1
  96. package/dist/tests/status.test.js +0 -238
  97. package/dist/tests/status.test.js.map +0 -1
  98. package/dist/tests/window.test.d.ts +0 -1
  99. package/dist/tests/window.test.js +0 -210
  100. package/dist/tests/window.test.js.map +0 -1
@@ -1,557 +0,0 @@
1
- /**
2
- * relay-client.test — `transport/relay.ts`:主机侧中继客户端的配对与密封簿记。
3
- *
4
- * 三条来自线上事故的硬要求(取证 docs/legacy-spec/relay-and-wireformat.md §2.3、
5
- * HANDOFF.md §4.5、docs/DESIGN.md §4 的 D1/D3):
6
- *
7
- * 1. `pair-ready.ttlMs` 是**服务端权威 TTL**,必须改写本地过期时间。忘了这一步:
8
- * 主机提前清掉 PSK → `peer-joined` 找不到密钥 → 静默丢 peer →
9
- * 手机端表现为"配对显示成功,但会话列表永远空白"。
10
- * 2. `peer-joined.pairingToken` 是唯一合法的取密钥依据。多码并存时取"最新那一张"
11
- * 就是当初那起事故(每一帧都解不开,且没有任何提示)。
12
- * 3. 中继重启(generation 变化)后旧配对全部作废;客户端断连(`peer-left`)时
13
- * 会话**必须留着**(D3),否则手机每次回前台都要重新扫码。
14
- *
15
- * 说明:`RelayClient` 自己 `new WebSocket(...)`,源码里没有 socket 注入点,
16
- * 也没有可注入的时钟以外的握手缝。所以这里用白盒方式把一只假 socket 接到
17
- * 私有字段上、再喂中继来帧文本——测的是帧处理与密钥簿记这些**真正的判据**,
18
- * 而不是 ws 的实现。若之后给 `RelayClientOptions` 加了 socket 工厂,
19
- * 把 `attachSocket()/feedFrame()` 换成注入即可,断言一条都不用改。
20
- */
21
- import { test } from 'node:test';
22
- import assert from 'node:assert/strict';
23
- import { Buffer } from 'node:buffer';
24
- import { PAYLOAD_TYPES, derivePskKey, open, seal } from 'dsh-remote-wire';
25
- import { RelayClient } from '../src/transport/relay.js';
26
- import { PairingSlots } from '../src/core/keys.js';
27
- import { FakeClock } from '../src/core/clock.js';
28
- /** `ws` 的 `WebSocket.OPEN` 常量值;`raw()` 只比较这个数。 */
29
- const SOCKET_OPEN = 1;
30
- function makeSocket() {
31
- return {
32
- readyState: SOCKET_OPEN,
33
- sent: [],
34
- send(text) {
35
- this.sent.push(String(text));
36
- },
37
- close() {
38
- this.readyState = 3; // CLOSED
39
- },
40
- terminate() {
41
- this.readyState = 3;
42
- },
43
- removeAllListeners() {
44
- /* 假 socket 没有监听器 */
45
- },
46
- on() {
47
- /* 同上:假 socket 不自己发事件,能挂上就够 */
48
- },
49
- };
50
- }
51
- function harness() {
52
- const clock = new FakeClock();
53
- const slots = new PairingSlots(() => clock.now());
54
- const socket = makeSocket();
55
- const joined = [];
56
- const gone = [];
57
- const left = [];
58
- const commands = [];
59
- const states = [];
60
- const logs = [];
61
- const client = new RelayClient({
62
- url: 'ws://127.0.0.1:1',
63
- hostId: 'h_test',
64
- label: '测试主机',
65
- token: 'fake-host-token-not-a-real-secret-0123',
66
- clock,
67
- log: (message, fields) => {
68
- logs.push(`${message} ${JSON.stringify(fields ?? {})}`);
69
- },
70
- onCommand: (conversationId, cmd, clientId) => {
71
- commands.push({ conversationId, cmd, ...(clientId === undefined ? {} : { clientId }) });
72
- },
73
- onPeerJoined: (conversationId, pairingToken) => joined.push({ conversationId, token: pairingToken }),
74
- onConversationGone: (conversationId) => gone.push(conversationId),
75
- onClientLeft: (conversationId, clientId) => left.push({ conversationId, clientId }),
76
- lookupPairingSlot: (token) => slots.resolveFor(token),
77
- onPairReady: (token, ttlMs) => {
78
- // 与 index.ts 的接法一致:服务端 TTL 改写本地过期。
79
- if (!slots.applyServerTtl(token, ttlMs))
80
- logs.push(`pair-ready for an unknown token ${token}`);
81
- },
82
- onState: (info) => states.push(info),
83
- });
84
- attachSocket(client, socket);
85
- const out = () => socket.sent.map((text) => JSON.parse(text));
86
- return {
87
- clock,
88
- slots,
89
- client,
90
- socket,
91
- out,
92
- outOf: (type) => out().filter((frame) => frame.t === type),
93
- feed: (frame) => feedFrame(client, JSON.stringify(frame)),
94
- feedText: (text) => feedFrame(client, text),
95
- joined,
96
- gone,
97
- left,
98
- commands,
99
- states,
100
- logs,
101
- };
102
- }
103
- function attachSocket(client, socket) {
104
- ;
105
- client.socket = socket;
106
- }
107
- function feedFrame(client, text) {
108
- ;
109
- client.onFrame(text);
110
- }
111
- /** 手机侧那一本镜像密钥:它拿 PSK + convId 自己派生,主机看不到它的密钥。 */
112
- function phoneKeys(psk, conversationId) {
113
- return {
114
- kC2H: derivePskKey(psk, 'c2h', conversationId),
115
- kH2C: derivePskKey(psk, 'h2c', conversationId),
116
- };
117
- }
118
- test('发布的 pair-begin 只带 6 位码,PSK 一个字节都不上过网(D1:中继结构性零知识)', () => {
119
- const { client, slots, outOf } = harness();
120
- const slot = slots.create(120_000);
121
- client.publishPairing(slot);
122
- const frames = outOf('pair-begin');
123
- assert.equal(frames.length, 1, '一条 pair-begin 都没发出去:手机扫码后永远等不到配对结果');
124
- const frame = frames[0];
125
- assert.equal(frame.pairingToken, slot.token, 'pairingToken 必须是这张码本身:中继按它路由并回显');
126
- const text = JSON.stringify(frame);
127
- assert.equal(text.includes('psk'), false, 'pair-begin 里出现了 psk 字段:中继内存里就会多一份密钥副本(D1 的出发点)');
128
- assert.equal(text.includes(slot.psk), false, 'PSK 真值被发了出去:零知识声明与实现不一致');
129
- });
130
- test('pair-ready 的 ttlMs 必须改写本地过期:忘了这一步就是"配对成功但列表永远空白"', async () => {
131
- const { client, clock, slots, feed, joined } = harness();
132
- const slot = slots.create(1_000); // 本地只给 1 秒
133
- client.publishPairing(slot);
134
- await clock.advance(5_000); // 本地认为它早过期了
135
- assert.equal(slot.expiresAt < clock.now(), true, '夹具自检:此刻本地已判过期');
136
- // 服务端说还能用两分钟——权威值必须覆盖本地值。
137
- feed({ t: 'pair-ready', pairingToken: slot.token, ttlMs: 120_000 });
138
- assert.equal(slots.resolveFor(slot.token) !== null, true, '服务端 TTL 没有改写本地过期:主机会在配对发生之前就把 PSK 清掉');
139
- feed({ t: 'peer-joined', sessionId: 'c_aaa111222333', clientId: 'k_mp', pairingToken: slot.token });
140
- assert.equal(joined.length, 1, 'peer-joined 取不到 PSK 被静默丢弃 → 手机显示配对成功、会话列表却是空的');
141
- assert.equal(client.hasPeer('c_aaa111222333'), true, '会话没建起来:后续每一条下行都返回 false');
142
- });
143
- test('peer-joined 缺 pairingToken 时不建会话(那是重连通知,不是新客户端加入)', () => {
144
- const { client, slots, feed, joined } = harness();
145
- slots.create(120_000);
146
- feed({ t: 'peer-joined', sessionId: 'c_bbb111222333', clientId: 'k_mp' });
147
- assert.equal(joined.length, 0, '没有 token 也建了会话:那是拿"最新那张码"的 PSK 猜密钥(多码事故的形状)');
148
- assert.equal(client.conversationCount, 0, `凭空建了 ${client.conversationCount} 条会话`);
149
- assert.equal(client.hasPeer('c_bbb111222333'), false, 'hasPeer 谎报有对端');
150
- });
151
- test('多码并存时按手机实际使用的那张码取 PSK:用 A 码建的会话必须用 A 的密钥(旧事故回归)', async () => {
152
- const { client, clock, slots, feed, joined } = harness();
153
- const older = slots.create(120_000); // 自动补发的那一张
154
- await clock.advance(10);
155
- const newer = slots.create(120_000); // 用户又手工 /drc pair 了一张
156
- assert.equal(older.token !== newer.token, true, '夹具自检:两张码必须不同');
157
- assert.equal(slots.latest()?.token, newer.token, '夹具自检:latest() 会给出更新的那一张(旧实现就是取了它)');
158
- feed({ t: 'peer-joined', sessionId: 'c_ccc111222333', clientId: 'k_mp', pairingToken: older.token });
159
- assert.equal(joined.length, 1, '用较早那张码配对被拒了:手机扫的是它屏幕上那张,不是最新那张');
160
- const conversation = client.conversations.get('c_ccc111222333');
161
- assert.ok(conversation !== undefined, '会话没建出来');
162
- assert.equal(conversation.psk, older.psk, `取到了错的 PSK(期望 older=${older.psk},实际 ${conversation.psk})`);
163
- // 最硬的一条:手机那一侧用 A 的 PSK 派生密钥,两侧必须能互解。
164
- const phone = phoneKeys(older.psk, 'c_ccc111222333');
165
- const wrongPhone = phoneKeys(newer.psk, 'c_ccc111222333');
166
- const payload = { t: PAYLOAD_TYPES.evResult, cmdId: 'cmd_1', ok: true };
167
- assert.equal(client.send('c_ccc111222333', payload), true, '下行发送失败');
168
- const frame = client.conversations.get('c_ccc111222333');
169
- assert.ok(frame !== undefined);
170
- // 把刚才那条 outbound 密文取回来,用手机的密钥解:解不开就是"配对成功、每一帧都解不开"。
171
- const sent = JSON.parse(String(client.socket.sent.at(-1)));
172
- assert.equal(open(phone.kH2C, { ciphertext: sent.ciphertext }) !== null, true, '手机用 A 码的 PSK 解不开主机下行 → 会话列表空白、没有任何提示');
173
- assert.equal(open(wrongPhone.kH2C, { ciphertext: sent.ciphertext }), null, '拿错码(B)的密钥竟然解得开:说明密钥没绑定到所用那张码');
174
- });
175
- test('上行命令用同一张码的 c2h 密钥解密并交给 runtime(两把方向密钥不许混用)', () => {
176
- const { client, slots, feed, commands } = harness();
177
- const slot = slots.create(120_000);
178
- feed({ t: 'peer-joined', sessionId: 'c_ddd111222333', clientId: 'k_mp', pairingToken: slot.token });
179
- const phone = phoneKeys(slot.psk, 'c_ddd111222333');
180
- const cmd = { t: PAYLOAD_TYPES.cmdListSessions, cmdId: 'cmd_ls_1' };
181
- feed({ t: 'enc', sessionId: 'c_ddd111222333', clientId: 'k_mp', ciphertext: seal(phone.kC2H, cmd).ciphertext });
182
- assert.equal(commands.length, 1, '解得开却没交给 runtime:手机点了"刷新列表"没有任何反应');
183
- assert.equal(commands[0]?.cmd.t, PAYLOAD_TYPES.cmdListSessions, '命令类型丢了');
184
- assert.equal((commands[0]?.cmd).cmdId, 'cmd_ls_1', 'cmdId 必须逐字交给 runtime:回执对答靠它');
185
- assert.equal(commands[0]?.clientId, 'k_mp', 'clientId 要带上来(D4 的成员校验要用)');
186
- // 用错方向的密钥密封:主机解不开,但绝不能崩。
187
- feed({ t: 'enc', sessionId: 'c_ddd111222333', ciphertext: seal(phone.kH2C, cmd).ciphertext });
188
- assert.equal(commands.length, 1, '方向搞反的密文被当成合法命令放行了:B5 的方向分离就白做了');
189
- });
190
- test('MAC 校验通过但载荷不是任何一条已定义命令:不进 runtime,也不许攒成"解不开两次就作废"', () => {
191
- const { client, slots, feed, commands, logs } = harness();
192
- const slot = slots.create(120_000);
193
- feed({ t: 'peer-joined', sessionId: 'c_dtd111222333', clientId: 'k_mp', pairingToken: slot.token });
194
- const phone = phoneKeys(slot.psk, 'c_dtd111222333');
195
- // 手机(或被改过的客户端)密封了一条我们没定义过的命令。
196
- feed({
197
- t: 'enc',
198
- sessionId: 'c_dtd111222333',
199
- ciphertext: seal(phone.kC2H, { t: 'cmd.drop_everything', cmdId: 'x_1' }).ciphertext,
200
- });
201
- assert.equal(commands.length, 0, '未定义的载荷被原样递进 runtime:下游是 switch + 真实内核调用,等于让一条密文决定宿主被怎么调');
202
- assert.ok(logs.some((line) => line.includes('failed cmd schema')), '拒收必须留痕:否则"手机点了没反应"没有答案');
203
- assert.equal(client.hasPeer('c_dtd111222333'), true, '形状错不是密钥错,不该计入"连续两次解不开就作废"');
204
- // 同一条通道上的合法命令仍然进得来(这次拒收没有把通道打死)。
205
- feed({
206
- t: 'enc',
207
- sessionId: 'c_dtd111222333',
208
- ciphertext: seal(phone.kC2H, { t: PAYLOAD_TYPES.cmdListSessions, cmdId: 'cmd_ok' }).ciphertext,
209
- });
210
- assert.equal(commands.length, 1, '一次形状拒收之后整条通道都哑了');
211
- });
212
- test('enc-batch 逐项解密并保持数组顺序(F12/T3:客户端没有排序能力)', () => {
213
- const { client, slots, feed, commands } = harness();
214
- const slot = slots.create(120_000);
215
- feed({ t: 'peer-joined', sessionId: 'c_eee111222333', clientId: 'k_mp', pairingToken: slot.token });
216
- const phone = phoneKeys(slot.psk, 'c_eee111222333');
217
- const items = ['a', 'b', 'c'].map((tag) => ({
218
- seq: 1,
219
- ciphertext: seal(phone.kC2H, {
220
- t: PAYLOAD_TYPES.cmdInterrupt,
221
- cmdId: `cmd_${tag}`,
222
- sessionId: 'ses_x',
223
- }).ciphertext,
224
- }));
225
- feed({ t: 'enc-batch', sessionId: 'c_eee111222333', items });
226
- assert.ok(commands.length >= 3, `批量帧解出 ${commands.length} 条:整批丢弃或漏项都会让手机的操作"点了一下没反应"`);
227
- assert.deepEqual(commands.map((item) => item.cmd.cmdId), ['cmd_a', 'cmd_b', 'cmd_c'], '批量帧内的顺序变了:同一会话的中断与发指令谁先谁后不可推断(T3 要求串行投递)');
228
- });
229
- test('hello-ok 之后 generation 递增:旧代配对全部作废并通知上层(中继重启后旧 convId 没人路由了)', () => {
230
- const { client, slots, feed, gone, outOf } = harness();
231
- feed({ t: 'hello-ok', role: 'host', hostId: 'h_test' });
232
- assert.equal(client.conversationCount, 0, '夹具自检:新连接还没有会话');
233
- const slot = slots.create(120_000);
234
- feed({ t: 'peer-joined', sessionId: 'c_fff111222333', clientId: 'k_mp', pairingToken: slot.token });
235
- assert.equal(client.hasPeer('c_fff111222333'), true, '夹具自检:会话已建立');
236
- // 中继重启:第二次 hello-ok 意味着新的代次。
237
- feed({ t: 'hello-ok', role: 'host', hostId: 'h_test' });
238
- assert.equal(client.conversationCount, 0, `代次变了还留着旧会话(${client.conversationCount} 条):主机对着一个不存在的通道发密文`);
239
- assert.deepEqual(gone, ['c_fff111222333'], '没有通知上层作废:手机端的"会话已失效,请重新配对"中文提示就发不出去');
240
- assert.equal(client.send('c_fff111222333', { t: PAYLOAD_TYPES.evRunState, sessionId: 'ses_x', state: 'running' }), false, '旧会话还能发出去');
241
- const resync = outOf('resync');
242
- assert.ok(resync.length >= 1, '鉴权成功后没发 resync:中继不知道该保留哪些会话(复核 R1 的恢复路径)');
243
- assert.deepEqual(resync[0].sessionIds, [], 'resync 应该只列出本端仍持有密钥的会话');
244
- });
245
- test('连续两次解不开同一会话就主动作废:对称于手机端"两帧解不开就丢配对"', () => {
246
- const { client, slots, feed, gone } = harness();
247
- const slot = slots.create(120_000);
248
- feed({ t: 'peer-joined', sessionId: 'c_000111222333', clientId: 'k_mp', pairingToken: slot.token });
249
- // 一条形状合法(标准 base64)、MAC 解不开的密文——像是手机端密钥已经被换掉。
250
- const junk = Buffer.alloc(24 + 16 + 4, 7).toString('base64');
251
- feed({ t: 'enc', sessionId: 'c_000111222333', ciphertext: junk });
252
- assert.equal(client.hasPeer('c_000111222333'), true, '一次解不开就丢配对太激进:小程序自己也给两帧机会');
253
- assert.equal(gone.length, 0, '第一次就通知作废了');
254
- feed({ t: 'enc', sessionId: 'c_000111222333', ciphertext: junk });
255
- assert.equal(client.conversationCount, 0, '两帧都解不开却还留着通道:手机会对着一个听不见的对端一直说话');
256
- assert.deepEqual(gone, ['c_000111222333'], '必须通知上层,让手机端看到"请重新配对"的中文提示');
257
- const leave = client.conversations.get('c_000111222333');
258
- assert.equal(leave, undefined, '密钥簿里还留着这条会话');
259
- });
260
- test('解不开计数在一帧成功解密后清零:偶发噪声不该攒成一次误废弃', () => {
261
- const { client, slots, feed, gone } = harness();
262
- const slot = slots.create(120_000);
263
- feed({ t: 'peer-joined', sessionId: 'c_111222333444', clientId: 'k_mp', pairingToken: slot.token });
264
- const phone = phoneKeys(slot.psk, 'c_111222333444');
265
- const junk = Buffer.alloc(24 + 16 + 4, 9).toString('base64');
266
- feed({ t: 'enc', sessionId: 'c_111222333444', ciphertext: junk });
267
- feed({
268
- t: 'enc',
269
- sessionId: 'c_111222333444',
270
- ciphertext: seal(phone.kC2H, { t: PAYLOAD_TYPES.cmdListSessions, cmdId: 'cmd_ok' }).ciphertext,
271
- });
272
- feed({ t: 'enc', sessionId: 'c_111222333444', ciphertext: junk });
273
- assert.equal(gone.length, 0, '中间成功过一帧,却被当成连续两次解不开而废弃:会话被误删,手机要重新扫码');
274
- assert.equal(client.hasPeer('c_111222333444'), true, '会话不该被误废');
275
- });
276
- test('base64 字符集不合法的密文只被拒收,不计入解不开次数(严进但不能因此丢配对)', () => {
277
- const { client, slots, feed, gone, logs } = harness();
278
- const slot = slots.create(120_000);
279
- feed({ t: 'peer-joined', sessionId: 'c_222333444555', clientId: 'k_mp', pairingToken: slot.token });
280
- for (const bad of ['####not-base64####', '', 'a']) {
281
- feed({ t: 'enc', sessionId: 'c_222333444555', ciphertext: bad.length === 0 ? 'AAAA' : bad });
282
- }
283
- assert.equal(gone.length, 0, `形状非法的帧被计成了"解不开"并导致废弃配对(gone=${JSON.stringify(gone)}):中继早就该拦下它`);
284
- assert.equal(client.hasPeer('c_222333444555'), true, '会话必须还在');
285
- assert.ok(logs.length >= 0, '夹具自检:日志通道可用');
286
- });
287
- test('peer-left 只摘掉那个客户端,会话与密钥必须留着(D3:手机回前台不该要求重新扫码)', () => {
288
- const { client, slots, feed, left, out } = harness();
289
- const slot = slots.create(120_000);
290
- feed({ t: 'peer-joined', sessionId: 'c_333444555666', clientId: 'k_mp', pairingToken: slot.token });
291
- assert.equal(client.conversationCount, 1, '夹具自检:会话已建立');
292
- feed({ t: 'peer-left', sessionId: 'c_333444555666', clientId: 'k_mp' });
293
- assert.deepEqual(left, [{ conversationId: 'c_333444555666', clientId: 'k_mp' }], '离开通知没交给上层:runtime 不知道该推一次列表');
294
- assert.equal(client.hasPeer('c_333444555666'), true, '客户端一走就把会话删了 → 手机切后台再回来必须重新扫码(旧实现的产品缺陷)');
295
- assert.equal(client.conversations.get('c_333444555666')?.psk, slot.psk, '密钥跟着丢了:同一条 convId 回来时再也解不开');
296
- assert.equal(out().some((frame) => frame.t === 'session-leave'), false, '不该因为 peer-left 就主动退出会话');
297
- const sent = client.send('c_333444555666', {
298
- t: PAYLOAD_TYPES.evRunState,
299
- sessionId: 'ses_x',
300
- state: 'running',
301
- });
302
- assert.equal(sent, true, '会话还在却发不出去:出站路径被 peer-left 悄悄断了');
303
- });
304
- test('主动作废已知会话:发 session-leave + 通知上层,且同一条通道只声明一次', () => {
305
- const { client, slots, feed, gone, outOf } = harness();
306
- const slot = slots.create(120_000);
307
- feed({ t: 'peer-joined', sessionId: 'c_444555666777', clientId: 'k_mp', pairingToken: slot.token });
308
- client.voidConversation('c_444555666777');
309
- assert.deepEqual(gone, ['c_444555666777'], '/drc unpair 之后上层不知道:手机还会以为配对仍在');
310
- const leave = outOf('session-leave');
311
- assert.equal(leave.length, 1, '没发 session-leave:中继会继续把这条会话的密文转过来');
312
- assert.equal(leave[0].sessionId, 'c_444555666777', '退出的必须是配对通道 id(c_ 前缀),不是 DSH 会话 id(F3)');
313
- client.voidConversation('c_444555666777'); // 同一原因再来一次
314
- assert.equal(leave.length, 1, `重复作废多发了 ${leave.length - 1} 条 session-leave:必须幂等`);
315
- assert.equal(gone.length, 1, '重复作废重复回调 gone:上层会收到两次"配对失效"');
316
- });
317
- /**
318
- * 复核 R1①:本端**没有**这条通道的记录时也必须声明 `session-leave`。
319
- *
320
- * 场景是这条链路上最难查的一个:主机进程重启 → 内存里的 PSK 全没了,中继却不知道,
321
- * 于是它继续把手机发来的密文转给一个解不开的对端。手机既等不到回复,也等不到
322
- * `unknown_session`(那个码只由"中继路由表未命中"产生,而这里表是命中的),
323
- * 表现是"发什么都没反应、也不提示重新配对"——整条链路上唯一的出口就是主机自己声明作废。
324
- * 第一版这里写的是 `if (!has(id)) return`,等于把出口堵死了。
325
- */
326
- test('对本端没有记录的 convId 也必须发 session-leave(主机重启后手机唯一的出口,复核 R1①)', () => {
327
- const { client, gone, outOf } = harness();
328
- client.voidConversation('c_重启之后不认识的会话');
329
- const leave = outOf('session-leave');
330
- assert.equal(leave.length, 1, '没钥匙又不声明:中继会一直把手机的密文转给一个解不开的对端,手机永远转圈');
331
- assert.equal(leave[0].sessionId, 'c_重启之后不认识的会话', '作废的必须是手机在用的那条 convId');
332
- assert.deepEqual(gone, ['c_重启之后不认识的会话'], '上层不知道这条已经死了:status.json 与自动补发都不会动');
333
- });
334
- /** 同一条路上更常见的触发方式不是有人调 API,而是手机发来一帧本端没有钥匙的密文。 */
335
- test('enc 打到一个本端不认识的 convId:立刻作废并声明,而不是静默丢帧', () => {
336
- const { client, slots, feed, gone, outOf } = harness();
337
- const slot = slots.create(120_000);
338
- feed({ t: 'peer-joined', sessionId: 'c_aabbccddeeff', clientId: 'k_mp', pairingToken: slot.token });
339
- client.conversations.close('c_aabbccddeeff'); // 模拟主机重启:内存里的密钥簿空了
340
- assert.equal(client.conversationCount, 0, '夹具自检:此刻本端一条会话都不该有');
341
- // 手机仍在旧 convId 上发。密文内容无所谓——本端连密钥都没有,走的是"查不到会话"那条分支。
342
- feed({ t: 'enc', sessionId: 'c_ffffffff0000', seq: 1, ciphertext: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' });
343
- assert.equal(outOf('session-leave').length, 1, '解不开又不声明:手机对着一个不存在密钥的通道说话');
344
- assert.deepEqual(gone, ['c_ffffffff0000'], '上层没被告知这条通道作废');
345
- assert.equal(client.hasPeer('c_ffffffff0000'), false, '不该顺手把陌生 convId 建成本端会话');
346
- });
347
- test('pair-fail 与未知帧名都要留痕:中继侧加一个名字,主机不许永远是哑的(F1)', () => {
348
- const { client, slots, feed, logs } = harness();
349
- slots.create(120_000);
350
- feed({ t: 'pair-fail', reason: 'already_used' });
351
- assert.ok(logs.some((line) => line.includes('pair failed') && line.includes('already_used')), `pair-fail 无人处理也不留痕(日志:${JSON.stringify(logs)}):手机扫完码主机侧完全无痕`);
352
- // 未定义的帧名:解析层就拒了,同样要留下一条"收到但丢弃"的痕迹。
353
- feed({ t: 'a-frame-we-do-not-know-yet' });
354
- assert.ok(logs.some((line) => line.includes('relay frame rejected')), '坏帧/未知帧静默蒸发:线上只能靠猜');
355
- assert.equal(client.conversationCount, 0, '上面两帧都不该建出会话');
356
- });
357
- test('出站 seq 逐帧递增且外层 sessionId 恒为配对通道 id(F3 的双 sessionId 不许混)', () => {
358
- const { client, slots, feed } = harness();
359
- const slot = slots.create(120_000);
360
- feed({ t: 'peer-joined', sessionId: 'c_555666777888', clientId: 'k_mp', pairingToken: slot.token });
361
- const socket = client.socket;
362
- socket.sent.length = 0;
363
- const payload = {
364
- t: PAYLOAD_TYPES.evMessageDelta,
365
- sessionId: 'ses_dsh_1',
366
- messageId: 'msg_1',
367
- delta: '你好',
368
- };
369
- client.send('c_555666777888', payload);
370
- client.send('c_555666777888', payload);
371
- const frames = socket.sent.map((text) => JSON.parse(text));
372
- assert.equal(frames.length, 2, '两条下行只发出一条:手机会少一段文本');
373
- assert.deepEqual(frames.map((frame) => frame.seq), [1, 2], `seq 序列是 ${JSON.stringify(frames.map((f) => f.seq))}:本端序号是"顺序可核对"的唯一依据`);
374
- assert.deepEqual(frames.map((frame) => frame.sessionId), ['c_555666777888', 'c_555666777888'], '外层 sessionId 必须是 convId:写成 DSH 会话 id 中继就路由不回去');
375
- assert.equal(JSON.stringify(frames).includes('ses_dsh_1'), false, '载荷里的 DSH 会话 id 泄漏到明文帧上了:中继会看到业务明文(红线 24)');
376
- });
377
- test('broadcast 只对活着的会话计数:断连期间不许假装"已发送"', () => {
378
- const { client, slots, feed } = harness();
379
- const first = slots.create(120_000);
380
- const second = slots.create(120_000);
381
- feed({ t: 'peer-joined', sessionId: 'c_666777888999', clientId: 'k1', pairingToken: first.token });
382
- feed({ t: 'peer-joined', sessionId: 'c_777888999aaa', clientId: 'k2', pairingToken: second.token });
383
- const payload = { t: PAYLOAD_TYPES.evSessionChanged, sessions: [] };
384
- assert.equal(client.broadcast(payload), 2, '两条会话都该收到广播');
385
- client.voidConversation('c_777888999aaa');
386
- assert.equal(client.broadcast(payload), 1, '作废之后广播数没降下来:调用方以为还有人在听');
387
- });
388
- test('畸形帧与未知帧名一律静默忽略且绝不抛:一条坏帧不该打断消息处理链', () => {
389
- const { client, feedText } = harness();
390
- assert.doesNotThrow(() => feedText('{not json'), '非法 JSON 把处理链抛断了:中继那边只是发了一帧脏数据');
391
- assert.doesNotThrow(() => feedText(JSON.stringify({ t: 'totally-new-frame', x: 1 })), '未知帧名抛了出去:F1 要求新帧名必须被静默忽略');
392
- assert.doesNotThrow(() => feedText(JSON.stringify({ t: 'pong', ts: 1 })), 'pong 必须被接受并忽略(T4:应用层不发心跳)');
393
- assert.doesNotThrow(() => feedText(JSON.stringify({ t: 'paired', sessionId: 'c_x', hostId: 'h_test' })), 'paired 是发给客户端的,主机侧必须忽略');
394
- assert.doesNotThrow(() => feedText(JSON.stringify({ t: 'error', code: 'unknown_session' })), 'error 帧要记进状态而不是抛');
395
- assert.equal(client.conversationCount, 0, '上面这些帧不该建出任何会话');
396
- });
397
- test('error 帧只进日志与状态,不主动清会话:清不清由 enc 路径判定(哪条通道只有那里知道)', () => {
398
- const { client, slots, feed, gone, logs } = harness();
399
- const slot = slots.create(120_000);
400
- feed({ t: 'peer-joined', sessionId: 'c_888999aaabbb', clientId: 'k_mp', pairingToken: slot.token });
401
- feed({ t: 'error', code: 'bad_token', message: 'token 不对' });
402
- assert.equal(gone.length, 0, '一条 error 帧就把配对清了:手机上表现为"莫名其妙要重新扫码"');
403
- assert.equal(client.hasPeer('c_888999aaabbb'), true, '会话必须还在');
404
- assert.ok(logs.some((line) => line.includes('bad_token')), '中继错误要进日志:否则"为什么没反应"没有答案(status.json 的 relayProblem 同源)');
405
- });
406
- test('stop() 之后一切出站都如实返回 false:调用方据此知道没人能收', () => {
407
- const { client, slots, feed, states } = harness();
408
- const slot = slots.create(120_000);
409
- feed({ t: 'peer-joined', sessionId: 'c_999aabbbccc0', clientId: 'k_mp', pairingToken: slot.token });
410
- assert.equal(client.send('c_999aabbbccc0', { t: PAYLOAD_TYPES.evRunState, state: 'idle' }), true, '夹具自检:停机前发得出去');
411
- client.stop();
412
- assert.equal(client.send('c_999aabbbccc0', { t: PAYLOAD_TYPES.evRunState, state: 'idle' }), false, 'socket 已关却返回 true:旧实现所有调用点都忽略返回值,这里必须诚实');
413
- assert.equal(client.broadcast({ t: PAYLOAD_TYPES.evRunState, state: 'idle' }), 0, '停机后广播数必须为 0');
414
- const last = states[states.length - 1];
415
- assert.equal(last?.relay, 'offline', `停机后的状态是 ${String(last?.relay)}:status.json 会一直谎报 online`);
416
- });
417
- test('ConversationBook 与 PairingSlots 的协作:同一条 convId 重复 joined 必须换回新密钥', () => {
418
- const { client, slots, feed } = harness();
419
- const older = slots.create(120_000);
420
- const newer = slots.create(120_000);
421
- feed({ t: 'peer-joined', sessionId: 'c_aaabbcccddd', clientId: 'k1', pairingToken: older.token });
422
- const before = client.conversations.get('c_aaabbcccddd')?.psk;
423
- feed({ t: 'peer-joined', sessionId: 'c_aaabbcccddd', clientId: 'k2', pairingToken: newer.token });
424
- const after = client.conversations.get('c_aaabbcccddd');
425
- assert.equal(after?.psk, newer.psk, `同一条 convId 的二次 joined 没有换钥(before=${before} after=${after?.psk})`);
426
- assert.equal(client.conversationCount, 1, '一条 convId 攒出了多条会话:簿记键必须是 convId 本身');
427
- // 手机此刻拿的是新那张码的 PSK:主机下行必须能用它解开。
428
- const socket = client.socket;
429
- socket.sent.length = 0;
430
- client.send('c_aaabbcccddd', { t: PAYLOAD_TYPES.evRunState, sessionId: 'ses_x', state: 'idle' });
431
- const frame = JSON.parse(socket.sent[0]);
432
- assert.equal(open(phoneKeys(newer.psk, 'c_aaabbcccddd').kH2C, { ciphertext: frame.ciphertext }) !== null, true, '换钥之后下行仍用旧钥密封:手机解不开');
433
- });
434
- test('中继来帧的 sessionId 逐字用作会话键(F3:两套 id 一旦混用整页无输出)', () => {
435
- const { client, slots, feed } = harness();
436
- const slot = slots.create(120_000);
437
- const convId = 'c_0123456789ab';
438
- feed({ t: 'peer-joined', sessionId: convId, clientId: 'k_mp', pairingToken: slot.token });
439
- assert.equal(client.conversations.ids().length, 1, '会话没建出来');
440
- assert.equal(client.conversations.ids()[0], convId, '会话键被加工过(加/去前缀都会让路由对不上)');
441
- assert.equal(client.conversationIds()[0], convId, 'conversationIds() 必须原样透出:runtime 靠它挑通道发审批卡');
442
- assert.equal(String(client.conversations.ids()[0]).startsWith('c_'), true, '前缀 c_ 是冻结字符串(B9)');
443
- });
444
- test('状态回调如实汇报会话数与代次:status.json 的 conversations/generation 就是从这来的', () => {
445
- const { client, slots, feed, states } = harness();
446
- feed({ t: 'hello-ok', role: 'host', hostId: 'h_test' });
447
- const slot = slots.create(120_000);
448
- feed({ t: 'peer-joined', sessionId: 'c_bbccddeeff00', clientId: 'k_mp', pairingToken: slot.token });
449
- const last = states[states.length - 1];
450
- assert.ok(last !== undefined, '一次状态都没回调:status.json 里 relay 会永远停在 connecting');
451
- assert.equal(last.relay, 'online', `状态是 ${last.relay}:手机上"连不上"与"配上了但一切不通"看起来一模一样`);
452
- assert.equal(last.conversations, 1, '会话数不对');
453
- assert.equal(last.generation, 1, '代次不对:发布循环靠它判断中继重启过没有');
454
- });
455
- test('配对槽位簿记与传输层用的是同一张表:pair-ready 对未知 token 要留下痕迹', () => {
456
- const { feed, slots, logs } = harness();
457
- feed({ t: 'pair-ready', pairingToken: '424242', ttlMs: 60_000 });
458
- assert.equal(slots.resolveFor('424242'), null, '夹具自检:本地根本没有这张码');
459
- assert.ok(logs.some((line) => line.includes('pair-ready for an unknown token')), '服务端为一张我们没发过的码发来了 TTL:这必须留痕,否则配对流程出现了第二份真相');
460
- });
461
- /**
462
- * 配对通道剪枝。D3 让通道跨断连长存,而**中继侧的空闲 TTL 是 7 天**
463
- * (`DRC_CONV_IDLE_TTL_MS`),所以"等中继先忘掉"等于永远不剪:
464
- * 每天配一次对的主机两周就能攒两百多条 PSK,并且每次广播都对废弃通道逐个密封。
465
- * 关键约束是:剪枝必须走 `voidConversation`(发 `session-leave` + 回调上层),
466
- * 只删内存就等于复核 R1 那个静默黑洞换了个入口重来一次。
467
- */
468
- test('空闲超时的通道被剪掉时必须发 session-leave 并通知上层(不能只删内存)', async () => {
469
- const { client, clock, slots, feed, gone, outOf } = harness();
470
- const first = slots.create(120_000);
471
- feed({ t: 'peer-joined', sessionId: 'c_old000000001', clientId: 'k1', pairingToken: first.token });
472
- // 第二条:刚活动过,不该被剪。
473
- await clock.advance(10);
474
- const second = slots.create(120_000);
475
- feed({ t: 'peer-joined', sessionId: 'c_new000000002', clientId: 'k2', pairingToken: second.token });
476
- await clock.advance(25 * 3600 * 1000); // 一天多没有任何收发
477
- client.send('c_new000000002', {
478
- t: PAYLOAD_TYPES.evKeepAwakeState,
479
- enabled: true,
480
- active: false,
481
- platform: 'darwin',
482
- backend: 'caffeinate',
483
- });
484
- const pruned = client.pruneConversations();
485
- assert.deepEqual(pruned, ['c_old000000001'], `剪掉的应该是那条一天没动静的,实际剪了 ${JSON.stringify(pruned)}`);
486
- assert.equal(client.hasPeer('c_old000000001'), false, '剪了内存却没关通道');
487
- assert.deepEqual(gone, ['c_old000000001'], '上层不知道:status.json 与自动补发都不会动');
488
- const leave = outOf('session-leave');
489
- assert.equal(leave.length, 1, '没发 session-leave:中继会继续把手机的密文转给一条已经没有钥匙的通道');
490
- assert.equal(leave[0].sessionId, 'c_old000000001');
491
- assert.equal(client.hasPeer('c_new000000002'), true, '刚有收发的通道被顺手剪了');
492
- });
493
- test('条数上界是真上界:超出后从最不活跃的开始剪,而不是拒绝新建', () => {
494
- const { client, clock, slots, feed } = harness();
495
- const policy = { idleTtlMs: 24 * 3600 * 1000, maxConversations: 3 };
496
- client.options.prunePolicy = policy;
497
- for (let index = 0; index < 5; index++) {
498
- const slot = slots.create(120_000);
499
- feed({ t: 'peer-joined', sessionId: `c_cap${index}`, clientId: `k${index}`, pairingToken: slot.token });
500
- void clock.advance(1); // 保证活跃时刻有先后
501
- }
502
- assert.equal(client.conversationCount, 5, '夹具自检:还没剪之前是 5 条');
503
- // 关键一步:让**创建最早**的那条重新活跃。不这样做的话"按最后活动剪"与
504
- // "按创建序剪"两种实现给出的结果一模一样,这条断言就什么都没守(变异验证抓出来的)。
505
- assert.equal(client.send('c_cap0', {
506
- t: PAYLOAD_TYPES.evKeepAwakeState,
507
- enabled: true,
508
- active: false,
509
- platform: 'darwin',
510
- backend: 'caffeinate',
511
- }), true, '夹具自检:c_cap0 要有收发记录');
512
- const pruned = client.pruneConversations();
513
- assert.equal(pruned.length, 2, `上界 3 却剪了 ${pruned.length} 条`);
514
- assert.deepEqual(pruned, ['c_cap1', 'c_cap2'], `必须按"最后活动"从最不活跃开始剪(刚有收发的 c_cap0 必须留下),实际剪了 ${JSON.stringify(pruned)}`);
515
- assert.equal(client.conversationCount, 3);
516
- assert.equal(client.hasPeer('c_cap0'), true, '刚发过数据的通道被剪:手机会突然撞上"会话已失效"');
517
- });
518
- test('停机时 socket 还停在 CONNECTING:close() 的异步 error 不许升级成 uncaughtException', async () => {
519
- // 这条**必须用真 ws**(所以这里不 attachSocket)。机制来自 ws:socket 还在 CONNECTING
520
- // 时 close() 走 abortHandshake,那条路径是 process.nextTick 抛 error ——
521
- // 假 socket(EventEmitter)复现不了,而**同步的 try/catch 也拦不住异步抛出**。
522
- // 于是 removeAllListeners() 摘掉 error 监听器之后它没人接,升级成 uncaughtException
523
- // 把进程带崩。表现是 e2e 偶发红:'WebSocket was closed before the connection was
524
- // established'(只有"连接还没建好就停机"这个窗口才触发,所以时红时绿,很难查)。
525
- const caught = [];
526
- const onUncaught = (e) => {
527
- caught.push(e);
528
- };
529
- process.on('uncaughtException', onUncaught);
530
- try {
531
- const clock = new FakeClock();
532
- const slots = new PairingSlots(() => clock.now());
533
- const client = new RelayClient({
534
- url: 'ws://127.0.0.1:1', // 没人监听 → 一直停在 CONNECTING
535
- hostId: 'h_connecting',
536
- label: '测试主机',
537
- token: 'fake-host-token-not-a-real-secret-0123',
538
- clock,
539
- log: () => { },
540
- onCommand: () => { },
541
- onPeerJoined: () => { },
542
- onConversationGone: () => { },
543
- onClientLeft: () => { },
544
- lookupPairingSlot: (token) => slots.resolveFor(token),
545
- onPairReady: () => { },
546
- onState: () => { },
547
- });
548
- client.connect();
549
- client.stop(); // 就在"连接还没建好"这个窗口里停机
550
- await new Promise((resolve) => setTimeout(resolve, 200));
551
- assert.deepEqual(caught.map((e) => e.message), [], '停机时 close() 一个 CONNECTING 的 socket 会异步抛 error;必须在摘完监听器后补一个 error 兜底');
552
- }
553
- finally {
554
- process.removeListener('uncaughtException', onUncaught);
555
- }
556
- });
557
- //# sourceMappingURL=relay-client.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"relay-client.test.js","sourceRoot":"","sources":["../../tests/relay-client.test.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};