Legt die Grundlage, auf der alle weiteren Meilensteine nur noch Fachlichkeit ergänzen: Next 16 mit App Router und TypeScript strict, Tailwind 4, Prisma 7, Vitest 5, Playwright, ESLint, Prettier und die Hooks für Lint und Commits. Zwei Dinge sind bewusst so gebaut und durch Tests festgehalten: Die Datenbank ist im Betriebsstand von außen nicht erreichbar. Sie hat kein ports:-Mapping und hängt allein im Netz "intern", das ohne Gateway läuft; nur "web" kommt zusätzlich nach draußen. tests/betriebsstand.test.ts schlägt an, falls ein Port-Mapping zurückkehrt. Geprüft, nicht behauptet: docker compose up startet den Stack, 5432 ist vom Host aus zu, aus "web" offen. pnpm pruefe:doku hält Dokumentation und Code zusammen — Version im Changelog, Issue-Dateien gegen ihre Übersicht, keine Verweise auf fehlende Dateien, keine fehlenden Bilder. Das Skript wurde gegen vier eingebaute Fehler gegengeprüft. Drei Versions-Obergrenzen sind nötig und in CLAUDE.md begründet: eslint bleibt auf 9.x, weil eslint-plugin-react keinen Nachfolger für eslint 10 hat und das Regelwerk sonst beim Laden abbricht; typescript bleibt auf 6.0.x, weil typescript-eslint TypeScript 7 noch nicht unterstützt; prisma ist exakt auf 7.10.0 gepinnt, weil sein latest-Tag auf einen 8.0-RC zeigt, der von @prisma/client aber nicht. Auth.js entfällt entgegen der ursprünglichen Vorgabe: v5 steht dauerhaft auf Beta, das Projekt ist im Wartungsmodus und sein Prisma-Adapter deckt Prisma 7 nicht ab. Stattdessen openid-client und jose, wie in ProxLedger. Dieser erste Commit geht direkt auf main, weil es noch keinen Branch gibt, von dem abzuzweigen wäre. Ab #006 läuft jedes Issue über einen eigenen Branch. Closes #5 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
96 lines
5.2 KiB
Markdown
96 lines
5.2 KiB
Markdown
# Abnahmekriterien für den MVP (v0.1.0)
|
|
|
|
Diese Liste wird von [#019](issues/019-betrieb-release.md) abschließend durchgegangen. Jeder
|
|
Punkt ist entweder abgehakt oder hat ein Folge-Issue — nichts bleibt stillschweigend offen.
|
|
|
|
## Betrieb
|
|
|
|
- [ ] `docker compose up` startet App und Datenbank, Migrationen laufen automatisch
|
|
- [ ] Seed läuft per dokumentiertem Befehl, nicht automatisch
|
|
- [ ] Die Datenbank ist vom Host aus **nicht** erreichbar (`nc -z localhost 5432` schlägt fehl), aus `web` schon
|
|
- [ ] Der Proxmox-One-Liner rollt einen LXC aus, in dem die App läuft und PostgreSQL nur am Unix-Socket hört
|
|
- [ ] Erneuter Aufruf des Skripts aktualisiert, ohne Daten oder Geheimnisse zu verlieren
|
|
- [ ] `shellcheck --severity=warning` über alle Skripte ohne Befund
|
|
- [ ] Läuft hinter einem Reverse Proxy ohne fest verdrahtete Adressen
|
|
|
|
## Anmeldung und Rechte
|
|
|
|
- [ ] Login per lokalem Konto funktioniert
|
|
- [ ] OIDC ist konfigurierbar und für authentik dokumentiert, inkl. Gruppen für Rollen
|
|
- [ ] Bei `AUTH_LOCAL_ENABLED=false` ist der lokale Login weg und der Endpunkt lehnt ab
|
|
- [ ] Rollenrechte: jede Rolle gegen jede Aktion getestet, Prüfung ausschließlich serverseitig
|
|
- [ ] Eine Rollenänderung greift ohne neue Anmeldung; ein deaktivierter Benutzer wird abgewiesen
|
|
- [ ] Passwörter stehen nur als argon2-Hash in der Datenbank, nie in einer API-Antwort
|
|
|
|
## Betriebsmodus
|
|
|
|
- [ ] Hauptablauf läuft in `INTERN` ohne jede Kundenanzeige
|
|
- [ ] Hauptablauf läuft in `DIENSTLEISTUNG` mit Kundenwahl
|
|
- [ ] Wechsel `INTERN → DIENSTLEISTUNG` übernimmt alle Daten auf den ersten Kunden
|
|
- [ ] Wechsel zurück wird bei zwei nicht archivierten Kunden abgelehnt
|
|
- [ ] Im Modus `INTERN` ignoriert die Service-Schicht eine mitgeschickte `kundeId`
|
|
- [ ] Der Modus ist ohne Neustart umschaltbar, jeder Wechsel steht im `Protokoll`
|
|
|
|
## Vorlagen
|
|
|
|
- [ ] Veröffentlichte Version ist unveränderlich; „Bearbeiten" erzeugt eine tiefe Kopie als Entwurf
|
|
- [ ] Höchstens ein Entwurf je Vorlage
|
|
- [ ] Veröffentlichen einer neuen Version verändert bestehende Läufe nicht
|
|
- [ ] Export und anschließender Import ergeben eine inhaltsgleiche Vorlage
|
|
- [ ] Unbekannte Platzhalter werden im Editor als Warnung angezeigt
|
|
|
|
## Läufe und Archiv
|
|
|
|
- [ ] Lauf ohne Mitarbeiter und ohne Gerät lässt sich starten, abschließen und archivieren
|
|
- [ ] Abschließen scheitert, solange ein Pflichtschritt offen ist
|
|
- [ ] `NICHT_ZUTREFFEND` und `FEHLGESCHLAGEN` verlangen eine Notiz
|
|
- [ ] „Abschnitt als nicht zutreffend markieren" setzt alle Schritte mit einer Notiz
|
|
- [ ] Archiv-Schreibschutz greift für Kopfdaten, Schrittergebnisse und Kommentare
|
|
- [ ] Nur `ADMIN` holt einen archivierten Lauf zurück, mit `Protokoll`-Eintrag
|
|
- [ ] Im Archiv wird über Titel, Notizen, Werte und Kommentare gefunden
|
|
- [ ] Druckansicht eines Laufs ist sauber und hell
|
|
|
|
## Mitarbeiter, Geräte, QR
|
|
|
|
- [ ] Mitarbeitersuche liefert standardmäßig nur aktive, Umschalter zeigt auch deaktivierte
|
|
- [ ] Ein von der Geräteseite gestarteter Lauf hat den Besitzer vorbelegt
|
|
- [ ] `/t/LZ-7K3F9Q` ohne Anmeldung führt nach dem Login auf die Geräteseite
|
|
- [ ] „Vorlage zuweisen" erzeugt einen `OFFEN`-Lauf, der unter „Zugewiesen" erscheint; „Starten" setzt `IN_ARBEIT`
|
|
- [ ] Unregistrierter Tag → Registrierformular → Geräteseite; unbekannter Tag → Hinweis
|
|
- [ ] `tagCode`: richtiges Alphabet, eindeutig, unveränderlich, nie wiederverwendet
|
|
- [ ] Etikettendruck in beiden Layouts sauber; QR maschinell zurücklesbar
|
|
|
|
## Platzhalter und Befehle
|
|
|
|
- [ ] Onboarding: Vorname und Nachname eingeben → UPN, `sam` und Mail werden vorgeschlagen
|
|
- [ ] Abteilung „Buchhaltung" wählen → `-Path "OU=Buchhaltung,…"` und Gruppen `G-Buchhaltung, G-Alle`
|
|
- [ ] Kopieren liefert exakt diesen Text, zeichengenau
|
|
- [ ] „Jörg Müller-Lüdenscheid" ergibt gültige Vorschläge (`joerg.mueller-luedenscheid@…`, `jmuellerluedensch`)
|
|
- [ ] `{{generiertes_passwort}}` erscheint im Befehl, steht aber nicht in Datenbank, Druckansicht oder `Protokoll`
|
|
- [ ] Werte mit Anführungszeichen werden für die jeweilige Shell korrekt maskiert
|
|
- [ ] „Alle Befehle als Skript kopieren" liefert die Schritte in richtiger Reihenfolge
|
|
- [ ] Unbekannte Platzhalter bleiben stehen; ersetzte Werte sind HTML-escaped
|
|
|
|
## Verzeichnis (LDAP)
|
|
|
|
- [ ] Erster Abgleich legt Mitarbeiter an, zweiter aktualisiert sie ohne Duplikate
|
|
- [ ] Entfernte oder deaktivierte Konten werden `aktiv = false`, nie gelöscht
|
|
- [ ] `{{ou}}` wird korrekt aus dem `dn` abgeleitet
|
|
- [ ] Das Bind-Passwort erscheint in keiner API-Antwort und keinem Log
|
|
- [ ] Zwei gleichzeitige Abgleiche derselben Quelle: der zweite wird von der Sperre abgewiesen
|
|
|
|
## Oberfläche
|
|
|
|
- [ ] Am Handy kein horizontales Scrollen — bei 390 px auf allen Hauptseiten geprüft
|
|
- [ ] Gestaltung nach Vorgabe: dunkel, ein Akzent, keine Emojis, keine Schatten, keine Verläufe
|
|
- [ ] Version mit Git-SHA unten links
|
|
|
|
## Projektorganisation
|
|
|
|
- [ ] Issues für alle Phasen und MVP-Meilensteine existieren
|
|
- [ ] `CHANGELOG.md` und `docs/devlog.md` sind gepflegt
|
|
- [ ] `v0.1.0` ist getaggt, Gitea-Release mit Changelog-Auszug
|
|
- [ ] `docs/anleitung/` vollständig mit Screenshots und als PDF
|
|
- [ ] `docs/screenshots/` enthält die Meilenstein-Bilder
|
|
- [ ] `pnpm lint && pnpm typecheck && pnpm test && pnpm pruefe:doku` grün
|