# 配置事务崩溃恢复补充验收 ## 范围与结论 本项接续双 SQL 未提交复制中断验收,验证配置事务落盘、根配置切换与启动恢复。**本项不等于整个项目生产验收通过。** - [✓] 真实终止测试子进程,而非仅在阶段钩子返回错误。 - [✓] 验证三种数据库配置选择下的回滚、保留新配置、重复启动与损坏拒绝启动。 - [✓] 修复新事务准备阶段崩溃残留导致下次启动被阻塞的问题。 - [✓] 云端重复终止测试、完整配置包回归与本地全量后端回归。 - [✓] 最新后端候选的隔离应用级 SQLite 迁移、邮件和重启回归。 - [ ] 完整应用的 SQL 提交与配置切换联合故障点、恢复过程再次被终止。 - [ ] 同一最终完整发行候选的统一生产验收与正式部署。 用户提供的管理员、域名和部署入口仍仅为测试参数,不转为产品验收标准。没有修改或暂存用户原来的 `云端全项目测试报告.md`,没有停止正式实例或其他项目。 ## 修复的问题 旧实现先在 `data/transaction/` 创建原始和候选目录,再写配置归档及首份事务清单。若在清单发布前突然退出,恢复扫描会遇到没有清单的活动目录,保留现场并拒绝启动。原配置虽然未变,但无法自动恢复可用。 新实现先写入 `data/transaction-staging/`,完成归档、清单与目录同步后,再把整个目录原子重命名到活动事务区。发布之后才允许修改活动配置文件。 - 发布前突然退出:活动配置保持原样,残留暂存不参与启动恢复,也不阻塞下一次提交。 - 发布后发生错误:保留完整活动事务,由既有恢复算法决定回滚还是保留新配置。 - 暂存路径拒绝符号链接,避免配置归档写出预期目录。 - 旧版活动区中的无清单、损坏或不可信记录继续失败关闭,不自动删除或当作正常事务接受。 - 崩溃暂存保留为证据;这是文件归档目录,不是新增数据库。清理策略不在本次修复范围内。 没有向 HTTP、环境变量或正式运行配置增加故障注入开关。新增准备阶段钩子由测试直接设置,等待和强制终止逻辑均位于测试二进制。 ## 故障矩阵与证据边界 每种 SQLite、MySQL、PostgreSQL 配置分别覆盖: | 故障位置或状态 | 恢复结果 | 注入方式 | | --- | --- | --- | | 准备目录已创建、尚未写归档 | 保持旧配置,后续提交正常 | 正式提交路径钩子处终止子进程 | | 归档与清单完整、尚未发布活动事务 | 保持旧配置,后续提交正常 | 正式提交路径钩子处终止子进程 | | 已发布 prepared 清单 | 恢复旧配置 | 正式阶段钩子处终止子进程 | | 仅一个分区被替换 | 恢复旧配置 | 使用正式原子替换函数构造落盘状态后终止 | | 所有分区已替换、根配置未切换 | 恢复旧配置 | 正式阶段钩子处终止子进程 | | 根配置已切换,清单仍是 sections_committed | 保留新配置 | 使用正式原子替换函数构造落盘状态后终止 | | root_committed 清单已写入 | 保留新配置 | 正式阶段钩子处终止子进程 | | verified 清单已写入 | 保留新配置 | 正式阶段钩子处终止子进程 | 另有两个强制终止后损坏归档的用例:分别改坏 original、candidate,启动必须拒绝,活动配置及损坏现场保留。独立测试保留旧版无清单活动目录的失败关闭行为,并验证暂存符号链接拒绝。 父进程确认到达目标点后强制终止子进程并等待退出;Linux 日志记录 `signal: killed`。随后两次调用正式 `NewConfigManager` 启动路径,检查代次、数据库选择、配置文件逐字节一致、锁释放及恢复幂等。 **上述三种数据库是配置选择矩阵,不是三种真实数据库的提交联合测试。** SQL 配置故意使用不可用的本地端口,证明文件恢复不依赖连接 SQL,也不会回退创建额外 SQLite。分区部分写入和根清单滞后是明确构造的磁盘状态,不声称在真实应用中捕获了对应指令间隙。再次成功启动不等于恢复途中再次被杀;进程强制终止不等于整机断电或物理存储耐久性验证。 ## 验证记录 证据目录:`test-log/production-remediation-20260921/`。时间均为北京时间;本轮从 2026 年 9 月 21 日晚间开始。 ### 修复前专项 云端目录:`/var/tmp/smail-review-transaction-20260921-234828/`。 - 原阶段专项重复三次:81 个测试及子测试通过,60 次强制终止,零失败、零跳过。 - 配置包:406 项通过,1 项跳过。 - 该结果不包含后续暂存发布修复,不能替代最终修复版本。 ### 修复后专项 云端目录:`/var/tmp/smail-review-transaction-20260921-235343/`。 | 范围 | 通过 | 失败 | 跳过 | 说明 | | --- | ---: | ---: | ---: | --- | | Linux 崩溃专项重复三次 | 114 | 0 | 0 | 78 次确认的 SIGKILL | | Linux 完整配置包 | 417 | 0 | 1 | 内含 26 次 SIGKILL;真实数据库集成测试未配置 | | Windows 完整配置包 | 401 | 0 | 15 | 权限、符号链接及真实 SQL 等平台条件分别保留跳过 | | Windows 全量后端 | 1945 | 0 | 42 | 62 个包通过,另有 22 个无测试文件包 | 测试及子测试计数包含父级条目,不是独立业务用例数;不同范围有重叠,不相加当作全量生产验收。 最终 Linux 配置测试二进制 SHA256: ```text 5f36f1cd0c5f5f182b3ea96fb9dcf599ee6db0773cc93d3368406e8b4ac46d76 ``` 对应构建输入:`transaction-build-20260921-235343.json`。其中 revision 是修改前源码基线,实际工作区改动以逐文件源码摘要为准,并非该提交的干净构建。 关键日志及结果: - `transaction-linux-20260921-235343-result.json` - `transaction-linux-20260921-235343-crash.log` - `transaction-linux-20260921-235343-config.log` - `transaction-staging-windows.jsonl` - `transaction-full-backend-windows.jsonl` 首次编写专项时,预期配置没有包含加载后的规范化结果,导致断言失败;改为读取归档原始字节并单独核对数据库选择。扩大 Windows 回归时发现就绪文件读取与文件操作之间的短暂共享冲突,改用目录标记。两次失败日志均保留,不覆盖为成功结果。 ### 隔离应用级回归 使用最新后端重新编译的 Linux amd64 候选,隔离实例为 `/var/tmp/smail-review-runtime-20260921-235814/`,构建基线为 `b8dbd3b` 加本轮未提交修复;逐文件摘要在最终复核时确认未漂移。程序 SHA256: ```text 89e115d94ef2f12fd2ab082888f22517460e87cbe9e1b5a98d32f55ae38426b8 ``` 以下应用级项目通过: - 全新隔离初始化及邮件协议探针。 - 占用目标拒绝覆盖,失败后释放维护状态;正常迁移完成配置切换。 - 切换后待重启期间拒绝写入;内部重启保持进程,进程级重启使用新进程。 - 原登录会话、历史邮件与新增邮件的正文、附件通过 IMAP、POP3 验证。 - 目标库不可用时失败关闭;源库和配置未被改写;恢复访问后邮件闭环继续正常。 - 配置历史随业务迁入目标库;新增邮件只进入目标,源库不再写入。 - 最终活动数据库为 `migrated.db`,完整性检查为 `ok`。`smail.db` 与 `occupied.db` 为离线源库及占用目标证据,不是第二个活动数据库。 应用级证据 13 份位于 `transaction-runtime-evidence/smail-review-runtime-20260921-235814/`,汇总为 `transaction-runtime-result-20260921-235758.json`,构建输入为 `transaction-runtime-build-20260921-235758.json`。 **该应用回归是 SQLite → SQLite,不把它扩展成最新候选的 MySQL/PostgreSQL 实机迁移验证。** 前端与 Linux 插件资源只复用并核对摘要,不宣称完整发行包已重新构建。正式实例未替换。 ## 安全与运行保护 云端配置测试使用全新目录及每用例独立临时目录,不连接正式数据库。测试以普通 smail 用户运行,使用私有网络、私有临时目录、只读系统、受保护路径和资源上限:192 MiB 硬内存上限、128 MiB Go 目标、单 Go 调度线程、25% CPU、禁止交换。 修复前后两轮配置测试均确认正式六服务运行标识、PID 和重启次数未变,正式程序摘要未变;测试单元结束后全部停止且 PID 为零。原用户报告摘要保持: ```text A142FAA660487656124A8BD4A3EF4F58ED80B3DEC0EDA4AAB0F20B8C3297FF08 ``` 应用回归后的独立复核记录为 `transaction-final-recheck.json`:21 个远端程序、工具及日志文件摘要一致,710 份构建输入未漂移,六个已核查测试单元停止且 PID 为零。隔离应用的活动事务与暂存区均为空;正式六服务和程序、用户原报告保持不变。验证只读查询摘要,不再次下载大程序或重复执行已完成测试。 历史凭据轮换、剩余静态安全告警、真实浏览器闭环、Windows 提权恢复通道、真实自动续期与全协议换证、外部最终投递、长时容量、告警、异机灾备及最终统一发行候选等门禁仍未关闭。