Repository navigation
fix(recovery): bind archive scans to their compressed byte witness - #7220
Conversation
Signed-off-by: aihop <4408344+hhyykk@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; effort=max
动机
需要核验备份、但不能让恢复副本取得执行权限的本地操作者。旧路径先校验归档 A,却可能解析中途被换成的 B;若随后恢复 A,最终 hash 仍可能接受。新路径为解析器实际读取的压缩字节生成摘要与字节数,遇到这种替换就在发布前拒绝。同一真实生产器归档在 File/SQLite 的预览与执行中均拒绝 A→B→A 替换,普通备份仍能生成内容一致、无执行权限的可读审计。这次不恢复当前身份、不激活 Goal,也不证明 M2 捕获一致性或 M3 完整恢复及长期收益。
改动思路
压缩字节见证属于现有归档 IO 边界;清单、恢复审计和权限判断仍由原 TypeScript owner 执行。无需新 store、操作协议或用户确认轮次。当前 PR 的完整边界是实际扫描输入与预检身份一致,并在复制发布前再次比较;不扩展到受控重新激活。这里的见证是摘要与字节数,由实际输入流推导,既不是用户新声明,也不是执行凭据。旧的最后一次 hash 只能证明最后看到 A,不能证明解析阶段也看到 A;因此只增加一次末次重读无法修复问题。现有压缩、展开、metadata 与路径限制继续在读取和复制时生效,失败仍由原调用者处理。
| 输入 | 原路径 | 当前 head |
|---|---|---|
| 普通有效归档 | 可预览、可生成 inert 审计 | 完整结果保持 |
| 校验 A、解析 B、随后恢复 A | 可能接受 | 在发布前拒绝实际输入不一致 |
| 一开始 digest 错误 | 在 tar 解析前拒绝 | 保留同一拒绝顺序 |
具体改动
评审 head:78b008a8aefc26d70ead4e56ca274d37f3f84147,独立基线 19ccb632845ceae49ca6463ef26e868e2dcc1a45。先读取原规范 docs/architecture/rfcs/complete-state-recovery-v0.md,再读实现;规范检查点的新增文字不充当自身验收。逐项映射:Archive and manifest bind exactly 已实现;Extraction is confined 保留并执行;M1 stays inert 保留并读回;v0 uncertainty is honest 保留为 held、不授予激活。M2/M3 与本次有界修复分开验收。
关键代码讲解
_ArchiveInput在每次向 gzip 交付压缩字节时累计 SHA-256 与计数;超过既有压缩上限直接拒绝。BufferedReader 只负责有界批量读取,没有复制成另一份完整归档,也不接管 caller 的文件句柄。_scan继续走原安全 tar 遍历、gzip EOF 与链接处理,返回实际读入身份;复制扫描把身份和原 member 观察一起比较。关闭包装流不会使后续原句柄重读失效。verify_state_backup在首轮扫描后、manifest/owner 审计前比较预检身份;执行分支继续要求复制观察一致及末次 hash 一致,保持 staging 清理和不覆盖发布。
全部五条改动路径都在范围内:运行时 IO、保留原断言的回归、英中 RFC 同步,以及按需加载的修复模式行。该行只解释已证实的诊断,不增加后台自动恢复、配额义务或权限。未引入公共 schema 或新的共享状态词汇;复用现有错误及恢复 owner。
对主干的风险
独立源码验证:原恢复套件 64 通过,原 native recovery 8 通过。同一当前测试 oracle 对不可变基线生产源码为 61 通过、3 失败,恰是两条 A→B→A 预览/执行拒绝和压缩读取预算;没有修改原断言使其通过。另从真实 producer 创建相同 File/SQLite 归档,执行完整公共 CLI 预览、执行和替换负例:基线错误接受,当前 head 返回 recovery_input_changed,不发布 destination 或残留 staging。只改 gzip mtime 的 B 仍含有效 tar 内容,因此这是输入一致性缺陷,不是远程入侵或执行权限证明。
普通 CLI 结果、组件、诊断和权限字段保持一致;仅归一化实际耗时、观察时刻及由它们产生的审计 seal,并先独立验证每份原 seal。实际 JSON 保存结果与返回值逐项读回;已有套件覆盖 loopback HTTP、原源不可用和 File/SQLite 历史审计。当前快速 premerge 6 direct +4 selected 全过。仓库 CI 按契约不查询、不等待。额外 hash/缓冲会有代价,不声明吞吐提升;复合最大容量、其他平台、安装包和 live recovery 没有被本次资格覆盖。
我的整体评价
APPROVE。这是一项完整、可回退的现有输入边界修复:真实消费者不再把另一轮读到的字节冒认为已校验输入,现有合法备份、历史状态和无执行权限约束保持。long_horizon 判断为 preserved,并非已证明模型采用或长期净收益;user_experience 在准确失败与读回上改善,原调用流程没有增加确认轮次。CLI 与既有 HTTP/Settings 调用共用原核验入口;本次没有改变页面布局、控件或渲染数据契约,因此视觉评审不适用。未重新验收安装包、浏览器整页或实际用户采用;本次无渲染改动。代码体量与这个可复现缺陷相称;更大的恢复服务或新存储不必要。当前 PR 的完整边界是实际扫描输入与预检身份一致,并在复制发布前再次比较;不扩展到受控重新激活。本结论不执行合并或启用恢复。
English verdict: APPROVE — 78b008a8aefc26d70ead4e56ca274d37f3f84147 binds both scans to their actually consumed compressed bytes. Independent real File/SQLite CLI ABA cases now refuse before publication; ordinary output/audit parity,64 Python tests,8 native tests and6+4 quick checks pass. Compound limits, broader platforms and installed/live recovery remain unqualified.
Goal And Delivered Outcome
Backup verification could hash archive A, parse different compressed bytes B, then accept A again after an ABA restore before its final hash. Both preview and execute reproduce this with an ordinary producer archive. The regression changes gzip identity while retaining valid tar members; this is an input-consistency defect, not evidence of execution authority or remote compromise.
Bind each parse to the compressed bytes it actually reads. A private bounded IO adapter records their SHA-256 and count under the existing gzip/tar stream. The first witness must match preflight; the copied scan's witness participates in the existing observation comparison. Keep the final source hash, early wrong-digest refusal, capacity/metadata guards and inert publication rules.
Source:
docs/architecture/rfcs/complete-state-recovery-v0.md, M1 and the immutable recovery-set decision, at main659c1fd441abf5bd9171f22d9a84981497856a63. Intended base:main.Author Declaration
Written by: model_agent — OpenAI Codex, GPT-6 family.
The existing module's
readseam now hides compressed identity as well as expansion checks. Buffering keeps witness updates bounded; the caller-owned archive handle remains available for subsequent passes. No new operation, persisted field, store, capability, dependency or authority is added. The public CLI/HTTP entrypoints keep their interfaces.Scope And Continuation
Complete for the scanned-input witness. The paired RFC checkpoint states this bounded M1 behavior. Reverting code requires no state conversion. Capture consistency M2, controlled reactivation M3 and broader platform/provider qualification retain their existing gates. No live recovery is performed.
Checked 43 open PRs and their changed paths. Only the shared repair-pattern table overlaps #7199, #7196 and #3412; their actual patches address admission timers, context delivery or settlement effects. None changes archive byte witnessing or adds this diagnostic pattern.
Validation
19ccb6328leaves all five patch files byte-identical; six targeted recovery cases and all eight native cases were rerun there.Complete-command Cost And Parity
This adds streaming hash work. The following results are retained costs, not a throughput improvement:
Ten measured samples per arm/workload, alternating base/head/head/base; one warmup block excluded, fresh Python processes and warm native runtime. The baseline restores only the original IO module from the pinned main; other source and the immutable archive pair are identical. No tests/builds overlap this run.
Full public results match after normalizing only destination, observation time, measured durations and the resulting audit seal. Each original seal is independently verified before normalization. Recovery/archive/manifest identities, component state, diagnostics and execution denial remain compared. Representative cost rose about 56/75 ms at the median and 126/210 ms at p95; the 8 MiB case does not qualify worst-case capacity or supported-platform performance.
Full repository CI, installed packages, browser journeys, live recovery and compound worst-case qualification have not been run here. No model call, provider activation, Goal mutation or external delivery is started by this proposal.
Frontend / Visual Evidence
Existing backup inspection entry and error path are reused. Public schemas, layout and controls are unchanged. Actual CLI/loopback HTTP recovery coverage is in the recovery suite; packaged-browser capture is not rerun for this archive IO repair.
Boundary Checklist
mainbase.