运维(08-28-production-arm-backup-transfer-incident): 固化只读调查合同
这个提交包含在:
@@ -0,0 +1,72 @@
|
||||
# 生产到 ARM 备份传输中断实施计划
|
||||
|
||||
## Phase 0:规划与授权
|
||||
|
||||
- [x] 创建 P1、`operations` Trellis task,记录来源事件和与恢复演练的阻塞关系。
|
||||
- [x] 固定只读调查、生产/ARM 写操作、手工补跑和测试告警为不同审批边界。
|
||||
- [x] 用户审阅并批准本规划及补充项后运行 `task.py start`;该批准只授权进入本地实施,不自动授权连接远端。
|
||||
|
||||
## Phase 1:本地只读调查准备
|
||||
|
||||
- [x] 从 `scripts/run-automatic-backup.sh`、receiver、dead-man 和 systemd installer 提取真实单位名、状态路径来源、阶段和退出码合同,禁止手写近似常量。
|
||||
- [x] 实现只输出 allowlist 的跟踪只读采集器:生产本地完整恢复点合同、本地成功/失败清理保留语义、partial 匿名字节比例、rsync 原始码、无法取得的传输时钟、两端容量;timer/service 继续复用既有只读 systemd 聚合合同,不在 Python 中另写一套。
|
||||
- [x] 为本地完整/无完整批次、成功清理/失败保留、相近/不同停止偏移、rsync `23/30/12/11/255`、缺失持续时间、权限拒绝、畸形 manifest 和敏感输出补合成回归。
|
||||
- [ ] 本地语法、合同、敏感扫描全部通过后,提交远端只读调查摘要与精确权限边界,单独申请执行批准。
|
||||
|
||||
### 本地准备结果(2026-08-28)
|
||||
|
||||
- 跟踪调查器:`scripts/qa/inspect-backup-transfer-incident.py`;仅接受显式绝对路径参数,不回显参数值,未知异常也只输出稳定类别。
|
||||
- 可复跑合同:`scripts/qa/run-backup-transfer-incident-contract.sh`;17 项合成检查通过,fixture 与 Python cache 零残留;权限拒绝不会被误写成“无有效备份”,其他阶段的旧日志不会冒充本轮 rsync 诊断。
|
||||
- 既有 `run-automatic-backup-contract.sh` 74 项通过;生产 wrapper 未改。现状没有持久化传输专属开始/结束时刻,故持续时间必须为 `NOT_AVAILABLE`。
|
||||
- rsync 原始码只在安全摘要明确为 `phase_offhost_transfer_failed` 时从 root 私有 `last-error.log` 固定正则提取,避免把 paired-backup/finalize 的旧诊断错误归因给传输。
|
||||
|
||||
## Phase 2:获批的远端只读调查
|
||||
|
||||
- [ ] 在不修改生产/ARM 的前提下采集四类证据;每个临时入口在同轮精确清理并由外层独立复核零残留。
|
||||
- [ ] 先判定“生产单点”或“无已证明可用备份”,再交叉判定主要根因、次要候选、清理/累积语义和容量预算;无法取得的字段标为 `NOT_AVAILABLE/NOT_MEASURED`。
|
||||
- [ ] 记录过渡恢复点决策;只读证据无法收敛时停止扩读,提交一次受控观测性重传的独立审批方案,不直接执行。
|
||||
- [ ] 更新本 task 证据,给出单一最小修复方案、回滚方案和生产写操作清单;停止并请求用户审阅。
|
||||
|
||||
## Phase 3:本地修复与变更审批
|
||||
|
||||
- [ ] 仅修改证据支持的脚本/installer/合同;不轮换已通过初始认证的密钥,不放宽 manifest/finalize 门禁。
|
||||
- [ ] 容量方案优先扩容或精确处置已确认的自动备份自有对象,证明不会触碰唯一恢复点、数据库或附件源。
|
||||
- [ ] 运行自动异机备份、receiver、dead-man、故障注入、回滚和敏感输出合同。
|
||||
- [ ] 列出生产/ARM 的每个写目标、旧值指纹、候选 SHA、执行/回滚命令和停止条件,单独申请实际变更批准。
|
||||
|
||||
## Phase 4:获批的实际修复
|
||||
|
||||
- [ ] 执行最小变更和容量处置;不做未批准的手工备份、timer 修改、partial 清理或测试告警。
|
||||
- [ ] 若另获手工补跑批准,只运行一次并记录真实 rsync 码、时长、原子 finalize 和残留;失败不自动重试。
|
||||
- [ ] 验证至少一个新原子批次、manifest/三文件/字节/SHA-256、三组 service exit `0` 和容量预算。
|
||||
|
||||
## Phase 5:两个自然周期观察
|
||||
|
||||
- [ ] 自然周期 1:daily 新原子批次 PASS;watchdog/dead-man service success;记录生产/ARM 容量、ARM partial 数量/聚合字节趋势和适用的告警响应锚点。
|
||||
- [ ] 自然周期 2:重复同一组断言;不以手工补跑或旧批次替代;ARM partial/容量趋势不得继续恶化。
|
||||
- [ ] 两个周期均通过后标记事件 `GO`,否则保留失败并返回 Phase 2/3,不临时放宽阈值。
|
||||
|
||||
## Phase 6:解除阻塞与收口
|
||||
|
||||
- [ ] 在 `08-23-isolated-backup-restore-drill` 追加本任务结果交叉引用并解除事件阻塞;恢复演练仍需新批次身份探针和单独实际恢复审批。
|
||||
- [ ] 运行 task validate、Trellis governance、process baseline、docs registry、敏感扫描和 `git diff --check`。
|
||||
- [ ] 中文提交引用 `08-28-production-arm-backup-transfer-incident`;不自动 push,不归档未满足两个自然周期的任务。
|
||||
|
||||
## 停止条件
|
||||
|
||||
- 只读操作将输出路径、身份、凭据、原始日志/JSON 或业务内容。
|
||||
- 需要新增 sudo、读取超出 allowlist 的 root 状态或改变生产/ARM 状态但尚未获独立批准。
|
||||
- 清理对象、配置目标、旧值或回滚路径不唯一。
|
||||
- 新原子批次不完整、service 非零、容量低于预算或任一自然周期失败。
|
||||
- 告警发送/人工确认锚点缺失时不得补造响应延迟。
|
||||
|
||||
## 验证命令
|
||||
|
||||
- `bash -n` / `python3 -m py_compile` 覆盖新增或修改的运维脚本。
|
||||
- 运行自动备份、receiver、dead-man 和相关敏感输出合同。
|
||||
- `python3 ./.trellis/scripts/task.py validate .trellis/tasks/08-28-production-arm-backup-transfer-incident`
|
||||
- `node scripts/qa/check-trellis-governance.mjs`
|
||||
- `node scripts/qa/check-process-contract.mjs --baseline --json`
|
||||
- `node scripts/qa/audit-docs.mjs --check-registry`
|
||||
- `node scripts/qa/check-sensitive-content.mjs`
|
||||
- `git diff --check`
|
||||
在新工单中引用
屏蔽一个用户