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>
106 lines
5.3 KiB
Markdown
106 lines
5.3 KiB
Markdown
# 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.
|