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>
2.6 KiB
2.6 KiB
#006 M1 – Datenmodell
Status: offen Meilenstein: v0.1.0 Labels: phase-1, backend Geschätzt: 5 h Tatsächlich: –
Ziel
Das vollständige Schema in deutscher Benennung, sodass alle folgenden Meilensteine nur noch Verhalten ergänzen und keine Strukturänderung mehr brauchen.
Aufgaben
- Prisma 7: Generator
prisma-clientmitoutput = "../src/generated/prisma",datasourceohneurl,@prisma/adapter-pg prisma.config.tsmitmigrations.seed = "tsx prisma/seed.ts"src/lib/db.ts: Lazy-Singleton-Proxy, damitnext buildohneDATABASE_URLläuft, Dev-Instanz anglobalThis- Modelle:
Benutzer,Kunde,Einstellung,Verzeichnisquelle,Mitarbeiter,Abteilung,Geraet,GeraetetypVorlage,Vorlage,VorlagenVersion,VorlagenVariable,VorlagenAbschnitt,VorlagenSchritt,Lauf,Schrittergebnis,Kommentar,Protokoll,AbgleichSperre - Enums:
Rolle,Betriebsmodus,LaufStatus,SchrittZustand,SchrittTyp,GeraeteTyp,VersionStatus,Herkunft - Unique-Constraints:
Geraet.tagCode,(laufId, vorlagenSchrittId)aufSchrittergebnis,(quelleId, externeId)aufMitarbeiter,(kundeId, name)aufAbteilung,(kundeId)partiell füristeigeneOrganisation pg_trgm-Erweiterung und GIN-Indizes für die Archivsuche überLauf.titel,Schrittergebnis.notiz,Kommentar.rumpf- Jede kundenbezogene Zeile trägt
kundeIdals Pflichtfeld:Geraet,Mitarbeiter,Abteilung,Verzeichnisquelle,Lauf src/lib/tagcode.ts: AlphabetABCDEFGHJKLMNPQRSTUVWXYZ23456789, PräfixLZ-, 6 Zeichen, Kollisionsprüfung serverseitigsrc/lib/geheimnisse.ts: AES-256-GCM ausAPP_SECRET(scrypt-abgeleitet), fürbindPasswortVerschluesselt- Erste Migration,
prisma/seed.tsals idempotenter Rumpf: Admin ausSEED_ADMIN_EMAIL/SEED_ADMIN_PASSWORDmit@node-rs/argon2, eigene Organisation,EinstellungmitBetriebsmodus.INTERN tests/setup-env.ts,tests/global-setup.ts,tests/helpers/db.tsnach ProxLedger-Muster
Akzeptanzkriterien
prisma migrate deployläuft auf leerer Datenbank durchpnpm db:seedzweimal hintereinander ohne Fehler und ohne Datenänderung- Tests:
tagCodebenutzt nur das erlaubte Alphabet, enthält nie0,O,1,IoderL, ist eindeutig über 10 000 Ziehungen - Tests: verschlüsseln und entschlüsseln ist verlustfrei, zwei Verschlüsselungen desselben Klartexts unterscheiden sich (eigener IV), ein manipulierter Geheimtext wirft
next buildgelingt ohne gesetzteDATABASE_URL