M3 share + watch: vup +<vault> export and snap --watch#6
Merged
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
vup +<vault> export [--path <p>]Frozen anonymous share links. The daemon generates a fresh
age::x25519::Identityper call, loads the local Transparent Node, re-encrypts its CBOR for the vault's existing recipients plus the ephemeral one, uploads the new blob tovault.blob_stores[0]and everyvault.meta_targets, and returns a share URL with the ephemeral secret in the fragment. The blob is content-addressed byBLAKE3(age_bytes).Recipient gets one snapshot. No future updates, no individual revocation; the URL is the capability.
--pathis 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
ExportVaultRPC +S5NodeClient::export_vaultflatten toResult<ExportedShare>, matching theRunTask/MountVaultpattern.vup +<vault> snap --watchNotify-driven debounced auto-snap. Takes one initial snapshot, registers a recursive
notifywatcher over each path in the vault source'spaths, and re-runs the snap whenever a 2 s burst of filesystem events quiesces. Continues until Ctrl-C.Existing
run_snapis split intobuild_backup_spec+run_backup_onceso the one-shot and watch paths share dispatch.notify::RecommendedWatcheris sync and runs on its own thread; the event handler hands off to tokio viampsc::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
vupcan exit and the watch keeps running) is a natural follow-up.Validation