# 0.4 恢复、健康证据与索引

## 不破坏原件的救援

优先尝试严格 restore。不要先删除或修复原始对象。`emergency-preview REPO ID NEW_TARGET [--key-file FILE]` 逐文件校验，返回健康/失败数量和绑定源状态、快照、选项、新目标的 confirmation。执行 `emergency-restore` 必须附 `--accept-partial --confirmation HASH`；参数或源状态变化要重新预览。

仓库读权限和新目标写权限分离：严格只读 Host 禁止仓库及恢复写入，新目标 writer 仅能写指定的新目录。不创建源锁或清理原件；逻辑只读会话不提供并发写隔离，应先停止其他写入。父目录必须可信，不接受链接/联接点。

只写健康文件及原目录拓扑，逐块重新校验，独立磁盘读回 SHA-256 后排他发布目标。坏文件不写、不补零。部分恢复 `ok:false / complete:false`，CLI 退出 1，即便健康部分已成功发布；不要据退出码假定输出不存在。救援仅数据，不恢复权限/时间。完全无健康文件且有错误时不发布；失败暂存保留，不自动递归删除。

## 独立密钥与恢复准备

key-export 的输出本身是秘密，须另行离线保管。紧急命令 `--key-file` 不依赖旧任务、DPAPI 或旧状态。工作台应急区支持独立密钥；巡检、清单和重建使用当前会话解锁，请先在密钥管理区解锁相应来源。

`recovery-checklist REPO NEW_PRIVATE_JSON` 导出快照 ID/时间、仓库身份及步骤，不含密码、密钥或文件名。只写仓库外新文件，不允许进入公开源码区（私有 .local 除外）。清单不是恢复证明。兼容运行包、独立密钥、仓库副本三者需各自保管；同机新状态演练不等于跨主机证据。

## 健康副本重建

`rebuild-copy DAMAGED_REPO PINNED_ID DONOR_REPO NEW_REPO` 只重建一个指定快照，两个来源只读。主清单损坏可获取副本同 ID 清单；所有对象检查逻辑哈希/长度。新仓库暂存、完整 audit 后发布；双边缺失或损坏则不发布，不原地修复、不重建全部历史。

加密源不默默降级明文。新目标密码来自 `MOONRESTORE_DEST_PASSWORD`；供体可用 `MOONRESTORE_DONOR_PASSWORD` / `MOONRESTORE_DONOR_KEY_FILE`，或在工作台分别解锁。密码勿放命令参数/公开日志。失败可能保留新私有暂存，原仓库不变。

## 持续健康证据

`scrub REPO --files 100 --bytes 268435456 [--snapshot ID]` 每次检查一批，持久保存游标，默认轮转最久未完成的快照。`health-status REPO --max-age-hours 168` 区分 unknown、failed、stale、verified_in_window。一个快照完整周期全部文件通过才记录；所有已知快照都在窗口内才整体通过。

预算按整个文件计算，不是大文件内字节游标。下一文件超预算明确失败不跳过，需显式提高 bytes。失败需后续完整健康周期才清除。新鲜度从周期开始计时；空仓库、未知、过期、状态损坏、仓库替换均不能报绿。同用户蓄意篡改状态不在保护范围，绿灯不是未来恢复保证。

私有状态锁中断后不猜测删除；先确认没有使用它的进程，备份状态后再处理该个锁目录。状态清理不删除仓库内容。报告默认不含错误文件路径；现场预览或明确详情仍需私有保管。

## 可丢弃搜索索引

`index-build REPO` 验证清单并建立路径索引；`index-search REPO QUERY [--offset N]` 每页最多 200 项。需要明确执行，不自动缓存私人名称。不含文件内容/分块数组；加密源索引用同一仓库密钥、独立用途认证加密。明文仓库索引不加密，Base64 不是保密措施，仍须 OS 权限。

每次搜索复核原始清单集合摘要，变化/损坏/加密不符拒绝并要求重建。索引绝不用于恢复或删除决策，命中不代表内容完整。上限 5000 快照、累计 64 MiB 解码清单、200000 行、16 MiB 正文，超限拒绝不静默截断。不是常量元数据内存；规模复现入口 scripts/history-scale.mjs。

本轮不启用分段清单、打包对象或压缩格式，不原地迁移旧仓库。巡检检查点、S3 对象级重试不是备份/恢复字节级续传。
