Files
Laufzettel/docs/issues/005-geruest-prozess-design.md
florian.wilde d8d5444e9f
Prüfung / pruefung (push) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s
feat(vorlagen): Versionierung, Unveraenderlichkeit und JSON-Austausch (#23)
2026-09-25 06:10:01 +00:00

69 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# #005 M0 – Gerüst, Prozess, Design-Token
**Status:** erledigt
**Meilenstein:** v0.1.0
**Labels:** phase-1, infra, docs
**Geschätzt:** 6 h **Tatsächlich:** 1 h 25 min
## Ziel
Ein lauffähiges, leeres Projekt mit allen Qualitätsschranken, dem gehärteten Betriebsstand und dem Design-Fundament. Danach ist jeder weitere Meilenstein reine Fachlichkeit.
## Aufgaben
- [x] Lokalen Branch `master` auf `main` umbenennen (Gitea-Default ist `main`), Remote unverändert lassen
- [x] `.nvmrc` = `24`, `packageManager: "pnpm@10.34.5"` über corepack, `engines.node >= 24`
- [x] Next 16.3.6 (App Router, TypeScript strict) mit `output: "standalone"`, `src/`-Layout
- [x] `tsconfig.json`: `strict`, `noUncheckedIndexedAccess`, `verbatimModuleSyntax`, `forceConsistentCasingInFileNames`, Alias `@/*` → `./src/*`
- [x] Tailwind 4 (`@import "tailwindcss"` + `@theme`, `@tailwindcss/postcss`), shadcn/ui initialisieren, `lucide-react`
- [x] ESLint flat config nach ProxLedger-Muster (`eslint-config-next/core-web-vitals` + `/typescript` + `eslint-config-prettier/flat`, `globalIgnores` inkl. `src/generated/**`), Prettier (`printWidth: 110`, `singleQuote: false`, `trailingComma: "all"`)
- [x] husky + lint-staged + commitlint (`@commitlint/config-conventional`) als Pre-Commit- und Commit-Msg-Hook
- [x] Vitest 5 (`vitest.config.mts`, `environment: "node"`, `fileParallelism: false`) und `vite@^7` als Peer; Playwright 1.63 (`playwright.config.ts`)
- [x] `Dockerfile` multi-stage (Basis → Abhängigkeiten → Bauen → Laufzeit), `node:24-alpine`, `tini`, Nutzer 1001, non-root
- [x] `docker-compose.yml` gehärtet: `postgres` **ohne** `ports:`, Netze `intern` (`internal: true`) und `extern`, `web` auf `${BIND_ADDR:-127.0.0.1}:3000`, `migrate` als One-Shot aus der Bau-Stufe, Healthchecks, `${VAR:?… fehlt in der .env}`
- [x] `docker-compose.dev.yml` (nur Postgres, Port 5433) und `docker-compose.test.yml` (Postgres; der OpenLDAP-Dienst kommt mit #016, wo er tatsächlich benutzt wird)
- [x] `.env.example` mit allen Variablen und Kommentar je Variable
- [x] `GET /api/gesundheit` → `SELECT 1` → 200/503
- [x] Sicherheitskopfzeilen in `next.config.ts`, CSP-Nonce in `proxy.ts` (Next 16: nicht `middleware.ts`)
- [x] `scripts/pruefe-doku.mjs` und `pnpm pruefe:doku`: Version hat Changelog-Abschnitt, Issue-Dateien und Übersicht stimmen überein, verlinkte Bilder existieren
- [x] `scripts/gitea-issues.ts` und `pnpm issues:sync`: spiegelt `docs/issues/*.md` in den Gitea-Tracker
- [x] `.gitea/workflows/ci.yml` nach ProxLedger-Muster, erweitert um Playwright und `shellcheck`
- [x] Design-Token als CSS-Variablen (Grund `#0B0D10`, Flächen `#14171C`/`#1B1F26`, Linien `#262B33`, Text `#F3F5F7`/`#98A2B3`, Akzent `#C6F135`, Status `#3DDC97`/`#F5B84A`/`#F87171`), heller Modus optional
- [x] Schriften selbst gehostet: `@fontsource-variable/space-grotesk`, `-manrope`, `-jetbrains-mono`
- [x] Wortmarke `laufzettel` (Space Grotesk 700, Laufweite −0.04em, Akzentpunkt) und Bildmarke `[ ✓ ]` als SVG, Favicon, PWA-Icon, `manifest.ts`
- [x] App-Shell: dunkle Sidebar mit „Scannen“-Knopf direkt unter dem Logo, Pillen-Buttons (40 px, am Handy 44–46 px), Karten mit Radius 16–18 px und 1-px-Linie ohne Schatten
- [x] Versionsanzeige unten links aus `NEXT_PUBLIC_APP_VERSION` und `NEXT_PUBLIC_GIT_SHA`
- [x] `README.md`, `CHANGELOG.md` (Keep a Changelog, deutsch), `docs/devlog.md`, `CLAUDE.md` mit Konventionen und Namensabbildung, `docs/architektur.md`, `docs/abnahme-mvp.md`
- [x] Gitea: Labels, Milestones `v0.1.0`…`v0.5.0`, Epic-Issues #001–#004 und Meilenstein-Issues #005–#019
## Akzeptanzkriterien
- [x] `docker compose up` startet App und Datenbank, Migrationen laufen automatisch
- [x] `nc -z localhost 5432` schlägt fehl, `docker compose exec web nc -z postgres 5432` gelingt
- [x] Ein Vitest-Test liest `docker-compose.yml` und schlägt an, wenn unter `postgres` ein `ports:` auftaucht
- [x] `pnpm lint && pnpm typecheck && pnpm test && pnpm pruefe:doku` grün
- [x] Ein Commit ohne Conventional-Commits-Betreff wird vom Hook abgelehnt
- [x] Die App zeigt Wortmarke, Bildmarke und Version unten links im vorgegebenen Farbschema
## Beim Bauen aufgefallen
- **pnpm 12 hat die Freigabe von Build-Skripten umbenannt.** `onlyBuiltDependencies` wird von
`pnpm config list` noch angezeigt, aber nicht mehr angewandt; wirksam ist `allowBuilds` als
Zuordnung in `pnpm-workspace.yaml`. Das `pnpm`-Feld in `package.json` liest pnpm 12 gar nicht
mehr und warnt darüber.
- **pnpm 12 prüft die Lieferkette.** Pakete, die jünger als 24 Stunden sind, werden abgelehnt.
`vite@8.3.1` und `lucide-react@1.48.0` erschienen am selben Tag und mussten auf `8.3.0` bzw.
`1.47.0` zurück. Die Richtlinie bleibt an — sie ist sinnvoll.
- **eslint 10 bricht mit `eslint-config-next`.** `eslint-plugin-react@7.37.5` unterstützt nur bis
`eslint ^9.7` und hat keinen Nachfolger. Festgestellt, nicht geraten:
`TypeError: contextOrFilename.getFilename is not a function`.
- **TypeScript 7 geht noch nicht.** `typescript-eslint@8` erlaubt `>=4.8.4 <6.1.0`.
- **`shadcn init` ist nicht skriptfähig** — es fragt nach einem Preset, auch mit `--yes`, und
bleibt hinter einer Pipe hängen. `shadcn add <bauteil> --yes --overwrite < /dev/null`
funktioniert dagegen. Die Registry importiert den Helfer als blanken Modulnamen `cn`, dafür
braucht `tsconfig.json` den Pfad `"cn": ["./src/lib/utils"]`, und die Bauteile brauchen das
Paket `radix-ui`.
- **Port 3000 war von ProxLedger belegt**, die Abnahme lief deshalb auf 3100 bzw. 3200.
- Die Migrationen laufen im Compose-Stand nachweislich automatisch; eingespielt wird ab #006
etwas, vorher meldet der Dienst korrekt „No pending migrations to apply“.