feat(vorlagen): Versionierung, Unveraenderlichkeit und JSON-Austausch (#23)
This commit was merged in pull request #23.
This commit is contained in:
+72
-4
@@ -11,11 +11,12 @@ als Unterpunkte mit Aufgabe und Dauer.
|
||||
| #006 | M1 – Datenmodell | 1 h 10 min |
|
||||
| #007 | M2 – Auth, Rollen, Benutzer | 1 h 35 min |
|
||||
| #008 | M3 – Betriebsmodus und Kunden | 1 h 20 min |
|
||||
| | **Summe** | **5 h 30 min** |
|
||||
| #009 | M4 – Vorlagen-Versionierung im Service | 1 h 20 min |
|
||||
| | **Summe** | **6 h 50 min** |
|
||||
|
||||
| Meilenstein | Tatsächlich | Status |
|
||||
|---|---|---|
|
||||
| v0.1.0 | 5 h 30 min | in Arbeit |
|
||||
| v0.1.0 | 6 h 50 min | in Arbeit |
|
||||
|
||||
---
|
||||
|
||||
@@ -43,7 +44,7 @@ als Unterpunkte mit Aufgabe und Dauer.
|
||||
- **Deutsch im Code, auch für Bezeichner.** Der Auftragstext verlangte Englisch; Florian hat sich
|
||||
für Einheitlichkeit mit ProxLedger entschieden. Verbindliche Namensabbildung in `CLAUDE.md`.
|
||||
- **Kein Auth.js.** v5 steht seit Jahren auf Beta (`5.0.0-beta.32`), authjs.dev führt das Projekt
|
||||
im Wartungsmodus („now part of Better Auth"), die Maintainer nennen „no immediate plans for v5",
|
||||
im Wartungsmodus („now part of Better Auth“), die Maintainer nennen „no immediate plans for v5“,
|
||||
und `@auth/prisma-adapter` deklariert Prisma nur bis 6 — wir fahren Prisma 7. Stattdessen
|
||||
`openid-client` + `jose` wie in ProxLedger. Dieselbe Überlegung wie dort, nur ein Jahr später
|
||||
noch deutlicher.
|
||||
@@ -246,7 +247,7 @@ als Unterpunkte mit Aufgabe und Dauer.
|
||||
- **Die Sichtbarkeit gehört in `kundeErmitteln`,** nicht in eine zweite Funktion daneben. Sonst
|
||||
müsste jeder künftige Service daran denken — und #009 ff. übernehmen diese Signatur.
|
||||
- **Lesemodelle filtern selbst.** Sie verlangen den Benutzer, statt sich auf den Aufrufer zu
|
||||
verlassen. `undefined` heißt „keine Einschränkung", `[]` heißt „sieht nichts"; die Umsetzung
|
||||
verlassen. `undefined` heißt „keine Einschränkung“, `[]` heißt „sieht nichts“; die Umsetzung
|
||||
steht an einer Stelle, und beide Fälle haben einen Test.
|
||||
- **`pg_advisory_xact_lock` statt Serializable.** Der Wechsel ist selten und kurz; ein Schloss auf
|
||||
Transaktionsebene ist verständlicher als eine Isolationsstufe, die man beim Lesen übersieht, und
|
||||
@@ -271,3 +272,70 @@ als Unterpunkte mit Aufgabe und Dauer.
|
||||
|
||||
- #009 Vorlagen-Versionierung: Veröffentlichen, tiefe Kopie als Entwurf, höchstens ein Entwurf,
|
||||
Unveränderlichkeit, JSON-Export und -Import.
|
||||
|
||||
---
|
||||
|
||||
## 2026-09-25 · Sitzung 5 · 07:00–08:20
|
||||
|
||||
**Issue:** #009 (M4)
|
||||
**Version:** 0.1.0
|
||||
|
||||
### Erledigt
|
||||
|
||||
- `src/server/services/vorlagen.ts`: Anlegen, Kopfdaten bearbeiten, Entwurf holen (tiefe Kopie),
|
||||
Speichern, Veröffentlichen, Verwerfen, Duplizieren, Archivieren
|
||||
- `src/server/services/vorlagen-austausch.ts` mit `docs/vorlagen-format.md`: ein Zod-Schema für
|
||||
Editor, Export und Import — eine Vorlage zieht als Datei zwischen zwei Installationen um
|
||||
- `src/lib/validierung.ts` als einzige Quelle für Zod samt deutscher Meldungen, mit ESLint-Regel
|
||||
- Migration `vorlagen_unveraenderlich`: vier Trigger, die die Unveränderlichkeit in der Datenbank
|
||||
durchsetzen — nicht nur im Service
|
||||
- Unabhängiger Review: drei Blocker (alle an der Mandantengrenze), acht weitere Befunde, alle
|
||||
abgearbeitet
|
||||
- **428 Tests** grün (vorher 336), davon neu: Mandantensicht, Datenbankregeln, Gleichzeitigkeit,
|
||||
Austausch mit unsauberen Daten
|
||||
|
||||
### Entscheidungen
|
||||
|
||||
- **Die Regel steht zweimal: im Service und in der Datenbank.** Der Service gibt die verständliche
|
||||
Meldung, die Datenbank die Garantie. Alles, was nicht durch den Service geht — Migrationen,
|
||||
`psql`, der Seed, ab Phase 4 die Connectoren —, läuft sonst an der einen Regel vorbei, die das
|
||||
Archiv überhaupt erst etwas wert macht. Die doppelte Haltung kostet einen Trigger und spart die
|
||||
Annahme, dass jeder künftige Schreibweg daran denkt.
|
||||
- **Ein Entwurf je Vorlage kommt vom partiellen Index**, nicht von einer Prüfung davor. Zwei
|
||||
gleichzeitige Klicks auf „Bearbeiten“ laufen damit unvermeidlich in `P2002` — und genau dort
|
||||
wiederholt der Service und gibt beiden denselben Entwurf zurück, statt einen Fehler zu zeigen,
|
||||
den niemand versteht.
|
||||
- **Optimistisches Sperren über `geaendertAm`,** nicht über eine Zählerspalte. Der Zeitstempel ist
|
||||
ohnehin da, und `updateMany` mit Bedingung erledigt den Vergleich in derselben Anweisung.
|
||||
- **Unbekannte `konfig`-Schlüssel überleben, unbekannte Werte bekannter Schlüssel nicht.** Ein
|
||||
neues Feld aus einer späteren Fassung darf einen Umzug nicht verhindern; eine unbekannte `shell`
|
||||
aber entscheidet darüber, wie ein Wert maskiert wird — sie stillschweigend zu verwerfen hieße,
|
||||
einen bash-Befehl nach PowerShell-Regeln zu maskieren, und das kann auf einem Server Daten
|
||||
kosten. Also laut abweisen, mit Pfad und erlaubten Werten.
|
||||
- **Der Export ist nachsichtig, der Import streng.** Herausgeben muss man auch, was nicht ins
|
||||
Schema passt, sonst verliert die Datei Inhalt. Annehmen darf man es nicht.
|
||||
- **`tests/datenbankregeln.test.ts` als Wächter.** Prisma erzeugt für jede künftige Migration
|
||||
Löschbefehle gegen die handgeschriebenen Objekte. Der Test zählt sie namentlich auf, damit ein
|
||||
übersehener `DROP` die Suite rot macht statt still die Mandantengrenze zu entfernen.
|
||||
|
||||
### Probleme
|
||||
|
||||
- **Die drei Blocker lagen alle an derselben Stelle: den Lesemodellen.** Der Suchfilter brachte
|
||||
einen zweiten `OR`-Schlüssel mit und überschrieb die Kundenbedingung — ein Buchstabe im Suchfeld
|
||||
genügte, um einem gebundenen Techniker alle Vorlagen aller Kunden zu zeigen. Historie und Aufbau
|
||||
einer Version filterten gar nicht. Zu `queries/vorlagen.ts` gab es keinen Test; die Sicht in #008
|
||||
abzusichern und in #009 nur den Service zu testen war der Fehler.
|
||||
- **`Prisma.validator`-Objekte mit zwei gleichen Schlüsseln sind kein Typfehler.** Ein
|
||||
zusammengebautes `where` mit `OR` aus zwei Quellen fällt weder ESLint noch `tsc` auf. Deshalb
|
||||
liegt die Mandantenbedingung jetzt in `AND`, wo ein zweiter Filter sie nicht erreichen kann.
|
||||
- **Prisma wollte sieben handgeschriebene Objekte löschen.** Die Migration musste von Hand
|
||||
geschrieben werden; zusätzlich fehlten `@default(now())` bei den `@updatedAt`-Feldern, weshalb
|
||||
Prisma bei jedem Lauf `DROP DEFAULT` vorschlug.
|
||||
- **Zwei gleichzeitige Testläufe gegen `laufzettel_test`** ergaben 62 falsche Fehlschläge. Der
|
||||
Review-Agent und ich haben uns die Daten weggetruncated; im Auftrag an den Agenten hatte ich die
|
||||
eigene Datenbank nicht verlangt.
|
||||
|
||||
### Nächster Schritt
|
||||
|
||||
- #010 Vorlagen-Editor: Liste mit Suche und Filtern, Abschnitte und Schritte per Drag & Drop,
|
||||
Vorschau, Veröffentlichen, Versionshistorie, Warnung bei unbekannten Platzhaltern.
|
||||
|
||||
Reference in New Issue
Block a user