Skip to content

2026-08-30 迭代 — 验收用例(TC) ​

依据 PRD 原文 与 技术方案。PRD 定义产品行为,技术方案定义实现契约; 本文只把两者转成可重复执行、可留证据的判定条件,不另行扩大范围。 本文与 PRD、技术方案一同评审,评审通过后方可作为本期验收依据。

任务追踪:GitHub 父 Issue · 组织 Project

1. 执行规则 ​

  • 会上只执行 10 条,每条判定时间不超过 3 分钟;双平台步骤由两人并行操作。
  • 其余用例在 2026-08-29 下午预跑前完成,并附截图、录屏、请求响应、数据库断言或日志之一。
  • 一条用例的全部判定条件均满足才算通过;部分满足、无证据或只能口头说明都记为不通过。
  • 因资产、环境或评审结论缺失而无法执行时记为阻塞,不允许把“未测”写成“通过”。
  • 涉及时间的用例以服务端时间为准;涉及跨端收敛的用例从触发动作开始计时。
  • 离线用例允许用验收配置缩短 30 天、14 天等长周期,但必须证明生产默认值仍正确。

1.1 本期冻结的验收基线 ​

项目验收值
心跳间隔 30s;允许连续丢失 2 次;第 3 次仍无响应时按 90s 判死
心跳收敛失活到连接资源释放、设备转离线不超过 95s;登录会话与设备记录不变
刷新令牌绝对有效期 30 天;连续 14 天无续期视为空闲到期
撤回时限MESSAGE_RECALL_WINDOW_MS=0,即本期不限制历史消息的撤回时间
本地通道依次探测 127.0.0.1:17650-17652;授权码有效期不超过 60s
P2P批量历史同步只走 WebRTC DataChannel,不用 TURN,不经业务服务端中转
P2P 加密评审选择“仅防第三方窃听”时以 DataChannel 强制 DTLS 为通过条件;若选择“同时防信令服务端”,还必须通过带外配对码校验。评审未记录选择则该功能阻塞
密码 H1PBKDF2-HMAC-SHA256,100_000 次,输出 32 字节;最慢目标设备单次计算 p95 ≤ 500ms
密码 H2沿用服务端 scrypt:cost=16384, r=8, p=1, keyLen=64,随机盐;本期不加 pepper

2. 环境前置 ​

  • 验收环境部署 nexo-auth、nexo-im-api、nexo-app、nexo-im-pc,HTTPS、WSS、反代与服务间 HMAC 可用。
  • 两个账号:账号 A、账号 B;A 至少同时登录三端,B 至少登录一端。
  • 设备甲:macOS,安装桌面包,并安装 Chrome、Safari、Firefox。
  • 设备乙:Windows,安装桌面包,并安装 Chrome、Edge、Firefox。
  • 两种网络:同一局域网,以及分属两个公网出口的跨网环境;另准备一个明确无法 P2P 建连的环境。
  • 准备可修改 Origin、令牌、PKCE 参数与系统时间/验收配置的调试工具。
  • 准备数据库只读查询、服务端日志、浏览器存储检查、系统凭证库检查与网络抓包能力。
  • 为 P2P 准备不少于 1_000 条、跨多个日期且可辨识来源设备的历史消息。
  • Windows 准备干净安装环境;macOS 准备可删除应用包但保留用户数据目录的环境。

3. 会上用例(固定 10 条) ​

编号用例操作摘要判定阈值
MTG-01桌面 WebView 内置登录桌面端从未登录态进入登录页并完成 A 登录不打开系统浏览器;登录页来自认证中心;授权成功回工作台且窗口不关闭;全程无手工复制凭证
MTG-02网页读取桌面登录态桌面 A 已登录,网页清登录态后打开;在桌面确认授权每次都显示请求 Origin;网页零次输密码;网页生成自己的 device/session;踢网页不影响桌面
MTG-03强制下线与完整退出设备甲踢设备乙,再由甲主动退出乙 ≤5s 回登录页并显示指定文案;甲不受影响;甲退出后页面可继续操作,内存会话/未读/草稿清空
MTG-04心跳判死后无感重连阻断乙的 WS 心跳,观察到离线后恢复网络≤95s 释放连接并转离线;设备/session 仍在;恢复后用原凭证重连,全程不出现登录页
MTG-05在线多端消息撤回A 发消息给 B,再从 A 任一端撤回A、B 所有在线端 ≤2s 显示“XX 撤回了一条消息”;正文不再可见;顺序不跳动
MTG-06P2P 按设备与时间同步B 端选择从 A 的指定设备、指定日期起同步只得到所选来源与时间范围;进度完成;业务服务端无批量正文流量;同步结果无重复
MTG-07桌面后台通知A 桌面端失焦,B 发消息,点击系统通知后台收到原生通知;点击直达正确会话;在前台且停留该会话时不再弹
MTG-08跨端未读只消费一次A 的两个端同时收到 B 的未读,其中一端打开会话另一在线端未读、红点、角标 ≤2s 归零;已弹通知不要求撤回
MTG-09本地历史与账号隔离A 拉取历史后断网重启,再退出改登 BA 离线历史可见;B 看不到 A 的消息、草稿和未读;A 再登录后仍可读本地历史
MTG-10双平台自绘窗口macOS、Windows 两人并行检查拖动、双击、三键、边缘缩放两个平台均无原生标题栏;全部交互有效;窗口空白区横向滑动无白边

会上记录只填本节 10 条;详细复现步骤与离线证据要求见后续同名覆盖用例。

4. A 组:登录、设备、会话与密码 ​

编号用例与步骤判定条件类型 / 证据
A01清除桌面端登录态,从应用内完成账号 A 登录WebView 加载认证中心托管页;继续走授权码 + PKCE;不打开系统浏览器;成功后回到工作台且窗口不自行关闭会上 MTG-01;录屏 + 网络请求
A02桌面 A 已登录,网页端清登录态后打开登录页并允许桌面确认弹窗展示准确 Origin 且每次新建网页会话都重新确认;网页零次输入密码;网页与桌面各有独立 device/session;吊销任一端不影响另一端会上 MTG-02;录屏 + /devices 响应
A03分别在桌面未运行、未登录、三个端口均被占用时打开网页登录页全部安静回退到常规密码登录,不弹错误、不无限等待;端口按 17650→17651→17652 顺序探测离线;浏览器网络面板 + 录屏
A04用白名单外 Origin、伪造 Origin 工具及预检请求访问本地通道非白名单返回 403,不带允许读取的 CORS 头、不弹确认框;白名单逐 Origin 回显,禁止 *;需要 PNA 时正确返回私网预检头离线;六浏览器矩阵请求响应
A05用户拒绝授权、授权码超 60s、同一码兑换两次、错误 code_verifier拒绝时网页保持未登录;过期、重放、PKCE 不匹配均不签发令牌;码绑定 client_id 与 code_challenge离线;请求响应 + 数据库断言
A06桌面端连续重启应用 10 次、重启系统一次、卸载重装一次账号 A 的桌面 device id 始终相同;每次仅新建 session;系统凭证库中的 device_key 不变离线;前后 /devices 响应 + 凭证库脱敏截图
A07同一浏览器退出/登录 10 次,再关闭重开、令牌到期后重登,最后清空站点数据再登录清站点数据前始终复用同一 device 行;清空后新增一条属预期;旧 session 均已失效离线;数据库计数断言
A08同一浏览器分别登录 A、B;同机桌面、Chrome、Safari/Edge 均登录 AA、B 的设备互不可见;A 在同机的各端分别占一条设备记录,可独立吊销离线;两账号 /devices 响应
A09从两个 IP 登录/续期后查看地址;令归属地服务超时或返回失败last_ip 与城市级归属地更新为最近活跃来源;查询失败展示“未知”,登录和列表渲染不受阻离线;接口响应 + 超时日志
A10在最慢目标设备登录,检查浏览器/WebView 请求、服务端日志、进程采样和数据库H1 参数符合基线且 p95≤500ms;线上只出现 H1 输出;H2 使用随机盐;明文与 H1 输出均不进 URL/日志;数据库只存 H2离线;性能采样 + 脱敏检查结果
A11分别提交错误密码与不存在用户名,重复采样响应状态、正文与耗时两类响应不可区分;不存在用户也完整执行确定性盐派生与 H1;不得暴露账号是否存在离线;至少 20 次采样结果
A12A 的桌面与网页同时在线;重放桌面端旧刷新令牌只吊销涉事 sid;网页 session、device 与 WS 不受影响;涉事 device 行保留;原因记为 token_reuse离线;数据库 + 两端行为
A13用有效令牌越权访问他人资源,再用过期/吊销令牌访问同一页面403 只提示无权访问且保持登录态;401 才清凭证回登录页;403 不得被统一拦截器改写为 401 行为离线;录屏 + 请求响应
A14一端强制下线,再执行主动退出;分别注入清令牌、关 WS 等步骤失败被踢端 ≤5s 显示“你的账号已在其他设备上退出登录”;主动退出与异常注入都完整执行 teardown;本地消息库不删除会上 MTG-03;录屏 + 客户端状态快照
A15用缩短的验收配置验证绝对到期与空闲到期,再核对生产默认配置两类到期均回登录页并显示“登录已过期,请重新登录”;连接断开本身不计为空闲;生产值为 30 天/14 天且启动时校验离线;配置 + 计时录屏

5. B 组:心跳与连接回收 ​

编号用例与步骤判定条件类型 / 证据
B01正常连接持续跨过至少 4 个心跳周期ping/pong 正常;连接不被误判;session 在线状态持续更新且无重复连接槽位离线;WS 日志
B02只阻断客户端心跳,保留认证服务可用第 1、2 次丢失不判死,第 3 次才判死;≤95s 释放 socket、槽位与路由表项并上报离线;不吊销 session、不删 device会上 MTG-04;计时录屏 + 数据库断言
B03B02 后恢复网络客户端以现有凭证自动重连;disconnected_at 清空/连接态恢复;全程不出现登录页、不重新输入密码会上并入 MTG-04;录屏
B04分别主动关闭客户端、杀进程与被动超时三条路径最终都不留僵尸连接、都不改变登录态;重复 unregister/disconnected 上报保持幂等离线;连接计数 + 日志
B05阻断 IM→Auth 的 disconnected 上报,再等待软状态兜底列表在 2×DEAD_MS 后按离线渲染;恢复后可自愈;任何鉴权与吊销判断都不依赖在线软状态离线;故障注入 + 列表截图
B06缺失、非法或互相矛盾的心跳配置启动服务;运行期刷新合法配置非法配置启动失败并指出具体字段;业务代码不直接读取环境变量;合法配置可重新获取,三参数关系始终一致离线;启动日志 + 代码审查记录

6. C 组:消息撤回 ​

编号用例与步骤判定条件类型 / 证据
C01A 向 B 发消息后撤回,双方保持在线所有在线端 ≤2s 收到撤回事件并显示“XX 撤回了一条消息”;消息原位置不变;正文不再出现在 UI会上 MTG-05;计时录屏
C02A、B 各登录两端;让其中一端离线后撤回,再恢复离线端在线四端同步更新;离线端按 after_seq 拉到 recall 事件并清掉本地正文,不需要全量重拉离线;多端录屏 + 增量响应
C03撤回后遍历列表、分页、搜索、增量等业务接口,并只读检查归档表所有业务接口均拿不到正文;messages.content='';归档表恰好保留一份原文且业务查询不关联归档表离线;接口集合 + 数据库断言
C04B 尝试撤回 A 的消息返回 403,不泄露正文、不产生归档/事件、不清 B 登录态;401/403 行为符合 A13离线;响应 + 数据库计数
C05对同一消息重复、并发撤回,并在事务第 2/3 步注入失败重复调用均返回成功但只产生一条归档和一条 recall 事件;任一步失败都整体回滚,无半撤回状态离线;并发测试 + 事务断言
C06撤回一条远早于本迭代的历史消息MESSAGE_RECALL_WINDOW_MS=0 时成功;service 层存在统一时限校验点,未来启用不改协议和客户端离线;请求响应 + 代码审查
C07撤回会话最后一条消息并检查顺序、预览和未读recall 占新 seq;原消息不跳到末尾;双方顺序一致;预览显示撤回文案;recall 行不计未读离线;两端序列快照 + 未读计数

7. D 组:本地存储与 P2P 同步 ​

编号用例与步骤判定条件类型 / 证据
D01A 拉取历史后断网,分别重启桌面端和浏览器桌面 SQLite、网页 IndexedDB 均可离线展示已有历史;重启后不要求重新全量同步会上并入 MTG-09;录屏
D02A 有消息/草稿/未读后退出改登 B,再重新登录 AB 看不到 A 的任何本地数据或内存态;库按 userId 隔离而非退出删库;A 回来后历史仍在会上 MTG-09;库名与页面截图
D03macOS 删除 .app 后重装,再从应用内执行“清空本地消息”重装后历史仍可读;主动清空后只清当前账号本地消息,设备标识与服务端消息不受影响离线;完整录屏
D04Windows 分别执行默认卸载重装,以及勾选“同时删除本地消息”后重装勾选项默认不选;默认卸载保留历史;明确勾选后本地历史删除;其他用户数据不被误删离线;干净机录屏
D05对比 SQLite 与 IndexedDB schema、版本和迁移;检查业务层调用messages/conversations/sync_ranges 同构且版本对齐;业务层只依赖统一存储接口,不出现运行端分支离线;schema diff + 代码审查
D06B 选择“从 A 的指定设备、指定日期起”同步不少于 1,000 条消息只同步选定数据源和时间范围;按 (conversation_id,seq) 去重;结束后范围完整、无重复会上 MTG-06;同步统计 + 本地库断言
D07在同网段、跨公网出口各同步一次;配置至少两个 STUN;检查 ICE 候选两种可建连环境均成功;跨网出现 srflx candidate;配置中无 TURN;STUN 更换只改集中配置离线;WebRTC internals + 配置
D08抓取客户端、信令 WS 与业务服务端流量并检查批次业务服务端只见 SDP/ICE 信令,不见批量正文;DataChannel DTLS 成功;先压缩后加密;批次有上限且不会一次占满内存离线;抓包 + 内存曲线
D09传到中途断网再恢复,并重放已完成批次从 sync_ranges 缺口继续而非从头开始;重放不产生重复;最终消息数、seq 区间与源端一致离线;故障注入 + 两端校验和
D10源设备离线、对称 NAT/禁 UDP/AP isolation、建连超时各跑一次明确提示“当前网络无法建立设备间连接”或设备离线;不无限转圈、不静默成功、不降级到服务端中转离线;录屏 + 服务端流量证明

8. E 组:账号级未读与通知 ​

编号用例与步骤判定条件类型 / 证据
E01桌面端后台/最小化/失焦时收新消息并点击通知;再在前台当前会话收消息三种后台态均发系统通知;点击直达正确会话;前台当前会话不发通知会上 MTG-07;录屏
E02网页首次分别允许、拒绝通知权限,之后重复收消息允许时走浏览器原生通知;拒绝后降级为标题提示且不反复请求权限离线;两浏览器 profile 录屏
E03客户端切换前后台和当前会话,观察 presence 上报建连带初始状态,切换即上报;字段准确;前台非当前会话与后台按决策规则通知离线;WS 帧 + 通知结果
E04A 两个在线端收到 B 的消息,一端读到目标 seq服务端 read_seq=GREATEST 单调推进;另一端未读/红点/角标 ≤2s 清零;乱序上报较小 seq 不回退会上 MTG-08;计时录屏 + 数据库断言
E05A 三端中两端后台、一端离线;B 发消息后由任一端读取两后台端允许都弹;读取后其余端不再弹新通知;已弹通知不撤回;离线端上线只得到当前真实未读离线;三端录屏
E06停止 presence 上报超过 TTL,并检查设备推送字段与通道结构过期按 background 处理;决策与 WS 投递实现解耦;push_channel/push_token 字段存在但本期为空且无 APNs/FCM 调用离线;日志 + schema + 代码审查

9. F 组:界面、桌面壳与缺陷 ​

编号用例与步骤判定条件类型 / 证据
F01构造同日与跨日消息,在会话列表和聊天详情查看同日精确到 HH:MM:SS;跨天含日期;列表与详情使用同一时区和格式口径离线;截图
F02在两个会话输入不同未发送草稿,多次切换通讯录和会话并重启草稿按 conversationId 隔离,不串、不丢;发送或主动清空后才移除离线;录屏 + 本地库断言
F03退出登录并注入 teardown 中间步骤失败内存中的会话、未读、草稿均清空,页面回登录态且可操作;本地历史按账号保留离线;状态快照 + 录屏
F04逐步增加消息直到需要纵向滚动,并比较容器宽度与气泡位置滚动能力保留但滚动条隐藏;出现/消失滚动区域时布局与气泡水平位置不变离线;前后像素对比
F05macOS/Windows 在空白区左右滑动、触控板横滑并改变窗口尺寸无横向溢出、无白边、无页面整体位移会上并入 MTG-10;双平台录屏
F06双平台验证拖拽、双击最大化、最小化/最大化/关闭、四边与四角 resize无系统原生标题栏;所有交互符合平台习惯;可拖区域不吞按钮点击;最小尺寸限制有效会上 MTG-10;双平台录屏
F07检查 macOS .icns、Windows .ico、favicon、登录页和关于页五处来自同一批准视觉资产且清晰无拉伸;资产未批准或任一处仍用旧图标时记阻塞/不通过离线;制品截图 + 资产哈希

10. G 组:迁移、发布、文档与回归 ​

编号用例与步骤判定条件类型 / 证据
G01在历史数据快照上执行 auth 与 IM 迁移,并重复执行迁移校验sessions 数量等于迁移前旧 devices 数;每条旧 device 原地保留并获得唯一 legacy:<id>;外键无悬挂;新增表/索引/partial unique 正确;失败可按发布计划重建离线;迁移报告 + SQL 断言
G02审查本期所有新增数据访问无新增 JOIN;无循环体内逐行查库;关联数据使用分层批量;业务逻辑不依赖数据库级联;auth 仍是用户/设备权威方离线;代码审查清单
G03由未参与开发的人按集中部署文档搭建环境,并构建文档站三个现有 docs/deploy.md 已集中到 docs 仓库的非站点目录;原仓只留索引;文档站无部署文档路由或导航;执行者提问次数为 0离线;部署记录 + 站点路由检查
G04检查所有新增配置并用缺失/非法值启动心跳、令牌时限、撤回窗口、本地端口、P2P 超时、STUN、presence TTL 均集中读取、带默认值和校验,并写入集中部署文档离线;配置清单 + 启动日志
G05按发布计划同时升级服务端与两个客户端,使用旧令牌和五个存量账号验证无 did 的旧令牌全部失效;所有账号完成密码重置并可登录;漏重置有明确发布检查阻断;不实现双读兼容离线;发布检查单 + 登录结果
G06依次触发设备 upsert、上下线、撤回、已读、本地授权、RTC 成败、密码失败每类事件均可按 user/device/session 追踪;归档正文、明文、H1 输出、完整令牌不进日志;device_key 脱敏离线;日志检索报告
G07回归上期 A5/A8、B2、C3、C5、D3,以及消息顺序、分页和收发授权码原子一次性;账号不可枚举;强制下线 ≤5s;重放只伤涉事 session;登录持久;吊销令牌被拦;双方顺序一致、分页完整、单向延迟 ≤1s离线;回归报告

11. 需求追踪矩阵 ​

需求覆盖用例
FR-1 设备识别A06、A07、A08、G01
FR-2 设备地址A09
FR-3 App 内置登录A01、A10
FR-4 网页读桌面登录态A02、A03、A04、A05
FR-5 心跳与连接回收B01—B06
FR-6 消息时间到秒F01
FR-7 消息撤回C01—C07
FR-8 本地存储与多设备同步D01—D10、F02、F03
FR-9 未读与系统提醒E01—E06
FR-10 应用外框自绘F05、F06
FR-11 Logo / 图标F07
FR-12 部署文档归档G03、G04
FR-13 密码端侧单向加密A10、A11、G05、G06
BUG-1 授权后窗口关闭A01
BUG-2 退出后页面不可操作A14、F03
BUG-3 重放误伤多端A12、G07
BUG-4 403 清登录态A13、C04
BUG-5 强制下线无提醒A14
BUG-6 自动退出时间不明A15
BUG-7 草稿未隔离/丢失F02
BUG-8 退出不清未读D02、F03
BUG-9 滚动条导致偏移F04
BUG-10 横向白边F05
非功能与发布约束A06、A07、A10、B02、B03、C01、D03、D04、E04、G01—G07

12. 验收记录 ​

2026-08-30 预跑证据汇总:见 《TC 预跑验收证据》。 本次汇总严格区分“阻塞 / 未执行”;下表的“阻塞数”包含未执行项,详细原因以报告矩阵为准。 Mac/Chrome Computer Use 交互截图见报告 §6.3;这些是单端预跑证据,不计为多端、跨平台或正式会上用例通过。

12.1 会上记录 ​

编号结果(通过 / 不通过 / 阻塞)实际耗时证据链接备注
MTG-01阻塞—报告缺真机桌面登录录屏;测试包构建不能代替验收
MTG-02阻塞—报告本地通道/确认弹窗无实机证据
MTG-03阻塞—报告缺多端强制下线 5s 录屏
MTG-04阻塞—报告缺 WS 故障注入与重连实测
MTG-05阻塞—报告缺在线多端撤回录屏/断言
MTG-06阻塞—报告P2P 威胁模型未拍板,且缺双网络实测
MTG-07阻塞—报告缺桌面后台通知真机证据
MTG-08阻塞—报告缺双端未读清零时序证据
MTG-09阻塞—报告离线重启受 nexo-web-sdk#17 影响
MTG-10阻塞—报告缺双平台真机窗口交互录屏

12.2 离线预跑汇总 ​

分组用例范围通过数不通过数阻塞数报告链接
A 登录/设备/密码A01—A150015报告
B 心跳/连接B01—B06006报告
C 消息撤回C01—C07007报告
D 本地存储/P2PD01—D100010报告
E 未读/通知E01—E06006报告
F UI/桌面壳F01—F07007报告
G 工程/回归G01—G07007报告

12.3 最终结论 ​

  • 通过条件:10 条会上用例全部通过;离线用例零 P0/P1 不通过;所有阻塞项已有明确移出本期的评审结论。
  • 不通过条件:任一安全准入项失败(Origin/CORS、PKCE、会话隔离、密码材料泄露、越权、撤回正文泄露),或任一硬阈值未达成。
  • 延期条件:Logo 资产、P2P 威胁模型或浏览器可行性未收口时,只能由评审明确移出对应 FR;不得用“未测”替代结论。