Smail/docs/发布安装回滚补充验收.md
smail 33eab66a50
Some checks are pending
Security Checks / security (push) Waiting to run
修复发布备份保护与回滚状态并补齐隔离验收
2026-09-21 20:56:02 +08:00

88 lines
5.6 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.

# 发布安装回滚补充验收
## 结论与范围
2026 年 9 月 21 日,基于已推送的 `7114e9e` 继续审查发布安装包。
本批修复已有恢复备份被覆盖、恢复不完整却返回回滚成功标记的问题。
Windows 回归与竞态检查、云端 Linux 隔离专项通过;**整体验收未通过,发布模块的路径与权限安全门禁仍未关闭。**
当前源码搜索中,`InstallPair` 和 `ReadManifest` 只有包内测试调用。
本批运行的是发布包测试程序,不是正式升级入口,不曾替换 `/opt/smail` 的正式程序。
不能将它写成正式升级、进程崩溃恢复或完整发行候选验收通过。
## 任务状态
- [✓] 复现已有恢复备份被覆盖。
- [✓] 复现恢复重命名失败却返回完整回滚标记。
- [✓] 修改前检查全部旧备份及目标文件类型。
- [✓] 汇总恢复删除、重命名及目录同步错误,区分完整与不完整回滚。
- [✓] Windows 包回归及竞态检查,Linux 受限隔离专项。
- [✓] 发布包 Linux 目标静态复扫,保留非零退出及全部告警。
- [!] 父目录符号链接、路径竞争、并发升级、断电与进程崩溃恢复尚未验收。
- [!] 来源程序真实性、版本声明绑定与正式升级调用链尚未验收。
## 原始问题与修复
原实现会先删除 `*.previous`,没有区分上一次失败留下的恢复证据;恢复中的删除和重命名失败又被忽略。
现在修改目标前先用 `Lstat` 检查全部恢复备份,普通文件、目录、悬空链接均拒绝覆盖;已存在的目标条目必须是普通文件。
恢复按固定反向顺序执行,只有恢复及目录同步全部成功才返回 `ErrUpgradeRollback`。
任一步失败返回 `ErrUpgradeRollbackFailed`,不携带完整回滚标记;未能恢复的旧备份保留供人工处理。
提交目录同步失败也走恢复流程,并再次检查恢复后的目录同步。
以上是条目级检查,不代表父目录可信或不存在检查与使用之间的竞争。
成功提交后清理旧备份的行为仍属于原有安装流程;本轮未对用户工作区执行文件删除。
## 反例与夹具修正
原始日志位于 `test-log/production-remediation-20260921/`:
- `release-recovery-before.log`:三个已有备份反例失败;首次恢复失败注入误击备份阶段,未准确复现错误标记。
- `release-recovery-before-v2.log`:将安装故障限制在暂存目录的管理员程序安装阶段,明确复现恢复失败仍被标为回滚成功。
两次日志都保留。夹具修正不是产品正向通过,不能隐藏第一次反例设置不准确的记录。
## 测试与证据
| 范围 | 结果 | 边界 |
| --- | --- | --- |
| Windows 发布包回归 | 21 个测试及子测试通过,零跳过 | 不含 Linux 链接专项 |
| Windows 发布包竞态回归 | 21 个测试及子测试通过,零跳过,退出零 | 不是多进程并发升级测试 |
| 云端 Linux 发布包 | 23 个测试及子测试通过,零跳过,退出零 | 全新临时目录,不操作正式数据库和正式安装目录 |
| Linux 目标发布包静态检查 | 5 条告警,退出 1,无包加载错误 | 4 条 G304、1 条 G306 均未整体关闭 |
覆盖三个已有恢复文件、六个重命名故障点、恢复重命名失败、提交及恢复目录同步失败、首次安装失败、目录备份、Linux 悬空备份链接及目标符号链接拒绝。
其中回滚删除失败的错误处理已经纳入实现,但尚无专门故障注入用例,不单独标为通过。
本地日志:
- `release-recovery-final.log`
- `release-recovery-race-20260921.log`
- `release-linux-tests-20260921-204015.log`
- `release-linux-result-20260921-204015.json`
- `gosec-release-recheck-20260921.json`
- `gosec-release-exit-20260921.json`
云端证据目录:`/var/tmp/smail-review-release-20260921-204015`。
单元:`smail-release-test-20260921-204015`。
测试采用非特权身份、私有网络及临时目录,正式 Smail、控制通道、数据库目录和 Nginx 配置均不可访问。
内存硬上限 96 MiB、Go 目标 64 MiB、CPU 配额 25%,禁止交换;记录的峰值为 2.2 MiB。
结束时单元 inactive、PID 为零,正式六服务进程标识及正式程序摘要保持不变。
测试程序 SHA-256:`4d5fd23de1a407e77443533457f5058d7853c769a7618ec0d8dbcecaa76161b2`。
云端日志 SHA-256:`1f431b3b974a9f4063cab7907c358789efe618a37c92696a0318e3039b05d210`。
本包源码摘要随结果文件保存,不改写此前恢复码批次的 616 份源码清单。
20:50 完成独立只读复核:云端测试程序和日志摘要与本地一致,本包源码摘要未漂移,正式程序及六服务状态未变,测试单元已停止。
结果保存在 `release-independent-recheck-20260921.json`。
静态工具模块版本为 `v2.22.10`,工具报告自身版本字段为 `dev`。
初次 PowerShell 调用未生成独立 JSON,原始控制台日志保留为 `gosec-release-20260921.log`;随后使用显式参数列表重跑,生成独立 JSON 并记录真实退出码。
没有添加批量忽略,没有把退出 1 改写成通过,也没有将本包复扫冒充全项目复扫。
## 未关闭的边界
发布模块仍需要验证父目录信任、符号链接与路径竞争、多进程互斥、崩溃中断后的事务恢复、来源程序真实性及正式部署集成。
全项目原有迁移中断临界点、历史凭据处置、浏览器流程、自动续期与全协议换证、外部投递、长时容量和异机灾备门禁继续保留。
本批只关闭已列明的回滚可靠性缺陷,不构成生产放行。