任务:桌面 App 与移动端
2026-10-14 立项。目标是在现有核心、Web API 和 React UI 之上交付 Tauri 桌面 App(macOS、Windows、Linux)以及 Android、iOS App,并补齐发布前已知的核心缺口。本页是完整计划;每步完整验证通过后单独提交,证据写入实现记录,README 只在行为落地后更新。项目未发布,格式和 API 可为本页改变;现有测试是回归基线,不放宽旧断言。
现状
- 核心是纯 Rust(redb、rustls、XChaCha20-Poly1305、Iroh),能编到各平台;
cipherfs-web已有解锁、文件、配对、撤销、冲突、保留策略和同步的全部路由;cipherfs-web-ui约四千行 React,客户端的baseUrl可配置。 - 一个仓库同一时刻只能被一个进程打开:redb 按进程持文件锁,后台同步循环活在打开仓库的进程里。第二个进程得到的是数据库层错误,CLI 与 Web、CLI 与将来的 App 不能同时使用同一仓库。
cipherfs-api是阻塞门面,主动拒绝在 tokio 运行时线程上调用;Tauri 的命令恰好跑在运行时线程上。- S3 凭据只从
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY读取,GUI 和手机没有合适的入口。 - P2P 钉在
iroh-net 0.28,该 crate 已并入iroh并停止演进;手机端需要当前版本。 - 工作区从未在 Windows 上编译;
rustix、导出的独占发布和小文件锁都只有 unix 实现。挂载只有 macOS(FUSE-T/macFUSE)和 Linux,没有 WinFsp。 - 没有明文目录监视:桌面上只能经挂载、CLI、Web 访问文件,没有"一个会同步的文件夹"。
- 配对/恢复证明和快照是单对象,上限 32 MiB,没有 multipart;百万文件、1 TB、100 GB 的规模验收没有执行;WebDAV 存放点和云盘 API 没有实现。
- 全部既有设备丢失后,凭恢复密钥加入的设备不能撤销和批准配对;这是有意限制,但对 App 用户是陷阱。
设计决定
- 仓库有唯一归属进程,其余进程是本地 API 客户端。 不换数据库,也不让两个进程同时写索引。打开仓库的进程是"服务",在仓库目录写
owner.json(pid、启动时间、本地端点、token 文件路径),关闭时删除;再次打开时先核对 pid 是否存活,陈旧文件直接覆盖,活着的归属进程返回Locked并附带端点。cipherfs-web增加 Unix socket / Windows 命名管道监听和 0600 的随机 token 文件,这就是进程间接口。CLI 在仓库被占用且端点可达时改走 HTTP,命令与现有路由一一对应;否则照旧本地打开。挂载由归属进程提供:cipherfs mount没有归属进程时自己成为归属进程,有则请求它挂载。Tauri 内嵌服务即归属进程;iOS 的 File Provider 扩展是归属进程,主 App 是客户端。 - Tauri 复用 Web API 与 UI。 Tauri 壳内嵌 Axum 监听本地端点,加载现有 React UI;不经
cipherfs-api。原生部分只做壳该做的:托盘、开机自启、钥匙串、系统文件对话框和拖拽、通知、签名与自动更新。 - 凭据入口。
cipherfs-sync打开存放点时通过CredentialProvider取凭据;默认实现读环境变量,Tauri 和手机用系统钥匙串,cipherfs-api与各绑定可传入。凭据仍然不写入仓库和日志。 - 升级到当前
iroh。 relay 配置保持可替换;手机端后台不能依赖 P2P,主力是存放点,与已确认需求一致。 - Windows 以
x86_64-pc-windows-msvc为目标。 core、sync、web、api、cli(不含 fuse)必须编译并通过测试;unix 门控的导出和锁要么补 Windows 实现,要么明确返回 Unsupported,不能编译失败。挂载用 WinFsp,作为独立步骤。需要一台 Windows 机器,登录信息由用户稍后提供。 - 手机绑定用 UniFFI 生成 Kotlin 和 Swift,在
cipherfs-api之上;cipherfs.h继续服务 Go。Android 先做:DocumentsProvider 在同一进程内运行,归属模型不受影响。iOS 后做:File Provider 扩展持有仓库,主 App 经扩展访问。手机端后台同步用系统任务(WorkManager / BGProcessingTask)定期对存放点同步,不依赖 P2P 常驻。 - 桌面"同步明文文件夹"模式作为挂载之外的第二种透明接入:归属进程监视一个本机目录,本机改动发布为版本,远端版本写回目录;冲突仍走共享版本模型,目录里不生成冲突副本;目录是缓存,删除目录不等于删除仓库数据。放在桌面 MVP 和挂载之后。
- 孤儿恢复设备的管理权限先在需求页裁决再实现;候选方案是恢复密钥加公示期:恢复设备发布管理请求,N 天内没有任何既有成员反对即生效,被撤销设备不能反对。裁决结果写入需求页。
- 规模与存放点缺口(multipart、WebDAV、云盘 API、规模验收)按规模预算和需求页的实现顺序排进本计划,手机端上线前完成 multipart 与至少一种 API 存放点。
交付顺序
| 步骤 | 范围 | 验收 |
|---|---|---|
| 1:归属进程与客户端 | Core 的 owner 文件与 Locked 端点;Web 的本地 socket / 命名管道监听与 token;CLI 客户端模式 | 两个进程打开同一仓库:第二个经端点完成 put/get/list/devices;归属进程退出后第二个可本地打开;陈旧 owner 文件不阻塞 |
| 2:凭据入口 | CredentialProvider,环境变量默认实现,API 与三套绑定的传入方式 | S3 夹具不设环境变量、只经 provider 通过;凭据不出现在仓库和日志 |
| 3:iroh 升级 | 依赖迁移,node_addr 文本格式不变 | 现有真实 QUIC 用例与 P2P 夹具全部通过,NodeAddr JSON 向量不变 |
| 4:Windows 编译与 CI | 目标编译、测试、CI 条目 | Windows 机器上 core/sync/web/api/cli 测试通过;unix 门控全部有 Windows 结果 |
| 5:孤儿恢复设备 | 需求裁决,实现公示期或所选方案 | 全部设备丢失后恢复设备能在规则内撤销与批准配对;既有成员反对时拒绝 |
| 6:multipart | 权限证明、快照、上传清单分片发布与认证 | 超过 32 MiB 的证明和快照在 Directory 与 S3 上发布、读取、GC 通过 |
| 7:WebDAV 存放点 | ObjectStore 的 WebDAV 实现,自建与云盘兼容 | 存放点契约测试在真实 WebDAV 服务上通过 |
| 8:规模验收 | 按规模预算执行百万文件、1 TB、100 GB、10 设备 | 预算表每一项有实测结果与证据 |
| 9:挂载由归属进程提供 | 归属进程内的挂载服务,CLI 与 App 请求挂载 | 已打开仓库的 App 可挂载和卸载;CLI mount 两种路径都通过 |
| 10:Tauri 桌面 MVP | 壳、内嵌服务、现有 UI、托盘、自启动、钥匙串、文件对话框与拖拽,macOS 打包 | 解锁、浏览、上传下载、配对、撤销、同步状态、挂载开关在 App 内可用;UI 测试沿用现有 Node 用例 |
| 11:Windows 挂载 | WinFsp 适配 | Windows 上挂载读写、冲突视图、卸载通过 |
| 12:Windows 与 Linux 打包 | Tauri 打包、签名、自动更新通道 | 三平台安装包可安装、升级、卸载 |
| 13:同步明文文件夹 | 目录监视、双向同步、冲突与删除语义、忽略规则 | 本机改动与远端版本双向收敛;冲突只出现在冲突视图;离线改动重连后发布 |
| 14:UniFFI 绑定 | Kotlin/Swift 生成,覆盖 cipherfs-api 全部门面 | 与 C/Python/Go 相同的生命周期断言在 Kotlin/Swift 测试通过 |
| 15:Android App | 解锁、浏览、按需读取、固定目录、DocumentsProvider、存放点后台同步 | 真机或模拟器上 Partial 角色按需读取、缓存预算与后台同步验收 |
| 16:云盘 API 存放点 | OneDrive、Dropbox、Google Drive 的 ObjectStore 实现与授权 | 各存放点契约测试通过;令牌只存钥匙串 |
| 17:iOS App | File Provider 扩展持有仓库,主 App 客户端,存放点后台同步 | 文件 App 内浏览与按需下载;扩展内存上限内通过 |
| 18:发布准备 | 格式冻结、版本号、变更记录、首个发布 | README、架构、实现记录与本页收尾;发布包和文档一致 |
依赖关系:1、2、3、5、6、7 彼此独立,可并行;4 等 Windows 机器;8 依赖 6;9 依赖 1;10 依赖 1、2、9;11 依赖 4、9;12 依赖 4、10;13 依赖 9;14 依赖 2、3;15 依赖 14、6;16 依赖 2;17 依赖 14、15、16 中至少一种 API 存放点;18 最后。
验收要求
- 每步宿主
scripts/projects.sh format --check、check、clippy零警告,scripts/projects.sh test在固定容器完整通过;不在宿主安装工具、包或工具链。Tauri CLI、Android SDK/NDK、iOS 目标与 Windows 工具链需要各自的构建环境,放在哪台机器或容器由用户决定后再开始对应步骤。 - 新增能力只在 Core 和 Sync 实现一次,壳层不复制规则、不把未实现操作报告为成功。
- 每步的失败与取消记录独立归档,不计入完整通过。