CipherFS
开发中 · 未发布 · 格式可能变化

实现与验证记录

验收目标见已确认需求,当前用法见项目 README。本记录按源码阶段保存实际运行结果、决策和未覆盖范围;旧阶段通过不证明后续源码。10-04 至 10-08 的旧记录可在 git 历史中查到,原生挂载证据仍在 evidence/fuse-t-20261008*,不能作为当前源码的实挂验收。

验证方式

宿主机只使用已有 Rust 工具链,不安装额外工具/包/工具链。步骤 4–8 每步先运行受影响测试,再串行执行 handoff 指定的默认/feature 工作区测试、clippy、fmt 和最小 CLI 检查;协调者最多复核一个测试目标后提交、推送。多个 CLI feature 构建不能并行覆盖同一个测试二进制。

完整平台组合由 scripts/test-container.sh(2026-10-13 前为 tools/test-container.sh)在固定 Rust 镜像、只读源码和 Docker 缓存卷中执行:Core、Sync 精简/完整 feature、CLI、FUSE feature 矩阵、Web、工作区全目标全功能编译,真实 C/Python/Go 绑定、前端构建/客户端测试和真实 Web 程序冒烟。运行脚本本身不是通过证据;默认忽略的实挂夹具不计入实挂验收。

2026-10-11 共享冲突、退休、设备权限、流式 I/O 与导出

按 handoff 从首个未完成的第 4 步顺序完成第 4–8 步,复核后分别提交到 main 并推送。第 9 步由协调者直接更新文档并执行完整容器验证。此运行时没有 handoff 指定的 Opus 选项,因此每一步使用可用的继承模型、一个实现 agent,步骤不并行;会话没有提供 attribution 行。Proto 未修改。

步骤提交实现及复核结果
4 冲突bd994e9稳定身份的内容/路径冲突,全部头可读,显式/隐式合并;CLI/Web/FUSE 共用只读冲突视图。协调者 Core conflicts 9/9。
5 退休与 GC217d108共享可取消退休、注入时钟、CAS 引用重建、孤儿 pack 清单、延迟回收与严格快照重放。协调者 Sync retirement_gc 7/7。
6 设备与密钥30028d4真 Iroh ticket/SAS、密码/恢复本机封装、随机新纪元、撤销 cutoff、独立 genesis 锚、恢复轮换/加入及权限证明。协调者 Core devices 12/12。
7 流式 SDK3ab66e4双槽 64KiB 异步/阻塞适配器、快照读取、EOF/取消/关闭屏障、原地 AEAD;修复退休提案与日志两次取时钟的竞态。协调者 streaming 11/11。
8 明文导出e466f05一次选择并固定快照、mtime/可执行位、历史/冲突独立选项、显式缺失路径、描述符锚定独占发布。协调者 export 13/13。
9 文档与容器本提交README、双语 Rust API/架构与本记录按当前实现重写;最终 handoff 删除,决策在本节保留。完整容器结果见下节。

最终宿主机矩阵

每行是该步骤最终源码的独立执行结果,不相加为不同测试数;每组均退出 0。宿主为 macOS arm64、已有 rustc/cargo 1.99.0。精确命令、环境覆盖、目标结果及日志校验和见宿主结果与原始路径到仓库证据的映射。第 4 步未记录起止时刻,由最终原始日志和当时状态恢复命令/计数,不补造耗时。

步骤默认:通过/失败/忽略指定 feature:通过/失败/忽略静态检查
4460 / 0 / 6476 / 0 / 8clippy 零编译警告,fmt、最小 CLI 通过
5486 / 0 / 6502 / 0 / 8同上
6514 / 0 / 6532 / 0 / 8同上;最终第 5 轮标准矩阵
7529 / 0 / 6547 / 0 / 8同上;最终第 2 轮标准矩阵
8546 / 0 / 6564 / 0 / 8同上;两组各 49 targets

工作区测试排除需要宿主 Python 头文件的 cipherfs-python;clippy 使用 PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1。指定 feature 集合为 CLI 的 sync/s3/iroh-p2p/fuse-t/web、Web 的 s3/iroh-p2p/redis-session、Core 的 full/compression/fuse 和 FUSE 的 abi-compat/fuse。默认忽略为六项 macOS 实挂;指定组合另忽略两项内核挂载。未在宿主安装 UI 依赖,UI/绑定运行时在容器验证。

早期失败及修正均保留在步骤 6 专项报告、步骤 7 专项报告和步骤 8 专项报告,不当作最终通过。步骤 6 修复 MemberUpdate 在重开/快照时丢失,以及迟到撤销与管理权限重放;其余失败涉及真实加入、精确 frontier 和完成同步的夹具。步骤 7 第一轮暴露真正的退休取时钟竞态,保持严格重放检查后用确定性时钟修复。步骤 8 初始四个失败是夹具未导入文件索引、未退休其他复用同一单元的旧版本;修正夹具后通过,断言未削弱。

512MiB 不可压缩合成数据实际写入/读回并检查字节数与摘要。安全 tracking allocator 计数跨线程 live allocations 和 realloc 重叠;最终源码峰值 17,085,168 bytes,小于 FastCDC max + 16MiB = 25,165,824 bytes。修复前峰值 25,487,936 超限的失败也保留。见最终内存用例日志。这是本机默认流式路径的回归,不是任意配置、远端读取或全部应用内存上限。

导出最终专项 Core 13/13、最小 CLI 4/4;完整受影响 Core 260 和 feature CLI 108 先于最后的归档长度窄修,最终标准矩阵覆盖该修正。用例包括真实 16MiB+17 流式字节/mtime、空文件、历史/删除/路径冲突、缺失和中途损坏、并发退休/缓存释放、目标竞争与父/暂存名替换、大小写/Unicode 碰撞,以及 4039-byte 键生成超过 4096-byte 的归档路径。只有完整正文计入 ExportReport.files;缺失为目标相对路径,CLI 非零退出仍保留已发布完整文件。

保留的 C1–C14 决策与格式扩展

决策当前实现
C1主密钥为零纪元,后续密钥随机;KeyEpoch 使用完整 32-byte 标识,generation/parents 决定排序,保留有效并发分支的历史解密密钥。
C2配对 ticket 为 NodeAddr + 128-bit 一次性秘密,两边显示六位 SAS,由已有设备显式确认,无存放点 rendezvous。
C3用户保管非对称恢复秘密,索引保管公钥;轮换创建新纪元,已有设备收到记录后重封本机 recovery wrap,无需恢复秘密。
C4并发撤销按 time/device 确定顺序,互撤只撤销一个,接受 cutoff 后的所有效果重新重放。
C5UnitRef 带纪元,范围修改的新单元使用当前纪元;当前根子树密钥派生不提供子树授权。
C6生效后本机释放再等 1 天,存放点 GC 再等 7 天;默认为提案后 30/31/38 天。
C7多段批次必须收齐后原子应用,目录重命名不暴露半个批次。
C8LOCAL_DIRS 为本机表,各接入层共用;空目录不共享、不导出。
C9FUSE 预留只读 /.cipherfs-conflicts,被目录遮蔽的文件也计冲突并可读取。
C10索引快照签名但不新增权限,必须核对完整原始重放输入;已覆盖远端段才可 GC,本机因果输入保留。
C11Partial 明文导出必须明确列出缺失,不静默跳过;当前原生实现要求全新、可无损表示的目标。
C12WebDAV 存放点留待以后;WebDAV 网关、S3 网关、TUI 曾移到 examples/unmaintained,2026-10-13 删除,最后版本见提交 6f4408b。
C13任意在线设备(包括 Partial)可按共享索引以 24-hour 节律评估退休候选。
C14epoch 只表示密钥纪元,原检查点 epoch 模型已经删除。

必要扩展:RetireOutcome 记录生效时受保护的目标,共享重放后允许新提案重新考虑;加密签名 u/<hash>-<len> 清单先于 pack 上传,配合 PackUploadAuthorization 在已接受日志位置签名精确清单摘要,覆盖孤儿包与重打包。清单权限证明按存放点 ACK 前缀修剪,读取时合并本机完整权限证明;不合法清单只保护它对应的包,不阻塞其他 GC。

恢复加入增加独立 genesis TrustAnchor 和恢复派生签名;bootstrap 校验原始签名链、精确 prev/deps、fork 和完整批次。RecoveryRatification 绑定确切自加入段及纪元:恢复设备可立即读写与创建首次快照,撤销、恢复轮换和配对批准需独立已有成员的因果在先批准。普通完整且无损坏的存放点同步自动发布批准,后来的批准不能补合法化此前管理操作。**所有已有设备丢失时,单个恢复设备仍不能管理设备,直到独立成员返回。**这是避免旧恢复秘密伪造高时钟轮换、回滚恢复权限所接受的限制。

配对/恢复冷启动权限证明和快照仍为单对象,预算 32MiB,multipart 未实现。过大的 r 发布以 recovery_proof_deferred 暴露,普通 i/p 与 GC 继续;首个没有 ACK 前缀的 u 证明仍可能超限,不能承诺任意长历史同步。快照不压缩掉本机全部因果日志。

第 9 步完整容器证据

第三轮在最终输入上从头完整执行 tools/test-container.sh,退出 0,开始 2026-10-11T04:12:28.773624+00:00,脚本耗时 1,214,442ms。Rust 各 feature 组共 598 次通过、0 次失败、2 项忽略,60 targets;这是执行次数,包含 Sync 精简/完整组合的重复用例,不当作不同测试数。Rust 编译警告为 0。

Cargo 组通过 / 失败 / 忽略targets
core-all-features261 / 0 / 013
sync-no-default-features33 / 0 / 014
sync-all-features80 / 0 / 014
cli-all-features109 / 0 / 03
fuse-fuse26 / 0 / 24
web-sync-s3-iroh-p2p89 / 0 / 012

C 运行时 15 项、Python 运行时 10 项、前端客户端 7 项通过;Go -race -timeout=180s -count=1、前端生产构建、真实 Web 二进制与 React assets 冒烟通过。最后的冒烟验证同名文件/目录正文读回、目录子项和遮蔽冲突,保持当前键模型;FUSE 的两项忽略仍不是实挂证据。FUSE 四种 feature 编译、最小 CLI 和工作区全目标全功能检查均由同一脚本完成。

Colima default 每轮临时为 8 CPU/16GiB,验证容器限制 3 CPU/6GiB、构建 jobs=3;各工具与附加依赖在容器/缓存卷中。第三轮结束已验证 default 运行于 2 CPU/2GiB,全局 Docker context 保持 default,未清理用户容器/卷或安装宿主工具。源码只读挂载,284 个构建输入在本轮前后 SHA-256 完全一致,之后只整理文档与证据。

最终输入以 e466f05 为 base,包含 C 夹具、C header/绑定 README 的目录说明与 Web 冒烟夹具修正;无绑定/Web/Core 实现变更。精确命令、环境、时刻、资源恢复与源码指纹见最终验证索引、第三轮报告、第三轮摘要和原始结果。前两轮失败及修正保留如下。

第一轮完整脚本的 Rust 各组共 598 次通过、0 次失败、2 项忽略,编译检查无警告;随后 C 运行时在旧的“非空目录删除应失败”断言处 abort,脚本退出 1,Python/Go/UI/Web 冒烟未执行。失败报告、摘要和原始日志保留;该轮结束已验证 Colima 恢复 2 CPU/2GiB,Docker context 未改变,构建输入未变化。

C 夹具现改为验证目录删除后的嵌套正文与派生目录消失、相邻前缀保留、重开后不复活;DirectoryNotEmpty 继续由覆盖非空目标的目录重命名验证,且检查被拒绝操作保留双方正文。Python/Go 原有夹具已遵守此语义,C header 与两份绑定 README 的旧目录描述一并更正。未改变绑定实现或 ABI 签名;第三轮在最终输入上从头通过完整验证。

第二轮 Rust 各组仍为 598 次通过、0 次失败、2 项忽略;C 运行时 15 项、Python 10 项、Go race、前端构建及客户端 7 项通过,随后真实 Web 冒烟因旧的目录上传 409 断言退出 1。需求和已有 Web 集成测试明确允许键 a 与 a/b 共存,此轮暴露的是旧冒烟假设。现改为验证正文可读、目录子项保留、目录优先列表和遮蔽冲突可见,未改 Web 实现或 Core 规则。第二轮报告与摘要保留,结束同样验证恢复 2 CPU/2GiB、Docker context 未改变、输入未变化。

2026-10-11 独立审查修复与验收

I.1 可安全移除与角色切换

Full → Partial → 驱逐 → Full 曾沿用旧 content mark,不回补正文且错误声明完整副本。vault/content_fetch.rs 现在在驱逐后按 CAS 核验并发布撤回的 SyncPosition;vault/positions.rs 在升 Full 时核验全部已接受版本,将新可用性与角色原子发布。保留仍完整的前缀,避免无必要地从零重取。

验收:驱逐后 A 精确列出仅本机持有的历史与当前版本;B 升 Full 后后台自动补齐两版,A 的列表清空;重开后遗留的持久 mark 同样重新核验。实现提交 c6b8569。

  • a_full_device_restores_evicted_content_without_claiming_a_stale_copy
  • promotion_to_full_rechecks_persisted_marks_against_cached_content
  • promotion_to_full_wakes_background_restoration_of_evicted_history(没有显式 fetch/read)

修前失败、最终 Core 262 项与 Sync 8 项通过、fmt 及协调者 Sync 8 项复核见本项证据。

I.2 GC 后的快照追赶

快照曾只供空索引设备加载,休眠设备遇到已回收的日志缺口无法前进。sync/engine.rs 现在为已有索引合并快照;Core vault/snapshot.rs 核对原作者签名的完整输入,再沿正常导入路径原子补齐缺口,保留已接受前缀、本机未发布分支和离线并发 head。重复版本 ID 必须对应真实签名来源,快照不能回滚已知权限或替换已见链。

新写入的 v2 快照把原始加密权限证明放在签名与 AEAD 绑定的前缀,vault/authority_keys.rs 按完整因果批次学习仅封装给自身的密钥,核验最终权限及正文后才提交;存活设备可跨多次纪元轮换追赶,被撤销设备取不到新密钥。v1 仍可读取,存放点对象上限仍为 32MiB。实现提交 1a8469e。

验收:真实 GC 删除所有覆盖段后,已有索引的设备在一轮同步中追上快照及后续日志,离线修改与并发正文保留并上传;连续两次撤销/纪元轮换同样通过。fork、输入增删、来源伪造、proof-only 越界、前缀篡改及加载拒绝后的密钥/数据库/已见位置保留均有回归。

  • snapshot_gc_catches_up_existing_index_and_publishes_offline_branch_in_one_round
  • snapshot_gc_catches_up_sleeping_member_across_epoch_rotation_in_one_round
  • snapshot_merge_preserves_frontiers_and_rejects_signed_forks_and_changed_inputs
  • snapshot_merge_accepts_identical_concurrent_versions_with_signed_origins
  • snapshot_merge_does_not_apply_file_records_from_proof_only_segments
  • snapshot_authority_bootstraps_rotations_without_leaking_or_committing_rejected_keys
  • authority_prefix_checks_version_framing_signature_and_aead_binding

原实现失败与新增边界失败保留;最终快照单测 12、恢复单测 9、GC 10、正文同步 8 项通过,Core/Sync clippy、fmt 干净;协调者在最终代码上重跑快照相关 14 项及 GC 10 项通过。见本项证据。

I.3 后台正文内存预算与取消

预取曾在整个版本入批后才检查预算,来源又积累整批正文;取消还会把未尝试单元误报为完整。现在按密文单元切批,达到预算即 flush,跨批次检查取消并保留全部缺失计数。CAS 核验并立即发布借用的正文,Directory/S3 的完整 pack 流式写入匿名临时文件;S3 忽略 Range 的 HTTP 200 同样走磁盘。P2P 双端逐单元传输,小 pack 写入不再复制单元。保留 Vec 便捷接口,后台路径使用流式接口。实现提交 36b8a98。

验收:12MiB 单版本在 128KiB 预算下只完成首批后取消,零预算和大于预算的单元各自成批;恢复后 AEAD 读取一致、Full 完整性重新成立。96MiB 真实 AEAD 密文跨六个 pack,range、无 range、两种超预算单元及 S3 忽略 Range 五种模式,计入临时元数据后的峰值最高 8,406,728 bytes ≤ 9,437,184 bytes(8MiB 预算加 1MiB 单元)。这不替代第四节的 100GB 长期验收,全部版本选择元数据仍随索引增长。

  • a_large_version_obeys_unit_budget_and_cancellation_resumes
  • real_ciphertext_range_and_whole_pack_fetches_stay_within_budget_plus_one_unit
  • streaming_prefetch_checks_hash_and_length_before_immediate_publication
  • default_streaming_read_does_not_fall_back_to_a_collecting_read
  • streaming_range_reads_verify_ignored_ranges_and_partial_response_lengths
  • whole_object_streams_verify_hash_length_and_transport_limit

原实现的取消与 heap 断言失败已保留;最终正文同步 9、CAS 17、Sync 单测 42、导出 13 和在途退休 1 项通过,Core/Sync clippy、fmt 干净。协调者独立重跑五模式 heap 及 GC 10 项通过;最小 feature 的正文回归通过,heap 目标仅编译验证。见本项证据。

I.4 并发加入与撤销后的密钥修复

离线批准的新成员曾身份合法却缺当前密钥。普通存放点同步现在核验每个成员已能读取的纪元封装,管理设备以现有 EpochKeys 补发当前及完整历史密钥;记录用收件人已知的纪元加密,密钥分别封装给公钥。历史分支晚到时同纪元补发,保留 generation/parents/排除成员/恢复权限,不额外轮换。零纪元恢复加入无需补发。实现提交 a0b756e。

Core 的候选学习可跨未知密钥前驱;保存前核验本机与远端完整原始签名链、因果批次、每个版本及最终权限闭包。增量密文暂存和新证明各限 32MiB;fork 提前拒绝,拒绝不改变密钥、数据库、权限证明或已见位置,文件仍沿正常导入路径重放。已有本机完整权限历史仍会增长,multipart 与长期规模留在第四节。

验收:X 撤销、离线 Y 批准 Z 后,Z 下一轮真实 Directory 同步即读写当前纪元,旧正文和重开可用;启用与禁用快照均通过,被撤销 W 得不到新密钥。只写元数据的并发历史纪元在补发前、后到达均补齐且不轮换,重复同步没有新记录。待批准恢复设备不能发布管理补发。

  • concurrent_enrollment_gets_missing_epoch_on_next_store_sync
  • snapshot_authority_repairs_concurrent_enrollment_on_next_store_sync
  • initial_epoch_recovery_ratification_converges_without_key_repairs
  • concurrent_metadata_epoch_history_is_repaired_before_or_after_current_delivery_without_rotation
  • repair_key_candidates_require_complete_final_authority_and_preserve_state_on_rejection
  • incremental_candidates_are_bounded_and_never_advance_state_without_complete_proof
  • pending_recovery_cannot_publish_missing_member_key_repairs

原实现的真实断言失败、最终 Core 49、Sync 28 项、clippy/fmt 与协调者独立真实存放点 3 项复核见本项证据。聚合计数包含不同测试目标的执行,专项重跑不另算不同用例。

I.5 时钟偏差下的并发移动与编辑

共同祖先曾按时间选取并在 4096 个节点处静默截断,使低时钟的移动链退回旧路径。index/apply.rs 现在完整扫描仅含父 ID 与时间的 DAG,在因果极大公共祖先间才按时间/ID 决胜,路径仍取 head 自身。合法加入后的回放还可能让高时钟旧祖先晚到;按父 DAG 裁剪文件头,防止祖先误成额外 head。实现提交 1dd2393。

验收:a → middle → final 与基于 middle 的编辑并发,编辑时间较新、较旧或相同,两种交换顺序均显示 final;两版正文、稳定 FileId、精确父关系、重开与后续合并均保持。真实 Directory 同步、超过 4096 层、多个因果极大基点、退休祖先及缺失/损坏祖先另有回归。

  • move_chain_and_newer_concurrent_edit_use_the_causal_base_despite_clock_skew
  • move_chain_and_older_concurrent_edit_use_the_causal_base_despite_clock_skew
  • move_chain_and_equal_time_concurrent_edit_use_the_causal_base_despite_clock_skew
  • move_chain_and_edit_prune_ancestor_heads_when_enrollment_follows_the_file
  • criss_cross_bases_use_time_and_id_only_between_causally_maximal_ancestors
  • a_common_base_beyond_4096_ancestors_still_keeps_an_edit_at_the_moved_path
  • a_low_clock_move_chain_and_newer_edit_converge_at_the_final_path_through_a_store

原生产代码的路径断言失败、候选实现的额外父节点失败与最终源码指纹见本项证据。最终 Core 库 173、Core conflicts 13、Sync conflicts 2 项通过;索引 17 项属于 Core 库,不重复累计。Clippy/fmt 干净,协调者独立全 feature conflicts 13 项通过。完整 DAG 扫描成本随历史增长,未据此宣称长期规模已验收。

I.6 Web 下载绑定不可变版本

Web 下载曾先选元数据再按路径打开正文,覆盖或路径复用使响应头与正文来自不同版本。api/files.rs 现在一次选择 head 的版本与大小,整段下载和 Range 均按 VersionId 读取。Core vault/history.rs 两种版本读取共用固定快照,保留按需单元认证、退休 pin 和锁定取消。实现提交 ed33b5d。

验收:仅测试的隔离同步门在元数据选择后插入覆盖写入,修前稳定得到 128/4096、0/4096 和 Range 正文错误;修后完整下载、空文件、Range、重命名/删除后原路径复用均读取所选旧版。

  • full_download_keeps_selected_version_during_overwrite
  • range_download_keeps_selected_version_during_overwrite
  • empty_download_keeps_selected_version_during_overwrite
  • downloads_keep_selected_version_during_rename_and_delete
  • historical_ranges_fetch_only_selected_units
  • closing_vault_revokes_full_and_range_streams_before_the_next_unit
  • retirement_keeps_admitted_streams_pinned_and_rejects_new_reads

修前已编译的四个断言失败、只测试差异、最终源码指纹及命令见本项证据。最终 Web 单元 46、文件 API 12,Core conflicts 13/retirement 10/version_streaming 6 项通过,Clippy 全 feature/fmt 干净;协调者独立全 feature 下载竞争 5 项通过。重跑的同一用例不另算不同测试。

II.1 首次 P2P 身份传播

真实回环 QUIC 回归确认:合法恢复设备的首轮同步曾在交换证明前被拒绝。sync/p2p.rs 现在先交换完整加密权限链,再按实际 QUIC NodeId 与本库 genesis、最新 cutoff 判断双方权限;普通对象/正文请求及来源注册均在准入之后。证明 framing 含头部共限 32MiB,声明长度和数量先验证。协议从 /5 升至 /6,两端须一起升级。实现提交 4c44f8e。

Core admit_authority_proof 在事务内保存已验证权限与密钥,不应用远端文件或推进远端普通 frontier;新权限重评既有本机效果并保留生效退休与读取 pin,相同证明不改写数据库。已授权管理设备可另行发布现有纪元密钥补发,使旧纪元合法新成员能验证回应;待批准恢复设备仍没有管理权限。

  • recovery_device_first_direct_quic_exchange_propagates_identity_and_content
  • offline_approved_device_first_direct_quic_exchange_reaches_unknown_old_member
  • independently_approved_unknown_peers_exchange_both_authority_branches_on_first_quic_connection
  • concurrently_approved_old_epoch_peer_learns_repaired_current_keys_during_quic_handshake
  • direct_quic_proof_rejects_bad_frames_other_vaults_and_identity_impersonation_atomically
  • peer_admission_is_atomic_and_proof_only_and_cannot_roll_back_revocations
  • peer_admission_does_not_ratify_a_recovery_device
  • peer_proof_reconnect_preserves_retirement_pins_local_directories_and_role

修前已编译的实际 QUIC 失败、最终源码指纹和命令见本项证据。最终 Core 23、P2P/Iroh 12、关闭屏障 2、后台/SDK 9、Web P2P 3 项通过,全部 0 ignored,Clippy 全 feature/fmt 干净;协调者独立 P2P/Iroh 12 项通过。计数为执行次数,重跑不另算不同用例。第四节的大历史/multipart 与公网验收仍未进行。

II.2 停滞上传、会话撤销与提交边界

上传曾全程持有 Web 仓库槽和 Core 读入锁,使锁定/退出等待 HTTP EOF,旧会话还可在替换后提交。现在先撤销会话、取消并排空请求与阻塞 worker,再关闭仓库;认证转换串行。加密正文在两层锁外暂存,提交才按槽、会话、Core 的顺序核验会话、仓库实例、纪元及目标 FileId。仅去掉槽锁不足以解除 Core 的等待,因此增加加密准备/提交接口。实现提交 0fe7371。

暂存的新单元及复用单元有 CAS 临时保护,引用重建、退休清理和缓存驱逐不会误删;取消/失败释放引用。文件改名、路径复用或并发创建导致身份改变时明确拒绝。数据库持久化后立即转移正文所有权,后续维护失败只报告维护问题,不删除已提交正文或伪报提交未发生。

  • stalled_raw_upload_does_not_block_logout_or_token_revocation
  • stalled_multipart_upload_does_not_block_lock_or_token_revocation
  • stalled_multipart_http_tail_is_cancelled_without_publishing_the_completed_part
  • upload_eof_cannot_commit_after_its_session_is_replaced
  • logout_revokes_before_waiting_for_slot_and_survives_a_disconnected_waiter
  • logout_wins_upload_eof_while_commit_is_waiting_for_the_slot
  • staged_new_and_reusable_units_survive_mid_read_retirement_rebuild_and_eviction
  • stale_path_identity_rejects_commit_after_rename_and_path_reuse

修前已编译的三项断言失败、源码指纹和实际命令见本项证据。最终 Core 215、SDK 流式 11、Web 100 次测试通过,Clippy 全 feature/fmt/diff 干净;协调者独立重跑上传接口 18 项通过。原始与 multipart 停滞、已完成 part 后仍停滞的 HTTP 尾部、取消退出 waiter 和 EOF/撤销并发均保留原正文并允许立即重开;没有新增 ignored。

II.3 仅存放点的 Web 后台恢复

只保存 Directory/S3 配置、没有 P2P peers 时曾不恢复后台同步,存放点打开失败也被丢弃。sync/background.rs 的存放点和正文任务现可独立于 Iroh 编译;Web 登录、解锁与重设密码按已签发会话恢复任一已保存的存放点或 peer。打开失败以安全类别和数量保留在 sync_state.last_error,健康存放点继续工作;后台运行错误可观察并在恢复后清除。实现提交 b0c4022。

退出先撤销会话,再等待已准入的后台初始化与任务排空;关闭后释放所拥有的 P2P 节点,保留已停止的后台句柄也不会继续占有 Vault。队列中的旧会话不能附着到新登录。存放点测试适配器补上流式读取转发,保留原有范围与整包读取次数断言。

  • saved_directory_restores_full_content_and_restarts_after_logout
  • saved_s3_only_restores_content_with_process_isolated_credentials(实际回环 S3,无 Iroh,凭据在隔离子进程中)
  • saved_store_open_failures_are_visible_without_peers_or_opened_stores
  • healthy_saved_store_continues_while_another_configuration_cannot_open
  • background_store_runtime_failure_is_visible_and_clears_after_recovery
  • logout_revokes_promptly_and_drains_an_admitted_background_setup
  • queued_resume_cannot_attach_to_a_replacement_session
  • shutdown_drains_store_workers_and_releases_every_owned_vault_clone

原生产代码的已编译断言失败及最终 S3 测试的隔离重现见本项证据。最终 Web 精简 102、无 Iroh S3 目标 5、完整 107,Sync 精简 23、完整 72,共 309 次顶层通过,另有 2 次隔离 S3 子测试;零失败/忽略。两种 Clippy、fmt 与差异检查通过。协调者独立重跑无 Iroh S3 目标 5 项及其隔离子测试、fmt、差异检查均通过。夹具分页错误、旧构建缓存误用和测试适配器失败单独保存,不计作验收;Web 复验输入未受随后适配器补丁影响。

II.4 Web 冲突正文与保留改名

冲突面板曾只能选择版本,无法比较正文或移动被目录遮蔽的文件。新增认证的 GET /api/v1/files/{encoded_path}/versions/{id},一次固定所选 head 的元数据与正文,复用完整/Range 流式下载;支持落败文件身份、并发移动后的实际路径和空文件,明确拒绝无关、过时、删除或不可读的选择。实现提交 8b4dee4。

Core keep_and_rename_head 原子发表一次所选 FileId 的合并与移动,使用指定 head 的正文,以该文件的全部 head 为父;原路径的其他文件身份和目录子项保留。目标占用或选择无效时不发表变更,a 与 a/b 共存规则保持。前端可逐个比较最多 64KiB 的正文、显示空文件/二进制/截断状态、下载所选 head,并输入目标路径保留改名;失败保留面板,切换路径或关闭即取消过时读取。

  • head_content_route_streams_shadowed_and_losing_heads_and_rejects_invalid_selection
  • head_route_uses_materialized_path_after_concurrent_move_and_reports_missing_content
  • keep_and_rename_preserves_shadow_directory_and_rejects_without_mutation
  • keep_and_rename_chooses_requested_body_without_removing_other_file_ids
  • keep_and_rename_selected_head_is_one_identity_preserving_resolution
  • keep_and_rename_preserves_key_shadows_and_other_contenders
  • keep_and_rename_rejects_invalid_stale_unrelated_and_deleted_heads_atomically
  • head_downloads_keep_pinned_metadata_and_body_after_resolution_move_and_delete
  • download_writer_is_bounded_and_stops_when_the_body_is_dropped

最终夹具在隔离的 a6e28c7 上重新运行,后端原有 1 项通过、新增 4 个断言失败,实际 React 组件原有行为 2 项通过、7 个交互断言失败;生产输入与夹具校验和均核对。修后 Core conflicts 16、Web 冲突 API 5、下载单测 7、文件 API 18,共 46 次 Rust 通过;有界容器内前端构建、客户端 15 和实际 React DOM 9,共 24 次 Node 通过。Clippy、fmt、差异检查干净,协调者独立重跑冲突 API 5 项、fmt 和差异检查通过。见本项证据。React 交互由 Jsdom 驱动,接口错误、正文边界与真实流式客户端另有验证;数据库重开夹具修正与构建准备不算修前失败证据。

III.1 接口、角色与内存保证

原待办要求消除 Partial 完整离线导出与 Vec 结果内存固定的矛盾。需求及双语 Rust API/架构文档现已明确:完整离线导出要求 Full 正文追上本机接纳的 frontier 且缓存完整;Partial/追赶中的设备报告所选正文缺失,原生目标须能无损表示所选键。缓冲读取失败返回 Err,writer/HTTP 流在晚发错误前可能已输出认证前缀,失败后应丢弃输出或中止发布。用户新增的挂载、缓存与离线读取“不挂起”要求保持,实际验收仍列为待办。实现提交 02cf007。

Core 新增 list_page、list_file_entries_page、file_history_page,SyncedVault 新增 list_page、history_page;限制为 1–1024,逐行扫描加密索引,最多保留 limit 个结果及一个正在进入的结果。值型续页绑定仓库与查询范围,历史还核对 FileId,可序列化并跨关闭重开,不持有数据库/句柄。每次查询当前视图;静止仓库拼页等于原 Vec 接口,并发变化不承诺跨页快照。Vec、单行正文引用/争用者、历史遍历 ID、完整索引与扫描时间仍有随数据增长的成本。

  • directory_pages_preserve_empty_derived_shadowed_and_contending_entries
  • history_pages_preserve_time_ties_cross_file_parents_and_deleted_views
  • history_traverses_live_ancestors_of_retired_versions_and_rejects_path_reuse
  • limits_and_scopes_are_rejected_and_values_survive_serialization_and_reopen
  • queued_page_requests_do_not_retain_the_database_or_block_close
  • encrypted_namespace_scans_do_not_allocate_the_full_result_for_a_two_entry_page

最终夹具 Core 页 6、SDK 页 1、排队关闭 1、分配测量 1,共 9 次通过,协调者独立重跑 Core 页 6/6。384 项、limit=2 时目录页/键前缀页峰值为 4,616/4,368 bytes,Vec 为 144,936/181,280 bytes;仅衡量查询分配,不包含初始化/写入,也不证明百万文件预算。Clippy、精简 feature、fmt、差异及文档范围检查通过。此前受影响 Core 55、选择器 1、SDK 关闭 10 等作为前一源码阶段的支持证据单独保留;时钟低于加入时间、删除时间平局导致的两次夹具失败均排除,保留原断言并修正时间后复验。见本项证据。

III.2 可测规模预算

原待办要求为规模目标指定参考设备、内存、启动/首次同步时间,以及 100 GB 经存放点的验收场景。需求现保留百万当前文件、1 TB 未退休版本正文、10 设备与 100 GB 单文件,并明确十进制 GB/TB 与二进制 GiB。参考 Partial 为 arm64 4 核/4 GiB/256 GB,Full 为 8 核/16 GiB/SSD;进程树 RSS 和 live heap 分别限制 512 MiB,冷启动 30 s、页调用 5 s,首次索引与 Full 正文分别为 1,800/21,600 s。它们是验收预算,尚非实测达成值。文档提交 4e11a04。

规模预算验收过程给出精确百万文件/1 TB 清单、固定 Clock/mtime、首中尾历史页,容量/暂存/密文余量,以及 Directory Range、S3 忽略 Range 的独立 100,000,000,000-byte 传输。源导入、完整发布、空白目标索引、正文补齐与流式摘要校验分别计时,全程上限 14,400 s;另测取消/进程终止后续传。三份正文及额外开销留 20% 空间,不额外保存第四个 100 GB 文件。冷暖运行、RSS/heap/CPU/网络/磁盘口径和失败条件均列明;32 MiB 权限证明/快照触限也算规模未通过。

budget-consistency 44 项与协调者 coordinator-budget-consistency 16 项通过,核对单位、容量/时间、源码常量、链接/frontmatter和规模节之外的字节保留,差异与 JSON lint 干净。见本项证据。本项未执行 Cargo 或长期实验;现有短回归和高配置宿主不是手机、百万文件或 100 GB 验收证据,实际运行仍属第四节待办。

III.3 需求验收表

文档提交 7ca06f1;验收表有 66 行,覆盖 21 个需求节/子节与 58 个条目组,130 个测试引用均核对到具体函数和断言。子代理结构检查 947 项、协调者独立检查 854 项通过;需求与规模预算正文、Proto 和 ignored 声明保持不变。README 描述现有行为,TODO 只保留 IV,并保留后来补充的挂载差距。见本项证据;全局构建和运行结果另见下节。

当前结论:主体完成,见待办。 下表逐节、逐子节与条目组对应已确认需求。“已实现;常规验证”表示有源码和本记录中的短回归/分阶段证据,只覆盖所列断言;“已实现;真实验收待办 IV”表示实现存在,但目标硬件、云账号、公网或实际挂载尚未验证;规模行的“预算规范已完成”只表示验收标准已确定,性能与规模目标尚未实测;“部分实现/待实现;待办 IV”保留具体缺口。“范围约束”记录明确不承诺的边界,不是缺失功能的通过声明。

本轮核对现有测试的实际步骤和断言,没有新增生产实现、测试或 ignored。正文、页结果和单对象预算不能替代整体规模验收:单版本 UnitRef、历史 visited IDs/待遍历父版本、文件 heads/路径争用者、完整成员/权限状态仍增长;加密命名空间的 HMAC 键不能直接按明文排序,页查询可能重复扫描;权限证明与快照仍为 32MiB 单对象,本机完整因果日志仍保留。

编号与需求实现/边界精确测试与证据状态
R01 仓库、设备、存放点;稳定文件身份与前缀目录共享记录、前缀目录:设备持钥,存放点仅持密文,FileId 独立于路径。concurrent_move_and_edit_follow_the_file_without_resurrecting_the_old_path;empty_directories_stay_on_their_device已实现;常规验证
R02 正文、名字与敏感元数据在设备内加密正文 AEAD、加密签名段、本机字段封装。local_database_hides_paths_and_content;round_trip_and_every_failure_mode已实现;常规验证
R03 错误密码、篡改、损坏失败;秘密不进入日志/存放点解封与读取、敏感 Debug;测试覆盖认证失败和 Debug 隐藏密钥,未以此声称全日志路径负证明。create_open_wrong_password_and_close;corrupted_local_content_fails_explicitly;test_filename_cipher_debug_does_not_expose_key已实现;常规验证
R04 可观察大小/数量/时序/设备数;多副本保证可用性公开对象名、多正文来源;服务拒绝或丢失不提供密码学可用性保证。multiple_sources_continue_after_absence_network_and_integrity_failures范围约束;常规验证;真实服务待验收 IV
R05 记住已见提交,多个来源交叉核对,重放不能倒退frontier 合并、快照完整重放;来源共用本机已接纳 frontier;未知且被所有来源隐瞒的更新无法从首次连接发现。replaying_an_older_listing_never_regresses_a_device;snapshot_cannot_roll_back_a_fresh_devices_known_revocation;证据 2已实现;常规验证
R06 撤销后记录拒绝、新正文密钥隔离;存放点凭据由用户撤销cutoff、连接准入、凭据轮换提示;不收回已持有内容或云账号凭据。revocation_preserves_old_reads_but_denies_new_keys_and_old_key_self_enrollment;revocation_denies_new_connects_and_closes_existing_sessions;证据 7已实现;常规验证;真实云账号待验收 IV
R07 完整当前/历史/删除/冲突/因果/成员/纪元/策略/退休元数据与引用;离线最后状态完整记录模型、共享导入、快照;索引不含明文正文。a_snapshot_bootstrap_equals_a_full_replay;identities_and_views_converge_after_reopen;证据 2已实现;常规验证;百万文件待验收 IV
R08 默认 Full 保留未退休正文;Partial 固定目录与读取缓存角色正文队列、本机策略;Full 不按缓存预算驱逐。a_partial_device_evicts_beyond_its_budget_and_a_full_device_never_does;证据 1已实现;常规验证
R09 缺正文从设备/存放点获取;小文件与大文件范围按单元选择多来源、范围选择、pack 来源。multiple_sources_continue_after_absence_network_and_integrity_failures;range_reads_fetch_only_needed_ranges_and_rangeless_stores_fetch_whole_packs;证据 3已实现;常规验证
R10 所有接入方式自动连接已配置来源,不需另开同步进程共享 CLI 内容运行时由 read/mount 启动已配置存放点、已保存对端与后台同步;退出排空任务。Web 自动恢复来源,SDK 接收显式 options。partial_mount_preparation_fetches_missing_content_from_configured_store、partial_mount_preparation_fetches_missing_content_from_saved_peer、shared_vault_content_sources_reach_fuse_handles_without_read_ahead;挂载接线证据已实现;常规验证;本机 fuse-t 挂载见 IV.3
R11 预算驱逐、固定/LRU 优先、未确认写入与打开句柄保护;不是同步删除正文轮次、保护与撤回位置、LRU/pin;普通读取与最后句柄释放调度驱逐,保护集保持,Full 不按预算驱逐。a_partial_device_evicts_beyond_its_budget_and_a_full_device_never_does、last_fuse_handle_release_schedules_pending_eviction、one_snapshot_survives_concurrent_changes_retirement_and_partial_eviction;读后调度证据、真实挂载驱逐已实现;常规验证;本机 fuse-t 驱逐已实测
R12 读取超预算后自动调度与预算入口Core 读取通知唤醒正文循环,成功同步即使零新段也驱逐;CLI/API 与设备面板 (cipherfs-web-ui/src/components/DevicesPanel.tsx)支持整数 bytes、0;面板空/null 保留预算。background_core_reads_schedule_partial_budget_without_explicit_wake、cached_reads_reschedule_eviction_after_protection_changes、zero_segment_exchange_evicts_newly_confirmed_content_without_prefetching_unpinned_files、short_lived_content_runtime_enforces_budget_after_draining_without_fetching、devices_safe_removal_and_device_settings;Core/CLI/面板证据已实现;常规验证;本机 fuse-t 调度已实测
R13 每台已完成同步 Full 与每个存放点持有所有未退休正文正文位置、正文先于索引发布;短回归核对精确位置和缓存,规模条件仍须实测。a_full_device_restores_evicted_content_without_claiming_a_stale_copy;a_segment_waits_until_its_content_can_be_uploaded;证据 1已实现;常规验证;长期副本验收待办 IV
R14 各版本持有者、仅本机列表;追赶 Full 按 Partial 判断version_availability/only_local_versions;升 Full 重新核验持久 mark,驱逐撤回声明。positions_tell_which_versions_only_this_device_holds;promotion_to_full_rechecks_persisted_marks_against_cached_content;证据 1已实现;常规验证
R15 先索引后正文、新版本优先、中断续传新到旧队列、后台获取。a_new_full_device_gets_the_index_first_then_content_newest_first;an_interrupted_content_fetch_resumes_after_reopening;证据 3已实现;常规验证;长期首同步待验收 IV
R16 零或多个;不可变写/按名读/前缀列/删,无锁/CAS/即时可见假设ObjectStore、各设备提交链;短缺与未到达延后,不跳过因果输入。immutable_named_objects_list_in_order_across_pages;gaps_and_truncated_segments_wait_and_forged_ones_fail_explicitly已实现;常规验证
R17 P2P 与存放点并用;不同时在线通过存放点交换peer/store 独立循环、P2P 交换。devices_that_never_meet_read_each_others_content_through_one_store;synced_vault_reads_content_from_a_shared_store;证据 9已实现;常规验证;公网待验收 IV
R18 文件夹与 API 两类;Directory/S3 第一优先已保存配置、Directory、S3 HTTP;云盘搬运是外部客户端职责。devices_that_never_meet_read_each_others_content_through_one_store;saved_s3_only_restores_content_with_process_isolated_credentials;证据 9已实现;真实验收待办 IV(云盘客户端/真实账号);本地与回环常规已验证
R19 WebDAV 下一阶段;移动端私有云盘 API 后续加入当前 Directory/S3 配置种类;没有 WebDAV/OneDrive/Dropbox/Google Drive 私有 API 或移动端。actual_capabilities_are_feature_accurate_and_ignore_legacy_settings;本表结构核对 requirements-acceptance-matrix待实现;待办 IV
R20 远端打包 4–8MiB 量级,小于本机目标远端目标 6MiB;超大单元单独成包,目标不是硬文件上限。packs_stay_within_bounds_over_a_mixed_workload已实现;常规验证
R21 对象长度/哈希不一致视为未到达并重试命名与 Fetch、读取验证。a_truncated_pack_is_not_arrived_until_the_whole_object_appears;gaps_and_truncated_segments_wait_and_forged_ones_fail_explicitly已实现;常规验证
R22 退休后延迟远端回收、内容寻址重传;GC 后已有索引追赶延迟 GC/重打包、快照补缺;默认提案后第 38 天远端回收。grace_plus_local_margin_plus_store_delay_deletes_old_content_and_never_current;snapshot_gc_catches_up_sleeping_member_across_epoch_rotation_in_one_round;证据 2已实现;常规验证
R23 Range 按块;不支持/忽略 Range 时整对象回退范围与流式整 pack、HTTP 200 回退;整 pack 经临时文件而非积累到 Vec。range_reads_fetch_only_needed_ranges_and_rangeless_stores_fetch_whole_packs;real_ciphertext_range_and_whole_pack_fetches_stay_within_budget_plus_one_unit;证据 3已实现;常规验证;100 GB 两种模式待验收 IV
R24 mtime 承诺同步;可执行位索引/API 保留、挂载尽力;无 POSIX 属性承诺ContentBody 元数据、挂载属性适配。mtime_executable_and_mixed_writer_policies_round_trip_through_a_store;modification_time_and_executable_bit_persist已实现;常规验证;真实挂载呈现待验收 IV
R25 因果版本、稳定身份;移动/重命名不新增历史/垃圾箱,离线修改跟随移动身份与因果路径合并、版本视图。moves_and_renames_create_no_history_or_trash_entries_at_the_old_path;move_chain_and_newer_concurrent_edit_use_the_causal_base_despite_clock_skew;证据 5已实现;常规验证
R26 删除是 tombstone;删目录逐文件、目录导出、空目录接入层本机保存目录操作、本机目录。removing_a_directory_tombstones_every_file_below_it;directory_rename_is_atomic_for_a_peer;empty_directories_stay_on_their_device已实现;常规验证
R27 共享历史/前缀折叠垃圾箱/多 head 冲突;来源设备与时间历史/垃圾箱、head 视图。history_restore_and_trash;concurrent_content_edits_survive_attribute_merge_with_origins_and_times已实现;常规验证
R28 因果后续优先;真并发内容胜删除,再按时间/标识;全部 head 保留当前选择规则、heads。causally_later_wins_even_with_an_older_clock_or_as_a_tombstone;concurrent_content_beats_delete_then_time_then_id;concurrent_edit_and_delete_keep_content_until_a_head_is_chosen已实现;常规验证
R29 不同 FileId 争同一路径;a/a/b 共存、挂载目录优先,文件在冲突视图路径争用、遮蔽适配。same_name_creations_are_readable_and_the_loser_can_be_moved_by_identity;a_directory_shadows_a_file_of_the_same_name_and_mkdir_is_local已实现;常规验证;真实挂载待验收 IV
R30 list/head、CLI/Web 来源时间与数量;挂载只读虚拟目录,无冲突副本CLI、Web、/.cipherfs-conflicts。conflict_routes_show_origins_and_counts_and_only_resolve_valid_heads;conflict_view_lists_every_content_head_and_shadowed_file_read_only;证据 10已实现;常规验证;真实挂载/浏览器待验收 IV
R31 以全部 head 为父解决;显式选择不改正文、已见全部头后写入自动合并,失败头入历史resolve/keep_and_rename_head、比较/下载/保留改名 (cipherfs-web-ui/src/components/ConflictsPanel.tsx)。concurrent_content_edits_survive_attribute_merge_with_origins_and_times;explicit_resolution_can_keep_the_losing_content_and_open_reads_stay_pinned;keep_and_rename_chooses_requested_body_without_removing_other_file_ids;证据 10已实现;常规验证
R32 历史与垃圾箱恢复发新版本、复用旧正文引用、参与同步restore_version/restore_trash_prefix;不重新加密/上传已有旧正文。history_restore_and_trash;business_io_replicates_index_fetches_ranges_and_shares_history已实现;常规验证
R33 显式清除与共享策略是仅有出口;默认 365 天、最低版本数,由在线设备发布候选与清除、共享策略重放、同步轮次评估。min_versions_is_kept_and_duplicate_proposals_do_not_double_drop_shared_units;retention_routes_preserve_current_and_tombstone_and_cancel_pending_proposals已实现;常规验证
R34 待退休→宽限期内撤销→到期丢弃;默认 30 天生效与本机延迟、存放点延迟;本机另等 1 天,存放点再等 7 天。policy_pending_cancelled_inside_grace_keeps_content_after_reopen_and_snapshot;grace_plus_local_margin_plus_store_delay_deletes_old_content_and_never_current已实现;常规验证
R35 被撤销设备后发退休记录一律拒绝权限重评、完整重放;先接受后收到 cutoff 也撤销该效果。late_revocation_undoes_every_effect_and_orphan_revoker_in_both_orders_reopen_and_snapshot;revoked_publisher_cannot_backdate_inventory_and_missing_authority_only_protects_its_pack已实现;常规验证
R36 当前/未发布/冲突 head 保护;显式清除不能删当前;句柄保护与本机策略不改共享历史退休保护、正文 pin、本机策略。current_conflict_heads_and_unpublished_parents_are_not_candidates;trash_purge_preserves_current_tombstone_and_open_unlinked_content;local_policy_does_not_change_shared_state_or_existing_content已实现;常规验证
R37 随机主密钥、纪元/子树派生、版本携带纪元;当前使用根子树随机纪元、上下文派生、UnitRef 纪元;派生存在,不提供子树授权。content_cipher_authenticates_key_context_nonce_and_ciphertext;revocation_preserves_old_reads_but_denies_new_keys_and_old_key_self_enrollment已实现;常规验证;子树授权待实现 IV
R38 长期设备密钥对/名字;加入封装当前密钥;按成员记录认证enroll_device、权限证明准入、QUIC 身份核对。offline_approved_device_first_direct_quic_exchange_reaches_unknown_old_member;peer_admission_is_atomic_and_proof_only_and_cannot_roll_back_revocations;证据 7已实现;常规验证
R39 配对:新设备短码/二维码,已有设备确认一次性 ticket 与六位 SAS;当前 ticket 文本和短码实现,批准需显式匹配。real_iroh_pairing_requires_matching_sas_and_consumes_ticket;web_pairing_requires_explicit_sas_consumes_requests_and_cancel_closes_connection已实现;常规验证(短码路径)
R40 无已有设备在场:初始化信息+恢复密钥加入init-info/genesis 加入、独立批准限制;可读写,管理需独立已有成员,全部旧成员丢失时不满足同权管理。recovery_self_join_is_provisional_until_independent_sync_ratification;peer_admission_does_not_ratify_a_recovery_device;证据 7部分实现;待办 IV;无独立成员管理有意限制,需求决策待办
R41 撤销新纪元/旧正文不重加密、拒绝连接;任一成员与并发撤销因果排序并发权限闭包、撤销、连接关闭;并发 time/device 确定排序,保留存活成员历史密钥。mutual_revocation_selects_one_winner_and_retains_survivor_history_from_losing_branch;revocation_denies_new_connects_and_closes_existing_sessions;证据 4已实现;常规验证;公网待验收 IV
R42 并发加入与撤销、旧纪元合法成员补当前/历史密钥;拒绝非法候选不改状态原子密钥学习/修复、下一轮补发;不新增额外纪元。concurrent_enrollment_gets_missing_epoch_on_next_store_sync;snapshot_authority_repairs_concurrent_enrollment_on_next_store_sync;concurrent_metadata_epoch_history_is_repaired_before_or_after_current_delivery_without_rotation;证据 4已实现;常规验证
R43 设备列表名字/角色/最近同步时间/位置;撤销与安全移除入口、凭据提示设备位置视图、CLI 入口、Web 列表/撤销。positions_tell_which_versions_only_this_device_holds;devices_safe_removal_and_device_settings;member_updates_survive_reopen_and_snapshot_but_require_the_owner_and_cutoff已实现;常规验证
R44 本机私钥双封装;密码不入同步、改密码仅本机;忘记密码重设身份不变password_config/change_password、双封装与重设。recovery_key_resets_password_and_keeps_the_device_identity已实现;常规验证
R45 恢复密钥一次生成/用户保管、解封与初始化加入;轮换重封、旧秘密失效非对称恢复密钥、轮换/重新封装、恢复。a_device_without_a_key_sets_up_exactly_one;recovery_rotation_rewraps_peers_without_secret_and_authenticates_current_store_join;a_stale_recovery_holder_cannot_forge_rotation_and_roll_back_a_ratified_rotator已实现;常规验证;单恢复成员管理限制见 R40
R46 百万当前文件、1 TB 未退休正文、10 设备、100 GB 单文件;参考硬件与容量/链路正文引用模型、规模过程固定十进制/Binary 单位、Partial 4 核/4GiB/256GB、Full 8 核/16GiB/SSD 与 20% 余量;高配 VM 不是手机执行证据。budget-consistency、coordinator-budget-consistency;证据 12(只核对规范/算术)预算规范已完成;规模/性能待验收 IV;参考硬件与完整夹具未运行
R47 整进程 RSS/live heap 各 512MiB、10 台 RSS 共 5GiB;冷启动 30s、页 5s有界页、加密命名空间扫描;单行引用、visited IDs、成员/权限状态和 HMAC 扫描成本计入整体预算。encrypted_namespace_scans_do_not_allocate_the_full_result_for_a_two_entry_page;real_ciphertext_range_and_whole_pack_fetches_stay_within_budget_plus_one_unit;证据 11、证据 12(短回归不是整体预算结果)预算规范已完成;规模/性能待验收 IV
R48 首次索引 1800s/10 台 3600s;Full 正文 21600s、合计 23400s;新版本优先/续传索引轮次、正文轮次;必须在规范共享链路上测 exact frontier、missing_units 与摘要。a_new_full_device_gets_the_index_first_then_content_newest_first;an_interrupted_content_fetch_resumes_after_reopening;证据 12(规范核对)预算规范已完成;规模/性能待验收 IV
R49 100,000,000,000-byte 独立源/存放点/空白 Full;Directory Range/S3 200 回退与阶段计时两种流式获取、规模过程:1800/3600/300/3600/1800s,各阶段及全程 14400s;记录缓存、RSS/heap/CPU、容量、续传和失败。real_ciphertext_range_and_whole_pack_fetches_stay_within_budget_plus_one_unit;证据 3、证据 12(96MiB 回归/规范,未执行 100 GB)预算规范已完成;规模/性能待验收 IV;32MiB 证明/快照触限也算失败
R50 路径/字节;Core 与 SDK reader/writer 正文流式,put 借用与 get Vec 成本Core 流式、SDK 双槽适配器、便利接口;正文窗口有界不等于全进程常量内存。borrowed_streams_roundtrip_ranges_and_history_on_current_thread;步骤 7 内存记录已实现;常规验证;整体规模待验收 IV
R51 目录/字面键前缀/历史有界页、1–1024、值型范围/FileId 绑定、跨重开、当前视图Core 三种页、SDK 两种页;无句柄/服务端游标;静态拼页等于 Vec,并发变化不保证快照,路径复用拒绝。limits_and_scopes_are_rejected_and_values_survive_serialization_and_reopen;current_view_skips_insertions_before_the_boundary_and_observes_later_edits;history_traverses_live_ancestors_of_retired_versions_and_rejects_path_reuse;证据 11已实现;常规验证
R52 Vec O(结果数)、页仅限制保留结果;成员/引用/遍历/扫描增长;绑定与 Web 流式但无 Rust 页逐行 HMAC/解密扫描、C 回调、Go 回调、Python reader/writer、HTTP 流;bytes/Blob/列表仍分配完整结果。encrypted_namespace_scans_do_not_allocate_the_full_result_for_a_two_entry_page;historical_ranges_fetch_only_selected_units;本轮完整绑定;步骤 9 绑定记录(历史阶段)已实现;常规验证;本轮完整绑定复验通过
R53 启用后台自动同步/重连/重试;写成功仅本机持久化,远端随后重连/退避/独立来源、本机提交通知;SDK enable_sync 需要显式打开来源。initially_offline_peer_is_retried_after_same_identity_and_port_restart;own_segments_stay_unpublished_until_a_real_peer_receives_them;证据 9已实现;常规验证;公网长时待验收 IV
R54 EOF 前取消不发布部分对象;EOF 后已接纳提交可完成;close 排空释放EOF/取消屏障、会话准备/提交。cancelled_sources_and_sinks_unblock_workers_and_release_admission;cancellation_after_explicit_eof_keeps_the_committing_worker_admitted;close_drains_a_retained_unpolled_download_and_reopens_immediately;证据 8已实现;常规验证
R55 缓冲读取失败返回 Err;writer/HTTP 可能输出认证前缀后失败,必须丢弃认证单元输出、流式 Body;不是成功返回部分对象。missing_and_tombstone_versions_never_produce_a_successful_stream;midstream_missing_removes_the_file_but_corruption_and_io_abort_publication;证据 6已实现;常规验证
R56 核心定义加密/事务/模型/同步规则;适配层不复制数据库、不伪报成功Core 规则、Core 适配、未支持返回 501;CLI 空壳命令已移除。core_patch_truncate_copy_and_rename_drive_fuse;unsupported_patch_never_creates_settings_or_changes_config_content_or_existing_file已实现;常规验证
R57 Rust/CLI/FUSE/Web 主要接入;绑定跟随本机 API;WebDAV/S3 gateway/TUI 为非验收示例Rust、CLI、Web、降级示例(已于 2026-10-13 删除,见提交 6f4408b);C/Python/Go 当前没有设备加入/同步或 Rust 页。actual_capabilities_are_feature_accurate_and_ignore_legacy_settings;步骤 9 绑定记录(历史阶段);当前实挂已实现;常规验证;本机 fuse-t 已实挂,其他平台见 IV
R58 Partial 挂载列出未持有文件,读取才获取;阻止索引器/预览/备份拉回整库挂载来源与后台、挂载 marker、Time Machine 核对;Finder 浏览见 IV.6。partial_mount_preparation_fetches_missing_content_from_saved_peer、macos_mounted_marker_is_read_only_and_does_not_enter_core;真实 fuse-t 记录、Finder 浏览记录完成;真实挂载 marker/备份/读取/驱逐已验证,Finder 浏览根目录与全部子目录后缓存不变
R59 已追上本机 frontier 且缓存完整的 Full 离线导出;Partial/追赶 Full 报缺失,退休不保证恢复选择与缺失报告;不代表已看到未同步新修改;不依赖在线来源才能导出已有缓存。current_export_round_trips_streaming_bytes_mtimes_empty_files_and_execute;partial_device_reports_each_missing_current_and_historical_destination;证据 11已实现;常规验证
R60 新目标/已存在无符号链接父路径/native 无损布局;历史与冲突独立、路径归档规则选择/布局、描述符锚定发布;a/a/b、大小写/原生名字碰撞明确拒绝,不自动改名;Linux/Android/Apple 有实现,其他平台 Unsupported。history_and_conflicts_are_independent_and_include_deleted_content;losing_path_heads_use_materialized_paths_and_old_versions_keep_original_paths;native_case_and_normalization_aliases_are_either_preserved_or_rejected已实现(Linux/Android/Apple);常规验证,实际平台范围以日志为准
R61 导出固定选择/pin,流式完整文件;并发修改退休不变选择,认证/I/O 中止,缺失只计不可用固定快照、完整文件发布;选择元数据仍增长。one_snapshot_survives_concurrent_changes_retirement_and_partial_eviction;midstream_missing_removes_the_file_but_corruption_and_io_abort_publication;a_target_created_during_streaming_is_preserved_and_parent_swaps_stay_anchored已实现;常规验证
R62 并发默认当前受时钟影响,但不丢其他 head并发选择、可读 heads。concurrent_content_beats_delete_then_time_then_id;concurrent_content_edits_survive_attribute_merge_with_origins_and_times范围约束;常规验证
R63 仅 P2P 且不同时在线不能交换连接与重试;无服务器存放点时不存在离线中转承诺。initially_offline_peer_is_retried_after_same_identity_and_port_restart范围约束;常规验证;公网待验收 IV
R64 不提供多用户共享/权限;仓库成员同权成员管理规则;Full/Partial 不是访问权限;恢复设备的临时管理限制与子树授权缺口见 R37/R40。mutual_revocation_selects_one_winner_and_retains_survivor_history_from_losing_branch范围约束;常规验证;恢复同权例外待办 IV
R65 宽限期后退休版本不保证恢复退休隐藏/释放、正文回收。effective_trash_purge_hides_unrecoverable_rows_and_preserves_empty_content_files范围约束;常规验证
R66 Partial 无可达正文来源明确失败、不挂起;缓冲 Err/流前缀丢弃;挂载立即 EIO正文来源跳过已知离线,QUIC/S3 首响与无进展有界;FUSE将 ContentUnavailable 映射为 EIO,后台重连独立。unresponsive_peer_single_content_read_fails_promptly、unresponsive_peer_batch_content_read_fails_promptly、unresponsive_s3_content_read_fails_promptly_and_recovers、partial_device_quic_vault_and_fuse_reads_evict_safely_and_fail_offline;实际断网 cat/EIO已实现;常规验证;本机 fuse-t 断网立即 EIO 已验收

状态转换断言核对

转换现有测试的实际断言证据
Full → Partial → 驱逐 → Fulla_full_device_restores_evicted_content_without_claiming_a_stale_copy 先确认两版正文及其他持有者,再驱逐并仅转发已发布段;核对 content frontier 清空、两版只在 A、B catching_up,补齐两版后 A 列表清空。promotion_to_full_rechecks_persisted_marks_against_cached_content 写入旧持久 mark,关闭重开后升 Full,确认 mark 被重新核验。promotion_to_full_wakes_background_restoration_of_evicted_history 仅改角色/策略等待后台缓存状态,没有显式 fetch/read。I.1、证据 01
已有索引休眠 → 快照 GC → 一轮追赶snapshot_gc_catches_up_existing_index_and_publishes_offline_branch_in_one_round 和 snapshot_gc_catches_up_sleeping_member_across_epoch_rotation_in_one_round 共用真实 Directory 夹具;逐个确认 GC 删除全部已覆盖日志,再发布快照后的 tail。一轮同步断言 snapshot_loaded、pending/waiting=0、frontier 追上,离线并发 head/正文和未发布文件仍在,离线段与 pack 已上传;第二种实际跨两次撤销/纪元轮换。I.2、证据 02
撤销与离线批准并发 → 缺失纪元修复concurrent_enrollment_gets_missing_epoch_on_next_store_sync 与快照变体核对合法 Z 初始缺新纪元,下一轮 pending=0,旧/新正文可读、新写段使用当前纪元、重开仍可写;W 不得到新钥且不能读写新正文。concurrent_metadata_epoch_history_is_repaired_before_or_after_current_delivery_without_rotation 遍历当前钥已送/未送两种顺序,补晚到历史分支后双方密钥集合一致,纪元数不增加。I.4、证据 04
并发互撤/迟到 cutoff → 权限与本机效果重评mutual_revocation_selects_one_winner_and_retains_survivor_history_from_losing_branch 确认仅一个撤销生效,存活第三方在落败纪元写的正文及历史钥仍可供新成员使用。late_revocation_undoes_every_effect_and_orphan_revoker_in_both_orders_reopen_and_snapshot 实际两种到达顺序核对文件回退、策略/退休清空、非法后加入成员及其撤销失效,并验证重开/快照;member_updates_survive_reopen_and_snapshot_but_require_the_owner_and_cutoff 保留 cutoff 前名字/Partial,拒绝 cutoff 后与代他人更新。步骤 6、I.4
权限证明候选 → 准入/拒绝原子边界repair_key_candidates_require_complete_final_authority_and_preserve_state_on_rejection 逐个损坏签名、前驱、依赖、批次、纪元和版本,加入 fork/被撤销签名者,均不改密钥/数据库/证明/frontier。peer_admission_is_atomic_and_proof_only_and_cannot_roll_back_revocations 准入只改变合法权限,不导入证明中的远端文件或推进普通 frontier;晚到 cutoff 重评已接受文件/后代身份,重开后旧证明仍拒绝。真实 QUIC 的 revocation_denies_new_connects_and_closes_existing_sessions 核对新连接拒绝、旧连接关闭与拒绝证明不改变本机状态。I.4、II.1、证据 07

当前源码全局复验

首轮完整容器在 Python 并发元数据夹具处失败:Rust 707 次、C 15 项通过,Python 9/10 通过;夹具在上传仍读取输入时要求新文件可见,与 II.2 的成功 EOF 原子发布语义不符。测试修正提交 f48c4f0 只增加显式读取/EOF 屏障与提交前不可见断言,保留原最终 exists/list/prefix 断言、2 s 启动/5 s future/20 s 子进程期限,并新增完整正文核对。最终定向 1/1、完整 Python 10/10 与协调者独立定向 1/1 通过,见夹具证据。生产代码未变;完整脚本随后重跑通过。首轮结束后已恢复 Colima 2 CPU/2GiB,失败与恢复日志保留,不计入最终通过数。

2026-10-12 本地日期归档。首次宿主记录对应实现提交 7ca06f1,完整容器复验对应夹具提交 f48c4f0,原生全 feature 复验对应提交 42801cd;以下为各次实际结果,旧阶段的 598/1044 等执行次数保持历史范围。Cargo 数量按各 feature 组的执行次数计,不能累计为不同测试总数。

门槛/范围实际结果
宿主 fmt、默认 clippy通过;cargo clippy --locked --workspace --all-targets -- -D warnings 无警告。
宿主默认工作区测试58 组,633 通过、0 失败、6 忽略;无编译警告。
宿主支持 feature 组合测试排除 Python,57 组,658 通过、0 失败、8 忽略;同组合 clippy 包含 Python,全部通过且无警告。精确 features 与 PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 见日志。
宿主首次原生检查 --all-featuresclippy 与测试均退出 101;fuser 的 macFUSE 构建在测试执行前失败,原始失败证据保留。
宿主原生全 feature 复验字面 --all-features clippy 与测试均退出 0,无 warning;测试 58 组,658 通过、0 失败、8 忽略。Darwin macFUSE backend 为 libfuse2 + macfuse-4-compat,见原生宿主日志。
完整容器 Rust 与 feature 矩阵73 组,707 通过、0 失败、2 忽略;FUSE/CLI 与工作区全部 feature 编译通过,无警告。
完整容器绑定C 15 项、Python 10 项通过;Go -race -count=1 ./... 整包通过,非 verbose 输出未推算逐用例通过数。
完整容器前端与 Web客户端 15 项、React DOM 9 项、前端构建与真实 Web 冒烟通过;完整脚本退出 0。

原审查 I–III 的修复与要求的验证门槛已完成。 首次原生检查缺少 macFUSE 构建依赖;复验只将官方 macFUSE 5.4.0 包解开到私有临时目录,使用原始 libfuse.2.dylib、MFMount 和 pkg-config 元数据,并由已有 Colima 容器中的 genuine pkg-config 解析只读元数据。官方包、库与 framework 的签名和指纹、实际 Darwin backend、精确命令、环境及源码一致性见原生复验证据。没有安装宿主工具或内核组件,没有运行包安装脚本,也没有修改官方二进制/元数据、关闭 feature 或改为跨目标构建;容器只代理构建工具,Cargo 编译、链接与非 ignored 工作区测试仍在原生 Darwin 上执行。

宿主期间只有不由 Cargo 执行的 Python 运行时夹具变化,原始 before/after 清单保留该差异,其余 297 个追踪输入逐字节一致;宿主与最终容器的 Rust 输入一致。最终容器全过程输入不变,两轮均在 Colima 8 CPU/16GiB 下运行并在结束后恢复 2 CPU/2GiB。为释放磁盘,仅清理验证卷中已结束编译的约 2.8 GB 示例产物,未删源码或用户数据。Proto 与原有 8 个 ignored 声明未变;普通测试与 feature 编译不算当前源码实际挂载。见首次宿主日志与结果、完整容器日志与资源恢复、原汇总与校验和。原生全 feature 复验的 298 个输入与最终完整容器逐字节一致,运行中源码与临时依赖均未变,Colima 始终保持 2 CPU/2GiB;新原生汇总补齐门槛,旧汇总的未通过字段保持历史事实。

原全局文档验收表独立复核 857 项通过,见原结构检查。原生复验补录后独立结构检查 1562 项通过,继续保留 66 行、21 节/子节、130 个精确测试引用,并核对原生结果、依赖 provenance、历史证据、IV 与 ignored 边界;见原生复验结构检查。

IV 本机空间扩展

IV.1 挂载来源与后台生命周期

原待办第 1 条已修复,实现提交 8f87995。mount 与 read 共用 ContentRuntime,自动注册已配置存放点和已保存/显式对端,持有 BackgroundSync;原生挂载循环让出 Tokio worker,退出或启动失败后等待任务排空。临时离线存放点保留重试,不阻断健康来源和本机正文;配置错误及缺少 feature 明确失败。

partial_mount_preparation_fetches_missing_content_from_configured_store 修前已编译运行,正文断言以 ContentUnavailable 失败;修后相同断言通过。保存对端测试 partial_mount_preparation_fetches_missing_content_from_saved_peer、独立 CLI saved_peer_is_automatically_used_for_partial_cli_reads、实际适配器句柄 shared_vault_content_sources_reach_fuse_handles_without_read_ahead 均通过;后者核对列目录和打开文件不取正文。native_startup_failure_stops_mount_runtime_and_removes_owner_record 与 runtime shutdown 测试核对立即重开数据库。

CLI 单元 24、FUSE 单元 26、无 sync CLI 单元 20、无 S3/P2P CLI 单元 24,以及独立 CLI/后台关闭各 1 项通过,fmt、定向 Clippy 无警告;协调者独立重跑正文准备 2 项、适配器 1 项和启动失败清理 1 项通过。原始日志与指纹保留修前失败、夹具编译错误和 Drop 观察竞态的分类,后两者不计作缺陷复现。初连对端的既有超时仍待第 4 条;本项不算真实挂载验收。

完整工作区默认测试随后捕获 CLI 自身未启用 S3、依赖 S3 被其他成员统一启用时返回错误类别不符。补丁 d46b138 在启动前检查 CLI 自身功能开关;原 configured_s3_store_is_not_ignored_without_s3_feature 编译后先失败,保持断言后通过,同组 6 项与 Clippy/fmt 通过。补充证据保留首次 workspace 24 通过/1 失败及修复前后日志;首次失败不计整套通过。

IV.2 普通读取与挂载预算调度

原待办第 2 条已修复,实现提交 fd8b19a。Core 读取(含缓存命中和失败前缀)、最后快照句柄关闭及角色/本机策略改变通知后台;成功同步即使没有新段也执行正文轮次。订阅注销不持有 Vault,通知不在注册表锁内执行。驱逐继续使用 protected_units,保留固定正文、未确认写入和活跃句柄;Full 不自动驱逐。短命 ContentRuntime 排空后台后只驱逐,不在退出时取正文。

修前已编译的 background_core_reads_schedule_partial_budget_without_explicit_wake、cached_reads_reschedule_eviction_after_protection_changes、zero_segment_exchange_evicts_newly_confirmed_content_without_prefetching_unpinned_files、last_fuse_handle_release_schedules_pending_eviction、short_lived_content_runtime_enforces_budget_after_draining_without_fetching 和 Core 策略/角色测试均在目标断言失败,修后通过。失败读取前缀与多订阅/注销也有回归。Web 实际面板测试先因缺预算输入失败,现支持安全整数 bytes、0 与空值;空/null 在既有 API 中表示保留预算,真实 devices_safe_removal_and_device_settings 核对整数、0、null 和省略字段。

正文精简组合 14、默认策略/角色 3、FUSE 27、CLI runtime 默认 6/无 sync 4、Web API 1、React DOM 10 项通过;定向 Clippy、fmt、TypeScript 和面板 ESLint 通过。协调者独立重跑正文 14、句柄释放 1、真实 API 1 和短命命令 1 项通过。证据保留全部阶段,原全 UI lint 的 8 条未改文件错误与一次初始轮次等待夹具竞态单列,不计入验收失败复现。未新增 ignored;真实挂载仍待 IV.3。

IV.3 macOS 挂载防护与真实运行

原待办第 3 条的挂载防护已实现,提交 1492a98;Finder 验收未完成。Mac 挂载专用零字节只读 marker 不进入 Core/CAS,真实同名文件或目录优先,普通适配器命名空间保持;run/spawn 在 ready 后验证 Time Machine,仅 Included 才用非 root tmutil addexclusion,必须再核对,失败关闭并 join。修前 macos_mounted_marker_is_read_only_and_does_not_enter_core 已编译运行并以 ENOENT 失败;修后 marker、真实名字、句柄和关闭保护共 32 项通过,Clippy/fmt/harness build 通过,协调者独立重跑 32 项通过。

2026-10-12 本地日期,本机 macOS 27.0.1 (26A434)、arm64、FUSE-T 1.2.9、UID 501。实际运行 cargo build --locked -p cipherfs-fuse --no-default-features --features fuse-t --example partial_mount_acceptance 的产物,通过 afterminal agent 租约控制 status、budget 65536、stop;A Full/B Partial 在同机真实 loopback QUIC 同步,8 个 txt/bin/有效 PNG 文件。挂载由 APFS device 16777233 变为 NFS 436207638,root marker 实读 0 字节,tmutil isexcluded <mount> 为 [Excluded],无需 root。Finder 阶段预算 885,554 bytes 高于全部 fixture 密文 820,018 bytes,确保取回内容不会被驱逐而掩盖增长。

cat <mount>/recent/first.txt 精确取回 102,400 bytes,86 ms;缓存由固定目录的 54,288 增至 156,704 bytes。budget 65536 后 111 ms 内旧正文自动驱逐,固定目录保留 54,288 bytes。stop 完成 mount worker join/后台停止,原 device 恢复、mount 表消失,终端观察到进程退出 0(清理约 9,406 ms);这些是实际挂载结果。日志、源码与二进制指纹包含修前实挂缺 marker、修后运行与退出记录。

Finder 未浏览,R58 不标完成。 cua.getApp("Finder")、reset 后 bundle id 重试、真实挂载就绪后的 cua.getState() 均返回 Sky Computer Use native pipe startup failed;无可见 GUI、截图或浏览结果。没有改 Finder 偏好或关闭预览。原待办第 3 条保留 Finder 验收;后续可使用同一 harness 复验。修前探针仅证明卸载,过早删除仍运行的终端不计正常退出;本次正常退出证明另存。退出后终端租约已消失的 404 归为管理清理观察,不是进程失败。

IV.4 离线读取与来源生命周期

原待办第 4 条“部分设备无来源可达时读取未持有文件立即失败,挂载返回 EIO,后台重试不阻塞读取”已修复并验收,实现提交 dc0a629。已知离线来源直接跳过;未知失联 QUIC/S3 的首响和无进展限制为 1 秒,持续传输仍有原 QUIC 120 秒/S3 60 秒总限,正常慢速正文和上传可超过 1 秒。FUSE 精确映射 ContentUnavailable → EIO;关闭先取消属于该后台的传输、关闭节点,再排空工作。S3 独立取消状态保留调用者共享 Arc 与停后重启语义,已停止来源可移除,临时失联来源可由后台恢复。

修前 QUIC 单/批正文、S3 无响应、完整 E2E 和 Core 错误类型均已编译并在目标断言失败;另补共享 S3 关闭回归先失败后修复。partial_device_quic_vault_and_fuse_reads_evict_safely_and_fail_offline 用真实 QUIC、A Full/B Partial 与 120,000-byte 预算,通过普通 Vault 读取和 FUSE 打开句柄取回 100,000-byte 文件;自动驱逐已确认旧正文,保护未发布写入、固定目录和活动句柄,释放后驱逐,保留离线 peer/重连并在 500 ms 内精确失败。定向 8 组共 93 次通过,512MiB heap 回归通过;Clippy/fmt/无 feature/harness build 通过。协调者独立重跑 E2E 1 与 S3 7 项通过。证据保留失败源补丁、全部原始日志和 13 项源码指纹。

完整 all-features 检查另发现健康 CLI 对端首次读取失败:Iroh 对复用 NodeId 的旧 UDP 路径仍有信任期,整段 1 秒预连接会过早取消。补丁 bf6eb11 并发探测保存对端;完全无回应仍限 1 秒,有本次认证发现回应才保留原最多两次 15 秒冷连接尝试,不等待后台重连。认证流按实际读写进度限制空闲,保留 120 秒总限、权限证明边界与双方授权;已建立来源的离线读取仍立即失败。

原 saved_peer_is_automatically_used_for_partial_cli_reads 与 real_cli_p2p_clients_sync_all_thresholds_retry_and_reject_another_vault 在 ce733bd 编译后均失败,现保持断言后 2 项通过;runtime 7、P2P 20,共 29 项通过,Clippy/fmt 干净。新增 many_unavailable_saved_peers_share_the_foreground_probe_window 核对 64 个静默对端聚合等待、后台保留与关闭后重开;认证停滞与慢速头/正文进展亦有回归。补充证据保留首次整套 116 通过/2 失败、原始失败与中间补丁失败,分阶段源码指纹不混计为最终通过。

同机 macOS 27.0.1 (26A434)、arm64、FUSE-T 1.2.9、UID 501 用新版 partial_mount_acceptance 实挂,APFS device 16777233 → NFS 436207639;marker 实读 0 bytes,/usr/bin/tmutil isexcluded <mount> 返回 [Excluded]。/bin/cat <mount>/recent/first.txt 取回 102,400 bytes / 106 ms,缓存 54,288 → 156,704 bytes;budget 65536 后 119 ms 驱逐至 54,288 bytes,保留固定目录。disconnect 关闭 A 后 B 仍有 1 peer,is_syncing=true;/bin/cat <mount>/offline/never-read.txt 在 65 ms 退出 1、输出 0 bytes,错误 Input/output error;独立 os.read 在 49 ms 返回 EIO=5,正文仍未缓存,缓存维持 54,288 bytes。stop 完成 join/后台停止(约 3,213 ms),进程退出 0,原 device 恢复且挂载表消失,之后才删除终端会话。

Finder 在新版真实挂载就绪后再次返回 Sky Computer Use native pipe startup failed,仍没有浏览或截图;R58 与 TODO 第 3 条继续待验收,本小节不能宣称全部完成或清空。

IV.5 最终工作区与容器验证

源码阶段 e6959b3 在干净工作区复验,三个最终阶段使用相同的 310 个源码输入,运行前后源码、Git 状态与日志 SHA-256 均核对。宿主 cargo fmt --all -- --check、默认及字面 --all-features 的工作区全目标 Clippy 均通过,0 编译警告;设置 PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1。默认工作区测试 672 通过 / 0 失败 / 6 既有忽略,全 feature 700 / 0 / 8,各 58 个测试目标;git diff --check 通过。默认阶段与全 feature 阶段保存完整命令和原始日志。

全 feature 构建、链接和测试均在 Darwin 原生执行。已有 fuse-t 不变;macFUSE 5.4.0 官方签名安装包只在私有目录解包,未安装或执行安装脚本;由已有 Colima 容器中的 pkg-config 解析官方包的只读 Darwin 元数据;Cargo 编译、链接与测试仍在原生 Darwin 上执行,不改 Rust target 或删减 feature。依赖文件前后指纹一致,未安装宿主工具。

完整 sh tools/test-container.sh 退出 0:Rust 754 通过 / 0 失败 / 2 既有忽略,73 个测试目标,0 编译警告;C 运行时 15、Python 10 项通过;Go 运行时检查通过,日志未逐项列出测试数;Node 客户端/React DOM 两组分别 15、10 项通过,前端构建与真实 Web 冒烟通过。统计按各 feature 组合的实际执行次数计,不合并为唯一测试数。Colima 开始验证前实际为 8 CPU / 16 GiB,结束后已实际恢复 2 CPU / 2 GiB;仅清理任务所属 Cargo 生成缓存。完整容器证据保留资源状态、命令、计数、日志及校验和。

最新 GUI inventory 已成功且 Finder 正在运行,但 Finder/Chrome 绑定返回 cgWindowNotFound、Dock 返回 timeoutReached;没有键鼠输入、目录浏览或截图,未改 Finder 设置。早先原生管道失败保留为历史观察,最新尝试原始记录随容器证据归档。IV.3–IV.4 的实挂证据属于各自源码阶段,本轮未重新实挂最终提交。Finder 缓存不增长仍未验收,R58 与 TODO 第 3 条保持未完成,该小节不能清空。

IV.6 Finder 浏览验收

2026-10-12,macOS 27.0.1、FUSE-T 1.2.9,提交 7381686 的夹具真实挂载。用 open 让 Finder 打开挂载根目录与全部 5 个子目录、定位 4 个文件(含 PNG),lsof 确认 Finder 持有这 6 个目录;浏览前后 cached_content_bytes 均为 54,288,缓存文件只有固定目录的 pinned/guide.txt,未生成 Finder 元数据文件,夹具退出 0。AppleScript 与截屏因终端缺少自动化/屏幕录制权限不可用,不影响测量。记录与事件日志。R58 完成,TODO 部分设备挂载小节清空。

需求更新后仍剩的差距

主体完成,见待办。 共享冲突/历史、退休宽限期与 GC、存放点正文、设备配对/撤销/恢复轮换、流式 SDK 和明文导出取得上述分阶段证据;独立审查所列问题的逐项修复与证据见上节,剩余工作见 TODO.md。尚未完成 WebDAV 存放点、移动端、子树授权、multipart 权限证明,以及没有独立已有成员时的恢复设备管理。百万文件/100GB 长期规模、真实公网/云账号尚未验收;本机回环 Partial 挂载、断网与 Finder 浏览结果见 IV.3–IV.6。

范围当前边界
容量与内存单对象证明/快照 32MiB;本机完整因果日志仍保留。Vec、UnitRef、历史遍历 ID、heads/争用者、完整成员/权限与选择元数据随数据增长;页查询可能重复扫描。默认后台正文批预算为 8MiB,按单元边界关闭,单个单元可使批次超预算;短 heap 用例不能替代整进程/百万文件/任意配置测量。
明文导出新目标、现有无符号链接父路径、native 可表示布局;文件/目录及大小写/Unicode 碰撞明确拒绝。Linux/Android/Apple 有实现,本轮实测平台以日志为准,其他平台 Unsupported;只复制 mtime/owner executable。
OS 与挂载当前源码普通测试默认忽略实际挂载;旧 macOS/Linux 实挂记录属旧源码。其他 Mac 后端/系统版本、Windows、远端覆盖时的实际挂载缓存和完整 POSIX/ACL/xattr/链接兼容尚未验收。
网络与服务当前网络用例主要本地 direct QUIC、Directory 和 S3 loopback;真实云账号、公网 NAT/relay/弱网长时、真实浏览器逐项交互未验收。
异常与规模有取消、中断、重开、时钟和 I/O/内容损坏用例;异常断电、强制杀死/睡眠唤醒、磁盘耗尽恢复、多 GiB 挂载、百万文件和长期高负载未系统验收。
接入层C/Python/Go 为本机 API,设备加入/同步走 Rust、CLI/Web;Rust 才有列表/历史页。Web 保存来源可后台恢复,未实现运行时设置与外部池仍返回 501。mount/read 共用来源与后台生命周期;普通读取、句柄释放和策略变化调度预算,设备面板提供预算输入。macOS marker/Time Machine、断网 EIO 与 Finder 浏览缓存不变已实测,见 IV.3–IV.6。

历史源码阶段的证据

以下记录保留当时结果和行为,涉及的旧格式、旧命令与默认按需正文均是历史背景,不能解释为当前功能声明。

2026-10-09 完整索引、按需正文与本机版本保护

按已确认需求实现格式 5:共享当前索引与正文获取分开,默认不上传或读取正文;Directory、S3 与双向 P2P 正文来源独立持有,按读取范围获取并认证内容。修改、删除与接收变更保留本机旧正文;本机历史、垃圾箱和冲突共用加密保留机制,未发布修改及并发失去当前地位的本机正文排除自动清理。恢复发布新修改,清理不改变共享索引、其他节点或活动读取。CLI 提供本机保留/清理与恢复;Web P2P 会话保留正文来源,HTTP Range 可按需播放,注销关闭来源与读取权限。密码封装和密码方案未改变。

本次执行范围最终结果
Core 全部功能375 单元、70 集成、21 文档,共 466 通过;检查点 10 项在修正旧备份/正文假设后单独复验,不宣称单条命令一次全部通过。无默认功能下本机历史 11 项另外通过,过滤 311 项。
Sync 全部功能 / 无默认功能181 单元 + 46 集成 + 9 文档 = 236 通过;无默认功能单条命令 141 + 30 + 9 = 180 通过。两组均实际执行最大 16MiB 单元、混合算法和检查点策略用例,没有沿用旧阶段过滤结果。
CLI / WebCLI 20 单元、8 基础和 92 覆盖用例共 120 个不同测试通过;完整执行后检查点 3 项与本机历史 3 项单独复验。Web sync,s3,iroh-p2p 下 68 项通过,含真实 P2P + HTTP Range、损坏、中断和注销。
其他接入层FUSE 25 单元 + 1 文档通过;TUI 7、WebDAV 14、S3 gateway 14 通过。S3 gateway 的尾部损坏用例适配小密文包后定向复验,其余 13 项来自完整组。
Linux 实际挂载隔离容器显式执行两项内核挂载夹具,2/2 通过,0 失败/忽略,10.14 秒;覆盖三种 AEAD、实际范围修改/追加/fsync、复制、重命名、删除与重开。普通 FUSE 运行的两个忽略项不算实挂证据。
编译与格式工作区全目标全部功能检查、CLI 无默认功能检查、FUSE 四种 Linux feature 组合检查通过;63 个修改/新增 Rust 文件在容器内格式整理,git diff --check 通过。未修改 Proto。保留编译 warning,没有把编译检查当作绑定运行时验证。

结构化结果及源码校验和、各阶段原始结果摘要保留在仓库。摘要保留早期旧夹具失败与最终复验结果;表中同组测试不重复累计。引用复制只发布已认证内容引用,不保证正文当时在本机可读;正文缺失在读取时明确失败,被覆盖目标的旧正文仍受本机历史保护。

构建、依赖、测试和格式工具均在容器内运行,源码在构建时只读挂载。复用已运行的 Colima 与项目缓存卷;为现有 2GiB VM 限制构建并行和链接内存,仅整理本次验证缓存,未安装宿主依赖或改变 VM 配置,结束时保留原运行状态。内核挂载和测试数据仅位于所属隔离容器;验证容器均使用 --rm。

本次未重新执行 macOS 原生挂载、语言绑定运行时、前端构建/真实浏览器交互、真实云账号或互联网 NAT/relay。2026-10-08 的 macOS 证据属于格式 4 基线,不能证明这次格式 5 改动。项目仍未发布,不提供旧开发格式迁移;需求文档位于网站内容目录,尚未部署网站。

2026-10-10 Rust 应用对象接口与后台同步

新增 cipherfs_sync::SyncedVault:应用启用同步后使用异步 put/get/get_range/delete/list,只传路径、字节和读取范围,不持有文件指针、游标或句柄。业务写入先本机加密持久化,后台自动交换索引、重连和退避重试;默认正文按需获取。接口也覆盖本机版本读取、恢复、清理和独立保留策略。Rust 接入文档及可运行双实例示例已替换过时入口。

本机私有缓存不再提前确认版本已同步;确认只覆盖真实对端已认证提交头中的精确记录,后续本机写入保持保护。正文连接先于索引可见准备,同一连接使用有界并发及独立正文配额,避免读取与同步确认相互等待。取消写入仍通知后台;关闭等待阻塞操作及异步请求释放捕获,已关闭的 facade 克隆不阻止同路径重新打开。

Sync 完整串行回归 190 单元 + 53 集成 + 9 文档,共 252 通过,含实际最大 16MiB 单元。随后补充异步请求退出屏障,最终源码的 Iroh/P2P 29、SDK 单元 2、SDK 集成 7 项再次通过;不重复累计,也不把完整组当作最后窄修后的单命令结果。工作区全目标全功能、Sync 无默认功能全目标检查、格式检查通过;双实例直接 QUIC 示例实际跑通。具体命令、阶段失败/修正及最终源码指纹见本轮证据。

构建、依赖、测试与格式工具均在所属容器内运行,未安装宿主依赖或改变 Colima 配置,仅清理本任务生成的缓存执行文件。本轮没有验证两台物理服务器、公网 NAT/中继、长期压力或很长提交链的确认性能;完整历史交换和确认仍扫描元数据。put/get 缓冲完整对象,不能承诺内存与对象大小无关。其他平台、UI 和语言绑定沿用此前分阶段证据。

2026-10-10 审查修正

对照需求审查核心、同步、测试与文档后修正:

  • 移动、重命名以及接收端的同变更移动不再把旧路径放入本机历史和垃圾箱。
  • 接收重复、延后或失去当前地位的变更时,捕获的快照若内容仍是当前版本即丢弃,且不写清除标记,后续真正替换仍会保留。对已提交的变更直接跳过捕获;重新捕获当前版本会刷新保留时间,因此重复同步不会让版本提前按时间过期。
  • 检查点 reset/rebase 不再把未变化的当前文件重复记入历史,避免它们挤掉真实历史的空间预算。
  • 截断与 O_TRUNC 不再获取将被丢弃的远端单元,离线也能截断仅有索引的文件;本机已有单元仍校验,部分保留的单元仍需正文。
  • 最后一个公开 Vault 句柄释放前,先停止并等待维护线程,修复启用自动清理后 drop 再立即打开时偶发的数据库占用。
  • 保留策略预取移出同步引擎的临界区。核心 prefetch_retained_content 跳过已完整缓存的文件,逐文件记录失败;P2P 在交换后或响应后于后台执行。单个损坏或不可用文件不再阻止全部同步。
  • 删除与需求冲突的旧 sync_types(向量时钟、冲突副本),以及未编译的根 examples/、main.rs.bak 和全部编译警告。
  • 文档:删除与当前实现矛盾的旧页面(evaluation、optimization、version-control、旧 sync/storage/security/cli/user-guide 与绑定说明),首页、架构、API、开发索引改为简短准确版本,README 只描述当前行为,本记录移除 10-04 至 10-08 的分阶段叙述。

新增回归测试:index_on_demand 中的移动不入垃圾箱、仅索引截断、检查点不重复历史、延后变更不抑制历史;local_versions 的重新捕获刷新保留时间。旧测试中断言“缺失单元必须使截断失败”与“重复导入保留当前值”的部分按新语义更新。

最终源码以 tools/test-container.sh 在新建、源码只读的容器中完整执行:58 组测试共 1044 通过、0 失败、2 忽略(FUSE 真实挂载夹具需显式设备权限),FUSE/CLI feature 矩阵与工作区全功能检查、C/Python/Go 绑定、前端构建和真实 Web 冒烟均通过,退出码 0。其中 Core 376 单元,Sync 全功能 143 单元 + 45 集成 + 9 文档(删除旧 sync_types 后单元数减少)。此后只为精简功能组合补充 cfg 标注、为新测试加 storage 条件,Core/Sync 无默认功能与全功能、FUSE/CLI 无默认功能及工作区全功能编译复查通过,受影响测试定向复验通过;工作区全功能无编译警告,精简功能组合仍有既有的死代码警告。

前四轮完整执行暴露的问题均已修正后重跑:新单元测试构造错误、旧测试对截断与重复导入的旧语义断言、服务端后台预取的测试等待,以及延后变更丢弃快照时写入清除标记导致之后真正替换不再保留历史(取决于导出顺序,已用确定性测试覆盖)。开发容器磁盘写满导致一次 No space left 失败,清理增量缓存后复验通过。

构建与测试只在 Colima 的容器内运行。为容纳工作区编译,Colima default VM 临时从 2 CPU/2GiB 调整为 8 CPU/16GiB,结束后恢复原配置;开发容器 74GB 的 debug 增量缓存已清理。宿主机未安装依赖。未重新执行 macOS 原生挂载、真实浏览器交互、真实云账号或公网 NAT/中继。

2026-10-10 macOS 宿主机验证与清理

首次在 macOS 宿主机(arm64,已有 Rust 1.99)上运行工作区测试,暴露并修正:

  • 目录对象库和 P2P 私有对象库逐级以 O_NOFOLLOW 打开根路径,遇到 macOS 的系统符号链接 /tmp、/var 即失败,导致这些路径下的库无法同步。两处改用共享的 anchored_path:只跟随文件系统根目录下 root 拥有的符号链接,其他位置的链接(包括 root 自己创建的)仍拒绝。
  • Darwin 上多个进程并发以非独占 O_CREAT 创建同名锁文件时会偶发 ENOENT。提交头锁和 CLI 挂载登记锁改为有限次重试。
  • S3 测试夹具在 BSD 上接受的连接继承监听端的非阻塞模式,已显式恢复阻塞。
  • 对端连接关闭后,其内容源在下一次读取前移除,不再在失败的交换后累积。传输错误本来就映射为正文不可用,因此此前不影响读取结果。

删除未接入或无法编译的代码:恢复码模块(只取 BIP39 种子前 32 字节,与实际密钥派生无关)及 bip39/pbkdf2/lz4 依赖、根 benches/ 与 bench.sh、孤立的 CLI remote_config.rs、Sync 中未被使用的 bandwidth/block_sync/discovery/hybrid_discovery、IrohNode 旧分片接口、S3Sync 拒绝式复制入口及其底层 list/head/delete 辅助函数,以及随之不再使用的依赖(mdns-sd、hostname、hmac、chrono、redb、anyhow、bincode、futures、iroh-net)。精简功能组合的死代码警告已消除,格式统一。

宿主机结果:工作区(除需宿主 Python 头文件的 cipherfs-python)50 组 882 通过、0 失败、6 忽略。此后删除死代码,再跑 Sync 全功能、CLI(iroh-p2p/s3/tui)与 Core 单元,全部通过;CLI 真实 P2P 用例在整组并发负载下有一次因宿主多网卡(含 Colima 网桥)的 Iroh 路径重置而连接失败,单独重跑两次均通过,属于宿主网络环境的不稳定。修正前的 HEAD 上同一用例在更早一步就因 /var 符号链接失败。新增测试:anchored_path 的用户符号链接拒绝与 macOS /tmp 跟随、CAS 关闭源移除;independent_directory_writers_have_exactly_one_head_cas_winner 在 macOS 上由失败变为稳定通过。

最终源码以 tools/test-container.sh 在新建、源码只读的容器中完整执行:58 组测试共 886 通过、0 失败、2 忽略(FUSE 真实挂载夹具),无编译警告;FUSE/CLI feature 矩阵、C/Python/Go 绑定、前端构建和真实 Web 冒烟通过,退出码 0。总数较上轮 1044 减少,主要是删除了旧 block_sync 等模块及其测试。第一次容器执行发现容器以 root 运行时,测试自建的 root 所有链接会被当成系统链接跟随,因此规则收窄为只跟随根目录下的链接后重跑。Colima default VM 为此临时调整为 8 CPU/16GiB,结束后恢复为 2 CPU/2GiB。

2026-10-10 Web 后台同步、恢复密钥与 clippy 清理

  • clippy:clippy.toml 允许测试代码 unwrap/expect/panic,集成测试入口同样放行;生产代码剩余的 unwrap/expect 改为显式处理,C/Go ABI 在模块文档中统一说明安全约定。工作区各 feature 组合 clippy 零警告。顺带修正 cipherfs find:此前未转义正则元字符且按整条路径子串匹配,*.pdf 会命中 a.pdf.txt,file(1).txt 无法匹配;现按文件名整体匹配通配符。
  • Web 后台同步:每个会话只绑定一个 BackgroundSync 节点,同时服务对端、运行已保存对端的循环并执行手动 P2P 同步。对端路由经核心加密存于本机(local_sync_peers,与本机内容策略同表、不进入共享索引),解锁后自动恢复,锁定、退出、改密码即停止;成功的写请求立即唤醒对端。保存路由在 vault 槽锁内读写,避免额外句柄让退出后的数据库仍被占用(测试中复现过随后登录失败)。以中继地址添加对端而当前节点仅直连时重新绑定节点。BackgroundSync 新增 remove_peer、synchronize 和 node_id。修正前端读取节点地址的字段不一致和能力列表缺少 P2P;容器验证与运行入口此前未以 iroh-p2p 构建 Web,原有 Web P2P 测试从未执行,现已启用。
  • 恢复密钥:Vault::create_with_recovery_key 生成 256 位随机恢复密钥,以 BLAKE3 派生的密钥 XChaCha20-Poly1305 封装主密钥,封装附带以主密钥派生密钥计算的 MAC。bootstrap 在有恢复封装时使用带魔数的 v2 格式,旧格式仍可读;以密码加入时用解锁所得主密钥校验 MAC,拒绝拼接自其他库的封装。新增凭恢复密钥加入(自设本机密码)、重设忘记的本机密码、为旧库生成一次恢复密钥;不支持替换已有恢复密钥,因为其他客户端和旧 bootstrap 仍会接受旧密钥。CLI 新增 reset-password、set-up-recovery-key 与 create-replica --recovery-key,init 显示一次恢复密钥;Web 在新建时显示,登录页可凭恢复密钥重设密码,设置页可为旧库生成。

验证:宿主机 clippy(各 feature 组合)零警告,Core、Sync 全功能、Web(sync/s3/iroh-p2p)及新增 CLI 用例通过。最终源码以 tools/test-container.sh 在只读源码容器中完整执行:60 组测试共 898 通过、0 失败、2 忽略(FUSE 真实挂载夹具),前端客户端测试 7 项通过,C/Python/Go 绑定、前端构建与真实 Web 冒烟通过,退出码 0。Colima default VM 临时调整为 8 CPU/16GiB,结束后恢复为 2 CPU/2GiB。

2026-10-10 CLI 空壳命令、绑定恢复密钥与 P2P 测试稳定性

  • CLI 删除从未接入、只会报“尚未接入”的命令和参数:remote、daemon、snapshot、pool、lock、maintenance start/stop、maintenance check --repair 以及 open 的尾随命令。它们出现在 --help 中却没有实现;现在解析即失败。按编译 feature 缺失给出提示的 sync p2p/s3、mount、read --peer 保留。Web 的 501 接口在 README 中有说明并由冒烟测试检查,保持不变。
  • C/Go/Python 绑定新增恢复密钥:生成一次(已有则 AlreadyExists)、查询是否存在、凭恢复密钥重设本机密码并打开仓库。绑定只管理本机仓库,不提供副本加入。C 与 Go 测试在宿主机已有工具链上通过(Go 缓存放在临时目录,不拉取工具链)。
  • CLI 真实 P2P 用例此前在宿主机整组运行时偶发失败:服务端发布所有网卡地址(含 VPN、容器网桥),负载下 Iroh 路径切换导致连接重置。测试改为保留节点身份、仅经 IPv4 回环拨号;仍是真实 QUIC 交换。宿主机完整 CLI 套件(93 个覆盖用例)随后通过。

验证:宿主机 clippy 零警告、完整 CLI 套件通过;C 与 Go 绑定测试在宿主机通过。容器完整执行:60 组测试共 899 通过、0 失败、2 忽略(FUSE 真实挂载夹具),Python 运行时 10 项、C/Go 绑定、前端客户端 7 项、前端构建与真实 Web 冒烟通过,退出码 0。该次运行在全功能编译下报出删除空壳命令后无人调用的 unsupported 辅助函数;随后按 feature 收窄其编译条件,并在容器中复查 CLI 全功能与无默认功能构建无警告。Colima 临时调整为 8 CPU/16GiB,结束后恢复为 2 CPU/2GiB。

仓库中的源文件