feat: Grundgerüst mit Anmeldung, Layout und Design-Tokens

Next.js 16, Prisma 7, Tailwind 4 und Vitest/Playwright, Konfiguration aus
Laufzettel übernommen, weil dort derselbe Stack erprobt ist.

Die Farben der Branding-Vorgabe stehen als Tokens in globals.css, das
helle Theme setzt dieselben Namen neu. Amber und Rot sind dort
abgedunkelt, sonst reicht der Kontrast nicht – ein Test prüft beide
Themes gegen 4,5:1.

Anmeldung mit lokalem Benutzer, Rolle je Anfrage aus der Datenbank,
Audit-Log per Trigger nur anhängbar. Geprüft im gebauten Stand auf
1440 px und 390 px.

Closes #001

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 09:23:41 +02:00
co-authored by Claude Opus 5.5
parent c3211d0fe2
commit 871bb3a77c
75 changed files with 10155 additions and 15 deletions
+105
View File
@@ -0,0 +1,105 @@
# Konventionen für ProxDeploy
Diese Datei ist verbindlich. Wer hier etwas ändert, ändert es auch in `docs/architektur.md`.
## Sprache
**Deutsch, überall wo ein Mensch liest oder benennt** – auch Bezeichner: Funktionen, Variablen,
Prisma-Modelle und -Felder, Enum-Werte, Fehlerklassen, Dateinamen, Kommentare, Testbeschreibungen,
Commit-Betreffs. **Umlaute in Bezeichnern ASCII-gefaltet** (`geaendertAm`, `pruefen`), in Texten für
Menschen richtig geschrieben („Verbindung prüfen“).
Englisch bleiben: vom Framework vorgegebene Namen (`GET`, `route.ts`, `page.tsx`, `proxy.ts`),
Fachjargon (`Token`, `OIDC`, `VMID`, `Node`, `Storage`, `Bridge`, `Template`, `cloud-init`) und die
**YAML-Schlüssel im Katalog** (`catalog/**`) – die sind ein Austauschformat aus der Vorgabe.
## Namensabbildung zur Vorgabe
| Vorgabe | Modell / Begriff | Vorgabe | Modell / Begriff |
|---|---|---|---|
| User | `Benutzer` | Deployment / Job | `Auftrag` (Art `AUSROLLEN`, `TEMPLATE_BAUEN`, `AUFRAEUMEN`) |
| API token (CLI) | `ApiToken` | Phase | `Phase` |
| SSH key | `SshSchluessel` | Job log line | `Logeintrag` |
| Server | `Server` | VMID lock | `VmidReservierung` |
| Node | `knoten` (Feld) | Proxmox template | `Template` |
| Distribution | `Distribution` | Preset | `Vorlage` |
| Profile | `Profil` | Audit log | `Protokoll` |
| Setting | `Einstellung` | Key provider | `SchluesselQuelle` |
API-Pfade sind deutsch: `/api/v1/server`, `/api/v1/auftraege`, `/api/v1/vorlagen`.
## Schichtung
```
src/engine/* Deploy-Logik, frameworkfrei: kein Next, kein Prisma, kein React.
src/server/services/* Regeln und Schreiboperationen; rufen Engine und Prisma.
src/server/auth/* Sitzung, Tokens, Rechte (RECHTE + darf()).
src/app/api/v1/* Route Handler: Recht prüfen, zod, Service. Sonst nichts.
src/components/* Darstellung, keine Geschäftslogik.
src/lib/* Framework-freie Helfer; was Client und Server teilen, liegt hier.
src/worker/* Hintergrundprozess (pg-boss).
```
- **Web-GUI und CLI nutzen dieselbe REST-API.** Keine Logik nur für eine Oberfläche.
- **Phasentexte kommen aus der Engine.** Web und CLI rendern Name, Status, Detail, Dauer, Ursache,
Hinweis – sie erfinden keinen Text.
- **Jede Seite und jeder Route Handler prüft sein Recht selbst** (`seiteSchuetzen`,
`rechtErforderlich`). `tests/zugang.test.ts` prüft das strukturell; Ausnahmen stehen dort mit
Begründung. Rolle und Aktiv-Status werden je Anfrage aus der DB gelesen.
- **Client-Komponenten importieren nichts aus `src/server/*`.**
- **Fehler an Aufrufer** nur als `AnwendungsFehler` (Status, Code, Nachricht, Hinweis); Format
`{ fehler: { code, nachricht, hinweis?, felder? } }`.
- **zod nur über `@/lib/validierung`** (deutsche Meldungen; ESLint erzwingt das).
- **Datenbankregeln** (Trigger, CHECK) stehen in den Migrationen und namentlich in
`tests/datenbankregeln.test.ts`.
## Werkzeuge und Versionen
Node 24 über nvm (`export NVM_DIR="$HOME/.nvm"; . "$NVM_DIR/nvm.sh"`), pnpm 12. Exakt gepinnt:
`next@16.4.0`, `react@19.3.0`, `prisma`/`@prisma/client`/`@prisma/adapter-pg` **`7.10.0`**
(der `latest`-Tag von prisma zeigt auf einen 8.0-RC), `vitest@5.0.1`, `@playwright/test@1.63.0`,
`pino@10.4.0`. Obergrenzen: **eslint 9.x** (eslint-plugin-react aus eslint-config-next kann 10 nicht),
**typescript ~6.0.3** (typescript-eslint 8 erlaubt < 6.1).
Next 16: `proxy.ts` statt middleware; `cookies()`, `headers()`, `params`, `searchParams` sind async.
Prisma 7: Client aus `@/generated/prisma/client`, Enum-Werte aus `@/generated/prisma/enums`, Zugriff
über den Lazy-Proxy `src/lib/db.ts`.
## Vor jedem Commit
```bash
pnpm db:up
pnpm lint && pnpm typecheck && pnpm format:pruefen && pnpm test
```
Ohne laufende Datenbank überspringt `pnpm test` die Datenbanktests und sagt es auf stderr.
## Oberfläche prüfen – immer im gebauten Stand
```bash
pnpm build && PORT=3310 APP_URL=http://127.0.0.1:3310 pnpm start &
pnpm test:e2e
```
`next dev` hydriert in dieser Umgebung nicht verlässlich; ein Screenshot beweist dann nichts. Die
Abläufe prüfen Desktop (1440 px) und Handy (**390 px, kein horizontales Scrollen**).
## Git, Versionen, Zeiterfassung
- Branch `main`; je Issue/Etappe `phase/NNN-kurzname`, nach Abschluss `--ff-only` nach `main`.
- Conventional Commits, deutscher Betreff ≤ 72 Zeichen, Körper erklärt das Warum, Fußzeile
`Closes #NNN` bzw. `Refs #NNN`. Identität `Florian Wilde <wilde.florian@gmail.com>`.
- SemVer; jede Etappe ein annotierter Tag `vX.Y.Z`. **1.0.0 erst nach dem Feldtest** auf echtem
Proxmox 8.x und 9.x (#020).
- `CHANGELOG.md` (Keep a Changelog, deutsch) und `DEVLOG.md` (Zeit je Issue/Meilenstein aus den
Commit-Zeitstempeln, Sitzungen mit „Erledigt“ und „Entscheidungen“) werden mit jedem Issue gepflegt;
`docs/issues/*.md` tragen Status und tatsächliche Zeit.
## Gestaltung
Farben nur als Tokens aus `src/app/globals.css` (`bg-panel`, `text-muted`, `border-linie`,
`text-akzent`, `text-laeuft`, `text-fehler`); keine rohen Hexwerte in Komponenten. Ausnahmen:
`themeColor` in `src/app/layout.tsx` (verträgt keine CSS-Variablen) und die Brand-Dateien unter
`public/brand/`. Kein Proxmox-Orange. Status immer Symbol + Farbe + Text (`<Status>`).
Karten mit 1-px-Linie, Radius 14 px, keine Schatten, keine Verläufe. Kontrast ≥ 4,5:1 in beiden Themes
(`tests/kontrast.test.ts`). Icons: Lucide.