ADR-0123: Draft Save-Points — Every Save Restorable, Kept for the Life of the Version¶
- Status: accepted (2026-08-23 — his ask during the live round, refined the same day: "I would not want a key-stroke level history but only the ability to return to a previously saved state", then "Is there a way we can keep them also after release? … If possible I would like to have this in 1.0")
- Date: 2026-08-23
- Deciders: Nicolas Burri
- Relates to: ADR-0001 (content-addressed blobs — what makes retention nearly free), ADR-0057 (tree as record), ADR-0115 (the collab recovery buffer, which stays keystroke-scoped and UNCHANGED), ADR-0025/ADR-0040 (disposal — the deletion this must ride), V094/V095 (dissolution walk), the RLS inventory guard (which will demand this table's classification).
Context¶
Version numbers rightly move only on release; within a draft there is no way back to an earlier saved state, and after release there is no record of how the document came to be. His use case is reconstruction: "If I ever have to reconstruct how a document was created, having access to the intermediate saves would be nice." The collab buffer cannot serve this — it holds only keystrokes since the last save and dies with it, by design.
Decision¶
- Every explicit draft save records a save-point: version id, sequence, actor, instant, and the content reference (tree snapshot / markdown blob — content-addressed, so storage cost is the delta only). No keystroke granularity, ever — save-points are the unit of intent.
- Retention: the life of the DOCUMENT VERSION, including after release — his ruling. They are deleted by disposal (the sweep must include the new table — the schema-extension lifecycle lesson, applied in advance) and reached by dissolution (scope-keyed, FK'd, so the derived walk sees it by construction).
- Restore lands as a NEW save carrying provenance ("restored from the save of …"), audited. History is append-only; nothing rewrites.
- Visibility follows draft access, not VIEW: pre-release states may contain unreviewed content, so the history (before and after release) is readable by those who could have seen the draft — not by every reader of the released record.
- In scope for v1.0 — his explicit wish. New FORCE-RLS content table (the inventory guard will refuse an unclassified one), write on save, list + restore endpoints, an editor history panel; sequenced after the v0.9.18 finding wave, before the tag.
Realization notes (built 2026-08-30)¶
Where the build sharpened silence into semantics: a SAVE is a lock advance through the one choke point (the collab flush never reaches it — capturing there would be keystroke history in a save's clothes); METADATA advances record points (the title is restorable state; content addressing makes them cost zero). POST-RELEASE the history is READ-ONLY — the refusal names "start a new version" as the way forward; new-version-from-point is a deliberate gap awaiting its own ruling. MARKDOWN-era points are readable but non-restorable (ADR-0058 permits no server-side markdown write). A restore lands as an OUTSIDER's save and supersedes any live room through the ADR-0115 path — the CRDT must never admit content it has not seen. The panel lives in the reading view too: history retained past release that only the draft editor could show would be unreachable in the one case it was retained for. (Sharpened 2026-08-31 after his finding: on a DRAFT, the reading-view panel LINKS each restorable point into the editor's history drawer rather than restoring in place — the act stays on the surface that can answer for the buffer reload, the room teardown and the dirty-guard; and the latest point says "current" instead of silently offering nothing.)