File versioning: design ADR, per-driver version storage, restore/download UI (#530, 4/4) #541
Labels
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Cordy/Cairn#541
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fourth and heaviest slice of #530. Per-file version history with Restore and Download per version, as in the OpenCloud reference.
ADR first — this is a design problem before it is a feature. The design must answer:
Then: backend TDD (version list/read/restore APIs), and the Versions panel in #538's details pane (list with per-entry Restore/Download). Restore writes an activity event (#539).
ADR drafted: PR #611 (
VERSIONING.mdon branchadr-541, deliberately unmerged). Core proposal: a version is an immutable byte-copy of the previous ciphertext, minted on overwrite — no renames (Garage-safe), no metadata index (the storage listing IS the version list, nothing to corrupt), keyscan/keydrain extended so rotation never strands old versions, versions bill quota, holds freeze the chain while restore stays allowed (restore mints first, so it only ever adds), mint-time GC (10 versions / 90 days defaults), WOPI coalescing (10 min) so office autosave can't mint hundreds. Four open questions at the bottom of the doc need your answers before the build.ADR accepted and merged (PR #611 →
VERSIONING.md). All four questions resolved at review: defaults confirmed (10 / 90 days / 10-min coalescing); recipient surface hidden in v1; quota rewritten to the Nextcloud-style model per Nikola — versions invisible to the user-visible quota, retention settings as the true billing lever, admin sees real usage, 50%-of-free-space valve documented as the v2 tightening; same-content overwrites mint nothing. The issue stays open for the build (backend TDD + Versions panel in #538's shell), which follows the #538/#539/#540 work.Shipped in v0.6.223 (PR #622, tag on
8bf73b3), live on both dogfoods. VERSIONING.md gained an "Implementation notes (v1)" section recording the two mechanism deviations.What landed, against the ADR sections:
internal/storage/versions— mint-on-overwrite byte-copies of the previous raw object (ciphertext) under<dir>/.cairn-versions/<basename>/<rfc3339>_<seq>_<author>.v. Mint happens before the write, so a crash leaves an extra version, never a lost file. Author rides the key (deviation #2 — §1 forbids an index and §9's listing + §7's coalescing both need an author).reserved— reserved sits below encrypt, where version blobs must stay reachable so downloads decrypt with the file's own path-scoped identity (the version dir shares the file's prefix). Same behavior: never listed, direct access = not-found, uploads refused; internal ctx marker for the API.baseStore(raw) already — version blobs are covered by rotation with zero changes. Custody outage: unreadable, never deleted (nothing version-specific to do).Heldhook from the holds store freezes prune/coalesce/unmint/chain-drop.versionsMaxPerFile,versionsMaxAgeDayswith -1 = forever,versionsCoalesceMinutes), read live, enforced at mint; age cap lazy at list + permanent at next mint. No background sweeper.inner.Delete) drops it under the existing hold/retention checks./sharedrefused; restore mints current first, emitsversion-restoreaudit (registered) + activity event. Versions panel in the pane: time · author · size, Download + Restore per row, restore hidden on read-only items.v1 edges to know while dogfooding:
/home/<you>/. Space restores are a follow-up.Eyeball: overwrite a file twice (upload the same name, or edit in Collabora), then Details → Versions — restore the older one and watch it mint the undo version first.