CipherFS
In development · unreleased · format may change

Architecture

CipherFS keeps encryption, file identity and shared version semantics in Core. Adapters use the same current-version, conflict, retention and device-authority rules.

ComponentResponsibility
cipherfs-coreStable FileId/version DAG, encrypted redb fields and CAS, per-device signed logs, membership/key epochs, snapshot validation, local content policy, retention and export
cipherfs-syncImmutable Directory/S3 objects, packs, authenticated Iroh peers/pairing, content sources, independent background loops and store GC
cipherfs-cli / cipherfs-fuseCommands and mount semantics, including the read-only conflict view
cipherfs-web / cipherfs-web-uiSession-bound HTTP/streaming, device/conflict/retention controls and React UI
cipherfs-ffi / cipherfs-python / cipherfs-goLocal file/directory and recovery-password APIs

WebDAV stores and mobile clients remain future work. The earlier WebDAV gateway, S3 gateway and TUI prototypes were removed from the tree; the last copy is in git history at commit 6f4408b.

Index and content

Each device appends an immutable encrypted, signed log with its own sequence/hash chain and causal dependencies. There is no shared mutable head, store lock or conditional update. Segments and complete multi-part batches apply atomically; known frontiers prevent replay rollback. Signed snapshots accelerate bootstrap only after their covered original inputs are checked against replay, and do not create authority of their own.

FileId survives moves. Paths materialize from versions; directories derive from prefixes, while empty directories are device-local. Concurrent content/path heads remain readable; current selection is deterministic and a later write parents all known heads. History, trash and conflicts are shared views, not additional copy files.

Stores carry ciphertext packs and index segments. Content locators map authenticated units into pack ranges; incomplete/missing objects wait, complete authentication failures report corruption. A Full device fetches all unretired content; Partial fetches pins and keeps a bounded read cache. Content positions and store acknowledgments describe known holders, separately from index positions.

Keys and retirement

DeviceId is the Ed25519/Iroh public identity. Password and recovery wraps protect a random local storage key plus device seed. The master key is epoch zero; later epoch keys are random and distributed only to remaining members and recovery. Revocation cutoffs rebuild accepted effects, including later management records. Pairing uses a one-use secret and an existing member's SAS approval.

Recovery initialization includes an independent genesis trust anchor. Recovery self-enrollment is provisional for management: content works immediately, but an independent existing member must ratify before revoke, rotate or pairing approval. This restriction also applies when all existing devices have been lost.

Retirement is shared and cancellable during grace; current/conflict/unpublished versions are protected again at effect time. Default timing is 30 days to effect, 31 to local release, 38 to earliest store GC. Runtime snapshots delay local release. Authenticated upload inventories cover orphan packs; repacks publish replacement content/locators before delayed deletion. Causal version metadata remains retained.

Boundaries and decisions

The root subtree is currently used; deriving subtree keys does not implement subtree access grants. Body APIs stream through bounded adapters; byte Vec/Blob results use O(object/range), and list/history/trash/conflict Vec results use O(entries). Core and SyncedVault provide bounded list/history pages with value continuations and current-view semantics. Complete index/membership state, history visited/parent IDs, heads/contenders and per-version unit metadata retain growing costs. Cold authority proofs and snapshots remain single objects limited to 32MiB, so arbitrary-history or million-file scalability is not established.

Complete offline plaintext export requires Full content synchronization through the accepted frontier and an intact local cache; Partial/catching-up devices report missing selected bodies. Export pins selected versions/content, streams bodies and retains selection metadata. Its fresh target must represent selected keys and archives losslessly, have symlink-free parents and support exclusive anchored publication; native name/path collisions fail. Writer/HTTP streams can emit authenticated prefixes before a later error, requiring output discard/abort; buffered reads return Err on failure.

See confirmed requirements, Rust integration and ADR records. Repository docs/IMPLEMENTATION_AUDIT.md records the current decisions and execution evidence; older ADRs describe their original context.

Source file in the repository