Release-Konsolidierung: Migrationen, Snapshot-, Transfer- und Befehlsversionen auf einen einheitlichen Stand bringen #22

Open
opened 2026-09-27 22:17:27 +02:00 by jappel · 1 comment
Owner

Zweck

Während der Entwicklung sind viele Migrationen und Schemaversionen entstanden, jeweils mit Kompatibilitätsschichten für ältere Stände. Sobald die Leistungsbilanz einen Releasestand erreicht, soll alles auf eine neue Baseline zusammengeführt werden. Dabei entfällt der Kompatibilitätscode für Vor-Release-Stände.

Dieses Issue wird bis zum Release fortgeschrieben. Jede neue Migration, jede Snapshot-, Transfer- oder Befehlsversion und jede additive Erweiterung ohne Versionssprung wird hier als Kommentar ergänzt, damit bei der Release-Migration nichts vergessen wird.

Stand der Analyse: main @ b50c00c (27.09.2026). In Arbeit: #3 (Einspeisung) auf feature/issue-3-logical-feeds, voraussichtlich Migration 0012 und Snapshot-Schema 9.

Inventar

SQL-Migrationen (src/db/migrations)

Nr. Inhalt
0000 Release-Baseline vom 31.07.: Kern-Schema (Projekte, Verteilungen, Listen, Gruppen, Stromkreise, Gerätezeilen, Schutz, Komponenten, Projektgeräte, Etagen, Räume, Historie, Snapshots, globale Geräte)
0001 projects.is_public_building
0002 external_csv_configurations
0003 externes Modell: Quellen, Importbatches, Objekte, Raum-Mappings
0004 external_import_batches.configuration_version
0005 circuit_device_rows.manual_quantity + Backfill aus quantity
0006 Indizes Gerätezeilen/Stromkreise
0007 Verteiler-Infofelder, document_branding_assets
0008 Deckblattfelder am Projekt, document_branding_settings
0009 buildings, floors.building_id
0010 Grobbilanz (estimate_balances/_groups/_rows)
0011 rooms.area_m2

0000 war bereits eine Zusammenführung. Ältere Entwicklungsdatenbanken werden seitdem nicht mehr unterstützt, und genau dieses Muster wird hier wiederholt.

Projekt-Snapshot-Schema (project-state-snapshot.model.ts, aktuell 8)

Version ergänzt Hochstufung älterer Stände
1 Baseline isPublicBuilding = false
2 Revit-CSV-Konfiguration externalCsvConfiguration = null
3 externes Modell leerer externer Zustand
4 manualQuantity manualQuantity = quantity
5 Verteiler-Infofelder null
6 Deckblattfelder null
7 Gebäude, floors.buildingId keine Gebäude, null
8 rooms.areaM2 null

Dazu kommt normalizeSnapshotPhaseTypes (leitet phaseType für ältere Stände ab). Die Datei hat 1287 Zeilen, ein großer Teil davon sind Legacy-Zod-Schemas und die Upgrade-Kette.

Transferformat (project-transfer.model.ts)

Version Inhalt
1 Snapshot ohne Grobbilanzen
2 zusätzlich alle Grobbilanzen (aktuell)

Der eingebettete Snapshot bringt seine eigene Schemaversion mit.

Befehlsversionen (gespeichert in der Projekthistorie)

  • Mehrere Versionen mit Hochstufung:
    • project-floor.*: v2 (buildingId), v1 legacy
    • project-room.*: v2 (areaM2), v1 legacy
    • project.update-settings: v3 (Deckblatt), v2 und v1 legacy
    • project.restore-state: v2, v1 (snapshotRestore) legacy
  • Additiv erweitert ohne Versionssprung (versteckte Kompatibilität):
    • distribution-board.update v1: Infofelder optional
    • Verteiler-Subtree-Befehle: normalizeDistributionBoardSubtreeSnapshot ergänzt fehlende Infofelder mit null
    • distribution-board.insert: normalizeDistributionBoardStructureProjectCommand
  • Nur v1: alle übrigen, rund 25 Befehlstypen (Stromkreis, Gerätezeile, Gruppen, Komponenten, Projektgeräte, externe Zuordnung, CSV-Konfiguration, Erstimport, Grobbilanz)

Weitere versionierte Formate

  • CSV-Konfigurations-JSON: externalCsvConfigurationSchemaVersion = 1
  • external_import_batches.configuration_version: monotone Fachversion der Projektkonfiguration. Keine Kompatibilitätsschicht, bleibt bestehen.

Wo versionierte Daten gespeichert sind

  • project_revisions / project_change_sets / project_history_stack_entries: Befehle mit schemaVersion für Undo/Redo
  • project_snapshots: benannte und automatische Snapshots mit schemaVersion
  • external_csv_configurations: JSON mit Schemaversion
  • exportierte Transferdateien außerhalb der App

Was bei einem sauberen Schnitt entfällt

  • Legacy-Schemas und die Upgrade-Kette 1 → 7 im Snapshot-Modell, dazu normalizeSnapshotPhaseTypes
  • Legacy-Befehlstypen, Assertions und upgrade*Command für Etagen, Räume, Projekteinstellungen und Restore v1 (project-location-structure-project-command.model.ts hat allein 803 Zeilen, ein erheblicher Teil ist Legacy)
  • Transferformat 1
  • Normalisierungen für additiv erweiterte Befehle; die Felder werden Pflicht
  • die zugehörigen Legacy-Tests (vor allem project-state-snapshot.test.ts, project-building-structure.test.ts, project-location-structure-project-command.repository.test.ts)
  • die Migrationen 0000–0011, ersetzt durch eine neue Baseline
  • lange Versionshistorien-Absätze in AGENTS.md, current-architecture.md, API-Doku und print-view.md

Grob geschätzt sind das mehrere hundert Zeilen Produktivcode plus Tests und Doku.

Was bleibt: der Versionierungsmechanismus selbst (schemaVersion in Befehlen, Snapshots und Transfer, das Upgrade-Muster). Ab dem Release gilt er wieder streng: Jede Änderung braucht eine neue Migration bzw. Version mit Upgrade-Pfad, angewendete Migrationen werden nie geändert.

Strategie (Vorschlag)

A) Sauberer Schnitt (empfohlen):

  1. Vorher: alle offenen Schemaänderungen abschließen (#3 usw.) und eine Datenbanksicherung anlegen.
  2. Alle Projekte über den portablen Export (aktuelles Transferformat) sichern.
  3. Kompatibilitätscode entfernen, alle Versionen auf 1 zurücksetzen oder als neue Release-Version einfrieren, neue Migration 0000 aus dem aktuellen Schema erzeugen.
  4. Neue, leere Datenbank, Projekte importieren.
  5. Globale Daten, die nicht im Projekttransfer enthalten sind, gesondert übernehmen: globale Gerätebibliothek (global_devices), Büroangaben und Logo (document_branding_*).

B) Daten in-place umschreiben (gespeicherte Befehle und Snapshots auf den neuesten Stand heben): nicht empfohlen, weil aufwendig und fehleranfällig, bei wenig Nutzen vor dem ersten Produktivbetrieb.

Offene Entscheidungen

  1. Was heißt „Release“? Zum Beispiel der Beginn des Produktivbetriebs mit echten Projekten. Danach gibt es keine Schnitte mehr.
  2. Historie: Bei A beginnen Undo/Redo, Revisionen und Snapshots je Projekt neu. Ist das akzeptabel?
  3. Import beim Umzug: Der heutige Import als neues Projekt vergibt neue IDs. Reicht das (BMKs, IfcGUIDs und Werte bleiben erhalten), oder braucht es einen ID-erhaltenden Release-Import?
  4. Versionsnummern: nach dem Schnitt alle auf 1 zurücksetzen oder die aktuellen Nummern einfrieren? Ein Zurücksetzen macht alte Exportdateien eindeutig inkompatibel, was gewollt sein kann.
  5. Grobbilanz in Snapshots: Sie ist heute bewusst nicht in logischen Snapshots enthalten (#7). Soll das beim Schnitt vereinheitlicht werden?
  6. Globale Daten: Braucht es einen eigenen Export/Import für globale Geräte und Büro-Branding, oder reicht Handarbeit?

Checkliste Release-Migration (fortschreiben)

  • alle offenen Schemaänderungen gemergt; Inventar oben aktuell
  • Datenbanksicherung und Export aller Projekte
  • Entscheidungen 1–6 getroffen
  • Kompatibilitätscode und Legacy-Tests entfernt; additive optionale Felder zu Pflichtfeldern gemacht
  • neue Baseline-Migration erzeugt und geprüft (Schemavergleich alt/neu identisch)
  • Import aller Projekte und globalen Daten verifiziert (Summen, BMKs, externe Objekte, Grobbilanzen)
  • Doku und AGENTS.md auf den Release-Stand gekürzt; Regel „angewendete Migrationen nie ändern“ gilt ab jetzt
  • Docker-/Produktionsstart gegen die neue Baseline getestet

Fortschreibung

Bitte bei jeder neuen Migration und jeder neuen Snapshot-, Transfer- oder Befehlsversion bis zum Release einen Kommentar ergänzen: Was kam hinzu, wo liegt die Hochstufung, was entfällt beim Schnitt?

## Zweck Während der Entwicklung sind viele Migrationen und Schemaversionen entstanden, jeweils mit Kompatibilitätsschichten für ältere Stände. Sobald die Leistungsbilanz einen Releasestand erreicht, soll alles auf **eine neue Baseline** zusammengeführt werden. Dabei entfällt der Kompatibilitätscode für Vor-Release-Stände. **Dieses Issue wird bis zum Release fortgeschrieben.** Jede neue Migration, jede Snapshot-, Transfer- oder Befehlsversion und jede additive Erweiterung ohne Versionssprung wird hier als Kommentar ergänzt, damit bei der Release-Migration nichts vergessen wird. Stand der Analyse: `main` @ `b50c00c` (27.09.2026). In Arbeit: #3 (Einspeisung) auf `feature/issue-3-logical-feeds`, voraussichtlich Migration `0012` und Snapshot-Schema 9. ## Inventar ### SQL-Migrationen (`src/db/migrations`) | Nr. | Inhalt | |---|---| | 0000 | Release-Baseline vom 31.07.: Kern-Schema (Projekte, Verteilungen, Listen, Gruppen, Stromkreise, Gerätezeilen, Schutz, Komponenten, Projektgeräte, Etagen, Räume, Historie, Snapshots, globale Geräte) | | 0001 | `projects.is_public_building` | | 0002 | `external_csv_configurations` | | 0003 | externes Modell: Quellen, Importbatches, Objekte, Raum-Mappings | | 0004 | `external_import_batches.configuration_version` | | 0005 | `circuit_device_rows.manual_quantity` + Backfill aus `quantity` | | 0006 | Indizes Gerätezeilen/Stromkreise | | 0007 | Verteiler-Infofelder, `document_branding_assets` | | 0008 | Deckblattfelder am Projekt, `document_branding_settings` | | 0009 | `buildings`, `floors.building_id` | | 0010 | Grobbilanz (`estimate_balances/_groups/_rows`) | | 0011 | `rooms.area_m2` | `0000` war bereits eine Zusammenführung. Ältere Entwicklungsdatenbanken werden seitdem nicht mehr unterstützt, und genau dieses Muster wird hier wiederholt. ### Projekt-Snapshot-Schema (`project-state-snapshot.model.ts`, aktuell 8) | Version | ergänzt | Hochstufung älterer Stände | |---|---|---| | 1 | Baseline | `isPublicBuilding = false` | | 2 | Revit-CSV-Konfiguration | `externalCsvConfiguration = null` | | 3 | externes Modell | leerer externer Zustand | | 4 | `manualQuantity` | `manualQuantity = quantity` | | 5 | Verteiler-Infofelder | `null` | | 6 | Deckblattfelder | `null` | | 7 | Gebäude, `floors.buildingId` | keine Gebäude, `null` | | 8 | `rooms.areaM2` | `null` | Dazu kommt `normalizeSnapshotPhaseTypes` (leitet `phaseType` für ältere Stände ab). Die Datei hat 1287 Zeilen, ein großer Teil davon sind Legacy-Zod-Schemas und die Upgrade-Kette. ### Transferformat (`project-transfer.model.ts`) | Version | Inhalt | |---|---| | 1 | Snapshot ohne Grobbilanzen | | 2 | zusätzlich alle Grobbilanzen (aktuell) | Der eingebettete Snapshot bringt seine eigene Schemaversion mit. ### Befehlsversionen (gespeichert in der Projekthistorie) - **Mehrere Versionen mit Hochstufung:** - `project-floor.*`: v2 (`buildingId`), v1 legacy - `project-room.*`: v2 (`areaM2`), v1 legacy - `project.update-settings`: v3 (Deckblatt), v2 und v1 legacy - `project.restore-state`: v2, v1 (`snapshotRestore`) legacy - **Additiv erweitert ohne Versionssprung (versteckte Kompatibilität):** - `distribution-board.update` v1: Infofelder optional - Verteiler-Subtree-Befehle: `normalizeDistributionBoardSubtreeSnapshot` ergänzt fehlende Infofelder mit `null` - `distribution-board.insert`: `normalizeDistributionBoardStructureProjectCommand` - **Nur v1:** alle übrigen, rund 25 Befehlstypen (Stromkreis, Gerätezeile, Gruppen, Komponenten, Projektgeräte, externe Zuordnung, CSV-Konfiguration, Erstimport, Grobbilanz) ### Weitere versionierte Formate - CSV-Konfigurations-JSON: `externalCsvConfigurationSchemaVersion = 1` - `external_import_batches.configuration_version`: monotone Fachversion der Projektkonfiguration. **Keine** Kompatibilitätsschicht, bleibt bestehen. ### Wo versionierte Daten gespeichert sind - `project_revisions` / `project_change_sets` / `project_history_stack_entries`: Befehle mit `schemaVersion` für Undo/Redo - `project_snapshots`: benannte und automatische Snapshots mit `schemaVersion` - `external_csv_configurations`: JSON mit Schemaversion - exportierte Transferdateien außerhalb der App ## Was bei einem sauberen Schnitt entfällt - Legacy-Schemas und die Upgrade-Kette 1 → 7 im Snapshot-Modell, dazu `normalizeSnapshotPhaseTypes` - Legacy-Befehlstypen, Assertions und `upgrade*Command` für Etagen, Räume, Projekteinstellungen und Restore v1 (`project-location-structure-project-command.model.ts` hat allein 803 Zeilen, ein erheblicher Teil ist Legacy) - Transferformat 1 - Normalisierungen für additiv erweiterte Befehle; die Felder werden Pflicht - die zugehörigen Legacy-Tests (vor allem `project-state-snapshot.test.ts`, `project-building-structure.test.ts`, `project-location-structure-project-command.repository.test.ts`) - die Migrationen 0000–0011, ersetzt durch eine neue Baseline - lange Versionshistorien-Absätze in AGENTS.md, current-architecture.md, API-Doku und print-view.md Grob geschätzt sind das mehrere hundert Zeilen Produktivcode plus Tests und Doku. **Was bleibt:** der Versionierungsmechanismus selbst (`schemaVersion` in Befehlen, Snapshots und Transfer, das Upgrade-Muster). Ab dem Release gilt er wieder streng: Jede Änderung braucht eine neue Migration bzw. Version mit Upgrade-Pfad, angewendete Migrationen werden nie geändert. ## Strategie (Vorschlag) **A) Sauberer Schnitt (empfohlen):** 1. Vorher: alle offenen Schemaänderungen abschließen (#3 usw.) und eine Datenbanksicherung anlegen. 2. Alle Projekte über den portablen Export (aktuelles Transferformat) sichern. 3. Kompatibilitätscode entfernen, alle Versionen auf 1 zurücksetzen oder als neue Release-Version einfrieren, neue Migration `0000` aus dem aktuellen Schema erzeugen. 4. Neue, leere Datenbank, Projekte importieren. 5. Globale Daten, die **nicht** im Projekttransfer enthalten sind, gesondert übernehmen: globale Gerätebibliothek (`global_devices`), Büroangaben und Logo (`document_branding_*`). **B) Daten in-place umschreiben** (gespeicherte Befehle und Snapshots auf den neuesten Stand heben): nicht empfohlen, weil aufwendig und fehleranfällig, bei wenig Nutzen vor dem ersten Produktivbetrieb. ## Offene Entscheidungen 1. **Was heißt „Release“?** Zum Beispiel der Beginn des Produktivbetriebs mit echten Projekten. Danach gibt es keine Schnitte mehr. 2. **Historie:** Bei A beginnen Undo/Redo, Revisionen und Snapshots je Projekt neu. Ist das akzeptabel? 3. **Import beim Umzug:** Der heutige Import als neues Projekt vergibt neue IDs. Reicht das (BMKs, IfcGUIDs und Werte bleiben erhalten), oder braucht es einen ID-erhaltenden Release-Import? 4. **Versionsnummern:** nach dem Schnitt alle auf 1 zurücksetzen oder die aktuellen Nummern einfrieren? Ein Zurücksetzen macht alte Exportdateien eindeutig inkompatibel, was gewollt sein kann. 5. **Grobbilanz in Snapshots:** Sie ist heute bewusst nicht in logischen Snapshots enthalten (#7). Soll das beim Schnitt vereinheitlicht werden? 6. **Globale Daten:** Braucht es einen eigenen Export/Import für globale Geräte und Büro-Branding, oder reicht Handarbeit? ## Checkliste Release-Migration (fortschreiben) - [ ] alle offenen Schemaänderungen gemergt; Inventar oben aktuell - [ ] Datenbanksicherung und Export aller Projekte - [ ] Entscheidungen 1–6 getroffen - [ ] Kompatibilitätscode und Legacy-Tests entfernt; additive optionale Felder zu Pflichtfeldern gemacht - [ ] neue Baseline-Migration erzeugt und geprüft (Schemavergleich alt/neu identisch) - [ ] Import aller Projekte und globalen Daten verifiziert (Summen, BMKs, externe Objekte, Grobbilanzen) - [ ] Doku und AGENTS.md auf den Release-Stand gekürzt; Regel „angewendete Migrationen nie ändern“ gilt ab jetzt - [ ] Docker-/Produktionsstart gegen die neue Baseline getestet ## Fortschreibung Bitte bei jeder neuen Migration und jeder neuen Snapshot-, Transfer- oder Befehlsversion bis zum Release einen Kommentar ergänzen: Was kam hinzu, wo liegt die Hochstufung, was entfällt beim Schnitt?
Author
Owner

Fortschreibung nach PR #25 / Merge-Commit 68d986f:

  • Neue additive Migration 0013_users: globale Tabelle users mit Anmeldename, scrypt-Passwort-Hash, Anzeigename, fester Rolle (admin/user), Aktivstatus, erzwungenem Passwortwechsel und Zeitstempeln; eindeutiger Index auf dem normalisierten Anmeldenamen.
  • Keine neue Projekt-Snapshot-, Transfer- oder Befehlsversion: Benutzer und Sessions sind globale Betriebsdaten außerhalb der Projekte. Sessions liegen nur im Speicher und werden nicht migriert.
  • Beim späteren Release-Schnitt muss users in die neue Baseline aufgenommen werden. Benutzerkonten sind zusätzlich zu globaler Gerätebibliothek und Büro-Branding als globale Daten zu entscheiden. Empfohlen ist, Konten über den Bootstrap-Admin und die Benutzerverwaltung neu anzulegen, statt Passwort-Hashes über den Projekttransfer zu bewegen.
  • Die Release-Dokumentation muss die Auth-Umgebungsvariablen und COOKIE_SECURE für HTTP/HTTPS erhalten.
Fortschreibung nach PR #25 / Merge-Commit `68d986f`: - Neue additive Migration `0013_users`: globale Tabelle `users` mit Anmeldename, scrypt-Passwort-Hash, Anzeigename, fester Rolle (`admin`/`user`), Aktivstatus, erzwungenem Passwortwechsel und Zeitstempeln; eindeutiger Index auf dem normalisierten Anmeldenamen. - Keine neue Projekt-Snapshot-, Transfer- oder Befehlsversion: Benutzer und Sessions sind globale Betriebsdaten außerhalb der Projekte. Sessions liegen nur im Speicher und werden nicht migriert. - Beim späteren Release-Schnitt muss `users` in die neue Baseline aufgenommen werden. Benutzerkonten sind zusätzlich zu globaler Gerätebibliothek und Büro-Branding als globale Daten zu entscheiden. Empfohlen ist, Konten über den Bootstrap-Admin und die Benutzerverwaltung neu anzulegen, statt Passwort-Hashes über den Projekttransfer zu bewegen. - Die Release-Dokumentation muss die Auth-Umgebungsvariablen und `COOKIE_SECURE` für HTTP/HTTPS erhalten.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: jappel/leistungsbilanz-ts#22
No description provided.