Skip to content

M3 share + watch: vup +<vault> export and snap --watch#6

Merged
redsolver merged 2 commits into
mainfrom
m3-share-watch
Apr 27, 2026
Merged

M3 share + watch: vup +<vault> export and snap --watch#6
redsolver merged 2 commits into
mainfrom
m3-share-watch

Conversation

@redsolver

Copy link
Copy Markdown
Contributor

vup +<vault> export [--path <p>]

Frozen anonymous share links. The daemon generates a fresh age::x25519::Identity per call, loads the local Transparent Node, re-encrypts its CBOR for the vault's existing recipients plus the ephemeral one, uploads the new blob to vault.blob_stores[0] and every vault.meta_targets, and returns a share URL with the ephemeral secret in the fragment. The blob is content-addressed by BLAKE3(age_bytes).

Recipient gets one snapshot. No future updates, no individual revocation; the URL is the capability.

--path is reserved for sub-tree exports and rejected today (whole-vault only) so the CLI can't silently produce a different scope than the user typed.

New ExportVault RPC + S5NodeClient::export_vault flatten to Result<ExportedShare>, matching the RunTask / MountVault pattern.

vup +<vault> snap --watch

Notify-driven debounced auto-snap. Takes one initial snapshot, registers a recursive notify watcher over each path in the vault source's paths, and re-runs the snap whenever a 2 s burst of filesystem events quiesces. Continues until Ctrl-C.

Existing run_snap is split into build_backup_spec + run_backup_once so the one-shot and watch paths share dispatch.

notify::RecommendedWatcher is sync and runs on its own thread; the event handler hands off to tokio via mpsc::blocking_send. Dropping the watcher (function exit) closes the channel and the loop bails, so no orphaned background threads after Ctrl-C.

Foreground only: the watch lifetime is tied to the CLI process. A daemon-side watch (so vup can exit and the watch keeps running) is a natural follow-up.

Validation

cargo build --workspace --locked
cargo test --workspace --lib --tests       # 39 sections, 0 failures

Wires the M3 share deliverable: one URL, one snapshot, no peer
relationship, no future updates.

Daemon side (`s5_node::export::run_export`): generates a fresh
`age::x25519::Identity` per call, loads the local Transparent Node,
re-encrypts the same CBOR for the vault's existing recipients plus
the ephemeral recipient, uploads the new blob to
`vault.blob_stores[0]` and every `vault.meta_targets` entry, and
formats the share URL with the ephemeral secret in the fragment.
The blob is content-addressed by `BLAKE3(age_bytes)`.

RPC surface (`s5_node_api`): `ExportVault { vault, path }` →
`ExportVaultResponse::Ok { url, blob_hash_hex }` /
`Refused { error }`, same tagged-enum shape as the other vault RPCs.
`S5NodeClient::export_vault` flattens to `Result<ExportedShare>`.
The `path` field is reserved for sub-tree export and rejected by the
daemon today (whole-vault only).

CLI (`vup +<vault> export [--path <p>]`): replaces the
`not yet implemented` stub. Prints the URL plus a one-liner
clarifying the capability semantics.

Validation: full workspace clippy, build, and test sweep clean.

Assisted-by: claude-opus-4-7
…to-snap

Wires the M3 `--watch` deliverable. When the user passes `--watch`,
the snap verb takes one initial snapshot, then registers a `notify`
recursive watcher over each path in the vault's source's `paths`
list and re-runs the snap whenever a 2 s burst of filesystem events
quiesces. Continues until Ctrl-C.

Existing `run_snap` is split into `build_backup_spec` (config →
`TaskSpec::Backup`) and `run_backup_once` (spawn + poll) so the
watch loop and the one-shot path share the same dispatch.

`notify::RecommendedWatcher` is sync and runs on its own thread; the
event-handler callback hands off to tokio via `mpsc::blocking_send`.
Dropping the watcher (function exit) closes the channel, which the
loop notices on the next `recv` and bails — no orphaned background
threads after Ctrl-C.

Foreground only for now: the watch lifetime is tied to the CLI
process. Daemon-side watch (so `vup` can exit and the watch keeps
running) is a follow-up.

Adds `notify = "7"` to `vup_cli/Cargo.toml`.

Validation: full workspace clippy, build, and test sweep clean.

Assisted-by: claude-opus-4-7
@redsolver redsolver merged commit f7ebc4a into main Apr 27, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant