Ziel, Erledigtes, die Entscheidungen mit Begründung, die Probleme samt Lösung und die offenen Punkte. Dazu die eigenen Fehler dieser Sitzung — die Commits auf main statt auf dem Meilenstein-Zweig, der vermischte Doku-Commit und das ungeprüfte Skript — damit sie nicht wiederkehren. Dauer laut zeiten.csv: 161 Minuten. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
138 lines
8.0 KiB
Markdown
138 lines
8.0 KiB
Markdown
# Entwicklungstagebuch
|
||
|
||
Neuester Eintrag oben. Die Dauer je Sitzung stammt aus `devlog/zeiten.csv`,
|
||
die Übersicht aus `scripts/zeit.sh summe`.
|
||
|
||
## Zeit je Meilenstein
|
||
|
||
| Meilenstein | Art | Minuten | Stunden |
|
||
| ----------- | ------ | ------- | -------- |
|
||
| M1 | claude | 161 | 2,68 |
|
||
| **Gesamt** | | **161** | **2,68** |
|
||
|
||
---
|
||
|
||
## 2026-09-10 – M1: Fundament
|
||
|
||
**Dauer:** 161 Minuten (12:06–14:47), Art `claude`.
|
||
|
||
**Ziel der Sitzung:** Das Projekt von Grund auf aufsetzen: Gerüst,
|
||
Datenbank, Anmeldung, Rollen, Audit, Instanzsteuerung, Betrieb und
|
||
Dokumentation.
|
||
|
||
### Erledigt
|
||
|
||
- Projektgerüst mit Next 16, React 19, TypeScript strict, Tailwind 4,
|
||
alle Versionen exakt gepinnt
|
||
- `npm run pruefen` als Sammelprüfung: Prettier, ESLint, `tsc`, Vitest,
|
||
ShellCheck
|
||
- Datenmodell und erste Migration: Benutzer mit Rolle, OIDC-Konten,
|
||
Passkeys, WebAuthn-Herausforderungen, Bereiche, Audit
|
||
- Anmeldung über OIDC, Passkey und Passwort, je Instanz zuschaltbar
|
||
- Rollenprüfung in Seite **und** Server Action, Audit je Schreibaktion
|
||
- Instanzsteuerung mit 404 statt Hinweis
|
||
- Bereiche verwalten, Protokollseite, Startseite, Einstellungen
|
||
- `/api/health`, Dockerfile, Compose-Stapel mit Migrationsdienst
|
||
- `backup.sh`, `update.sh`, `scripts/release.sh`, `scripts/zeit.sh`
|
||
- Unit-, Integrations-, Migrations- und E2E-Tests
|
||
- Screenshot-Kette mit eigener Wegwerf-Instanz
|
||
- README, Schnellstart, Handbuch, ROADMAP, CHANGELOG
|
||
|
||
### Entscheidungen mit Begründung
|
||
|
||
**Prisma 7.10.0 statt der notierten Fassung 6.** Fassung 6 ist überholt,
|
||
Fassung 8 liegt nur als RC auf `latest`. Prisma 7 nimmt die Verbindung
|
||
nicht mehr im Schema entgegen — sie steht in `prisma.config.ts`, der
|
||
Client bekommt den pg-Treiberadapter.
|
||
|
||
**TypeScript 6.0.3 statt 7.0.2.** TS 7 ist zwar `latest`, aber
|
||
`typescript-eslint@8.70` verlangt `typescript >=4.8.4 <6.1.0`. Mit TS 7
|
||
wäre die Lint-Kette kaputt gewesen.
|
||
|
||
**ESLint 9.39.5 statt 10.** Das in `eslint-config-next@16` gebündelte
|
||
`eslint-plugin-react` ruft noch `context.getFilename()`, das ESLint 10
|
||
entfernt hat. Der Lint-Lauf brach reproduzierbar ab.
|
||
|
||
**Eigener Auth.js-Adapter.** Der mitgelieferte `@auth/prisma-adapter`
|
||
greift fest auf `prisma.user` und `prisma.account` zu; unsere Modelle
|
||
heißen `Benutzer` und `Konto`. Der Adapter ist schmal und ersparte es,
|
||
die Fachbegriffe der Konvention zu opfern.
|
||
|
||
**Passkeys direkt über SimpleWebAuthn 14.** Der WebAuthn-Provider von
|
||
Auth.js ist als experimentell markiert und auf SimpleWebAuthn 9
|
||
festgelegt. Direkt angebunden bleibt die Fassung aktuell und der Ablauf
|
||
nachvollziehbar. Für die npm-Auflösung brauchte es `overrides`, weil
|
||
next-auth die älteren Fassungen als optionale Peers deklariert.
|
||
|
||
**Sitzungen als JWT, Rolle trotzdem aus der Datenbank.** Credentials-
|
||
Provider verlangen JWT. Damit eine Sperre nicht bis zum Ablauf des Tokens
|
||
wirkungslos bleibt, liest der `session`-Callback Rolle und Status bei
|
||
jeder Anfrage frisch. Die Tabellen `sitzung` und `verifizierungs_token`
|
||
wären damit tot und wurden wieder entfernt, solange es nur eine einzige
|
||
Migration gab.
|
||
|
||
**Migrationen als eigener Compose-Dienst.** Der Versuch, nur die
|
||
Prisma-CLI ins schlanke Laufzeitabbild zu kopieren, scheiterte an ihren
|
||
transitiven Modulen (`effect` über `@prisma/config`). Alle mitzunehmen
|
||
hätte das Abbild aufgebläht. Ein Einmaldienst aus der Bau-Stufe läuft vor
|
||
der App und muss sauber durchlaufen.
|
||
|
||
**Aufgabe, Zeitblock und Kalenderkonto bewusst nicht modelliert.** Sie
|
||
kommen mit M2, M4 und M3 — dann mit den Feldern, die der jeweilige
|
||
Provider wirklich braucht, statt heute geraten.
|
||
|
||
### Probleme und Lösungen
|
||
|
||
| Problem | Lösung |
|
||
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| `prisma validate` lehnte `url` im Schema ab | Prisma 7 erwartet die Verbindung in `prisma.config.ts` und einen Treiberadapter im Client. |
|
||
| Integrationstest brach nach der ersten erwarteten Verletzung ab | In PostgreSQL bricht ein fehlgeschlagener Befehl die ganze Transaktion ab. Der Test läuft jetzt ohne Sammeltransaktion; alle Testdaten tragen eine Kennung und werden am Ende entfernt. |
|
||
| `prisma migrate diff` kannte `--from-url` nicht | In Prisma 7 heißen die Flaggen anders. Der Test vergleicht jetzt die eingespielte Wegwerf-Datenbank über `--from-config-datasource` gegen das Schema — und braucht damit keine Schattendatenbank. |
|
||
| Nach der Anmeldung ging es nicht zum ursprünglichen Ziel zurück | Das Layout leitet um, bevor die Seite drankommt, und kennt seinen Pfad nicht. Ein schlanker Proxy reicht ihn als Kopfzeile durch — ohne Anmeldelogik, weil er im Edge-Umfeld läuft. |
|
||
| Der Docker-Bau brach beim Sammeln der Seitendaten ab | Prisma-Client und Auth.js-Konfiguration wurden beim Laden des Moduls ausgewertet und brauchten Umgebungsvariablen, die es zur Bauzeit nicht gibt. Beide entstehen jetzt faul. |
|
||
| Ein Typfehler in `scripts/screenshots.ts` blockierte den Abbild-Bau | Entwicklungsskripte gehören nicht in den Docker-Kontext. `.dockerignore` schließt sie aus; geprüft werden sie von `npm run pruefen`. |
|
||
| ESLint beanstandete `setState` im Effekt | Der Hydratations-Trick im Farbschema-Knopf war unnötig: `next-themes` setzt die `dark`-Klasse vor der Hydratation, das erledigt CSS ohne Zustand. |
|
||
|
||
### Eigene Fehler, die ich korrigiert habe
|
||
|
||
- Die ersten vier Commits lagen direkt auf `main` statt auf einem
|
||
Meilenstein-Zweig und ohne Attributionszeile. Historie umgebaut:
|
||
`main` trägt nur noch einen leeren Wurzel-Commit, die Arbeit liegt auf
|
||
`m1-fundament`.
|
||
- Ein `git add -A` zog die Proxy-Umbenennung in den Doku-Commit. Wieder
|
||
getrennt.
|
||
- `scripts/screenshots.ts` wurde geschrieben, ohne danach `npm run
|
||
pruefen` laufen zu lassen; der Typfehler fiel erst im Docker-Bau auf.
|
||
|
||
### Offene Punkte
|
||
|
||
- Die `origin`-URL fehlt noch. Push und Merge stehen ohnehin erst nach
|
||
der Freigabe an.
|
||
- Der Schnellstart endet beim Passkey statt beim ersten Kalenderkonto und
|
||
der ersten Aufgabe — beides gibt es erst mit M3 und M2.
|
||
- Der Demo-Seed enthält noch keine erfundenen Termine; einen
|
||
Demo-Kalenderprovider gibt es erst mit M3.
|
||
- Lokal weichen die Ports ab (Datenbank 5435, App 3001), weil 5432 und
|
||
3000 auf diesem Rechner belegt sind. In `.env.example` stehen die
|
||
üblichen Werte.
|
||
|
||
### Commits
|
||
|
||
- de1f923 chore: Projektgerüst und Werkzeugkette einrichten
|
||
- 748d032 feat(datenbank): Datenmodell für Anmeldung, Bereiche und Audit
|
||
- e2b00f4 feat(instanz): Instanzsteuerung mit serverseitigem Riegel
|
||
- 19ca082 feat(zeit): Zeitrechnung und Anzeigeformate in Europe/Berlin
|
||
- 4ff67c1 feat(oberflaeche): Grundlayout, Navigation und Farbschema
|
||
- cc013fd feat(anmeldung): OIDC, Passkeys und Passwort mit Auth.js v5
|
||
- e9a2b4b feat(bereiche): Bereiche verwalten mit Rollenprüfung und Audit
|
||
- 1876ae4 feat(betrieb): Health-Endpunkt und Seed für eine frische Datenbank
|
||
- 24a799d chore: tsconfig-Anpassungen von Next 16 übernehmen
|
||
- 126ad93 test: Integrations-, Migrations- und E2E-Tests ergänzen
|
||
- f91d015 feat(betrieb): Abbild, Compose-Stapel und Betriebsskripte
|
||
- 56b5356 docs: README, Schnellstart, Handbuch, Fahrplan und CHANGELOG
|
||
- e3390c8 refactor: middleware in proxy umbenennen
|
||
- a882731 chore: Screenshot-Kette und Demo-Seed
|
||
- cf28ec1 test: Rollentrennung end-to-end absichern
|
||
- 6d04bc2 fix(oberflaeche): Kopfleiste einzeilig halten, Demo-Uhr feststellen
|
||
- 688d9f5 docs: Handbuchbilder aufnehmen
|