Add automatic project snapshots

This commit is contained in:
2026-07-25 23:27:51 +02:00
parent 59d442593f
commit 1a77eedaa8
23 changed files with 2232 additions and 26 deletions
+5 -1
View File
@@ -33,7 +33,8 @@ this value for optimistic concurrency checks.
- executes the eligible inverse or forward command as a new auditable
revision
- `GET /projects/:projectId/snapshots`
- lists named logical snapshot metadata without returning payload JSON
- lists named and automatic logical snapshot metadata, including `kind`,
without returning payload JSON
- `POST /projects/:projectId/snapshots`
- body:
`{ "expectedRevision": 12, "name": "Vor Ausschreibung", "description": "Optional" }`
@@ -44,6 +45,9 @@ this value for optimistic concurrency checks.
- snapshot creation does not increment the project revision or alter
undo/redo stacks
- duplicate names and stale revisions return `409`
- the central revision boundary additionally creates `automatic` snapshots
after 25 further revisions and retains the newest 12 per project; named
snapshots are never removed by this policy
- `POST /projects/:projectId/snapshots/:snapshotId/restore`
- body: `{ "expectedRevision": 13 }`
- verifies the stored payload checksum and atomically restores the complete
@@ -6,9 +6,9 @@
eligibility is restored from server history after a page reload.
- The project page exposes the paginated revision timeline; the circuit editor
itself currently exposes only the next eligible Undo/Redo actions.
- Named logical project snapshots can be created, listed and restored through
the project page with persistent Undo/Redo. Automatic periodic snapshots are
not implemented yet.
- Named and automatic logical project snapshots can be listed and restored
through the project page with persistent Undo/Redo. Automatic snapshots are
created every 25 revisions and only their newest 12 entries are retained.
- No Revit/CSV/IFCGUID import and export workflow is implemented yet.
- Persistence currently targets local SQLite; PostgreSQL is an architectural option, not an implemented runtime.
- The global device library supports basic CRUD and copy operations, but has no
+18 -13
View File
@@ -69,24 +69,24 @@ besitzt einen projektbezogenen Revisionszähler sowie getrennte Revision-/Change
Tabellen. Ein getestetes Repository kann diese Historienmetadaten optimistisch
und atomar fortschreiben. Vorwärts- und Rückwärtskommandos besitzen einen
versionierten, JSON-sicheren Umschlag; Typ und Payload können dadurch nach
einem Neustart verlustfrei rekonstruiert werden. Konkrete Fachkommandos und
bestehende Fachoperationen sind aber noch nicht allgemein an diese Grenze
angeschlossen. Für Circuit- und Gerätezeilen-Feldänderungen existieren interne
Command-Stores, die Fachänderung, automatisch erzeugtes inverses Kommando und
Revision gemeinsam committen beziehungsweise zurückrollen können.
einem Neustart verlustfrei rekonstruiert werden. Alle aktuell unterstützten
Circuit-, Gerätezeilen-, Projektgeräte- und Projekteinstellungsänderungen
verwenden typisierte Command-Stores, die Fachänderung, automatisch erzeugtes
inverses Kommando, Revision und Historienstapel gemeinsam committen
beziehungsweise zurückrollen.
Gerätezeilen-Kommandos bewahren dabei auch lokale ProjectDevice-Overrides und
prüfen Projektzugehörigkeit von Verknüpfungen und Räumen. Projektweite,
persistente Undo-/Redo-Stacks verwalten die zulässige LIFO-Reihenfolge und
verwerfen den Redo-Zweig bei einem neuen Benutzerkommando. Ihr Status ist über
`GET /api/projects/:projectId/history` lesbar. Die unveränderliche,
absteigend paginierte Revisions-Timeline ist ohne Befehls-Payloads über
`GET /api/projects/:projectId/history/revisions` lesbar. Ein zentraler Dispatcher führt
die unterstützten Typen `circuit.update` und `circuit-device-row.update` über
öffentliche Command-, Undo- und Redo-Endpunkte aus. Zusätzlich sind
`circuit-device-row.insert` und `circuit-device-row.delete` als atomare
Strukturkommandos vorhanden. Beim Löschen wird die vollständige Zeile im
inversen Kommando gesichert, sodass Undo dieselbe UUID und alle Fachwerte
wiederherstellt. `circuit.insert` und `circuit.delete` behandeln einen
`GET /api/projects/:projectId/history/revisions` lesbar. Ein zentraler
Dispatcher führt die nachfolgend beschriebenen typisierten Kommandos über
öffentliche Command-, Undo- und Redo-Endpunkte aus.
`circuit-device-row.insert` und `circuit-device-row.delete` sind atomare
Strukturkommandos. Beim Löschen wird die vollständige Zeile im inversen
Kommando gesichert, sodass Undo dieselbe UUID und alle Fachwerte wiederherstellt.
`circuit.insert` und `circuit.delete` behandeln einen
Stromkreis mit null, einer oder mehreren Gerätezeilen als vollständigen Block.
Undo bewahrt dabei sämtliche Circuit-/Row-UUIDs und ändert keine
Betriebsmittelkennzeichen. Bestehende Circuit- und Gerätezeilen-Zelländerungen
@@ -109,6 +109,12 @@ Projekteinstellungen, Verteiler, Stromkreislisten, Bereiche, Stromkreise und
Gerätezeilen sowie Projektgeräte, Geschosse und Räume. Globale Geräte,
Legacy-Consumer und Migrationsberichte sind nicht Teil des Projekt-Snapshots.
Create/List verändern weder Projektrevision noch Undo-/Redo-Stapel.
`kind` unterscheidet benannte und automatische Stände. Die zentrale
Revisionspersistenz erzeugt nach jeweils 25 weiteren Projektänderungen
transaktional einen automatischen Stand. Pro Projekt bleiben die neuesten 12
automatischen Stände erhalten; ältere automatische Stände werden in derselben
Transaktion entfernt. Benannte Stände und die unveränderliche Revisionshistorie
sind von dieser Aufbewahrung ausdrücklich ausgeschlossen.
`POST /api/projects/:projectId/snapshots/:snapshotId/restore` prüft Payload,
Prüfsumme, erwartete Revision und den unmittelbar zuvor gelesenen
Projektzustand. Der Restore ersetzt alle unterstützten Projektdaten in einer
@@ -216,7 +222,6 @@ bei einem späteren Wechsel trotzdem einen eigenen PostgreSQL-Adapter.
## Noch nicht unterstützt
- automatische periodische Projekt-Snapshots und Aufbewahrungsrichtlinie
- Mehrbenutzerbetrieb und Konfliktauflösung
- Revit-/CSV-/IFCGUID-Round-trip
- vollständige elektrische Dimensionierung
@@ -101,6 +101,17 @@ Implemented named-snapshot foundation:
explicit inline restore confirmation and cursor-based loading of older
revisions; a successful restore reloads all project read models
Implemented automatic-snapshot policy:
- `project_snapshots.kind` distinguishes `named` from `automatic`
- the central revision boundary captures the complete post-command state after
every 25 additional project revisions
- the newest 12 automatic snapshots per project are retained
- retention never removes named snapshots, immutable revisions or physical
database backups
- automatic capture and retention run inside the same transaction as the
triggering project revision
## Revit / CSV / IFCGUID Round-Trip Direction
External model exchange should use explicit staging and link entities instead of writing imported rows directly into circuits.
@@ -258,7 +269,6 @@ Completed foundation:
Remaining constraints before completing project version history:
- define and implement a periodic snapshot and retention policy
- extend project-scoped commands only when further project mutations are
deliberately added to history; the generic versioned envelope is complete
- do not model IFCGUID as an overloaded circuit equipment identifier
@@ -266,7 +276,6 @@ Remaining constraints before completing project version history:
## Deferred Decisions
- exact snapshot frequency and retention policy
- whether large snapshot payloads remain in PostgreSQL or move to object storage
- branch visualization after undo followed by new edits
- user/role model and actor attribution
+4 -1
View File
@@ -368,7 +368,7 @@ Tasks:
command payloads
- [x] add explicitly named logical project snapshots with schema-versioned
payloads and integrity checksums
- add periodic logical project snapshots
- [x] add periodic logical project snapshots with a bounded retention policy
- [x] restore a historical snapshot as a new auditable revision with
persistent undo/redo
- [x] expose named snapshots, confirmed restore and the paginated revision
@@ -401,6 +401,9 @@ Implemented foundation:
- named snapshot Create/List endpoints persist complete project-scoped runtime
state with the source revision and SHA-256 without changing revision or
undo/redo stacks
- the central revision boundary captures an `automatic` snapshot after every
25 new revisions and retains the newest 12 automatic snapshots per project
without deleting named snapshots or immutable revisions
- the project page lists, creates and explicitly restores named snapshots and
displays paginated revision metadata without exposing command payloads
- the version-card header reads persisted undo/redo eligibility and executes