C04 多设备能力收口
C04 对应“多端在线 / 多设备消息同步”能力。rev25 补齐了设备级投递游标与离线补收:Web/Electron/Android/Flutter 四端 SDK 自动生成并持久化 deviceId,服务端按设备独立记录 deliveredSeq。本页汇总能力、平台状态、证据、验收清单与剩余边界。
矩阵状态(Lead 汇总)
缺口矩阵:C04-web / C04-electron / C04-android / C04-flutter 已置 implemented;C04-native 仍 partial;C04-ios / C04-harmony missing(reserved)。
总计:382 implemented / 125 partial / 59 missing / 11 na / 14 excluded(591 行,由 Lead 更新,文档不改矩阵)。
能力清单与证据
| 能力 | 实现 | 证据 |
|---|---|---|
| 多端同时在线 | 同一 userId 允许多条 WS 会话;新连接不踢旧连接;消息扇出到全部在线端 | 服务端 online 列表 + 投递路径 |
| 稳定设备标识 | 各端 SDK 首次生成随机 deviceId 并持久化,重连/重启复用;业务无需传入 | Web localStorage;Electron device.json;Android ImStore;Flutter device storage |
| WS query 与 hello | WS 可选 deviceId(≤128,超长拒绝握手);hello 回显并在 syncState 返回该设备 deliveredSeq | IDL rev25;服务端 rev25 |
| 每设备投递游标 | {app}:{user}:{device}:{conv} 记录最大已 ack seq;A ack 不推进 B | rev25 单测(两设备隔离/legacy 隔离/重连持久化) |
| 每设备离线补收 | hello 后按该设备游标补发未 ack 消息,最后 sync_done;受每会话 500 条上限 | rev25 单测(新设备全量/重连不重复) |
| read / read_receipt 推进设备游标 | 已读后重连不再补收已读消息;回执同样推进当前设备游标 | rev25 单测(read / read_receipt) |
| legacy 兼容 | 无 deviceId 的旧客户端继续用用户级游标,行为不变 | rev25 单测(legacy ack 与 device ack 独立) |
| 两阶段冒烟 | 27 项多设备冒烟(设备 A/B 隔离、新设备、重连、legacy) | 服务端 181 tests + 冒烟 |
平台状态
| 平台 | 状态 | 说明 |
|---|---|---|
| Web / Electron / Android / Flutter | ✅ implemented | SDK 自动生成并持久化 deviceId、建连携带、hello 回显处理;测试:Web v32 22/0、Electron 100、Android 402、Flutter 146+60 |
| Native(C ABI) | 🟡 partial | C ABI 无 deviceId/游标控制;离线补发按用户游标(等价 legacy),无跨端设备隔离 |
| iOS / HarmonyOS | ⛔ missing(reserved) | 声明同构、无运行时代码 |
验收清单
- 同一账号同 Token 建两条 WS(两条不同 deviceId)→ 都收到 hello,且 hello.deviceId 与各自 query 一致。
- A 设备 ack 一条消息 → B 断开重连 → B 仍补收该消息(A ack 不影响 B)。
- B 设备持续在线并 ack → 断开重连 → 不再重复补收已 ack 消息(游标持久化)。
- 新 deviceId 首次连接 → 收到全部未 ack 消息(≤每会话 500 条);超过时用历史分页补齐。
- 同一客户端断线重连复用同一 deviceId(不因重连生成新设备)。
- 旧客户端(不带 deviceId)与新版并存:legacy 游标独立推进,行为与升级前一致。
- deviceId >128 字符 → 握手被拒绝(HTTP 400/1001);空白视为未提供。
- read 会话后再重连:不再补收已读消息;其他设备未读行为保持用户级(已知限制)。
剩余边界
| 项 | 现状 |
|---|---|
| 端级未读 / 端级已读明细 | 未实现:未读与已读回执仍按用户聚合(read 会清用户级未读) |
| 设备凭证 | deviceId 是客户端自报,无设备级鉴权 |
| Native / iOS / HarmonyOS 运行时 | C ABI 无设备游标;iOS/Harmony 无运行时 |
| 任务栏/角标按端 | 未实现(依赖端级未读) |
| 设备管理页 | 未提供设备列表/下线接口(deviceId 仅用于游标) |