11 KiB
11 KiB
NixMsg 验收对照表(PRD 第 10 节)
生成时间:2026-09-30T08:17:19Z
汇总:通过 19,部分通过 4,失败 0,未测 0
整项「通过」表示该行 PRD 一句话里的子项均有测试证据。部分覆盖不得标通过。
| 编号 | 一句话 | 结果 | 备注 |
|---|---|---|---|
| F01 | 批量开通整批校验、停用、删除群主转让、删除后同编号重开不串数据 | 通过 | 子项 5/5 通过 |
| F02 | 新设备登录后旧设备自动退出、换 IP 用令牌重连、两种密码锁定、重置密码后被踢、服务器故障不误报密码错误 | 通过 | 子项 6/6 通过 |
| F03 | 断开后状态及时变离线,全表可列出 | 部分通过 (2/4) | F03c 未测:环境/时长限制,本波不跑;F03d 未测:环境限制;验收用关连接模拟断线 |
| F04 | 只通知订阅了的端 | 通过 | 子项 1/1 通过 |
| F05 | 崩溃不丢已提交消息,消息号去重和冲突,密码门生效,配额生效 | 通过 | 子项 5/5 通过 |
| F06 | 群成员收到同一份,入群前不补,发送者不收到自己的 | 通过 | 子项 2/2 通过 |
| F07 | 256 KiB 通过,超出拒绝,接收上限生效 | 通过 | 子项 3/3 通过 |
| F08 | 弱网最终送达且应用层不重复,重启后续传 | 部分通过 (3/4) | F08d 未测:本机 Windows;test/chaos/q3_weak_test.go TestQ3NetemUntested |
| F09 | 保留时间从发送时刻起算,超时过期 | 通过 | 子项 2/2 通过 |
| F10 | 短断线送到,长断线丢弃,服务器重启后宽限内重连送到 | 通过 | 子项 3/3 通过 |
| F11 | 发送方离线后到点仍发送 | 通过 | 子项 1/1 通过 |
| F12 | 延迟窗口内撤回对方收不到 | 通过 | 子项 1/1 通过 |
| F13 | 未推送必撤成功;群部分确认得到部分撤回 | 通过 | 子项 2/2 通过 |
| F14 | 回执能补送给当时离线的发送方 | 通过 | 子项 1/1 通过 |
| F15 | 输一次记住、改密失效、回复免密、进群仍要密码、防多账号轮流猜 | 通过 | 子项 5/5 通过 |
| F16 | 群主权限、退出后不再收到、解散后同编号新群不收旧消息 | 通过 | 子项 4/4 通过 |
| F17 | 后台管端、管注册、管群、查记录,响应里没有正文;API 令牌可用且不能越权 | 通过 | 子项 6/6 通过 |
| F18 | 送达后正文消失;记录天数 0 时连记录消失;防重仍在 | 通过 | 子项 3/3 通过 |
| F19 | 四种 SDK 通过同一清单 | 通过 | 子项 1/1 通过 |
| F20 | 裸 MQTT 能登录、收、确认、发 | 通过 | 子项 1/1 通过 |
| F21 | 默认一个端口提供后台、WebSocket、TCP、注册;后台可分到单独端口 | 部分通过 (2/3) | F21b 未测:验收用例只走 WebSocket;listener 首字节识别见 internal/listener/listener_test.go TestIdentifyPlainHTTPAndMQTT,不足以上升为通过 |
| F22 | 初始化后单文件或 Docker 启动、备份恢复、升级迁移、证书自动重载、指标可抓取 | 部分通过 (5/6) | F22f 未测:镜像未推送;本波未跑 compose 全量 |
| F23 | 注册开关、安全码校验、换码不影响已注册、输错锁定 | 通过 | 子项 2/2 通过 |
子项
| 子项 | 摘要 | 结果 | 证据或原因 |
|---|---|---|---|
| F01a | 开通一端并可 MQTT 登录 | 通过 | test/accept/accept_test.go runEndpointCreate |
| F01b | 批量开通整批校验 | 通过 | internal/admin/endpoints_test.go TestEndpointImportDuplicateRejectsAll、TestEndpointImportBOMAndCreate |
| F01c | 停用 | 通过 | internal/app/identity/lifecycle_test.go TestF01DisableVoidsScheduledAndRejectsNew;internal/admin/endpoints_test.go TestEndpointDisableKickAndUnlock |
| F01d | 删除群主转让 | 通过 | internal/app/identity/lifecycle_test.go TestF01DeleteOwnerTransfersEarliest |
| F01e | 删除后同编号重开不串数据 | 通过 | internal/app/identity/lifecycle_test.go TestF01DeleteReopenNoOldReceipts |
| F02a | 密码登录后 hello / 会话令牌 | 通过 | test/accept/accept_test.go;internal/broker/f02_test.go TestF02PasswordLoginReturnsTokenAndHandshake |
| F02b | 新设备密码登录后旧设备退出 | 通过 | internal/broker/f02_test.go TestF02TakenOverByPasswordLogin、TestF02OldTokenRejectedAfterPasswordLogin |
| F02c | 换 IP 用令牌重连 | 通过 | internal/broker/f02_test.go TestF02TokenReconnectDifferentIPKeepsToken |
| F02d | 两种密码锁定 | 通过 | internal/broker/f02_test.go TestF02IPLockDoesNotAffectOtherIP、TestF02EndpointLockAllowsTokenReconnect |
| F02e | 重置密码后被踢 | 通过 | internal/broker/f02_test.go TestF02AdminResetPasswordFatal;cmd/nixmsg/fatal_revoked_integration_test.go TestUplinkResetPasswordFatal |
| F02f | 服务器故障不误报密码错误 | 通过 | internal/broker/f02_test.go TestF02DBErrorClosesWithout086;internal/broker/broker_test.go TestInternalAuthErrorDoesNotReturnBadPassword |
| F03a | 断开后状态及时变离线 | 通过 | test/accept/rest_accept_test.go;internal/app/presence/presence_test.go TestF03PresenceAndDirectory |
| F03b | 目录可列出 | 通过 | test/accept/rest_accept_test.go;internal/app/presence/presence_test.go TestF03PresenceAndDirectory |
| F03c | 1000 端全表 1s 内返回 | 未测 | 环境/时长限制,本波不跑 |
| F03d | 真拔网线后心跳超时离线 | 未测 | 环境限制;验收用关连接模拟断线 |
| F04a | 只通知订阅了的端 | 通过 | test/accept/rest_accept_test.go;internal/app/presence/presence_test.go TestF04PresenceWatch |
| F05a | 双端在线单聊送达与确认 | 通过 | test/accept/accept_test.go runMessagingAccept |
| F05b | 崩溃不丢已提交消息 | 通过 | test/chaos/q3_crash_test.go TestQ3CrashSubmitThenRestart |
| F05c | 消息号冲突 | 通过 | internal/app/message/submit_test.go TestSubmitTable/conflict |
| F05d | 密码门生效 | 通过 | internal/app/message/submit_test.go TestSubmitTable 对话密码用例 |
| F05e | 配额生效 | 通过 | internal/app/message/submit_test.go TestSubmitTable/quota_exceeded |
| F06a | 群成员收到同一份、发送者不收到自己的 | 通过 | test/accept/accept_test.go;internal/app/group/group_test.go TestF06GroupSendMembership |
| F06b | 入群前不补 | 通过 | internal/app/group/group_test.go TestF06GroupSendMembership(发送后入群无旧投递) |
| F07a | 256 KiB 通过 | 通过 | test/accept/rest_accept_test.go |
| F07b | 超出拒绝 | 通过 | test/accept/rest_accept_test.go body_too_large |
| F07c | 接收上限生效 | 通过 | test/accept/rest_accept_test.go max_receive_bytes=1024 |
| F08a | 重启后续传 | 通过 | test/accept/accept_test.go;test/chaos/q3_crash_test.go |
| F08b | 应用层不重复(同号同指纹) | 通过 | internal/app/message/submit_test.go TestSubmitTable/idempotent_hit |
| F08c | toxiproxy 弱网保留送达 | 通过 | test/chaos/q3_weak_test.go TestQ3ToxiproxyOfflineKeepDelivered |
| F08d | Linux netem 20% 丢包 | 未测 | 本机 Windows;test/chaos/q3_weak_test.go TestQ3NetemUntested |
| F09a | 离线保留期内上线送达 | 通过 | test/accept/accept_test.go |
| F09b | 超时过期 | 通过 | internal/app/message/delivery_test.go TestDeliveryStateMachine/F09_keep_ttl_expire_via_cleanup |
| F10a | 短断线送到 | 通过 | test/accept/rest_accept_test.go |
| F10b | 长断线丢弃 | 通过 | test/accept/rest_accept_test.go |
| F10c | 服务器重启后宽限内重连送到 | 通过 | test/accept/rest_accept_test.go |
| F11a | 发送方离线后到点仍发送 | 通过 | test/accept/rest_accept_test.go |
| F12a | 延迟窗口内撤回对方收不到 | 通过 | test/accept/accept_test.go |
| F13a | 未推送必撤成功 | 通过 | test/accept/accept_test.go |
| F13b | 群部分确认得到部分撤回 | 通过 | internal/app/message/delivery_test.go TestDeliveryStateMachine/F13_recall_race_partial |
| F14a | 回执能补送给当时离线的发送方 | 通过 | test/accept/rest_accept_test.go |
| F15a | 输一次记住 | 通过 | test/accept/rest_accept_test.go;internal/app/identity/self_talk_test.go TestF15TalkPasswordAuth |
| F15b | 改密失效 | 通过 | test/accept/rest_accept_test.go;internal/app/identity/self_talk_test.go TestF15ReplyGrantAndChange |
| F15c | 回复免密 | 通过 | test/accept/rest_accept_test.go;internal/app/identity/self_talk_test.go |
| F15d | 进群仍要密码 | 通过 | test/accept/rest_accept_test.go;internal/app/identity/self_talk_test.go TestF15JoinNeedsPasswordDespiteGrant |
| F15e | 防多账号轮流猜 | 通过 | test/accept/rest_accept_test.go |
| F16a | 建群拉成员后可群发 | 通过 | test/accept/accept_test.go |
| F16b | 群主权限 | 通过 | internal/app/group/group_test.go TestF16CreateAddPasswordAndOwner |
| F16c | 退出后不再收到 | 通过 | internal/app/group/group_test.go TestF16LeaveRemoveDissolve |
| F16d | 解散后同编号新群不收旧消息 | 通过 | internal/app/group/group_test.go TestF16LeaveRemoveDissolve |
| F17a | 管理登录、CSRF、错误密码锁定 | 通过 | test/accept/accept_test.go runAdminAuth |
| F17b | 管端开通 | 通过 | test/accept/accept_test.go runEndpointCreate |
| F17c | 管注册 | 通过 | test/accept/accept_test.go runRegistration;internal/admin/a3_test.go TestRegistrationToggleAndGenerate |
| F17d | 管群 | 通过 | internal/admin/a3_test.go TestGroupsCRUD |
| F17e | 查记录响应无正文 | 通过 | internal/admin/a3_test.go TestMessageDetailHasNoBody |
| F17f | API 令牌可用且不能越权 | 通过 | internal/admin/admin_test.go TestAPITokenAuthAndRestrictions |
| F18a | 送达后正文消失 | 通过 | test/accept/rest_accept_test.go;internal/app/message/delivery_test.go TestDeliveryStateMachine/F18_body_gone_record_zero_idempotent_kept |
| F18b | 记录天数 0 时连记录消失 | 通过 | test/accept/rest_accept_test.go |
| F18c | 防重仍在 | 通过 | test/accept/rest_accept_test.go;internal/app/message/submit_test.go TestSubmitTable/idempotent_hit |
| F19a | 四种 SDK 接入清单(仓库内已有测试,本波不重跑全量) | 通过 | sdk/go/itest_checklist_test.go;sdk/js/test/checklist.test.ts;sdk/python/tests/test_checklist.py;sdk/java ChecklistTest |
| F20a | 裸 MQTT WebSocket 登录、收、确认、发 | 通过 | test/accept/accept_test.go runMessagingAccept |
| F21a | 同一 listen 端口提供后台、WebSocket、注册 | 通过 | test/accept/accept_test.go |
| F21b | 裸 TCP MQTT 登录收发 | 未测 | 验收用例只走 WebSocket;listener 首字节识别见 internal/listener/listener_test.go TestIdentifyPlainHTTPAndMQTT,不足以上升为通过 |
| F21c | 后台可分到单独端口 | 通过 | internal/listener/listener_test.go TestAdminSeparateMQTTClosedAndAdmin404OnListen |
| F22a | 空目录 admin init + serve 健康检查 | 通过 | test/accept/accept_test.go runInitHealthz |
| F22b | 备份 | 通过 | cmd/nixmsg/commands_test.go TestBackupVacuumInto |
| F22c | 升级迁移前备份 | 通过 | internal/store/db_test.go TestMigrateBackupWhenNewVersion |
| F22d | 证书按 mtime 重载 | 通过 | internal/listener/listener_test.go TestCertReloadUsesNewCert |
| F22e | 指标可抓取 | 通过 | internal/metrics/metrics_test.go TestMetricsHandlerExposesText;internal/httpx/metrics_test.go TestMetricsGateSharedPort |
| F22f | Docker 全量冒烟 | 未测 | 镜像未推送;本波未跑 compose 全量 |
| F23a | 注册开关、安全码校验、换码不影响已注册 | 通过 | test/accept/accept_test.go runRegistration;internal/app/identity/register_test.go TestRegisterF23_* |
| F23b | 输错锁定 | 通过 | internal/app/identity/register_test.go TestRegisterF23_WrongCodeLock |