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