加固备份恢复本地基线(07-26-internal-ops-recovery-baseline)

这个提交包含在:
2026-07-26 20:41:22 +08:00
父节点 b3df123330
当前提交 706941eb5c
共修改 16 个文件,包含 792 行新增和 61 行删除
@@ -0,0 +1,61 @@
# 内部 OA 运行与恢复底线设计
## 总体边界
本任务将现有四个底层脚本保留为单一职责工具,在其上增加一个成对备份入口和一个隔离演练入口。所有默认值面向本地/影子环境;真实环境只能沿 runbook 的人工门禁执行。
```text
backup pair entry
├─ backup-db.sh → <run-id>.db.dump
├─ backup-storage.sh → <run-id>.storage.tar.gz
└─ integrity checks → <run-id>.manifest
isolated drill
├─ disposable PostgreSQL/database
├─ disposable source/restore directories
├─ synthetic marker + synthetic attachment
└─ restore → compare → cleanup exact targets
```
## 备份合同
- 一个批次只使用一个 `run_id`,由上层入口传递明确的 `OUT_FILE` 给现有底层脚本。
- 先把产物写入批次临时目录;DB 和附件均成功并通过完整性检查后,再写 manifest 并把批次标记为完整。
- manifest 使用稳定、脱敏的键:`schemaVersion`、`runId`、`createdAt`、`buildSha`(如可安全取得)、两份相对文件名、字节数和 SHA-256。
- 不把连接串、容器密码、存储源路径、真实业务文件清单或主机绝对路径写入 manifest。
- 本任务不负责异机传输实现;runbook 要求操作者把完整批次复制到异机/异盘,并记录保留周期。
## DB 恢复安全合同
- 恢复前通过数据库连接读取 `current_database()`,不得只相信 URL 字符串或调用者描述。
- 调用者必须提供与实际数据库名一致的确认值,并显式选择 `shadow`。
- 实际目标库名还必须包含独立的 `shadow`、`drill` 或 `restore_test` 标记,不能仅靠调用者把模式写成 `shadow`。
- 确认缺失、连接失败、数据库名不匹配或模式不是 `shadow` 时,在 `pg_restore --clean` 之前退出。
- Docker fallback 也必须执行同样的数据库名探测和确认,不得成为绕过路径。
- 真实/生产恢复不在本任务脚本默认路径内;未来如确需开放,应另建任务定义双人确认和事故编号。
## 附件恢复安全合同
- 必须显式传入恢复目标,不再默认落入试运行数据目录。
- 明确拒绝仓库的默认试运行附件目录,即使该目录碰巧为空。
- 影子恢复目标必须为空;非空时退出,不执行覆盖或合并。
- 解压前列出归档成员并拒绝绝对路径、空成员和包含 `..` 路径段的成员。
- 只对已验证的归档执行解压;演练通过内容 SHA-256 比较证明往返一致。
## 隔离演练
- 数据库只使用一次性本地容器或明确命名的 disposable database,插入不含业务信息的 marker 表/行。
- 附件只使用临时目录和合成文本/二进制样件。
- 演练记录开始/结束时间、各阶段通过状态和相对产物名;不记录连接串、容器密码或临时绝对路径。
- 清理只针对演练创建的明确容器、数据库和临时目录;不得使用宽泛路径或工作区根目录。
## 兼容与回滚
- `backup-db.sh` 和 `backup-storage.sh` 的现有单独调用继续可用;推荐运维入口改为成对备份命令。
- `restore-db.sh`/`restore-storage.sh` 的安全收紧属于有意的命令合同变化,runbook 和 checklist 必须同步更新。
- 回滚代码可恢复旧脚本,但已经生成的 dump/tar 仍保持 PostgreSQL/tar 标准格式,不被新 manifest 锁定。
- 如演练环境缺少 PostgreSQL 客户端和 Docker,停止 DB 动态演练;仍可完成 shell 静态检查和附件演练,不得转向真实环境补测。
## 外部门禁
以下事项不因本地演练通过而自动获批:读取真实运行环境、复制真实备份、建立异机定时任务、停机、恢复真实库/附件、部署和公网 `/ready`。进入这些步骤前再次列出目标、只读/写入范围和回滚方式并取得明确批准。