Smail/docs/SQL切库与部署回归补充验收.md
smail 2de629fb79
Some checks are pending
Security Checks / security (push) Waiting to run
归档SQL切库恢复证据并复核云端部署测试
2026-09-21 06:00:26 +08:00

77 lines
7.1 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.

# SQL 切库与部署回归补充验收
## 结论与边界
北京时间 2026 年 9 月 21 日,在云服务器隔离实例补齐 MySQL/PostgreSQL 同引擎切库及部署脚本回归。正式 `/opt/smail` 未替换、正式数据未清空,共享数据库及其他项目未停止。
- [✓] MySQL/PostgreSQL 同引擎切库、内部重启及真实系统级进程重启。
- [✓] 目标账号不可用时明确停止,不回退源库;恢复账号后可以重新启动。
- [✓] 三阶段真实 SMTP 收信、IMAP/POP3 读取旧新中文正文及附件。
- [✓] 源库不再有应用连接且逻辑内容不变,配置历史完整保留在目标业务库。
- [✓] 两种 SQL 运行目录均没有 SQLite 文件。
- [✓] 验收器 55 项本地回归;云端扩大部署回归 125 项、零跳过。
- [ ] 跨引擎应用级迁移重启矩阵、复制/提交途中进程被杀后的恢复。
- [!] 其他生产门禁尚未关闭,不能据本记录宣布整个项目审计或部署验收通过。
迁移源库保留为离线证据,不是第二个活动业务库,未经许可不删除。最终运行仍是 SQLite/MySQL/PostgreSQL 三选一,业务数据与配置历史使用所选同一数据库。
## 工具与权限控制
`test/tools/runtime_sql_migration.py` 通过正式迁移 API 完成切库。目标数据库不预创建;目标账号随机生成,只服务于本轮测试。连接凭据通过标准输入或子进程环境传递,不输出到证据或命令行。
- MySQL 仅对准确的目标库授权,下划线转义,不授予全局权限。
- PostgreSQL 为创建目标库临时授予 `CREATEDB`,迁移准备完成即撤销,结束后禁止登录。
- 只锁定本轮目标账号模拟故障,不停止共享数据库、不操作正式账号。
- 独立限时网络单元保持迁移前后的网络命名空间,避免把数据库桥接随应用进程替换丢失误判为应用缺陷。
- 全表行摘要证明源库不变,配置历史按完整行比较;MySQL 对字段取十六进制并保留空值,避免二进制字段破坏摘要序列化。
结果中的 `temporary_creation_privilege_revoked=true` 对 MySQL 是无操作的通用阶段标记;MySQL 从未获得 PostgreSQL 式全局临时建库权限,不能据此宣称撤销过这种权限。
## 云端结果
| 项目 | MySQL | PostgreSQL |
| --- | --- | --- |
| 实例目录后缀 | `20260921-053754` | `20260921-054131` |
| 内部重启前后 PID | `774526`,不变 | `775325`,不变 |
| 系统重启后 PID | `774998` | `775619` |
| 故障恢复后 PID | `775106` | `775757` |
| 三阶段源/目标连接数 | 各为 `0 / 3` | 各为 `0 / 3` |
| 目标账号不可用 | MainPID 为零、failed、退出码 1 | MainPID 为零、failed、退出码 1 |
| 源/目标配置历史条数 | `1 / 1`,完整行一致 | `1 / 1`,完整行一致 |
| SQLite 文件 | 零个 | 零个 |
| OOM、资源采集错误、清理错误 | 全部为零 | 全部为零 |
实例完整路径前缀为 `/var/tmp/smail-review-runtime-`。内部重启保持 PID、InvocationID 和旧会话;系统级重启验证 PID、InvocationID 改变。待重启阶段拒绝业务写入,返回 `DATABASE_RESTART_REQUIRED`。故障阶段配置仍指向目标库;账号恢复后读写成功,新增邮件仅出现在目标库。
本地证据目录为 `test-log/production-remediation-20260921/sql-migration-runtime-evidence/`。汇总为 `sql-migration-results-20260921-053743.json`;05:57 再次核对两轮共 26 份本地与远端文件摘要,记录为 `sql-migration-recheck-20260921-055702.json`。
数据库桥接、应用和网络锚点均已停止,源/目标账号均锁定。05:57 再次查询数据库系统表,四个账号状态符合收尾要求,PostgreSQL 两个账号均不可登录且没有建库权限;远端记录为 `/var/tmp/smail-sql-account-check-20260921-055742.json`。
## 扩大部署回归:保留失败及修正过程
本地 Windows 执行 `test/deployment/test_*.py` 时,86 项中有 2 个失败和 2 个错误:Linux `fcntl` 不可用以及平台路径分隔符差异。不能把它记录为全部通过,也未通过跳过测试消除问题。
| 云端隔离目录 | 结果与原因 |
| --- | --- |
| `smail-review-python-20260921-054448` | 105 项、8 个错误;证书测试要求隔离 root 身份及文件所有权 |
| `smail-review-python-20260921-054632` | 125 项、1 个错误;隔离 Nginx 工作进程 `setuid(65534)` 返回 `EPERM` |
| `smail-review-python-20260921-055549` | 125 项、零失败、零错误、零跳过,退出零 |
诊断目录为 `/var/tmp/smail-review-capabilities-20260921-055359/`。实际 `/proc/self/status` 显示能力边界为 `0xc1`,但许可及有效集仅为 `0x41`,缺少 `CAP_SETUID`;独立 Python 降权探针与隔离 Nginx 的系统调用跟踪均复现权限错误。这里确认的是实际进程缺少能力,不推断未经验证的系统组件内部原因。
仅增加 `AmbientCapabilities=CAP_SETUID` 后,有效集恢复为原边界内的 `0xc1`,小探针成功降权至 UID 65534,随后另建空工作目录重跑完整套件通过。能力边界仍仅为 `CAP_CHOWN CAP_SETUID CAP_SETGID`;保留私有网络、只读系统、隐藏正式目录及服务控制接口、禁止新增权限等隔离属性,没有使用完整 root 能力。
最终隔离单元内存限额 96 MiB、交换限额零、CPU 25%、进程数 32、运行时限 120 秒;实际运行约 7.6 秒,内存峰值 28.3 MiB,无交换使用。真实隔离 Nginx 换证重载与失败回滚用例通过,不能扩大为正式 Nginx 或全协议换证已经完成验收。
最终日志为 `python-linux-tests-20260921-055549.log`,SHA-256 为 `05e48d2669483bcfd921af5cfd46e6db1d90e012ed77ea294a4bcb8200a07581`,已与远端文件核对。摘要为 `python-linux-result-20260921-055549.json`。测试日志中的续期提示来自受控测试路径,不证明实际申请了公网证书。
## 构建与正式环境保护
候选版本 `review-sql-migration-20260921`,构建源码标识 `375ffcabfea607690ea89e31b72cc346cfc122f3`,主程序 SHA-256 为 `6b700120e8bc0b6ca1ce723d0319852259d4aa983646bbc69c4c2fe73e88309d`。`sql-migration-build-manifest.json` 记录产物与验收工具摘要,`restart-source-manifest.json` 覆盖 610 个后端 Go 文件。
本次重新编译后端,复用此前未改动的前端与 Linux 插件资源,不声称本次再次构建前端。新增工具和测试提交为 `4844762`;它不修改应用源码,不能混淆为候选二进制已经包含不同的应用修改。
复核时正式 Smail、Nginx、MySQL、Scert、FDM、PostgreSQL 六个服务 PID 和 InvocationID 均与测试前一致,没有运行中的本轮测试单元。正式主程序摘要仍为 `c14ef1c5ba1dc2096c312c8357039a7330c985cbeac90765aed01d8151e05e1f`。用户原有 `云端全项目测试报告.md` 保持不变,不加入本次提交。
历史凭据撤销轮换、剩余静态安全告警、真实浏览器、正式管理员交互及 Windows 提权 IPC、DNS 自动续期与失败告警、外部邮箱最终收件、外部插件、长时容量与异机灾备仍需后续证据。本轮没有将其中任何一项改为通过。