refactor(core): drop per-terminal device labels
Remove sealLabel/openLabel and their label constants; devices are no longer named per channel. Rename the create setting seats to max_members and point the e2e join helper at POST /join.
This commit is contained in:
1 parent
d946fc5e8a
commit
5fd4ddd411
6 files changed
+12
-171
No files matched your search
@@ -51,7 +51,6 @@ ws.onmessage = async (m) => {
|
||||
| 加密成帧、padding、IV、AAD | 发送队列(IndexedDB)、失败重发 |
|
||||
| 解密、完整性校验、乱序/重复/篡改处理 | 把事件渲染成界面 |
|
||||
| 链接生成与解析、降级防御 | 持久化链接和**终端密钥** |
|
||||
| 设备名加解密 | 复制、下载(把流写到文件)、预览 |
|
||||
| 日志记录解析 | **Cap 验证码**(见下文) |
|
||||
|
||||
## API
|
||||
@@ -67,7 +66,6 @@ ws.onmessage = async (m) => {
|
||||
| `session.link(origin, 'member' \| 'owner')` | 生成分享链接 |
|
||||
| `session.verifyChannelInfo({ id, mode })` | 核对服务端返回的频道信息,不一致抛 `ModeMismatchError` / `LinkError` |
|
||||
| `session.id` / `.mode` / `.role` / `.endpointSecret` / `.endpointHash` | 只读属性 |
|
||||
| `session.deviceName` | 设置后,加密的条目元数据里会带上设备名 |
|
||||
| `session.dispose()` | 尽力清零密钥材料(JS 无法保证擦除) |
|
||||
|
||||
### 发送
|
||||
@@ -91,7 +89,7 @@ ws.onmessage = async (m) => {
|
||||
| `snapshot` | 快照必须是单帧(约 1 MiB 以内),不能 GATED |
|
||||
| `itemId` | 重试和续传必须复用同一个 id |
|
||||
| `fromFrame` | 上传断点续传:从第 k 帧开始产出(字节与完整加密完全相同)。仅支持 `Blob` / `Uint8Array` |
|
||||
| `ts`, `dev` | 覆盖时间戳和设备名 |
|
||||
| `ts` | 覆盖时间戳 |
|
||||
|
||||
**GATED 的判断**:来源长度已知时创建计划时就确定;来源是流时,要产出第 0 帧之后 `plan.gated` 和 `frame0Headers` 才确定,请在拿到第 0 帧后再读取。
|
||||
|
||||
@@ -131,13 +129,12 @@ const { complete, nextIndex, meta } = await result;
|
||||
| 调用 | 说明 |
|
||||
|---|---|
|
||||
| `parseLogRecords(bytes)` / `parseLogRecord(bytes)` | 解析 `GET /log` 的响应或一条 WebSocket 消息 |
|
||||
| `session.sealLabel(name)` / `session.openLabel(blob, endpointHash)` | 设备名(`PUT /seats/me` 的请求体 / 席位列表里的 `label`) |
|
||||
| `parseLink(url)` / `buildLink(origin, parts)` | 链接 |
|
||||
| `splitEnvelopes(stream)` | 把「封装首尾相接」的字节流切成一个个封装 |
|
||||
|
||||
## 必须注意的几点
|
||||
|
||||
**1. 终端密钥必须持久化。** `session.endpointSecret`(32 字节)标识「这台设备在这个频道里」,服务端按它登记独立设备席位以便认证和撤销;频道成员上限按账号数计算,同一账号的多台设备不重复占名额。不持久化的话,每次打开链接都会登记一个新设备终端。用 IndexedDB 保存,下次 `open(link, { endpointSecret })` 传回来。
|
||||
**1. 访客终端密钥必须持久化。** `session.endpointSecret`(32 字节)标识「这个访客终端在这个频道里」,服务端按它登记访客以便认证和移除;登录账号以账号会话鉴权,不需要它,同一账号的多台设备也不重复占名额。访客不持久化的话,每次打开链接都会登记一个新访客终端。用 IndexedDB 保存,下次 `open(link, { endpointSecret })` 传回来。
|
||||
|
||||
**2. Worker。** `ChannelSession` 实例不能跨线程传递(它持有 `CryptoKey` 和闭包)。在 Worker 里用链接和 `endpointSecret` 重建它,主线程只传链接、帧字节和事件。
|
||||
|
||||
@@ -167,10 +164,10 @@ npm run vectors:check # 校验 test-vectors/vectors.json 是最新的
|
||||
| 文件 | 内容 |
|
||||
|---|---|
|
||||
| `vectors.test.ts` | 逐字节复现 `test-vectors/` 里 node:crypto 独立生成的全部向量,含 17 个负例 |
|
||||
| `session.test.ts` | 创建、链接、角色、降级防御、收发、设备名、raw 模式、条目计划 |
|
||||
| `session.test.ts` | 创建、链接、角色、降级防御、收发、raw 模式、条目计划 |
|
||||
| `reader.test.ts` | 日志记录、重放、乱序、缺帧、FINAL 冲突、标志变化、模式隔离 |
|
||||
| `stream.test.ts` | 任意切分的字节流、流式解密、篡改/拼接/丢帧/截断、断点续传 |
|
||||
| `properties.test.ts` | 每个字节每一位的篡改、padding 档位、随机往返、来源块边界对齐、性能底线 |
|
||||
| `e2e.test.ts` | 真实服务端:HTTP、WebSocket、大文件、下载上限、上传与下载续传、设备名 |
|
||||
| `e2e.test.ts` | 真实服务端:HTTP、WebSocket、大文件、下载上限、上传与下载续传 |
|
||||
|
||||
另外对测试集做过**变异检验**:故意在实现里注入 10 类典型错误(AAD 少一字节、跳过零填充检查、去掉模式/条目 id 校验、base64 不查规范性、分块边界差一、IV 不含帧序号、重复帧不比较、FINAL 后不拒绝、链接不拒绝查询串密钥),测试都能变红。其中「分块边界差一」最初漏网,说明测试有缺口,已补上专门的边界对齐用例。
|
||||
Reference in new issue
Block a user