357ac45281
- 登录门:非 signed_in 全屏盖 app,登录/注册/找回三页,只盖 UI
不断机器通道(U-1);status 通道异常落登录页不砖(U-3)
- U-5:登录成功当场校验本机 installation ∈ 会话用户列表,不符即
销毁会话并提示绑定者邮箱;绑定状态损坏 fail-closed
- relay 客户端补注册/找回四通道 + installations/binding-owner 查询;
IPC 预期失败全部结构化 {ok:false, code} 返回
- i18n userAccount 48 键 × 6 语言;electron +11 / ui +7 测试全绿
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
47 lines
1.6 KiB
TypeScript
47 lines
1.6 KiB
TypeScript
import assert from 'node:assert/strict'
|
||
|
||
import { test } from 'vitest'
|
||
|
||
import { loadMachineBinding, MachineBindingError, parseMachineBinding } from './machine-binding'
|
||
|
||
const VALID = JSON.stringify({
|
||
relay_binding: {
|
||
site: 'https://relay.example.com/',
|
||
agent_id: 'inst-1',
|
||
route: 'r',
|
||
host_key_fingerprint: 'AAAA-AA',
|
||
key_epoch: 1,
|
||
host_refresh_token: 'SECRET',
|
||
protocol_version: 1,
|
||
bound_at: '2026-09-19T00:00:00Z',
|
||
last_connected_at: null
|
||
},
|
||
host_identity: { private_key: 'ALSO-SECRET' }
|
||
})
|
||
|
||
test('合法绑定只取 site + installationId,site 规范化', () => {
|
||
assert.deepEqual(parseMachineBinding(VALID), { site: 'https://relay.example.com', installationId: 'inst-1' })
|
||
})
|
||
|
||
test('无 relay_binding 键 = 未绑定', () => {
|
||
assert.equal(parseMachineBinding('{}'), null)
|
||
assert.equal(parseMachineBinding('{"relay_binding":null}'), null)
|
||
})
|
||
|
||
test('损坏/缺字段/坏站点 fail-closed 抛 binding_state_invalid', () => {
|
||
assert.throws(() => parseMachineBinding('{broken'), MachineBindingError)
|
||
assert.throws(() => parseMachineBinding('{"relay_binding":{"site":"https://r"}}'), MachineBindingError)
|
||
assert.throws(() => parseMachineBinding('{"relay_binding":{"site":"http://evil.example.com","agent_id":"x"}}'), MachineBindingError)
|
||
})
|
||
|
||
test('loadMachineBinding:ENOENT = 未绑定;损坏抛出', () => {
|
||
assert.equal(
|
||
loadMachineBinding(() => {
|
||
throw new Error('ENOENT')
|
||
}),
|
||
null
|
||
)
|
||
assert.equal(loadMachineBinding(() => VALID)?.installationId, 'inst-1')
|
||
assert.throws(() => loadMachineBinding(() => '{broken'), MachineBindingError)
|
||
})
|