feat(backend): Historie in zwei Ebenen, gezielter Repository-Zugriff (Schritt 2)

Meilensteine sind die nutzersichtbare Historie und bleiben; Sync-Versionen
tragen die Diffs des Live-Editings und werden nach der Aufbewahrungsfrist
verdichtet (D76). Ohne die Trennung wuerde die Historie beim getakteten
Schreiben zum Transaktionslog.

Die Schreibpause braucht keinen Zeitgeber: Die naechste Aenderung stellt
fest, dass eine Pause war, und befoerdert die Version davor nachtraeglich.
Strukturelle Aenderungen sind immer Meilensteine.

Das Historie-Repository greift jetzt gezielt zu (eine Version, juengster,
aeltester, Meilensteine, maxVersion) statt stets alle Eintraege zu laden und
in Kotlin zu filtern — bei hunderten Volltext-Versionen je Dokument war das
untragbar. Restore liest den letzten Stand aus dem Tombstone: der ueberlebt
das Verdichten, die Version davor womoeglich nicht.

Dabei die D76-Unschaerfe aufgeloest: RESTORED heisst nur noch "ein
geloeschtes Dokument ist wieder da" (der Client hebt seine Sperre auf), der
Rueckfall eines lebenden Dokuments ist ROLLED_BACK.

81 Tests. Gegenprobe: Schreibpause ignoriert -> genau die danach benannte
Zusicherung faellt; Rueckfall wieder als RESTORED -> Unit- und
Cucumber-Test dazu; juengster Stand aus der Historie genommen -> genau einer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-26 16:51:46 +02:00
co-authored by Claude Opus 5
parent 0f3bd8f5b8
commit d5cdff6058
16 changed files with 530 additions and 94 deletions
+14 -4
View File
@@ -127,11 +127,13 @@ paths:
operationId: getDocumentHistory
summary: Historie eines Dokuments abrufen
description: >
Liefert alle Versionen eines Dokuments in chronologischer Reihenfolge.
Die Historie bleibt auch nach dem Loeschen des Dokuments erhalten.
Liefert die nutzersichtbaren Staende (Meilensteine) in chronologischer
Reihenfolge, dazu immer den juengsten Stand. Kurzlebige Sync-Versionen
des Live-Editings bleiben aussen vor. Die Historie ueberlebt das
Loeschen des Dokuments.
responses:
"200":
description: Historie des Dokuments (aelteste zuerst)
description: Meilensteine des Dokuments (aelteste zuerst)
content:
application/json:
schema:
@@ -253,6 +255,10 @@ components:
description: Optional; wird spaeter fuer Optimistic Locking ausgewertet.
DocumentHistoryEntry:
description: >
Ein Stand der nutzersichtbaren Historie. Sync-Versionen des
Live-Editings erscheinen hier nicht - sie tragen das Protokoll, nicht
die Erzaehlung.
type: object
required: [documentId, version, title, content, changeType, timestamp]
properties:
@@ -268,7 +274,11 @@ components:
type: string
changeType:
type: string
enum: [CREATED, UPDATED, DELETED, RESTORED]
description: >
RESTORED heisst: ein geloeschtes Dokument ist wieder da.
ROLLED_BACK ist der Rueckfall eines lebenden Dokuments auf eine
aeltere Version.
enum: [CREATED, UPDATED, DELETED, RESTORED, ROLLED_BACK]
timestamp:
type: string
format: date-time