feat(seed): sieben Vorlagen, Beispielbestand und Demo-Kunden (#33)
This commit was merged in pull request #33.
This commit is contained in:
@@ -331,6 +331,41 @@ hinter einem Reverse Proxy kommen sich sonst in die Quere. Der Zeitplan nimmt
|
||||
ausdruecklich **keine** eigene Sperre — sie traege einen anderen Schluessel und
|
||||
liefe an der des Dienstes vorbei.
|
||||
|
||||
## 5h. Der Seed: einrichten, nicht aufraeumen
|
||||
|
||||
Die sieben Vorlagen stehen als **JSON im Austauschformat** unter
|
||||
`prisma/seed-daten/vorlagen/` und nicht als TypeScript-Literale. Damit prueft sie
|
||||
dasselbe Zod-Schema, das auch Import, Export und Editor benutzen: eine
|
||||
Seed-Vorlage ist genau das, was ein Redakteur einspielen koennte, und ein Fehler
|
||||
faellt beim Einrichten auf statt im ersten Lauf.
|
||||
|
||||
Angelegt werden sie **nicht** ueber `vorlageImportieren`. Der Import erzeugt
|
||||
absichtlich einen Entwurf und schreibt einen Protokolleintrag mit dem handelnden
|
||||
Menschen; der Seed hat keinen Menschen und braucht veroeffentlichte Versionen,
|
||||
weil sich sonst kein Lauf starten liesse. Er geht trotzdem denselben Weg wie ein
|
||||
Redakteur — **erst Entwurf, dann veroeffentlichen**: die Trigger aus #010
|
||||
verbieten jedes Schreiben an Abschnitten, Variablen und Schritten einer
|
||||
veroeffentlichten Version. Eine Version gleich als `VEROEFFENTLICHT` anzulegen und
|
||||
danach zu fuellen scheitert an der Datenbank, und das ist richtig so.
|
||||
|
||||
**Der Seed richtet ein, er raeumt nicht auf.** Jede Zeile hat einen sprechenden
|
||||
Schluessel — die Vorlage ihren Namen, die Abteilung `(kundeId, name)`, die Person
|
||||
ihren UPN, das Geraet seinen `tagCode` —, und was es schon gibt, bleibt
|
||||
unberuehrt. Kein `upsert` mit gefuelltem `update`: eine im Betrieb geaenderte
|
||||
Ziel-OU, eine bearbeitete Vorlage und ein umgeschalteter Betriebsmodus ueberstehen
|
||||
jeden weiteren Lauf. Zweimal hintereinander aufgerufen aendert der zweite Lauf
|
||||
nichts, und `tests/seed.test.ts` haelt das fest.
|
||||
|
||||
Im Modus DIENSTLEISTUNG haengt der Beispielbestand an der **Musterfirma** und nicht
|
||||
an der eigenen Organisation: der Auftrag verlangt, dass `LZ-7K3F9Q` dort auf
|
||||
`MUS-PC-001` fuehrt. Ein Tag-Code gehoert genau einem Geraet, beides zugleich
|
||||
ginge also ohnehin nicht — „erzeugt **stattdessen**“.
|
||||
|
||||
Die Tag-Codes der Beispielgeraete sind **fest** und nicht gezogen. Ein Seed, der
|
||||
jedes Mal fuenf neue Codes zieht, waere nicht idempotent: beim dritten Lauf laegen
|
||||
fuenfzehn Aufkleber im Stapel. Weil ein `tagCode` global eindeutig ist und nie
|
||||
wiederverwendet wird, bekommt jeder Demo-Kunde seinen eigenen Satz.
|
||||
|
||||
## 6. Betrieb: zwei Wege, eine Regel
|
||||
|
||||
Die Datenbank ist auf beiden Wegen von außen nicht erreichbar:
|
||||
|
||||
+79
-2
@@ -19,11 +19,12 @@ als Unterpunkte mit Aufgabe und Dauer.
|
||||
| #014 | M9 – QR-Tags, Geräteseite, Etiketten, Scanner | 3 h 35 min |
|
||||
| #015 | M10 – Dashboard und Archiv | 2 h 20 min |
|
||||
| #016 | M11 – Verzeichnis und LDAP-Abgleich | 3 h 25 min |
|
||||
| | **Summe** | **26 h 10 min** |
|
||||
| #017 | M12 – Seed der sieben Vorlagen | 1 h 30 min |
|
||||
| | **Summe** | **27 h 40 min** |
|
||||
|
||||
| Meilenstein | Tatsächlich | Status |
|
||||
|---|---|---|
|
||||
| v0.1.0 | 26 h 10 min | in Arbeit |
|
||||
| v0.1.0 | 27 h 40 min | in Arbeit |
|
||||
|
||||
---
|
||||
|
||||
@@ -752,3 +753,79 @@ als Unterpunkte mit Aufgabe und Dauer.
|
||||
|
||||
- #017 Seed der sieben Vorlagen — alle sieben wortgetreu als veröffentlichte Version 1, dazu die
|
||||
Beispieldaten und der Modus `DIENSTLEISTUNG` mit „Musterfirma GmbH“ und „Bäckerei Reiter“.
|
||||
|
||||
---
|
||||
|
||||
## 2026-09-26 · Sitzung 13 · 02:35–04:05
|
||||
|
||||
**Issue:** #017 (M12)
|
||||
**Version:** 0.1.0
|
||||
|
||||
### Erledigt
|
||||
|
||||
- **Drei Teile parallel**: Vorlagen 1 und 4, Vorlagen 2 und 3, Vorlagen 5 bis 7 (je ein Sub-Agent);
|
||||
die Seed-Infrastruktur selbst
|
||||
- Die sieben Vorlagen als JSON im Austauschformat: 36 Abschnitte, 155 Schritte, 28 Variablen,
|
||||
jeder Schritt mit Hilfetext, als veröffentlichte Version 1 im Seed
|
||||
- Beispielbestand (3 Abteilungen, 5 Personen, `PC-001`, `NB-001`, 5 vorgedruckte Tags,
|
||||
Schnellstart je Gerätetyp), deaktivierte Beispiel-Verzeichnisquelle, Namensregeln und Sperr-OU
|
||||
- `SEED_MODE=DIENSTLEISTUNG` legt „Musterfirma GmbH" und „Bäckerei Reiter" an — der
|
||||
Beispielbestand hängt dann an der Musterfirma, `LZ-7K3F9Q` führt auf `MUS-PC-001`
|
||||
- Unabhängiger Review: **zwei Blocker**, neun Befunde, sieben Anmerkungen — alle abgearbeitet
|
||||
- Zwei Zusagen der Oberfläche eingelöst, die niemand deckte: `{{ou_gesperrt}}` kommt jetzt wirklich
|
||||
aus den Einstellungen, und der Hilfetext neben einem Befehl zeigt kein zweites Passwort mehr
|
||||
- **1131 Tests** (vorher 1098) grün, im gebauten Stand durchgeklickt: Lauf aus der
|
||||
Onboarding-Vorlage, `-Path "OU=Buchhaltung,OU=Benutzer,DC=firma,DC=local"` und
|
||||
`"G-Buchhaltung, G-Alle"` kommen aus der Abteilung, kein roher Platzhalter bleibt stehen
|
||||
|
||||
### Entscheidungen
|
||||
|
||||
- **Die Vorlagen sind Daten, kein Code.** Als JSON im Austauschformat prüft sie dasselbe Schema wie
|
||||
Import, Export und Editor: eine Seed-Vorlage ist genau das, was ein Redakteur einspielen könnte.
|
||||
Wer eine ändern will, ändert eine Datei und braucht keinen Übersetzer.
|
||||
- **Der Seed geht denselben Weg wie ein Redakteur**: erst Entwurf, dann veröffentlichen. Nicht aus
|
||||
Stilgefühl — die Trigger aus #010 verbieten jedes Schreiben an einer veröffentlichten Version.
|
||||
- **Der Seed richtet ein, er räumt nicht auf.** Kein `upsert` mit gefülltem `update`: eine
|
||||
bearbeitete Vorlage, eine geänderte Ziel-OU und ein umgeschalteter Betriebsmodus überstehen jeden
|
||||
weiteren Lauf.
|
||||
- **Tag-Codes fest statt gezogen.** Ein Seed, der jedes Mal fünf neue Codes zieht, ist nicht
|
||||
idempotent — beim dritten Lauf lägen fünfzehn Aufkleber im Stapel.
|
||||
|
||||
### Probleme
|
||||
|
||||
- **Die Datenbank hat den Seed korrigiert.** Der erste Entwurf legte die Version gleich als
|
||||
`VEROEFFENTLICHT` an und füllte sie danach — die Trigger aus #010 haben das abgewiesen. Genau
|
||||
dafür stehen sie dort.
|
||||
- **Zwei verschiedene Passwörter auf einer Seite** (Blocker): die Hilfetexte trugen
|
||||
`{{generiertes_passwort}}`, und das Lesemodell löste Hilfetexte ohne das Passwort des
|
||||
Seitenaufbaus auf. Im Befehl stand A, im Hilfetext daneben B. Die Warnung davor stand seit #012
|
||||
wörtlich in der Kopfdokumentation des Moduls, das beides erzeugt.
|
||||
- **Ein verbrannter Tag-Code kam zurück** (Blocker): der Seed fragte nur nach dem Gerät, nicht nach
|
||||
dem Vergabebuch — und der Kommentar derselben Funktion beschrieb genau den Fehler, den sie machte.
|
||||
- **„Stattdessen" hieß „zusätzlich".** Im Modus DIENSTLEISTUNG hing der Beispielbestand weiter an
|
||||
der eigenen Organisation; das Abnahmekriterium `LZ-7K3F9Q` → `MUS-PC-001` wäre in keinem Modus
|
||||
erfüllt gewesen. Ein Wort im Auftrag, drei Dateien Arbeit.
|
||||
- **Mein eigener Test konnte nicht scheitern** — zum zweiten Mal in zwei Meilensteinen. Die Suche
|
||||
nach Klartextpasswörtern lief gegen `JSON.stringify`, wo vor jedem Anführungszeichen ein
|
||||
Backslash steht; ein eingebautes `passwort = "Sommer2026!"` blieb unbemerkt. Gefunden durch die
|
||||
Gegenprobe, die seitdem zum Schreiben eines solchen Tests gehört: einmal absichtlich verletzen.
|
||||
- **Eine Wegwerfdatei im Wurzelverzeichnis** ließ `pnpm format:pruefen` scheitern, während der
|
||||
Review lief. Sie gehört in das Verzeichnis für Zwischenstände, nicht neben den Quelltext.
|
||||
- **Zum zweiten Mal gegen einen veralteten Server geprüft.** `pkill -f "next-server"` erwischte den
|
||||
eigenen Shell-Prozess statt den Server; der lief mit dem Stand von neunzehn Minuten zuvor weiter.
|
||||
Das sah aus wie ein Codefehler — `ChunkLoadError`, leere Editor-Seite, fünf rote Abläufe. Seitdem:
|
||||
`ps -eo lstart` gegen `.next/BUILD_ID` halten, bevor man der Seite glaubt.
|
||||
- **Der E2E-Lauf schrieb in eine andere Datenbank, als der Server las.** Die Abläufe legen ihre
|
||||
Fixtures über `prisma` aus `.env` an, der Server bekommt seine Adresse über die Umgebung. Zeigen
|
||||
beide woandershin, heißt die Meldung „0 Treffer" und sagt nichts über die Ursache.
|
||||
- **Der Seed hat die E2E-Suite rot gemacht.** Die Abläufe wählten ihre Vorlage über `index: 1` —
|
||||
eine Annahme über die Sortierung der Vorlagenliste, die genau so lange hielt, wie es nur eine
|
||||
Vorlage gab. Jetzt wird sie am Namen gesucht.
|
||||
|
||||
### Nächster Schritt
|
||||
|
||||
- Zwei Folge-Issues aus dem Review: [#020](issues/020-vorgesetzter-manuell.md) (Vorgesetzter
|
||||
für von Hand angelegte Personen) und
|
||||
[#021](issues/021-stabiler-schluessel-vorlagen.md) (stabiler Schlüssel für Seed-Vorlagen)
|
||||
- #018 E2E-Tests, Anleitung und PDF — die Hauptabläufe in beiden Betriebsmodi, die bebilderte
|
||||
Anleitung für Techniker und Admins und der PDF-Export über Chromium.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# #017 M12 – Seed der sieben Vorlagen
|
||||
|
||||
**Status:** offen
|
||||
**Status:** erledigt
|
||||
**Meilenstein:** v0.1.0
|
||||
**Labels:** phase-1, backend
|
||||
**Geschätzt:** 8 h **Tatsächlich:** –
|
||||
**Geschätzt:** 8 h **Tatsächlich:** 1 h 30 min
|
||||
|
||||
## Ziel
|
||||
|
||||
@@ -11,27 +11,94 @@ Die App ist nach dem Seed fachlich sofort brauchbar: sieben vollständige, fachl
|
||||
|
||||
## Aufgaben
|
||||
|
||||
- [ ] Vorlage 1 „PC Neuinstallation“ (Client), Variablen `os_version`, `join_typ`; Abschnitte Vorbereitung, Installation, Einbindung, Software, Sicherheit, Benutzer, Abschluss
|
||||
- [ ] Vorlage 2 „Mitarbeiter-Onboarding“ (Benutzer), Variablen `konto_typ`, `vorname`, `nachname`, `upn`, `sam`, `mail`, `abteilung`, `ou`, `gruppen`, `eintrittsdatum`, `vorgesetzter`; **beide** Konto-Abschnitte (AD und Entra ID), weil bedingte Abschnitte erst Phase 3 sind
|
||||
- [ ] Vorlage 3 „Mitarbeiter-Offboarding“ (Benutzer), Variablen `austrittsdatum`, `ou_gesperrt`, `postfach_verbleib`, `vertreter`
|
||||
- [ ] Vorlage 4 „Server-Inbetriebnahme Windows-VM“ (Server), Variablen `vmid`, `ip_adresse`, `vlan`, `rolle`, `os_version`
|
||||
- [ ] Vorlage 5 „Firewall-Rollout OPNsense“ (Netzwerk), Variablen `wan_typ`, `lan_netz`, `vpn_typ`
|
||||
- [ ] Vorlage 6 „Monatlicher Patchday“ (Wartung), Variable `monat`
|
||||
- [ ] Vorlage 7 „Backup-Restore-Test“ (Wartung), Variablen `system`, `restore_typ`
|
||||
- [ ] Alle Schritte wortgetreu nach Auftrag mit Typ, Pflichtkennzeichen und `konfig`; die im Auftrag genannten Hilfetexte übernehmen, die übrigen fachlich korrekt und kurz ergänzen
|
||||
- [ ] 5 Mitarbeiter, darunter „Maria Huber“, `m.huber@firma.example`, `sam` `mhuber`, Abteilung Buchhaltung, Vorgesetzte „Petra Klein“
|
||||
- [ ] 3 Abteilungen: Buchhaltung → `OU=Buchhaltung,OU=Benutzer,DC=firma,DC=local` mit Gruppen `G-Buchhaltung, G-Alle`; Vertrieb; IT
|
||||
- [ ] Eine **deaktivierte** `Verzeichnisquelle` als Beispielkonfiguration
|
||||
- [ ] Geräte `PC-001` (PC, `LZ-7K3F9Q`, Besitzerin Maria Huber) und `NB-001` (Notebook, `LZ-M2XH4T`), dazu 5 unregistrierte Tags
|
||||
- [ ] `GeraetetypVorlage`: PC und NOTEBOOK → „PC Neuinstallation“; SERVER → „Server-Inbetriebnahme Windows-VM“ und „Backup-Restore-Test“; FIREWALL → „Firewall-Rollout OPNsense“
|
||||
- [ ] `SEED_MODE=DIENSTLEISTUNG` (Alias `SERVICE`) erzeugt stattdessen „Musterfirma GmbH“ (`MUS`) und „Bäckerei Reiter“ (`REI`) mit je einer Person, einer Abteilung und einem Gerät
|
||||
- [ ] Alles idempotent über `upsert` mit stabilen Schlüsseln
|
||||
- [x] Vorlage 1 „PC Neuinstallation“ (Client), Variablen `os_version`, `join_typ`; Abschnitte Vorbereitung, Installation, Einbindung, Software, Sicherheit, Benutzer, Abschluss
|
||||
- [x] Vorlage 2 „Mitarbeiter-Onboarding“ (Benutzer), Variablen `konto_typ`, `vorname`, `nachname`, `upn`, `sam`, `mail`, `abteilung`, `ou`, `gruppen`, `eintrittsdatum`, `vorgesetzter`; **beide** Konto-Abschnitte (AD und Entra ID), weil bedingte Abschnitte erst Phase 3 sind
|
||||
- [x] Vorlage 3 „Mitarbeiter-Offboarding“ (Benutzer), Variablen `austrittsdatum`, `ou_gesperrt`, `postfach_verbleib`, `vertreter`
|
||||
- [x] Vorlage 4 „Server-Inbetriebnahme Windows-VM“ (Server), Variablen `vmid`, `ip_adresse`, `vlan`, `rolle`, `os_version`
|
||||
- [x] Vorlage 5 „Firewall-Rollout OPNsense“ (Netzwerk), Variablen `wan_typ`, `lan_netz`, `vpn_typ`
|
||||
- [x] Vorlage 6 „Monatlicher Patchday“ (Wartung), Variable `monat`
|
||||
- [x] Vorlage 7 „Backup-Restore-Test“ (Wartung), Variablen `system`, `restore_typ`
|
||||
- [x] Alle Schritte wortgetreu nach Auftrag mit Typ, Pflichtkennzeichen und `konfig`; die im Auftrag genannten Hilfetexte übernehmen, die übrigen fachlich korrekt und kurz ergänzen
|
||||
- [x] 5 Mitarbeiter, darunter „Maria Huber“, `m.huber@firma.example`, `sam` `mhuber`, Abteilung Buchhaltung, Vorgesetzte „Petra Klein“ — **teilweise:** Petra Klein ist angelegt, die Zuordnung selbst lässt sich nicht speichern (siehe Ergebnis)
|
||||
- [x] 3 Abteilungen: Buchhaltung → `OU=Buchhaltung,OU=Benutzer,DC=firma,DC=local` mit Gruppen `G-Buchhaltung, G-Alle`; Vertrieb; IT
|
||||
- [x] Eine **deaktivierte** `Verzeichnisquelle` als Beispielkonfiguration
|
||||
- [x] Geräte `PC-001` (PC, `LZ-7K3F9Q`, Besitzerin Maria Huber) und `NB-001` (Notebook, `LZ-M2XH4T`), dazu 5 unregistrierte Tags
|
||||
- [x] `GeraetetypVorlage`: PC und NOTEBOOK → „PC Neuinstallation“; SERVER → „Server-Inbetriebnahme Windows-VM“ und „Backup-Restore-Test“; FIREWALL → „Firewall-Rollout OPNsense“
|
||||
- [x] `SEED_MODE=DIENSTLEISTUNG` (Alias `SERVICE`) erzeugt stattdessen „Musterfirma GmbH“ (`MUS`) und „Bäckerei Reiter“ (`REI`) mit je einer Person, einer Abteilung und einem Gerät
|
||||
- [x] Alles idempotent über stabile Schlüssel — **nicht** über `upsert`, sondern nachsehen und nur anlegen (siehe Ergebnis)
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
- [ ] `pnpm db:seed` zweimal hintereinander: keine Fehler, keine Duplikate, keine geänderten Zeilen
|
||||
- [ ] Alle sieben Vorlagen liegen als `VEROEFFENTLICHT`, Version 1 vor
|
||||
- [ ] Im Onboarding-Lauf steht im Schritt „Konto anlegen“ der vollständige `New-ADUser`-Befehl mit Name, UPN, `-Path "OU=Buchhaltung,OU=Benutzer,DC=firma,DC=local"` und der Gruppen-Befehl mit `G-Buchhaltung, G-Alle`
|
||||
- [ ] `SEED_MODE=SERVICE` erzeugt `MUS-PC-001` gemäß Hostname-Regel `{kundenkuerzel}-PC-{nnn}`
|
||||
- [ ] Die Beispiel-Verzeichnisquelle ist deaktiviert und löst keinen Abgleich aus
|
||||
- [ ] Kein Seed-Datensatz enthält ein Klartext-Passwort außer dem Admin-Passwort aus der Umgebung, und das nur als argon2-Hash
|
||||
- [x] `pnpm db:seed` zweimal hintereinander: keine Fehler, keine Duplikate, keine geänderten Zeilen
|
||||
- [x] Alle sieben Vorlagen liegen als `VEROEFFENTLICHT`, Version 1 vor
|
||||
- [x] Im Onboarding-Lauf steht im Schritt „Konto anlegen“ der vollständige `New-ADUser`-Befehl mit Name, UPN, `-Path "OU=Buchhaltung,OU=Benutzer,DC=firma,DC=local"` und der Gruppen-Befehl mit `G-Buchhaltung, G-Alle`
|
||||
- [x] `SEED_MODE=SERVICE` erzeugt `MUS-PC-001` gemäß Hostname-Regel `{kundenkuerzel}-PC-{nnn}`
|
||||
- [x] Die Beispiel-Verzeichnisquelle ist deaktiviert und löst keinen Abgleich aus
|
||||
- [x] Kein Seed-Datensatz enthält ein Klartext-Passwort außer dem Admin-Passwort aus der Umgebung, und das nur als argon2-Hash
|
||||
|
||||
## Ergebnis
|
||||
|
||||
Erledigt am 2026-09-26. **1129 Tests** (vorher 1098), Screenshots in `docs/screenshots/m12/`.
|
||||
|
||||
Die sieben Vorlagen liegen als JSON im [Austauschformat](../vorlagen-format.md) unter
|
||||
`prisma/seed-daten/vorlagen/` — 36 Abschnitte, 155 Schritte, 28 Variablen, jeder Schritt mit
|
||||
Hilfetext. Ein maschineller Abgleich gegen den Auftragstext (Titel, Pflichtkennzeichen, Typ,
|
||||
Reihenfolge, Position für Position) meldet **eine** Abweichung, und die ist eine Auslegung: „Zeitzone
|
||||
korrekt, [COMMAND] Zeitsynchronisation prüfen" steht im Auftrag als *ein* Aufzählungspunkt mit der
|
||||
Typangabe mitten in der Zeile und wurde ein Befehlsschritt statt zweier Schritte.
|
||||
|
||||
Zwei Punkte weichen bewusst vom Wortlaut der Aufgabenliste ab:
|
||||
|
||||
- **Idempotenz ohne `upsert`.** Ein `upsert` mit gefülltem `update` schriebe bei jedem Lauf zurück,
|
||||
was im Betrieb geändert wurde. Der Seed sieht stattdessen nach und legt nur an, was fehlt.
|
||||
- **Die Vorgesetzte lässt sich nicht speichern.** Petra Klein ist als Person angelegt, die Zuordnung
|
||||
„Maria Huber → Petra Klein" aber nicht: `vorgesetzterExterneId` zeigt auf die `externeId`
|
||||
derselben Verzeichnisquelle, und eine von Hand angelegte Person hat beides nicht — beide Lesepfade
|
||||
(`src/server/queries/mitarbeiter.ts`, `src/server/services/platzhalter.ts`) steigen ohne `quelleId`
|
||||
aus. Einen Wert zu schreiben, den niemand liest, wäre schlechter als die Lücke. Sie gehört in ein
|
||||
eigenes Issue.
|
||||
|
||||
### Der unabhängige Review
|
||||
|
||||
Zwei Blocker, neun Befunde, sieben Anmerkungen — die wichtigsten:
|
||||
|
||||
- **Blocker: zwei verschiedene Passwörter auf einer Seite.** Die Hilfetexte des Onboardings trugen
|
||||
`{{generiertes_passwort}}`, und `src/server/queries/laeufe.ts` löste Hilfetexte **ohne** das
|
||||
Passwort des Seitenaufbaus auf — im Befehl stand A, im Hilfetext daneben B. Wer B in den
|
||||
Passwortmanager legt, sperrt den neuen Mitarbeiter aus. Genau davor warnt
|
||||
`src/lib/platzhalter-werte.ts` in Regel 4 seiner eigenen Kopfdokumentation. Behoben an beiden
|
||||
Enden: Titel und Hilfetext bekommen jetzt dasselbe Passwort wie der Befehl, und die Hilfetexte
|
||||
nennen es gar nicht mehr.
|
||||
- **Blocker: der Seed vergab einen verbrannten Tag-Code neu.** Er fragte nur nach dem Gerät, nicht
|
||||
nach dem Vergabebuch. Wer den Beispiel-PC endgültig gelöscht hatte, bekam beim nächsten Lauf
|
||||
denselben Code auf einem neuen Gerät — und der alte Aufkleber im Regal zeigte auf ein fremdes
|
||||
Objekt. Jetzt werden beide Bücher gefragt, wie im Gerätedienst.
|
||||
- **„Stattdessen" hieß „zusätzlich".** Im Modus DIENSTLEISTUNG hing der Beispielbestand weiter an
|
||||
der eigenen Organisation, `LZ-7K3F9Q` führte also auf `PC-001` statt auf `MUS-PC-001` — das
|
||||
Abnahmekriterium des Auftrags wäre in **keinem** Modus erfüllt gewesen. Jetzt bekommt die
|
||||
Musterfirma den vollen Bestand, die Bäckerei den kleinen, die eigene Organisation keinen.
|
||||
- **Der Seed schrieb in fremde Kundendaten.** Die Demo-Kunden wurden nur am Kürzel erkannt: ein
|
||||
echter Kunde „Muster und Söhne KG" mit dem Kürzel MUS bekam eine erfundene Person, eine erfundene
|
||||
Ziel-OU und ein Gerät — und die Ausgabe sagte „vorhanden".
|
||||
- **Der Seed stürzte ab**, wenn eine Vorlage gleichen Namens nur als Entwurf existierte — also genau
|
||||
dann, wenn jemand eine der sieben Dateien eingespielt und noch nicht veröffentlicht hatte.
|
||||
- **Zwei falsche Zusagen in Hilfetexten:** „vorbelegt aus der Abteilung" (nichts wird vorbelegt; die
|
||||
leeren Felder fallen auf die Abteilung zurück) und „das Passwort beendet die bestehenden
|
||||
Anmeldungen" (ein Reset im AD verhindert nur die erneute Anmeldung).
|
||||
- **Keine Namensregeln im Seed.** „Namen aus den Regeln vorschlagen" antwortete nach einem frischen
|
||||
Seed mit „keine Namensregeln hinterlegt" — das MVP-Kriterium war nicht vorführbar. Jetzt legt der
|
||||
Seed die Regeln an, die zu seinen eigenen Daten passen, und die Sperr-OU fürs Offboarding dazu.
|
||||
- **Ein Test, der nicht scheitern konnte** (schon vor dem Review selbst gefunden und behoben): die
|
||||
Suche nach Klartextpasswörtern lief gegen `JSON.stringify`, wo vor jedem Anführungszeichen ein
|
||||
Backslash steht.
|
||||
|
||||
Die drei Skripte `pnpm beispiel:vorlage`, `beispiel:stammdaten` und `beispiel:lauf` tragen im Kopf
|
||||
„Mit #017 wird das Skript gelöscht". Sie bleiben, und der Kopf ist berichtigt: der Seed richtet eine
|
||||
**Installation** ein, die Skripte stellen her, was **Screenshots und Abläufe** brauchen — einen
|
||||
offenen Entwurf, einen halb abgearbeiteten Lauf, eine Person aus dem Verzeichnis. Das in den Seed zu
|
||||
legen hieße, jeder frischen Installation Demo-Läufe mitzugeben, die dort niemand bestellt hat. Die
|
||||
Zusammenführung dieser Fixtures steht in [#018](018-e2e-anleitung-pdf.md).
|
||||
|
||||
Offen geblieben und bewusst nicht behoben: wird eine Seed-Vorlage **umbenannt**, legt der nächste
|
||||
Lauf sie erneut an — der Seed kennt sie nur an ihrem Namen. Ein stabiler Schlüssel dafür gehört ins
|
||||
Austauschformat und damit in ein eigenes Issue.
|
||||
|
||||
@@ -17,6 +17,10 @@ Nachweis, dass die Abläufe wirklich durchlaufen, und eine Anleitung, mit der ei
|
||||
- [ ] Playwright-Onboarding-Ablauf: Vorlage starten → Vorname und Nachname eingeben → UPN, `sam` und Mail werden vorgeschlagen → Abteilung „Buchhaltung“ wählen → im Schritt „Konto anlegen“ steht der fertige `New-ADUser`-Befehl → Kopieren liefert exakt diesen Text (Clipboard auslesen)
|
||||
- [ ] Playwright-Mobilprüfung: auf allen Hauptseiten bei 390 × 844 ist `scrollWidth <= clientWidth`
|
||||
- [ ] Playwright-Rollenprüfung: `LESER` sieht keine Schreib-Knöpfe und wird serverseitig abgewiesen
|
||||
- [ ] Die Abläufe suchen ihre Vorlage **am Namen**, nicht über `select ... { index: 1 }`. Aufgefallen in #017: gegen eine frisch geseedete Datenbank steht an erster Stelle „Mitarbeiter-Offboarding“ mit Pflichtvariablen, die der Helfer nicht füllt — sechs Abläufe liefen je 30 s in den Zeitablauf. Ein Ablauf, der von der Sortierung der Vorlagenliste abhängt, prüft nicht, was er zu prüfen vorgibt
|
||||
- [ ] Die Voraussetzungen eines E2E-Laufs stehen an einer Stelle und werden geprüft, statt im Kopfkommentar zu stehen (`pnpm beispiel:vorlage`, `pnpm beispiel:stammdaten`, `pnpm beispiel:lauf`) — besser noch: die Abläufe legen an, was sie brauchen. Die drei Skripte tragen auch die Screenshots; was davon bleibt und was in die Abläufe wandert, wird hier entschieden. In den Seed gehört es **nicht**: eine frische Installation soll keine Demo-Läufe und keine offenen Entwürfe mitbringen (in #017 geprüft und so entschieden)
|
||||
- [ ] Kein Ablauf setzt voraus, dass die Datenbank schon Läufe enthält. `uebersicht-druck.spec.ts` sucht sich mit `lauf.findFirstOrThrow()` irgendeinen Lauf und „Zuletzt bearbeitet" muss gefüllt sein — gegen eine frisch eingerichtete Installation scheitert beides mit „No record was found", und das sagt nichts über die Ursache (gesehen in #017)
|
||||
- [ ] Der E2E-Lauf prüft beim Start, dass er **dieselbe** Datenbank benutzt wie der Server unter Test. Die Abläufe legen ihre Daten über `prisma` aus `.env` an, die Adresse des Servers steht in `E2E_APP_URL` — zeigen beide auf verschiedene Datenbanken, schreibt der Test in die eine und sucht in der anderen. Die Meldung heißt dann „0 Treffer“ und sagt nichts über die Ursache (gesehen in #017)
|
||||
- [ ] `pnpm docs:screenshots`: Playwright-Skript, Desktop 1440 × 900 und Handy 390 × 844, Seed-Daten, dunkles Design, mit Markierungen (Rahmen, Nummern) für die beschriebenen Stellen; Ablage `docs/anleitung/bilder/`
|
||||
- [ ] `pnpm docs:pdf`: Anleitung als PDF über Chromium (`page.pdf`, A4, `printBackground`), Ablage `docs/anleitung/laufzettel-anleitung.pdf`
|
||||
- [ ] `docs/anleitung/` auf Deutsch, getrennt für Techniker und Admins: Erste Schritte · Vorlagen bauen · Läufe abarbeiten (Desktop und Handy) · QR-Tags drucken und registrieren · Mitarbeiter und Abteilungen · Betriebsmodus · Admin: Verzeichnis, Benutzer, Einstellungen · Fehlerbehebung
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# #020 Vorgesetzter auch für von Hand angelegte Personen
|
||||
|
||||
**Status:** offen
|
||||
**Im Tracker:** [#31](https://git.wilde-server.de/florian.wilde/Laufzettel/issues/31) — die Zählung dort schließt Pull Requests ein und läuft deshalb auseinander
|
||||
**Meilenstein:** v0.2.0
|
||||
**Labels:** phase-2, backend
|
||||
**Geschätzt:** 3 h **Tatsächlich:** –
|
||||
|
||||
## Ziel
|
||||
|
||||
Eine Person, die nicht aus dem Verzeichnis kommt, kann heute keinen Vorgesetzten haben. Das fiel in
|
||||
[#017](017-seed-sieben-vorlagen.md) auf: der Auftrag verlangt für den Beispielbestand „Maria Huber,
|
||||
Vorgesetzte Petra Klein“, und genau diese Zuordnung lässt sich nirgends speichern.
|
||||
|
||||
## Woran es liegt
|
||||
|
||||
`Mitarbeiter.vorgesetzterExterneId` trägt die `externeId` des Vorgesetzten, und die ist nur
|
||||
**innerhalb einer Verzeichnisquelle** eindeutig. Beide Lesepfade steigen deshalb aus, wenn die
|
||||
Person keine Quelle hat:
|
||||
|
||||
- `vorgesetzterVon()` in `src/server/queries/mitarbeiter.ts`
|
||||
- `vorgesetztenLesen()` in `src/server/services/platzhalter.ts`
|
||||
|
||||
Das ist für Verzeichnis-Personen richtig. Für eine von Hand angelegte Person gibt es schlicht kein
|
||||
Feld — `{{vorgesetzter_sam}}` bleibt dort immer leer.
|
||||
|
||||
## Aufgaben
|
||||
|
||||
- [ ] Entscheiden: eigene Selbstbeziehung `vorgesetzterId` (sauber, aber zwei Wege zur selben
|
||||
Auskunft) **oder** `vorgesetzterExterneId` auch im Bereich „ohne Quelle“ auflösen (`quelleId
|
||||
IS NULL`), mit stabilen Kennungen für manuelle Personen
|
||||
- [ ] Beide Lesepfade und `{{vorgesetzter}}` / `{{vorgesetzter_sam}}` entsprechend erweitern
|
||||
- [ ] Oberfläche: Vorgesetzten auf der Mitarbeiterseite setzen und entfernen
|
||||
- [ ] Der Abgleich darf die Zuordnung nicht überschreiben, wenn das Verzeichnis keinen `manager`
|
||||
liefert — und keine Schleife zulassen (A ist Vorgesetzter von B ist Vorgesetzter von A)
|
||||
- [ ] Seed: Petra Klein als Vorgesetzte von Maria Huber eintragen
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
- [ ] Test: eine von Hand angelegte Person bekommt einen Vorgesetzten, `{{vorgesetzter_sam}}` löst auf
|
||||
- [ ] Test: die Zuordnung gilt nur innerhalb desselben Kunden
|
||||
- [ ] Test: ein Abgleich ohne `manager` löscht eine von Hand gesetzte Zuordnung nicht
|
||||
@@ -0,0 +1,31 @@
|
||||
# #021 Stabiler Schlüssel für Seed-Vorlagen
|
||||
|
||||
**Status:** offen
|
||||
**Im Tracker:** [#32](https://git.wilde-server.de/florian.wilde/Laufzettel/issues/32) — die Zählung dort schließt Pull Requests ein und läuft deshalb auseinander
|
||||
**Meilenstein:** v0.2.0
|
||||
**Labels:** phase-2, backend
|
||||
|
||||
**Geschätzt:** 2 h **Tatsächlich:** –
|
||||
|
||||
## Ziel
|
||||
|
||||
Der Seed erkennt seine sieben Vorlagen am **Namen**. Wird eine umbenannt, legt der nächste Lauf sie
|
||||
erneut an — und `GeraetetypVorlage` bekommt eine zweite Zeile, der Schnellstart steht auf der
|
||||
Geräteseite doppelt. Aufgefallen im Review zu [#017](017-seed-sieben-vorlagen.md).
|
||||
|
||||
## Aufgaben
|
||||
|
||||
- [ ] Ein optionales Feld `schluessel` im [Austauschformat](../vorlagen-format.md) — gedacht für
|
||||
mitgelieferte Vorlagen, nicht für die Oberfläche; beim Import **nicht** übernommen, damit eine
|
||||
eingespielte Kopie nicht den Platz des Originals einnimmt
|
||||
- [ ] `Vorlage.seedSchluessel` mit partiellem eindeutigen Index (nur wo gesetzt)
|
||||
- [ ] Der Seed sucht über den Schlüssel und fällt auf den Namen zurück, solange noch keiner gesetzt
|
||||
ist — eine bestehende Installation darf beim ersten Lauf danach keine Dubletten bekommen
|
||||
- [ ] Dokumentieren, was der Schlüssel **nicht** tut: er macht eine Vorlage nicht unveränderlich und
|
||||
erlaubt dem Seed nicht, eine bearbeitete Vorlage zu überschreiben
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
- [ ] Test: umbenannte Seed-Vorlage, zweiter Seed-Lauf legt keine zweite an
|
||||
- [ ] Test: zweiter Lauf erzeugt keine zweite `GeraetetypVorlage`-Zeile
|
||||
- [ ] Test: eine über den Import eingespielte Kopie bekommt **keinen** Schlüssel
|
||||
@@ -21,7 +21,9 @@ Diese Dateien sind die Quelle; `pnpm issues:sync` spiegelt sie in den Gitea-Trac
|
||||
| #014 | [M9 – QR-Tags, Geräteseite, Etiketten, Scanner](014-qr-tags-geraeteseite.md) | erledigt | v0.1.0 | 12 h | 3 h 35 min |
|
||||
| #015 | [M10 – Dashboard und Archiv](015-dashboard-archiv.md) | erledigt | v0.1.0 | 8 h | 2 h 20 min |
|
||||
| #016 | [M11 – Verzeichnis und LDAP-Abgleich](016-verzeichnis-ldap.md) | erledigt | v0.1.0 | 12 h | 3 h 25 min |
|
||||
| #017 | [M12 – Seed der sieben Vorlagen](017-seed-sieben-vorlagen.md) | offen | v0.1.0 | 8 h | – |
|
||||
| #017 | [M12 – Seed der sieben Vorlagen](017-seed-sieben-vorlagen.md) | erledigt | v0.1.0 | 8 h | 1 h 30 min |
|
||||
| #018 | [M13 – E2E-Tests, Anleitung, PDF](018-e2e-anleitung-pdf.md) | offen | v0.1.0 | 14 h | – |
|
||||
| #019 | [M14 – Betriebswege und Release v0.1.0](019-betrieb-release.md) | offen | v0.1.0 | 10 h | – |
|
||||
| | **Summe** | | | **136 h** | **26 h 10 min** |
|
||||
| #020 | [Vorgesetzter auch für von Hand angelegte Personen](020-vorgesetzter-manuell.md) | offen | v0.2.0 | 3 h | – |
|
||||
| #021 | [Stabiler Schlüssel für Seed-Vorlagen](021-stabiler-schluessel-vorlagen.md) | offen | v0.2.0 | 2 h | – |
|
||||
| | **Summe** | | | **141 h** | **27 h 40 min** |
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 135 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 444 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 121 KiB |
Reference in New Issue
Block a user