从孤儿 worktree(artifacts/isolated-worktrees/20260909-ops-preparation、 20260910-reimbursement-payment-integration)合并回填两轮从未提交的真实 执行记录: - 2026-09-09 ARM 管理员会话完成首次隔离数据库恢复,回执 DB_RESTORE_PASS, 66 项迁移精确匹配、12 类关键表可读。 - 2026-09-11 第二次配对恢复,AC1/AC3/AC6 勾选完成;对发票池一条历史缺失 附件做 SHA-256 比对、来源元数据核对、生产/ARM 归档/周检查点全量搜索, 均未命中,按用户决定非破坏性标记、暂不追查(AC4 仍未过)。 无产品代码改动,无生产/ARM 操作;仅补齐 Trellis 任务文档与既有证据记录, 使 in_progress 状态反映真实已发生的执行历史。 Co-Authored-By: Claude Sonnet 5 <[email protected]>
62 KiB
隔离备份恢复演练实施计划
2026-09-15 简单配对恢复的集中批准边界(未执行)
不新增runner。已知可识别的历史输入为receipt-followup-release回滚备份:manifest 56a9addf57556580c46205ae8e68b01a8e23a45ae7757d4cfce9ec9c92660c86、来源8d08d46d;对应镜像归档SHA256 d17d7efaef073b5cc6b78f1ce2a73e938835e4910946c83e855b48e61780541b,历史回读通过。它不是已核最新自然备份,不能报24小时内,也不能换成b7或当前本地代码假装同源恢复。
拟定单次范围:在ARM侧隔离的一次性Postgres16及匹配应用容器中恢复该固定源DB和storage,使用专用空卷、无端口映射的internal网络、禁OCR/通知/支付/ERP等外联和定时任务。实施前只读重核源manifest/包摘要/镜像身份、目标容量与生产ready基线;无法获得无业务副作用的应用启动配置则停在DB+附件结果,不把app记PASS。镜像加载、源副本、容器/卷创建和恢复均待专项批准。
验证仅限迁移集合/校验和、关键表聚合计数、附件引用存在性及可用大小/摘要、隔离应用健康与授权可读性;不回传原件或账号,不改生产引用。历史缺失附件仍无可定位的治理落库证据,若再次出现,分类报告NO_GO,不自动排除“测试件”。只删除本轮确实创建且身份可核的容器/网络/卷/临时副本,保留原备份、旧回滚镜像与生产服务;末尾复核ready及清理结果。
此固定历史源方案只回答“已备份的数据能否配对恢复”。最新自然批次/异机传输/当前生产灾备就绪是另一个只读时效核验,必须以执行时的新事实作结论,不能用此历史恢复代替。当前状态PREPARED_SCOPE_NOT_AUTHORIZED,不是恢复通过或完整生产就绪。
2026-09-15 统一收口接续
统一计划入口见09-08-reimbursement-payment-closeout/implement.md六项计划,本task负责C的配对恢复,ARM传输事实由08-28-production-arm-backup-transfer-incident核对。当前已知有历史DB恢复PASS和近期备份/镜像完整性PASS,不能回退说“从未恢复数据库”,也不能因此宣称DB+附件+应用恢复已完整通过。
先核09-04任务历史缺失附件的实际治理结果/批准范围,不能把“可能是测试”当可删除授权清单。准备同一manifest的DB/附件、匹配应用镜像、固定隔离目标/禁止生产连接和通知OCR外联、容量上限、清理范围与停止条件;形成一次准确受控恢复请求,不重复升级复杂runner。授权后一次简单恢复核迁移、关键表、附件引用及适用摘要、应用只读健康/可读性,原件内容不出日志。任何缺失归因分清备份不全、历史源缺失与工具误判,不强行删除引用通过门禁。
2026-09-11 配对恢复准备(未执行)
用户曾回传一次 DB_RESTORE_PASS:66 条迁移集合匹配、12 类表已验、隔离资源已清理。这是管理员回执,不是本轮独立复验;不能继续写“数据库从未成功恢复”。附件与应用配对恢复尚未证明。
接续采用简单隔离流程,不再扩复杂演练器。先获准只读核验最新本地/ARM 自然批次、manifest/包大小摘要、来源版本、时效、磁盘和独立镜像制品。历史备份时点及旧磁盘数值不当成今日事实。
实际恢复需单独授权具体隔离目标与资源:同一 manifest 的 DB 和附件恢复到一次性 PostgreSQL 与空目录;源/目标身份隔离、禁生产数据库连接及通知/OCR/支付外联;核对迁移、关键表、附件引用存在性与适用大小摘要,必要应用只读。只回传脱敏匹配数和异常类别,不输出记录或文件路径。仅清理本轮创建资源,旧备份和回滚制品不删。
摘要匹配不等于实测恢复;旧镜像不撤销留痕删除或票据释放;若未来恢复生产,备份时点后数据丢失风险仍须另批。当前只准备清单,未 SSH、未复制或恢复真实备份。
2026-09-11 已完成历史缺失标记:保留归档记录、暂不追查
用户:"可能是测试时候的……不在当前报销单里,影响不大的情况下,可以删除或标记就行。"选择保留原记录并在本任务/恢复缺口材料标记,不硬删、不伪造原件或改变存储路径。现有 invoice-pool PATCH 只允许 available/ocr_failed;archived 不允许编辑,因此不绕过接口状态守卫直接修改备注。此处置是任务/运维记录标记,不声称已新增系统页面标签或写入发票字段。
- 限定单条只读回核:记录/路径摘要一致,仍 archived/manual,当前原件缺失、报销/明细/差旅及同路径报销/采购/回单/请假附件关联均不存在。UTC 2026-09-11 06:22 实测,只返回 1 条、7 个关联布尔值均 false,生产版本 fe025e65、运行身份不变。
- 在当前 task 与 provenance/historical-missing-disposition.json 登记"已知历史附件缺失,低当前业务影响,保留归档记录、暂不追查";不再作为继续业务开发/其他验收的阻塞项。
- 保留技术结论:该固定备份 DB 恢复通过、附件引用缺 1、app 未测试。标记不是恢复成功或发布例外批准,不修改恢复门禁或历史备份,不删除数据。未来关联/重要性证据变化时重新打开该缺口。
本阶段处置闭合:选择标记而非删除,不再反复恢复、扩大搜索或索取同一处置授权。标记仅在现有任务和恢复证据里,未给生产票据加 UI 标签、未修改其备注/状态,也未新增审计或业务记录;不能对外称"生产数据已打标"。回核代码语法与 5 个本地合成条件通过(无关联、已关联、文件重新存在、状态变化和投影未知);原始回执在 provenance/disposition-precheck-result.json。这里接受的是已知历史缺口的低当前业务影响,不是"已确认测试数据"或"完整恢复通过",也不替代候选独立复核和发布审批。
2026-09-11 单份 PDF 摘要比对完成:大小和摘要均未命中
用户对"只将此前提供的那份发票 PDF 与登记文件摘要比对,需要读取字节、不展示内容、不写回、不扩大搜索"回复"是"。复用本 task 与原证据 provenance 子目录,不新建任务。
- 只读取指定本地 PDF;拒绝符号链接/非普通文件、超限及读取期间变化,原始摘要仅在内存中传给既有受控只读生产通道,不展示或写入证据。本地读取字节是本次明确授权范围,不能把整次操作称为"未读文件内容";远端没有读取发票文件。
- 精确定位既有记录/路径双摘要,在有超时的 READ ONLY 事务内比较登记摘要和大小;仅返回布尔结果、范围与运行身份未变。
- 4/4 合成测试验证大小/摘要四种组合、目标变化和失败回滚、非法输入不连接、SQL 投影边界;实际生产只读查询退出 0,结果未匹配。按约定停止,不扫描其他 PDF。
结果:候选文件 56436 字节,PDF 文件头有效且读取前后身份/大小/修改时间未变;目标此前登记 57786 字节,本次数据库直接比较 sizeMatches=false、sha256Matches=false、exactFileMatch=false。既有记录/路径及 archived/manual 标记核对一致,生产运行镜像/容器身份不变。文件内容及实际文件摘要均未展示,原件未上传生产,未改库、补文件、触发备份、恢复或部署。
该结果只证明候选文件与登记原件字节不一致,不证明两份 PDF 的业务内容必然不同;本轮未做票据解析或内容比较。不能以"相似文件"替换登记原件,也不删除/忽略缺失引用。此次限定比对已经结束;保留历史缺失和整体恢复 NO_GO,后续只能基于新的明确原件线索或单独批准的缺失处置方案推进,不再原样恢复或逐次扩大目录搜索。运行时候选和发布授权均未变化。
证据:provenance/single-candidate-result.json。测试命令 node --test artifacts/qa-flow/20260911-invoice-reference-readonly/provenance/compare.test.cjs(4/4);沿用已验证的有界生产读取封装,不改此前冻结脚本。新比对代码只属本地诊断材料,不进入运行时候选。
2026-09-11 单条来源元数据核对完成:历史 mock OCR、手工归档标记
用户回复"是,同意"。复用当前 task 与原证据目录的 provenance 子目录;只查该记录,不扩展到个人访问/登录历史、全量审计或其他票据。
- 对照当前生产版本的 schema、上传与归档写入路径,确定来源字段能证明什么;988 个本地受版本控制的源码文件做静态字符串路径摘要对照,精确命中 0,不覆盖动态生成路径或未跟踪材料。
- 有超时的 RepeatableRead READ ONLY 单条查询,按既有记录/规范化路径双 SHA-256 核对身份,只输出安全枚举、时间、技术元数据和身份关系布尔值;5/5 本地测试通过,含一次性真实 PostgreSQL 精确行筛选、成功/身份不符后的数据不变与清理;Python 语法检查通过。
- 既有生产 SSH 通道执行成功,恰 1 条记录;SQL 定位摘要和 Node 规范化路径摘要一致,生产仍 fe025e65、镜像/容器启动身份前后不变。未读单张文件、未访问 OCR 服务、ARM 或历史数据库,未部署或写库。
- 回填结果和证据边界,不自动补原件、改路径、删除或排除该条记录。
当前行实测:UTC 2026-07-27 12:07:48 创建(北京时间 20:07),12:16:37 归档(约 8 分 48 秒后);status=archived、archived_reason=manual,而不是 unused_timeout。创建/上传/归属对应同一账号,当前更新人也是该账号;不读取账号身份,不将当前 updated_by 等同于已查明的归档操作者。技术元数据为 PDF、57786 字节、日期/UUID 上传路径形态,存储摘要格式合法;ocr_provider=mock、VAT、尝试 1 次,存在请求/完成标记及结果引用,但未读取 OCR 结果内容。当前报销/明细/差旅关联仍均为空。
证据解释:这是一条 7 月的历史记录,带 mock OCR 和手工归档标记;不是自动超时归档标记,不是现在腾讯 OCR 配置的核验结果。路径形态与标准上传生成方式一致,但数据库没有可靠的"真实上传/测试来源"专门字段;mock OCR 可以处理真实 PDF,不能据此确认为测试数据。988 个源码静态路径无精确命中也不能排除动态夹具。当前及本地历史手工归档实现只更新状态/元数据,不删文件;未证明该历史提交就是当时部署版本,不据此声称已查明删除原因。
本轮已完成获准来源元数据核对,不再追加同路径恢复或扩大个人历史查询。缺失原因、原件内容、创建入口和测试身份仍未获确证,整体恢复继续 NO_GO(DB 已通过、附件引用未通过、app NOT_TESTED)。处置应保留该历史缺口:若后续寻找原件,建议先将用户此前明确提供的那一份发票 PDF 与该记录保存的文件摘要做定向比对,不扩大到整个 input 目录;这需要读取候选文件字节计算摘要,不能伪称纯元数据检查,须另批这个单文件范围。匹配只能证明候选文件与登记摘要一致,补回仍另批;不匹配则如实收口,不自动全盘搜索。补文件、改引用或经核实后的清理同样另批;不让员工代做恢复验证。
安全回执与测试汇总位于 artifacts/qa-flow/20260911-invoice-reference-readonly/provenance/production-result.json、source-and-result-summary.json、selftest-result.json。生产只返回脱敏定位摘要、时间、枚举、技术值和关系布尔值,未读取票据正文/金额/备注/银行字段、人员账号、访问日志或审计 payload。没有修改运行代码、提交或推送。
收尾 task validate、Trellis 治理、流程基线及 git diff --check 通过;本地脚本摘要与实际执行输入一致。敏感扫描仅命中合成测试的随机 credential 变量引用,主会话核为误报,保留原始 FAIL 与说明于 provenance/completion-checks.json;不修改扫描规则,不冒充独立复核。此轮没有新的规约变化,复用既有只读最小投影合同。
2026-09-11 历史备份目录项定位完成:限定范围内未命中
用户批准下一步限定只读查找,复用当前 task 和证据目录的 history 子目录,不改变运行候选或部署授权。
- 仅从既有生产自动备份合同与 ARM 接收器合同定位正式历史备份根;不遍历全盘、inbox 或临时事务目录,不读取数据库包。
- 本地合成用例验证路径规范化、目录项匹配、危险条目拒绝、读权限/损坏/变化独立报告,禁止 extractfile/extractall;设置批次数、归档大小、条目数和总耗时上限。python3 -B -I artifacts/qa-flow/20260911-invoice-reference-readonly/history/selftest.py:12/12 通过。
- 完成两端获准正式历史目录项扫描。生产本地 7 份、ARM 日归档 7 份及周检查点 4 份均未匹配该路径;ARM 回执经既有 SSH 直接读取,冻结脚本摘要再次一致。ARM 日根另有 1 个非规范目录项未纳入,类型/内容未验证,不宣称全盘或所有历史备份都已检查。
- 保留已扫描范围、失败/跳过原因及当前恢复仍 NO_GO 的结论;找到仅标待验证原件,补回或改引用另批。没有新增部署、备份、数据库或业务写入。
生产只读结果:正式本地保留批次 7/7 扫描完成,覆盖 UTC 2026-09-05 18:30 至 2026-09-10 18:30,路径匹配 0;非规范目录项 0,归档元数据及运行容器身份前后不变。该结果只排除这 7 份归档中的同一路径,不排除其他路径、较早备份或原始上传文件,不能推出永久丢失。没有核验单张文件内容或历史数据库身份,不把元数据稳定当作全包完整性通过。
执行前 ARM 普通身份目录访问为 PERMISSION_DENIED,sudo -n 需交互密码;管理员现已在自己的终端执行固定摘要脚本,权限前置已解决,不再要求重复输入或重新扫描。脚本最多每根 64 个批次、单归档 512 MiB、展开流 2 GiB/20000 条目、总扫描期限 120 秒并设 150 秒信号上限;只遍历目录项、不调用 extractfile/extract/extractall,不恢复或写业务数据。
ARM 实际结果 SEARCH_COMPLETE,UTC 2026-09-11 05:45 回执:日归档 7/7(备份时点 UTC 09-04 至 09-10),周检查点 4/4(最早 UTC 08-17);路径匹配 0,已扫归档元数据前后不变。11 个 ARM 目录对应 10 个不同 manifest,周/日存在重复来源,不计作 11 个独立恢复点。另 1 个非规范目录项只计数排除,未查类型或内容;未读历史数据库,不能由早期检查点无该路径推断当时已有这条记录或原件永久丢失。
本轮证据为 history/production-summary.json(远端 stdout 的脱敏汇总,非原始逐批回执)、arm-confirmed-result.json(SSH 回读实际完整安全回执)、completed-receipt.json;执行前权限受限回执、暂存及合成测试证据继续保留。SSH 回读不冒充外部独立复核,不修改此前阶段回执。限定路径搜索完成,但缺口未修复:数据库恢复 PASS、附件引用失败、应用 NOT_TESTED,整体仍 NO_GO。
下一步建议结束同路径重复扫描,围绕这一条记录确认来源与预期原件,再决定补原件、修路径或经核实后的历史缺失处置;进一步数据读取或任何修复须明确最小范围,不以"已归档、未关联"自动认定测试数据或忽略失败。不让员工代做恢复测试,不重复要求管理员运行同一命令,当前不部署、不提交推送。
2026-09-11 生产侧只读核对完成:源端同样缺少已归档发票文件
沿已授权生产通道完成最小字段 RepeatableRead READ ONLY 查询和应用实际存储根的 realpath/stat 检查;未打开单张发票内容,未读取金额、银行资料、人员信息或访问日志。6 个本地测试通过,其中一次性真实 PostgreSQL 验证了实际 SQL、关联投影、只读事务与记录不变;另 4 个合成归档目录项用例通过,禁止 extractfile。生产脚本退出 0,无需用户再次操作 ARM。
实测当前发票引用 42:源文件存在 41、缺少 1,无权限拒绝。缺少的引用同时不在已固定 manifest 对应的 107 个附件归档文件路径中。该记录 status=archived、archived_at 非空,创建和更新时点均早于备份;当前没有报销、明细、差旅关联,也不存在同路径的报销附件、采购附件、付款回单或请假附件引用。只保留记录/路径 SHA-256 脱敏定位,不回传原始 ID、路径或账号。
生产仍 fe025e65;容器启动时间/镜像未变,源端同一附件归档前后摘要匹配。没有生产业务写入、恢复、清理、下载真实备份或部署。该证据表明缺口在当前源端也存在,不是仅恢复副本缺文件;但本轮没有再次读取备份数据库的逐条身份,不能只凭当前数量和时间戳相同就声明已证明历史缺失原因。原件是否位于其他路径或更早备份、该记录是否来自测试以及何时/为何缺失仍未验证。
源码核对:当前 invoice-pool 手工归档路由和 invoiceArchiveJob 只更新状态/归档元数据,不删除文件;业务规约要求保留 PDF 原件。因此不把"已归档、未关联"自动视为可删或可排除条件,不改变 AC4 和整体 NO_GO。它当前没有查到报销/回单关联,不能扩大成整个系统所有业务已验收。
下一步建议围绕这一个脱敏引用查找可用原件或历史备份,并另行形成补文件/修引用或缺失处置方案。任何真实文件补回、引用修正、测试数据清理或发布例外继续另批;不再原样重跑恢复。就本轮授权而言,只读核对已经完成,数据缺口未修复,未做文件内容或历史备份搜索。
证据复用 artifacts/qa-flow/20260911-invoice-reference-readonly/:production-result.json、probe-inputs.json、selftest.log、final-receipt.json 与 evidence-manifest.json;脚本及回执均不进入运行时候选。收尾 task validate、治理、流程基线、git diff --check 通过,文档登记检查错误 0(保留既有警告)。定向敏感扫描命中本地合成测试的随机密码变量引用 1 处,主会话核为非凭据字面量的误报,保留原始 FAIL 与复核说明,不修改扫描规则,不冒充独立复核;未提交或推送。
2026-09-11 已授权生产引用与源文件只读核对
用户对限定只读核对回复"是"。本轮可连接当前生产,只查询发票引用定位、状态及关联标记,并用文件元数据判断源文件是否存在;不读取发票正文、金额、银行资料、完整人员信息或访问历史,不登录业务账号,不修复或删除记录。复用原 task,不新增任务。
执行顺序:核对当前生产容器及同一备份 manifest 身份;在有超时的 RepeatableRead READ ONLY 事务中取得最小引用投影;在实际应用存储根下做路径安全和 stat 检查;必要时只遍历同一附件归档的目录项,对照规范化路径摘要,不解包落盘或读取单张附件正文。缺文件、权限拒绝、路径异常必须分开;只输出数量、状态和脱敏引用标识。生产当前引用和备份时点的数据库引用不得因数量相同就冒称完全相同;历史来源因果不明时明确保留缺口。前后回读运行身份不变;不部署、不恢复生产、不清理测试数据。
2026-09-11 第三次诊断结果:发票池 1 条引用缺文件
已从 ARM 的 result.json 读取管理员实际执行回执,诊断不是仅由聊天转述:NO_GO / verify_attachment_references / ATTACHMENT_REFERENCE_MISMATCH。数据库再次 DB_RESTORE_PASS,68 条迁移集合和摘要匹配、异常 0,12 类关键表可读。当前同源批次年龄约 10.57 小时,manifest/包完整性通过。
- 附件解包成功,归档普通文件 107、解包普通文件 107,文件数一致。
- 发票池引用 42:41 条通过存在性、大小和 SHA-256,1 条 FILE_MISSING;该缺失条目未进行大小/摘要验证。
- 报销附件引用 5/5、付款回单引用 1/1 均通过存在性、大小和 SHA-256;采购/请假引用均为 0。
- 合计引用 48、通过 47、缺失 1、外部存储 0;诊断计数与原校验器一致,未跳过任何记录。
- 容器、卷、临时文件已清理,sourceArchiveUnchanged=true,生产前后公网健康与 ARM timer 状态未变;未部署或修改生产业务数据。
结论仅为"这份已校验备份恢复后,有 1 条发票池引用的目标路径不存在",不等于整包损坏,也不能推出原始票据永久丢失或该条一定属于测试数据。107 个归档文件是否在其他路径含有同一内容、生产源端是否仍存在目标文件、该引用是否关联真实报销均未验证。AC4 继续未通过,整个配对恢复仍 NO_GO,应用 NOT_TESTED;保留已有 DB 恢复通过证据。
接下来不原样重复恢复、不删除或排除这条记录。建议增加受控生产侧只读核对,与同一备份对照:只取发票引用定位所需元数据/关联状态和源文件存在性,区分源端缺失、备份遗漏、路径变化或历史异常;不读金额、票据正文、银行资料或个人访问历史。此生产附件/引用核对超出原"生产仅健康和备份元数据"的范围,待用户明确同意再执行;任何补文件、改引用、清理测试记录仍须另批写入。原任务继续承接,不新建 task,不声称原因已修复。
安全回执为 artifacts/qa-flow/20260911-paired-restore/arm-attempt3-result.json;此前两次结果和冻结脚本保留。当前没有遗留影子库可供继续查询,后续若需查看同批次数据库引用,须明确临时隔离读取和清理边界,不以此为由改查完整生产业务数据。
2026-09-11 配对恢复第二次:DB 通过,附件引用未通过
管理员回执由普通 SSH 独立读取:NO_GO / verify_attachment_references / ATTACHMENT_REFERENCE_MISMATCH。DB restore 退出 0,68 条迁移集合和 SQL 摘要一致、异常 0,12 类表可读;数据库恢复能力在当前 fe025e65 备份上已得到实证。ARM 最新同一 manifest 完整性通过、年龄约 9.97 小时、余量约 89.41 GiB;生产前后公网健康与 ARM timer 未变,源归档摘要未变,本轮容器/卷/临时数据已清理。
storage=NOT_TESTED 不是"未解包":执行到该阶段意味着 restore-storage.sh 已退出 0、归档和解包普通文件数已经一致;但回执未在最终引用门禁前写入这些结果。旧校验器只返回总数/不一致数/s3 数,本轮包装器又在写入计数前抛错,所以现有证据不能判断缺文件、大小不符、摘要不符、路径/行格式或外部存储是哪一类。不得称为备份损坏,也不得称为整个配对恢复通过;未启动 OA 应用。
接续仅补诊断,不修复或排除任何数据:按原五类影子库引用逐表运行原校验器,另计算白名单失败类别计数并与原结果交叉核对;所有表检查完再保持原失败门禁。解包/文件数、引用总数、适用大小/摘要验证与失败类别在清理之前写入脱敏结果,不输出账号、单据 ID、路径、内容或原始校验行。不读生产附件字段,不修改生产、备份或已恢复数据,不把真实备份下载到开发机。旧脚本与摘要保存在 attempt2/,真实失败回执为 arm-attempt2-result.json。原隔离资源已按约清理,若要定位现场原因须执行带诊断的同范围隔离过程,不能在没有现场数据时猜测原因或宣称已经修复。
诊断版准备完成:python3 -I selftest.py 20/20 通过,含真实 PostgreSQL 合成配对正例、迁移失败/附件缺失后的完整清理、12 种合成附件条件与原校验器逐一对照、重复引用不去重。缺失反例完整报告五类来源而非遇第一处即停止,解包成功和失败计数在清理后仍保留。本地本轮容器/卷残留 0;ARM 普通账号实测同一公网检查与两个 timer 通过。源端同一 manifest 再次完整性通过(约 10.32 小时),未触发新备份。
诊断脚本已普通账号暂存并由另一 SSH 回读摘要匹配,一次 sudo -n 尝试仍要求管理员密码,诊断版未实际恢复。待管理员执行新摘要命令后读取 attachmentChecks 的分类计数;不承诺下一次会 PASS,不将原附件引用失败降级忽略。当前候选、生产版本和备份不变,未部署;任务整体仍未完成。
2026-09-11 配对恢复首次执行暂停:校验器口径错误
ARM 管理员回执已由普通 SSH 读取确认:PAUSED / preconditions / PRODUCTION_CHANGED,restoreStarted=false;没有开始归档校验、复制、建容器或恢复,三个 Removed=true 表示没有本轮恢复资源需要清理,并非已经恢复后清理成功。
只读定位发现 server/src/config.js 的 normalizeBuildSha 将公网 buildSha 截成 12 位,而本轮校验器错误地直接与完整 40 位比较。当前公网 200/ok、版本前缀 fe025e65cfb5;生产容器完整版本和镜像再次核对未变,同一源端备份完整性仍通过(本次约 9.23 小时)。不能将该错误码解释为真实生产部署或备份损坏。
修订保持原任务范围:公网值严格等于已固定完整提交的前 12 位,不接受任意长度前缀;manifest/build/image 仍完整匹配。用实际 getConfig 生成测试值,补错误前缀、全长误用、过短/空值、非法期望值和失败零资源检查,并先在 ARM 普通身份实测公网检查再交付重试。旧脚本、摘要、测试和指令保存在同一证据目录 attempt1/,实际失败回执单独保留;不覆盖旧失败,不自动部署,不扩大 sudo 权限。
修订验证:python3 -I selftest.py 完整复跑 18/18 通过,本地本轮容器/卷残留 0;ARM 普通账号调用同一 production_ready 后实际通过,两个监控 timer 也通过。首次新增实际配置测试遇到本地 Node 不在执行器受限 PATH 的测试环境问题,测试改为解析当前 Node 绝对可执行位置后复跑通过,未改变远端执行器 PATH。不能再用"把输入完整 SHA 原样回显"的 stub 声称验证了生产健康接口。
修订脚本新目录暂存并由另一 SSH 回读摘要匹配;一次 sudo -n 受控执行尝试仍要求交互密码,未开始恢复。现在仅待管理员运行修订后的固定摘要命令;旧命令对应已证实错误的检查器,不再使用。新接续回执见 arm-unprivileged-precheck.json、arm-revision2-execution.json;schema、生产配置、备份和运行候选均未修改,独立候选复核仍待外部。
2026-09-11 接续:一次性 DB+附件配对恢复
用户"执行下一步工作"承接已推荐的 ARM 隔离配对恢复,不包含生产恢复、部署、真实业务操作或权限扩张。官方 current 已切回本 task;候选 fedcaed1 不变,独立复核仍标为待外部,不以 inline 主会话自审替代。
- 刷新 ARM 既有 SSH 管理员渠道:仍需交互 sudo 密码;不改 sudoers、不申请通用 root shell、不收聊天密码。
- 复用已发布的 restore-db.sh、restore-storage.sh 和附件校验器,准备固定摘要的一次性脚本;仅普通账号暂存,管理员在自己终端输入一次密码执行完整限定流程。
- 先用本地合成备份验证真实 PostgreSQL 恢复、附件配对、失败关闭和本轮资源清理;本地通过不算 ARM 恢复通过。
- ARM 执行前重验最新归档及固定来源 manifest、24 小时时效、来源 build/image、现存 PG16 镜像、磁盘预算与监控;变化则暂停,不自动选择旧批次或拉镜像。
- 同一 manifest 的 DB+附件恢复至随机专属容器/卷与空目录;无宿主端口、network=none、随机临时凭据,不执行 migrate/seed、不启动 OA 或通知/OCR/银行调用。
- 对照来源提交动态核验迁移集合/摘要/异常项、12 类表及适用附件引用/大小/摘要;数据库记录只供机器校验,输出仅统计与安全错误类别。
- 无论成败,只清理本轮创建资源并回读确认;正式归档前后摘要匹配,生产只读健康、ARM 监控状态单独核验。实际结果出来后补原 task 回执,不提前声明完成。
本轮简化执行优先于下方历史 runner 的安装、sudoers、三阶段诊断和八段 RTO 装置要求;不扩建这些装置。保留数据 RPO/恢复总耗时与失败阶段,应用恢复明确 NOT_TESTED。当前备份早于今日两条所属主体修正,不能证明含备份之后变化;生产数据恢复仍需另批。脚本及本地合成证据留在联合副本 artifacts/qa-flow/20260911-paired-restore/,不纳入运行时候选。
本地 python3 -I selftest.py:15/15 通过,真实 PostgreSQL 合成 DB+附件正例、迁移摘要不符和附件缺失两类恢复后失败都完成清理;另覆盖 manifest 固定、来源身份、损坏、超龄、危险 tar/重复项、错误标签拒删、脱敏诊断和公网健康响应合同。12 类表和 68 个来源 migration 指纹用于合成验证,不冒充正式备份的行数验证。运行期间未下载真实备份、未调用 OCR/银行、未部署。
候选已提交树的 32/32 文件摘要仍与原冻结包一致,independentReview=PENDING_EXTERNAL_INLINE。源端最新备份再次完整性匹配,核验时约 8.69 小时,仍早于今日回填;ARM 两个监控 timer 的实际名称、enabled/active 已只读核对。ARM 脚本 0600、暂存目录 0700,另一 SSH 回读摘要匹配;现在仅等管理员终端密码执行,不是授权不足或恢复已失败。恢复脚本、输入摘要、本地日志与暂存回执分别见同目录 bundle-manifest.json、selftest-result.json、arm-staging.json。新增脚本只属本地受控执行材料,不改变 fedcaed1 候选,不自行提交推送这些补记。
2026-09-11 当前应用镜像制品已固定(不是恢复通过)
用户单独批准保存当前生产镜像并校验。本轮 fe025e65 镜像已保存为独立文件,1,119,357,440 字节,配置摘要/14 层/归档摘要通过,另一次 SSH 回读一致;文件 0600、目录 0700,独立于 Docker 存储但仍在生产同机。服务未重启,未 docker load,生产剩余约 40.04 GiB;旧镜像/备份全部保留。
同次另一窄授权仅回填财务/yj 的所属主体,已两行更新及独立连接回读。今日 02:30 的数据库备份早于该修正,不含这些后续变化;没有启动新备份。镜像回退不撤销主数据修正,配对 DB/附件和应用恢复仍待单独授权及受控管理员渠道,不用制品摘要匹配冒充恢复成功。
定位与完整回执共用联合副本 artifacts/qa-flow/20260911-authorized-preparation/,没有复制真实备份到开发机或向聊天输出银行资料。此前"当前版本独立制品未找到"是此授权执行前事实,已由本节更新;ARM 归档当前受交互凭据限制的缺口仍存在。
2026-09-11 限定只读刷新回执(未恢复)
本轮获准只读预检,没有恢复或镜像持久化授权。生产仍 fe025e65,候选 fedcaed1 已推送;今日 02:30:49 同版本备份的 manifest/DB/附件包大小摘要匹配,核验约 7.27 小时,PASS_INTEGRITY_ONLY。生产余量 41.09 GiB;现有登记回滚目录没有当前生产版本镜像的独立制品,3 份其他版本回执保留。
源端成功回执及最新 watchdog 时效检查正常;ARM dead-man 今日 06:30 退出 0、timer active,但本次普通账号归档路径读取被拒,sudo 非交互访问要求管理员密码。没有绕权限,今日 ARM 归档文件及目录容量未独立核验,也没有恢复、复制真实备份或清理资源。此前管理员回传的一次 DB_RESTORE_PASS 仍有效,仅不替代本次 DB+附件+应用配对验证。
证据共用联合副本 artifacts/qa-flow/20260911-readonly/。接下来先给受控隔离目标的管理员执行渠道,再按明确批准做配对恢复;只读检查不自动授权 docker save/load、服务重启或生产数据回退。不扩复杂演练器、不索要聊天明文密码。
2026-09-09 最小恢复阶段执行记录
- 已完成本地准备:在独立 ops-preparation worktree 修订 PRD/design,直接复用 restore-db.sh、restore-storage.sh 和已有附件关联校验器,固定三文件摘要;没有修改任何恢复脚本、安装器或 runner。
- 未访问 ARM 或生产,未选择当日备份、未核对当日容量/新鲜度、未创建容器或恢复数据。不能用历史09-08完整性结果当作本次前置。
- 实际执行待明确授权,授权对象须区分"数据库最小恢复"与"配对附件恢复";未批准附件就只出 DB 结果。代码提交/推送、正式应用恢复及生产切换均不包含在本阶段。
- 本地验收:恢复 shell 语法、task validate、Trellis governance 和 diff 检查;这些不替代真实恢复成功。原整体 AC 保持原状;下一次远端成功/失败证据仍追加 research/restore-drill-evidence.md,不创建新证据体系。
| 代码 | 发布 | 业务/恢复验收 | 等谁 |
|---|---|---|---|
| 只修订本地操作方案,无恢复脚本改动 | 不适用,本轮不发布 | 正式备份最小恢复未执行 | 等用户单独批准受控 ARM 操作,执行时再核对最新批次与容量 |
2026-09-09 获批数据库最小恢复:访问前置停止
用户已明确批准仅数据库的ARM隔离恢复、结果检查及本轮精确清理;附件未授权。本次不再处于"等待恢复授权",而是"管理员通道不可用"。
北京时间2026-09-09 09:22:40执行既有SSH通道的最小检查:SSH退出0、当前UID=1000、sudo -n true未通过。只证明当前非交互通用提权不可用;未采集sudo原始报错,不把它进一步断言为具体密码/策略故障。没有尝试新账号、读取密码、修改权限/sudoers、利用Docker绕过文件权限,亦未反复试探其他提权方式。
结果STOP_ADMIN_CHANNEL_UNAVAILABLE;backupRead=false、containerCreated=false、restoreStarted=false。未选择最新批次、未核对当日备份完整性/年龄,不复用昨日结果冒充已验;无本轮远端临时文件、容器或卷需要清理。该结果不是新的pg_restore失败,也不说明正式备份不可恢复。
脱敏回执保存在原主工作区artifacts/qa-flow/project-roadmap-execution-20260909/restore-minimal/access-check.json。下一步使用用户已说明可用的ARM管理员交互会话执行最小操作;密码只在用户终端输入,不要求发到聊天,不以清理或诊断为名扩权。本地规划与清单仍保留,生产部署和真实付款继续暂停。
2026-09-09 最小数据库恢复阶段闭合
- 用户既有管理员交互会话完成最新批次完整性检查;原版恢复脚本退出 0。
- 管理员回传来源 migration 66 项精确匹配、异常 0,12 类关键表可读及数量摘要;本地来源/候选 migration 目录集合一致。
- 管理员回传本轮容器、卷及临时文件已精确清理;不读取或保存业务明细与临时凭据。
- 配对附件恢复、引用验证、应用恢复及原整体演练其余验收:本次未执行,不以数据库阶段成功代替。
- 独立远端复核:未执行;本阶段以管理员执行回执为证,代理本地审查不称独立复核。
证据见 research/restore-drill-evidence.md 的同日最小恢复记录。旧访问停止段为历史前置,不再是本阶段当前阻塞;没有变更 task 的整体完成状态。未提交、未推送、未部署。后续规划仍先 seed 初始化/升级分离,不在本轮扩大恢复范围或自动发布。
执行前门禁
- 确认任务已在用户审阅最终规划摘要后由
task.py start进入in_progress。 - 只读确认本地
main、当前生产构建事实、来源/当前 migration 集合和现有恢复脚本;现场两构建均为 65 且目录无变化,但后续执行不硬编码数量。 - 只读确认生产公网
/ready正常;不读取生产数据库或执行生产写入。 - 连接 ARM 后只读核对 receiver 配置有效、最新正式日批次身份、dead-man 状态、Docker 可用性和磁盘余量;不列出完整目录或原始 manifest。
- 磁盘安全预算至少满足“批次总字节数 5 倍 + 2 GiB”;不足则
PAUSE。 - 若当前账号没有对正式归档只读和本轮临时区/Docker 的最小权限,停止并给用户一条窄权限操作步骤;不得申请通用 root shell 或扩大既有健康监控 sudo 入口。
有序执行清单
- 生成不含主机信息的本轮 run id,记录 UTC 开始时间和生产前置
/ready状态。 - 在 ARM 正式日归档中选择 manifest 时间最新的 complete 批次,验证三文件、字节数、SHA-256 与 24 小时 RPO 门禁;在本地仓库确认来源提交是当前构建祖先或相同,并单独记录是否严格相等。
- 创建权限
0700的本轮临时工作区;启动 RTO 计时,复制整个批次并对临时副本重新执行同一校验。 - 创建无宿主端口、无业务网络、无持久 volume 的一次性 PostgreSQL 16 容器;数据库名含
drill,凭据随机且仅存在本轮进程环境。 - 使用
scripts/restore-db.sh的 shadow 合同恢复数据库;任何警告、确认不匹配或 restore 非零立即停止后续验证并进入清理。 - 从来源提交动态冻结 migration 名称集合;通过错误即停的只读 SQL 验证恢复库成功且未回滚的 migration 集合精确匹配来源、无失败/未知项,并静态记录来源与当前构建的 migration 差异;随后验证固定 12 类关键表并记录行数。
- 使用
scripts/restore-storage.sh恢复附件到本轮空目录;比较归档与解包普通文件数。 - 在影子库中聚合本地附件引用,以不输出路径的校验程序验证路径安全、文件存在及适用的大小/SHA-256;记录引用总数和不一致数。
- 所有数据检查通过时停止 RTO 计时;按 manifest 时间计算 RPO,记录当前发布到首个同源恢复点的可用滞后,形成区分“原始数据可恢复性”和“当前 schema 升级状态”的
GO/PAUSE/NO_GO脱敏结论。 - 清理本轮容器、临时网络(若有)、临时附件目录、临时批次副本和临时凭据;确认无本轮残留。
- 再次只读检查生产公网
/ready和 ARM dead-man/健康 timer 状态,确认演练没有影响在线生产与现有监控。 - 将证据写入当前 task,并在既有事实源补充当前状态;不提交任何真实备份、日志或业务内容。
Attempt 1 执行状态
- 最新 ARM 候选在
select_latest_batch阶段因 manifestbuild_mismatch失败关闭;复制、容器创建、数据库恢复和附件恢复均未开始。 - 失败后的只读复核确认:公网
/ready与生产自动备份 unit 的构建短标识一致,两个生产侧事实均为7b86ffb3;因此当前不是计划事实源过期或备份 unit 冻结构建漂移。 - ARM 一次性 root 入口和本轮 runtime 均为零残留,两个监控 timer 仍为 active;本轮 5 个普通用户暂存文件已按 SHA-256 精确匹配并删除,未宽泛删除目录。
- Attempt 1 保持
NO_GO。在当时取得最新 ARM manifest 的脱敏构建短标识、run id 配对关系和 manifest 摘要一致性前,不进入第 3 步及之后的恢复流程。
Attempt 1 后只读调查清单
- 生成固定无参数的 root-owned ARM 只读身份探针和最小 sudoers,只允许读取 receiver 路径配置及最新正式日归档。
- 本地执行
bash -n、候选 SHA-256、sudoers candidatevisudo(环境可用时)和禁止写入/恢复关键字人工复核。 - 上传到 ARM 普通用户私有暂存目录;由用户输入 sudo 密码安装固定入口,安装前再次核对全部候选 SHA-256 和系统 sudoers 语法。
- 运行一次固定入口,记录构建短标识、批次年龄、manifest 配对、产物聚合完整性和入口自清理状态。
- 对照公网
/ready与生产自动备份 unit 的当前短标识:相等时记录同源恢复点已形成;不相等时在本地仓库核对是否为当前构建祖先,祖先且完整/新鲜仍可形成原始恢复重试方案,未知或非祖先才NO_GO。 - 按 SHA-256 精确删除普通用户暂存文件;不得删除 ARM 正式归档或宽泛清理目录。
只读调查执行结果
- 探针候选通过本地/ARM SHA-256、Bash 语法和 ARM sudoers candidate 校验。
- 固定入口只读读取最新正式批次并自删除;未复制、解包、启动容器或恢复数据。
- 最新批次
ec682565在 24 小时内,run id/目录配对及 DB/附件大小、SHA-256 均通过,但与当前7b86ffb3不匹配。 - 只读对时确认自动备份合同刷新晚于最新批次生成;finding 收敛为“发布后尚未产生新构建恢复点”。
- root 入口残留为 0,3 个普通用户候选及暂存目录已按精确身份清理,两个 ARM 监控 timer 仍 active。
- 08-24 最新自然批次只读探针通过:来源与当前构建相同、年龄不超过 24 小时、run id 配对及 DB/附件 SHA-256 均通过;临时入口和暂存零残留。当前可提交恢复重试审批,尚未获得恢复授权。
Attempt 2 恢复重试结果
- 用户批准后安装并执行动态 migration 集合版固定恢复入口。
- ARM 正式归档最新批次首次门禁通过,并开始复制到本轮私有临时区。
- 临时副本复检因 runner 错把正式源目录 basename 身份规则应用到固定名
batch而触发batch_identity;失败阶段为create_isolated_runtime,数据库容器和恢复均未开始。 - runtime、root 入口、6 个普通用户候选和暂存目录均精确清理为零残留,两个 ARM 监控 timer 保持 active。
- 修订 runner:正式源目录继续强制 basename/run id 配对;临时副本 manifest run id 重绑到源侧已验证 run id,并继续校验完整内容合同及源/副本元数据精确一致。补齐 2 正例 + 3 负例后重新执行只读身份探针,实际恢复另行批准。
Attempt 3 准备批准边界
- 用户已批准修复 runner,并重新执行 08-25 最新正式批次只读身份探针。
- 回归已覆盖:正式源通过、同内容改名副本通过、内容篡改副本失败、源 basename/run id 错配失败、副本 run id 与源侧已验证 run id 不同失败。
- Attempt 3 未复用 Attempt 2 新鲜度:08-25 最新批次年龄约 6 小时 11 分,来源与当前构建相同,run id 配对、大小与 SHA-256 均通过。
- 用户复核探针后明确批准 Attempt 3 实际恢复,范围仅限 ARM 隔离影子恢复。
Attempt 3 恢复结果与停止点
- 修复后的候选在本地和 ARM 通过 SHA-256、Bash 与 sudoers 语法校验后安装;正式归档门禁和临时副本源侧身份重绑通过。
- runner 在
restore_database阶段因restore-db.sh返回非零而以database_restore_failed失败关闭;migration、12 类关键表、附件恢复与关联验证均未执行。 - 一次性容器、本轮 runtime、临时 root 入口和普通用户候选均精确清理为零残留;ARM 两个监控 timer 保持 active,生产演练后
/ready仍为相同构建的PASS。 - 在任何 Attempt 4 前修复失败诊断合同:分别记录 dump 列表校验与实际 restore 的脱敏阶段码,并确保失败清理前只保留安全聚合诊断;本地回归已通过,远端探针和实际恢复仍需重新批准。
Attempt 4 前的修复清单
- runner 在调用
restore-db.sh前,以同一 PostgreSQL 16 容器对临时副本执行独立pg_restore --list,记录dump_list=PASS|FAIL|NOT_RUN。 - 独立确认影子目标数据库名与连接状态,记录
target_confirmation=PASS|FAIL|NOT_RUN;不输出数据库名或连接信息。 - 仅在前两项通过后执行实际 restore,记录
restore_apply=PASS|FAIL|NOT_RUN;失败类别区分为dump_list_failed、restore_target_confirmation_failed或restore_apply_failed_after_list_pass。 - 原始 stderr 只进入本轮
0600私有日志并随 runtime 删除;最终输出只含 allowlist 阶段状态和既有脱敏聚合。 - 补三条阶段负例、敏感输出负例和每条失败路径零残留回归;通过后重新执行最新批次身份探针,再请求 Attempt 4 实际恢复批准。
Attempt 3 后本地修复结果
dump_list、target_confirmation、restore_apply固定输出PASS/FAIL/NOT_RUN,并增加执行路径、脚本/pg_restore 退出码、对象错误计数与稳定类别。- 诊断在清理前输出;注入 apply 退出码
23后,调用方在 runtime/access 清理完成后仍可读取阶段状态和退出码。 - partial-success 规则保持失败关闭:任何 pg_restore 非零均为
FAIL/NO_GO,不设置可忽略对象错误白名单。 - PostgreSQL 16 custom dump 直接驱动真实
scripts/restore-db.sh的 Docker stdin 与 host-file 两条路径,均恢复成功。 - dump-list 失败、目标确认失败、apply 失败及敏感输出负例通过;既有成对备份/恢复回归和自动异机备份合同通过。
- 用户另行批准并完成 Attempt 4 前最新批次只读探针:构建
SAME、年龄约 7 小时 24 分、run id/产物完整性与 migration 集合门禁通过,入口及暂存零残留;尚未执行实际恢复。
Attempt 4 前的持久化门禁
- 将已验证的 runner 和附件校验器从个人 workspace 收敛为
scripts/qa/下的跟踪文件,不改变恢复边界或生产脚本。 - 将八类 runner 回归收敛为可独立执行的
run-offhost-shadow-restore-runner-contract.sh,直接驱动真实restore-db.sh双路径。 - 合同脚本必须机械验证三阶段诊断、执行路径、两个退出码、非零失败关闭、源/副本身份、dynamic migration、敏感输出和清理顺序;对候选生成稳定 SHA-256。
- 运行新合同、既有成对备份/恢复、自动异机备份 74 项、Trellis 治理与敏感扫描;全部通过后才允许把跟踪文件打包为 Attempt 4 候选。
- 本阶段仅本地修改与测试;新批次探针结果和持久化门禁均通过后,再单独申请 Attempt 4 实际恢复。
Attempt 4 前持久化门禁结果
- runner 已收敛为
scripts/qa/offhost-shadow-restore-runner.template.sh;现场路径、账号、容器/数据库命名、timer、构建和 migration 指纹均为经严格校验的私有渲染字段。 - 附件关联校验器已收敛为
scripts/qa/validate-offhost-shadow-restore-attachments.py。 scripts/qa/run-offhost-shadow-restore-runner-contract.sh可独立复跑并提供render模式;相同私有配置生成确定性候选 SHA-256,shell 注入在输出候选前失败关闭。- 源/副本身份、内容篡改、dynamic migration、附件安全、三阶段诊断、真实 restore 双路径、NOT_RUN、退出码、清理顺序和敏感输出合同全部通过。
- 新增三个文件由
check-sensitive-content.mjs定向扫描,3/3文件、finding0;本地测试容器残留0。 .gitignore增加/.restore-drill-private/专用目录;合同分别证明仓库内未忽略的私有 JSON、未忽略的现场候选均在创建输出前失败,ignored 输入/输出正例通过。- 私有原始日志保留唯一初始化截断,五个固定阶段均以标记分隔并追加写;静态合同拒绝后续阶段再次截断。
- 完整复跑 runner 合同、既有隔离备份/恢复演练和自动异机备份 74 项;task、Trellis、process、默认/定向敏感扫描及空白门禁通过,测试容器和本地私有路径残留均为
0。 - Attempt 4 最新批次只读探针重新执行并通过;候选已由提交
5ec7db1的跟踪模板确定性渲染,完整合同、依赖钉住和 SHA-256 复核通过。 - 用户批准 Attempt 4 后,候选在 ARM 安装前再次通过 SHA 清单与语法校验并执行;
dump_list=PASS/0,随后在target_confirmation阶段失败,实际 restore apply、migration、关键表和附件均未运行。 - Attempt 4 runtime、临时 root 入口和普通用户上传暂存均清理为
PASS/0;按预先裁决规则转入本地合同路径与 ARM 实际环境的只读差异调查,不直接修补 runner 或创建 Attempt 5。 - 只读差异矩阵与本地精确复现收敛到 PostgreSQL 初始化就绪竞态:合同夹具等待连续两次真实查询,runner 仅等待首次
pg_isready;本地稳定数据库上的同一 target query 为PASS/0,ARM 所有临时对象复核残留0。 - Attempt 4 后正式归档只读探针与执行前为同一构建和同一 manifest 脱敏摘要,run id 配对、产物 SHA-256、24 小时新鲜度均通过;探针入口与暂存残留
0,正式归档内容级零修改已补证。 - 演练后腾讯云生产
/ready已由执行方沿既有只读路径补证:状态PASS、12 位构建前缀7b86ffb3c9ef,与演练前一致;未记录地址或原始响应。 - 用户已批准仅在本地实施和回归 PostgreSQL 稳定就绪修复;该批准不包含连接 ARM 或执行 Attempt 5。
Attempt 5 前仅本地修复结果
- 在跟踪 runner 中以容器内 TCP 回环
127.0.0.1的真实SELECT current_database()作为结构性就绪判据,并以最多 60 次、间隔 1 秒、连续两次成功且名称精确匹配作为额外保险,替换首次 Unix socketpg_isready即通过逻辑;名称错配立即失败,查询非零重置连续成功计数。 - 增加 target query 退出码、名称匹配、尝试次数和连续成功次数的 allowlist 诊断,区分查询非零与名称错配;私有原始日志、失败先诊断后清理和零残留边界不变。
- 可复跑合同直接提取并驱动 rendered runner 中同一稳定就绪函数;fixture 外围与 runner 不同源的等待循环已删除。
- “socket 可用但 TCP 不可用仍失败”、首次失败后恢复、streak 重置、名称错配立即失败、永久查询失败有界退出五类回归通过;真实
restore-db.shDocker stdin/host-file、源/副本身份、dynamic migration、附件安全、敏感输出和清理合同继续通过。 - 已审计合同全部覆盖机制,未发现第二套自写等价恢复逻辑;完整 runner 的 migration/12 类表/附件编排仍只能由真实隔离恢复验证,已作为明确限制保留,不能由本地组件合同替代。
scripts/restore-db.sh相对生产构建字节未改;runner、成对备份/恢复、自动异机备份 74 项、task、Trellis、process、docs、敏感扫描和空白门禁均通过。- 本地修复阶段未连接 ARM、未生成或安装 Attempt 5 现场入口;提交后已重新选择最新批次、执行只读探针、重新渲染候选并核对 SHA-256,实际恢复另行取得了明确批准。
Attempt 5 前只读身份探针结果
- 用户批准后仅安装并执行最新正式批次只读探针;未复制、解包、启动容器、读取业务数据或执行恢复。
- 最新批次来源与当前生产构建相同,探针时年龄
64625秒且不超过 24 小时;run id 配对、DB/附件大小与 SHA-256、source digest 均通过。 - 来源/当前 migration 目录为
65/65、差异0;仓库 HEAD 相对生产构建的应用代码漂移文件数0。 - 探针 root 入口与普通用户暂存残留均为
0;按已验证私有配置取得的 dead-man/健康 timer 实际 unit 状态为active/active。 - 本次探针完成时 RTO 八阶段实现尚未批准,因此当时未渲染 Attempt 5 最终候选、未生成最终候选 SHA-256,也未执行实际恢复;后续本地实现授权单独追加,不改写该时点事实。
Attempt 5 前 RTO 分阶段实施(已批准仅本地实现)
- 设计口径已固定为总 RTO 加八段串行秒数:批次复制、容器启动、dump list、目标确认、restore apply、migration/12 类表、附件恢复与关联校验、最终源/副本复核。
- runner 增加固定 allowlist 阶段字段,成功时八段均为非负整数且精确加总为
data_restore_rto_seconds;失败时已完成段和当前失败段保留数字,后续段为NOT_RUN。 - 合同注入各阶段成功/失败,验证最长 TCP 轮询只进入目标确认阶段、后续
NOT_RUN、总数精确加总、输出不含路径/SQL/凭据;原有清理与恢复合同继续通过。 - 用户批准的当前边界仅为本地修改 runner、更新可复跑合同并执行回归;不连接 ARM、不重新渲染 Attempt 5 现场候选、不执行实际恢复。
- 八阶段计时与完整合同通过后,满足 24 小时门禁的批次已直接进入 Attempt 5 候选渲染、SHA-256 核对、只读探针和实际恢复审批流程;期间未插入新的非阻断增强。
- 八阶段状态必须在失败路径清理前输出;阶段边界沿用
dump_list、target_confirmation、restore_apply等既有诊断词汇,不建立第二套同义命名。
Attempt 5 最终候选与执行前探针
- 从提交
0b94b97的跟踪模板和 ignored 私有配置完成两次确定性渲染;候选字节一致、完整 runner 合同通过,候选 SHA-256 为7904052aa5a8c31d54734bc2fbf2d9caf2dac8b0116135119519f8467b3dae27。 - 候选固定的是生产构建前缀和来源 migration 集合指纹,不固定探针时的 source run id;实际执行会在 ARM 上重新选择当时最新正式批次,并对该批次重新执行完整身份、产物 SHA-256、24 小时 RPO 和 migration 集合门禁。
- 最终只读探针重新选择执行时最新正式批次:来源构建与当前生产相同,年龄
68889秒且不超过 24 小时,run id/目录配对、DB/附件完整性和 source digest 均通过。 - 本地复核来源/当前 migration 为
65/65、差异0,候选 migration 指纹与来源集合一致,应用代码漂移和scripts/restore-db.sh字节漂移均为0。 - 探针 root 入口、sudoers 和普通用户暂存残留均为
0;本地 runner 合同容器残留为0。本阶段未复制、解包或恢复正式归档,未连接腾讯云生产。 - Attempt 5 实际隔离恢复已在新鲜度门禁成立时另行批准并执行;紧邻执行前探针通过,但 runner 在选择实际恢复批次之前即因依赖库入口合同失败,因此本轮不存在“实际选择批次”,不能宣称恢复输入与探针批次相同。
Attempt 5 实际结果与安装器差异调查
- 安装前候选 SHA-256 与已批准值精确一致;紧邻执行前只读探针通过,批次年龄
70444秒,来源构建与当前生产相同,run id 配对、产物完整性和 source digest 门禁通过。 - runner 在
entry_contract阶段以restore_library_missing失败关闭;批次选择、正式归档复制、PostgreSQL 容器启动、数据库/附件恢复和全部八阶段 RTO 均未运行,原始结果保留为NO_GO。 - 失败分类为
installer_path_mismatch:已批准 runner 从固定libexec位置加载三项依赖,本轮一次性安装器却把同一组依赖安装到相似但不同的lib位置。该结论指向演练安装器,不证明 runner 或备份不可用。 - 对错误安装目录做精确只读检查:三项依赖均为 root 拥有的普通文件、SHA-256 前缀与本地包一致、额外条目数
0;随后只清理该已确认目录并得到runner_lib_cleanup=PASS。 - 诊断脚本在 sudo 上下文中用
$HOME推断普通用户暂存位置,导致自删除误指向 root 家目录;随后由普通用户外层对已知暂存脚本执行精确清理。后续安装器不得在 sudo 脚本中用$HOME推断调用用户路径。 - Attempt 5 后腾讯云生产
/ready为PASS,12 位构建前缀仍为7b86ffb3c9ef;失败发生在归档选择之前,未触碰腾讯云生产或正式归档内容。 - 最终只读复核确认 runner/probe 入口与 sudoers、正确
libexec、错误lib、普通用户暂存、Docker 容器和 runtime 六类残留全部为0,dead-man/健康 timer 为active/active;复核脚本自身清理PASS。 - ignored/workspace 安装器已把三项依赖安装目标对齐 runner 已批准的
libexec合同;诊断脚本改用经 basename、普通文件和非链接校验的调用路径自清理,不再以 sudo$HOME推断普通用户路径。runner 与候选字节未改、无需重新渲染。 - 再次实际恢复前重新选择满足 24 小时门禁的新鲜批次,执行只读身份探针并单独申请实际恢复批准;不得复用 Attempt 5 的批次新鲜度或既有实际恢复授权。
08-27 最新批次只读身份探针
- 安装器与 rendered runner/probe 的共享路径完成本地静态核对:runner
SELF_PATH/LIB_DIR/SUDOERS_PATH、probeSELF_PATH/SUDOERS_PATH均在首次特权写入前精确比对;WORK_ROOT未在安装器重复编码,sudoers candidate 从最终路径推导。 - 探针上传准备中一次 basename 截取错误被远端 SHA-256 校验在普通用户暂存阶段拦截;未执行 sudo、未安装入口、未读取归档。三个已确认截短文件逐个精确清理后,以真实 basename 重传并通过三文件 SHA-256 与 Bash 语法校验。
- 最新正式批次只读探针执行成功:来源构建与当前生产相同,run id/目录配对、DB/附件产物完整性和 source digest 均通过;探针入口与普通用户暂存残留为
0/0。 - 最新批次年龄
124137秒,约 34 小时 29 分,超过 24 小时门禁37737秒,约 10 小时 29 分;本次恢复前置判定为NO_GO/stale_latest_batch,不得改选旧批次或执行实际恢复。 - 用户批准后完成生产与 ARM 两侧只读调查:daily/watchdog timer 均按计划触发但最近 service 均
exit-code/1;ARM 最新原子归档超龄且存在两个不完整 partial,定位为生产到 ARM 的传输未完成,不是调度漏跑或完整传输后的 finalize 失败。 - dead-man 实际阈值为
93600秒并正确记录FAIL_OFFHOST_DEADMAN/archive_stale;journal 聚合存在一次sent=true,证明 detector 与发送调用未被去抖静默抑制。健康 timer 保持 active,两端调查入口和暂存均清理为零残留。 - 两个 partial 证明 SSH 会话已完成初始认证并开始写入,后续排查不再以密钥失效、authorized_keys 或 host key 初始拒绝为首要假设;独立事件调查优先采集 partial 聚合字节偏移、真实 rsync 退出码和传输持续时间。
- 在生产自动备份传输恢复、ARM 形成新的 24 小时内原子批次之前,恢复演练保持阻塞;补跑备份、修复传输配置/网络、修改 timer 或发送测试告警均需新的明确批准。
- 将生产到 ARM 的传输中断拆为独立 Trellis 生产事件任务,当前演练任务只保留交叉引用和阻塞关系;创建任务、生产侧只读深查与实际修复均另行取得批准。
验证命令类别
- 本地/仓库:
bash -n覆盖备份、DB 恢复、附件恢复和 receiver 脚本;只读统计 migration 目录。 - ARM 前置:receiver
validate-config、systemd 公共状态、Docker 版本/容量、候选 manifest 脱敏校验。 - 恢复输入:
sha256sum、manifest schema/文件集/字节数校验、pg_restore --list、tar -tzf/tar -tvzf。 - DB 验证:
psql -v ON_ERROR_STOP=1的 migration 名称/状态集合和固定表计数查询;本地用 Git 比较来源/当前 migration 目录,不执行 migrate。 - 附件验证:
find普通文件计数及不输出路径的 Python 只读校验;只输出引用数和 mismatch 数。 - 任务门禁:
python3 ./.trellis/scripts/task.py validate .trellis/tasks/08-23-isolated-backup-restore-drillnode scripts/qa/check-trellis-governance.mjsnode scripts/qa/check-process-contract.mjs --baseline --jsonnode scripts/qa/audit-docs.mjs --check-registrynode scripts/qa/check-sensitive-content.mjsgit diff --check
具体远端命令在执行阶段依据 ARM 已安装的 root-owned receiver 配置生成,不把真实地址、账号、目录或凭据写入本计划。
停止条件
- 最新批次不存在、超过 24 小时、manifest 或 SHA-256 不一致,或来源提交未知/不是当前构建祖先或相同。仅“不严格相等”不再单独停止。
- 权限、Docker、PostgreSQL 16 或磁盘预算不满足。
- 命令目标可能指向腾讯云生产、ARM 正式归档、receiver 管理目录或既有容器/网络。
- DB restore、migration、固定表、附件安全、文件引用、哈希/大小任一检查失败。
- 生产
/ready在演练期间异常,或现有 ARM dead-man/健康监控状态改变。 - 清理对象身份不明确。此时保留现场并报告,不使用宽泛删除命令。
变更与证据文件边界
- 允许写入:当前 Trellis task、既有 OPS7 Runbook/人工试运行报告中的脱敏状态摘要、本轮 ARM 私有临时区和一次性 Docker 对象。
- 禁止写入:产品代码、migration、生产/ARM 正式配置、生产 DB/附件、ARM 正式归档、企业微信。
- 计划新增的 task 内证据:
research/restore-drill-evidence.md;只在实施实际发生后创建。
审查与收口
- 本任务涉及真实备份数据和远端运维边界。执行完成后做一次只读复核,重点确认:生产零变更、归档未修改、RTO/RPO 口径正确、附件验证没有漏项、敏感内容未进入证据、临时对象已清理。
- 若现有脚本需要修改,回到规划阶段补充设计和新的批准;不得在远端临时放宽 shadow/路径/确认门禁。
- 门禁通过后用中文 commit 引用
08-23-isolated-backup-restore-drill,是否推送仍按用户当时授权执行。