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

7.1 KiB
Raw Blame History

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 自动续期与失败告警、外部邮箱最终收件、外部插件、长时容量与异机灾备仍需后续证据。本轮没有将其中任何一项改为通过。