Grant Milestone Progress Report (April)
What progress was made on your grant this month?
- Completed Milestone 3 (Multi-Device Sync & Sharing) end-to-end: a second device can now restore a vault from a remote relay using only its paper recovery key, with full cryptographic verification.
- Replaced the on-the-wire registry format with a v3 schema that namespaces every entry by
vault_id. One device-signing key now covers any number of vaults, and concurrent producers (rw mounts, parallel snaps from N writers) converge to the union of every writer’s changes without per-vault locking, thanks to a verify-and-retry-with-merge loop in the publisher and strict-CAS in the registry. - Locked the
vupCLI grammar around sigil-prefixed references:vup +<vault> <verb>for vault-scoped commands, single-letter aliases on every verb, and a clean separation between bootstrap verbs (onboard,_daemon) and the RPC frontend that everything else flows through. - Rebuilt the FUSE adapter on fuse3 0.9 and moved it onto the daemon. The CLI is now a thin RPC client that sends
MountVaultand blocks on Ctrl-C; the daemon owns the mount handle, opens the stores, and runs a debounced flush + publish loop for--rw.vup_clino longer depends ons5_fuse,s5_fs_v2, ors5_store_local. - Shipped frozen-anonymous share links (
vup +<vault> export): one URL per call, valid for the current snapshot only, decrypts with the secret embedded in the URL fragment. No registry write, no peer relationship, the URL itself is the capability. - Added
vup +<vault> snap --watch: notify-driven recursive watcher with a 2 s debounce that re-snaps automatically until Ctrl-C. - The
vup sync push/pulldeliverable from the original M3 plan is now obviated by the convergence loop landing in foundation work — multiple devices simply publish to the same relay and the next reader sees the merged result. No separate verbs needed.
Merged this month
| Milestone | Task | PR | Notes |
|---|---|---|---|
| M3: Multi-Device Sync & Sharing | v3 registry + convergent publish + composable FS5 layers | #2 | Wire format namespacing entries by (pubkey, vault_id); strict-CAS + atomic put_bytes; ReadableLayer / Pipeline / MergedView / WritableOverlay primitives; publish convergence loop and peer-snapshot loading. Removes [peer.*] config and the vup sync push/pull verbs (obviated). |
| Async relay via remote store | #3 | v3 paper-key disaster recovery: enumerate relay blobs, age-decrypt with paper key, derive vault_id and recovery_signing_key, walk registry to the latest snapshot. End-to-end test covers Device A → relay → A offline → Device B restores with SHA-256 verification of every file. |
|
vup CLI grammar, lifecycle, real snap/restore |
#4 | Sigil grammar (vup +music snap, vup new +music); lifecycle / vault / onboard / stubs modules; argv preprocessor with 16 unit tests; bootstrap-only verbs are onboard and _daemon, everything else routes through the daemon. |
|
vup +<vault> mount [--rw] (FUSE) |
#5 | s5_fuse rebuilt on fuse3 0.9 with read / write / debounce / mount modules and a generic until: F cancellation future. New MountVault / UnmountVault RPC + daemon-side MountManager so vup_cli no longer depends on s5_fuse. --rw accumulates in an in-memory overlay that the daemon folds + publishes on idle. |
|
vup +<vault> export (share) |
#6 | Frozen anonymous share links. Daemon re-encrypts the current Transparent Node with a fresh ephemeral age recipient added, uploads the new blob, returns a URL with the secret in the fragment. One snapshot, no future updates, no individual revocation. | |
vup +<vault> snap --watch |
#6 | Recursive notify watcher over the vault source’s paths, 2 s debounce, runs until Ctrl-C. Foreground only; daemon-side watch is a natural follow-up. |
Validation (after git checkout main):
cargo install --path vup_cli
vup new +backup # creates vault, prints recovery key
vup +backup add ~/Documents
vup +backup snap # snapshot + publish
vup +backup mount /mnt/backup # FUSE-mount, browse files
vup +backup export # frozen share URL
vup +backup snap --watch # auto-snap on changes
# Workspace tests covering the M3 invariants:
cargo test --test concurrent_publish # 10-way convergent publishers
cargo test --test peer_load # peer-side snapshot load via relay
cargo test --test async_relay # device A → relay → device B restore
What will you be working on next month?
- Begin Milestone 4:
s5_store_indexdcrate implementing the S5Storetrait against the indexd SDK (sia-sdk-rs), including key derivation, app registration, and theBlobLocation::IndexdObjectvariant for direct RHP4 downloads. - Run the full backup / mount / edit / restore cycle against indexd.
- A few items already flagged as natural follow-ups during M3 will land alongside: daemon-side store handle reuse so the mount path supports remote backends (S3, Sia, indexd), and a daemon-resident
--watchso the CLI can exit while the watch keeps running.