# 每日自动异机备份实施计划 ## 实施步骤 - [x] 实现宿主自动备份 wrapper:安全绝对路径、唯一 Compose 来源、活动 mount/build 校验、`flock`、成对备份、ARM 推送/finalize、成功状态和源端 7 日保留。 - [x] 实现 ARM 受限 receiver:只允许 rrsync 写 inbox 和 finalize,严格校验三文件 manifest/大小/哈希、原子归档、7 日 + 4 周保留和最后成功保护。 - [x] 实现生产与 ARM 安装器:专用账号/密钥/known_hosts 边界、systemd daily/watchdog/quarterly units、安装/卸载幂等和默认不触发真实任务。 - [x] 泛化现有企微运维告警的 stdin summary、issueId 和备份建议,使用独立状态文件并补单元测试。 - [x] 增加合成契约测试:来源漂移、锁冲突、不完整/损坏/重复批次、续传 partial、拒绝普通 shell、保留轮转、stale 和季度降噪。 - [x] 更新部署环境契约、runbook、checklist、管理员手册的最小操作入口和 `.trellis/spec/hyb-oa/deployment-trialrun.md`;不新增平行长文档。 - [x] 生成一页脱敏恢复卡内容,优先放在现有 runbook 的首部紧急段;由用户复制到公司知识库并安排第二人走查。 - [x] 完成本地全量门禁并提交;生产、ARM 安装另行请求批准。 - [ ] 获批后先安装 ARM 接收端并用合成批次验证,再安装生产 units,手工运行首次真实自动批次,最后 enable timers。 - [ ] 获批执行一次可控传输失败告警并恢复正常链路;不读取附件正文、不执行业务或企微其他写入。 - [x] 删除个人工号默认值,新增生产/ARM 共用的 root-only 企微群机器人 helper;两端 systemd 只绑定 Webhook 文件路径。 - [x] 增加 ARM 26 小时 dead-man service/timer,覆盖缺批次、超龄、损坏、重复降噪和恢复通知。 - [x] 将 buildSha 不同降级为 finding;缺失/损坏/超龄/project 不同继续硬失败,并支持部署后立即运行一次备份。 - [x] 为 backup/rsync/finalize 保存 `0600` 最近失败诊断,summary 与群消息只保留脱敏类别。 - [x] 把同 UTC 日不同 run_id 从拒绝改为“完整校验后原子取代”,覆盖失败回滚和周检查点重建。 - [x] 增加 Webhook 不进入 `.env.example`/仓库配置/报告的否定断言,并在 runbook 记录调整 `BACKUP_RUN_AT` 后需人工确认次日窗口。 - [x] 本地门禁通过并完成只读复核后提交;不推送、不部署、不配置真实 Webhook。 ## 预计文件边界 - 新增 `scripts/run-automatic-backup.sh`:生产 host 编排与 safe summary。 - 新增 `scripts/receive-offhost-backup.sh`:ARM forced-command receiver、finalize 和 retention。 - 新增 `deploy/trialrun/install-automatic-backup-timer.sh`:生产 units 安装/卸载。 - 新增 `deploy/trialrun/install-offhost-backup-receiver.sh`:ARM rsync/账号/目录/公钥安装检查;软件安装和账号创建只在获批远端阶段执行。 - 新增 `scripts/qa/run-automatic-backup-contract.sh`:纯合成正负向测试。 - 修改 `server/src/scripts/send-wecom-ops-alert.js` 及其单测,仅做通用脱敏 summary 兼容。 - 修改 `deploy/trialrun/validate-env-contract.js`、现有 runbook/checklist/管理员手册和部署规约。 - 新增一个不含 Secret 的宿主告警 helper;只读取安装时传入的 root-only Webhook 文件。 ## 验证命令 - `bash -n scripts/run-automatic-backup.sh scripts/receive-offhost-backup.sh deploy/trialrun/install-automatic-backup-timer.sh deploy/trialrun/install-offhost-backup-receiver.sh scripts/qa/run-automatic-backup-contract.sh` - `bash scripts/qa/run-automatic-backup-contract.sh` - `bash scripts/qa/run-backup-restore-drill.sh` - `cd server && node --check src/scripts/send-wecom-ops-alert.js` - `cd server && npm test -- --run tests/unit/scripts/send-wecom-ops-alert.test.js` - `node deploy/trialrun/validate-env-contract.js` - `python3 ./.trellis/scripts/task.py validate .trellis/tasks/07-27-automatic-offhost-backup` - `node scripts/qa/check-trellis-governance.mjs` - `node scripts/qa/check-sensitive-content.mjs` - `node scripts/qa/audit-docs.mjs --check-registry` - `node scripts/qa/check-process-contract.mjs --baseline --json` - `git diff --check` - 合成测试必须模拟源端不再产生 finalize,并由 ARM dead-man 得到失败;不能只直接调用“发送消息”路径。 ## 外部门禁与回滚点 - 安装 ARM rsync/账号/authorized_keys/目录属于远端配置写入,须单独批准;不得复用普通登录账号或本地工作站私钥。 - 安装生产 SSH key/config/systemd units、首次真实备份、真实异机传输和企微失败告警均须单独批准。 - 创建企微运维群机器人及把 Webhook 写入两台主机 root-only 文件由用户手工完成;Codex 不读取、不回显、不记录其内容。 - 首次真实执行前记录现有手工批次数量、磁盘余量、活动容器/mount/build 和现有 timer;只输出脱敏计数/布尔值。 - 任何目标身份、主机指纹、活动 mount、manifest 或哈希不匹配立即停止,不猜路径、不接受新指纹、不清理源端批次。 - 回滚新 timer/receiver 时只撤销调度和专用授权;ARM archive、源端完整批次和原 WARCH3 timer 保留。 ## 本地实施与验证证据 - 已实现生产 wrapper、ARM forced receiver、独立群机器人 helper、ARM dead-man 和两端安装器;生产 3 组 timer 与 ARM 1 组 timer 均默认只安装为 disabled。 - `run-automatic-backup-contract.sh` 使用临时目录与 mock Docker/SSH/rsync 完成 46 项正负向合同,不连接真实主机;覆盖同日取代与回滚、坏候选保留、周检查点重建、Webhook 权限/链接/格式负例、build finding、状态损坏、源端停止、重复降噪和恢复通知。 - 企微告警聚焦单测 15 项通过;stdin 路径被替换为安全类别,AUTO_BACKUP 首次失败/季度提醒发送且相同重复状态降噪。 - `run-backup-restore-drill.sh` 本地合成 DB/附件往返通过,本次合成 RTO 为 8 秒;该结果不是生产 RTO 或 ARM 恢复证据。 - `scripts/check-minimal.sh` 通过:server 162 个测试文件、1004 项测试全部通过,client typecheck/build 通过。 - 环境合同、Trellis task/governance、敏感扫描、文档注册、流程合同和 `git diff --check` 均通过;文档注册保留既有 22 个未注册文件 warning,无本任务新增文档。 - 最终只读复核修正了三个本地缺陷:生产安装器残留个人工号校验、ARM 重装可能改变 dead-man 状态文件属主、stale 状态未校验 run id/manifest SHA;修正后 46 项合同与 `scripts/check-minimal.sh` 全量复跑通过。 - 更新后的 ARM dead-man/helper、生产 helper/runner、真实有效首批、四组 timer enable、真实企微失败链路和第二人季度走查仍为外部门禁,未执行、不得写成已完成。 ### 首次远端执行增量 - ARM 已安装 rsync、密码锁定专用账号和 forced-command receiver;从生产验证普通 shell、sender/read、delete 均拒绝,写通道 dry-run 通过且未生成归档。 - 生产三组 units 已安装为 disabled/inactive,并绑定活动 Compose project、PGDATA、附件挂载、构建标识和固定 SSH 身份。 - 首次真实备份曾在 `runtime_identity` 阶段因 Docker `println` 参数间空格 fail-closed;runner 改用 `docker inspect` mount JSON 后,后续真实源端成对批次已生成并传输。 - ARM finalize 随后因同 UTC 日已有不同 run id 而拒绝,因此尚无可作为自动备份闭环证据的新批次;本轮已在本地实现“完整校验后同日取代”,更新后的远端脚本、首批和 timer enable 仍待另行批准。