feat(seed): sieben Vorlagen, Beispielbestand und Demo-Kunden (#33)
This commit was merged in pull request #33.
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user