Files
NixMsg/test/accept/ACCEPTANCE.md
T

110 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 |