chore: Projektgeruest mit Next.js 16, Prisma 7 und pnpm (#001)

Konfiguration aus Laufzettel uebernommen, damit alle Projekte gleich
gebaut und geprueft werden. Entwicklungsdatenbank auf 5436, weil 5433
und 5434 von ProxLedger und Laufzettel belegt sind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 09:05:15 +02:00
co-authored by Claude Opus 5.5
parent cd83542482
commit cef9510f18
29 changed files with 8127 additions and 9 deletions
+100
View File
@@ -0,0 +1,100 @@
# Konventionen für SSHKeyVault (`sshkv`)
Diese Datei ist verbindlich. Plan und Begründungen: `docs/PLAN.md`. Arbeitsweise wie in
Laufzettel und ProxLedger.
## Arbeitsweise
- Issues liegen als Dateien in `docs/issues/NNN-slug.md` und sind die Quelle der Wahrheit;
`pnpm issues:sync` überträgt sie nach Gitea (#030).
- Je Issue ein Branch `phase/NNN-slug`, Merge nach `main` mit `--no-ff`.
- Conventional Commits auf Deutsch, Betreff ≤ 72 Zeichen, Umlaute im Betreff gefaltet,
`(#NNN)` am Ende. Der Body erklärt das **Warum**.
- `DEVLOG.md`: Zeit je Issue und Meilenstein, Sitzungen mit „Erledigt“ und „Entscheidungen“.
- `CHANGELOG.md`: Keep a Changelog, deutsch. Tag `vX.Y.Z` je Meilenstein; Version in `package.json`.
## Sprache
**Deutsch, überall wo ein Mensch liest oder benennt** – auch Bezeichner (Funktionen, Variablen,
Prisma-Modelle und -Felder, Enum-Werte, Dateinamen, Tests). **Umlaute in Bezeichnern werden
ASCII-gefaltet** (`Schluessel`, `geaendertAm`). Oberflächentexte, Fehlermeldungen und
Protokoll-Aktionen schreiben sich richtig („Schlüssel widerrufen“).
Englisch bleiben Framework-Namen (`page.tsx`, `route.ts`, `GET`) und Fachjargon
(`Host`, `Fingerprint`, `Token`, `OIDC`, `authorized_keys`, `Public Key`, `Private Key`, `Drift`).
Kommentare erklären **warum**, nicht was, und tragen wo hilfreich die Issue-Nummer `(#007)`.
## Namensabbildung zum Plan
| Plan | Modell | Plan | Modell |
|---|---|---|---|
| User | `Benutzer` | PublicKeyUsage | `PublicVerwendung` |
| Person | `Person` | PrivateKeyUsage | `PrivateVerwendung` |
| Customer | `Kunde` | ManagedAccount | `Zielkonto` |
| Host | `Host` | Template | `Vorlage` |
| HostGroup | `Hostgruppe` | Observation | `Beobachtung` |
| HostKey | `HostSchluessel` | DriftFinding | `Abweichung` |
| SshKey | `Schluessel` | Operation | `Vorgang` |
| AuditEvent | `Protokoll` | Setting | `Einstellung` |
## Schichtung
```
src/server/services/* Regeln und Schreiboperationen.
src/server/queries/* Lesemodelle. Wenden die Rolle selbst an.
src/server/actions/* Dünne "use server"-Einstiege: Recht prüfen, zod, Service rufen.
src/server/auth/* Anmeldung, Sitzung, Rechte, Re-Auth.
src/lib/* Framework-freie Helfer (kein Next, kein React, kein Prisma) – gut testbar.
src/lib/ssh/* OpenSSH-Formate, authorized_keys-Parser, Fingerprints. Rein.
src/worker/* Alles, was SSH spricht oder den Master-Key braucht. Läuft nur im Worker.
src/components/* Darstellung, keine Geschäftslogik.
```
## Feste Regeln
- **Private Keys** erscheinen nie in Logs, Fehlermeldungen, Listenantworten, Props von
Client-Komponenten oder im Protokoll. Prisma-Abfragen auf `Schluessel` nutzen feste
`select`-Listen; `privatVerschluesselt` liest nur `src/worker/geheimnisse.ts`.
- **Master-Key nur im Worker.** Der Webprozess importiert nichts aus `src/worker/*`.
- **Kein Klartext-Passwort** (Bootstrap) in Datenbank, Job-Payload, Log oder Protokoll.
- **Host-Keys werden strikt geprüft.** Es gibt keinen Codepfad, der einen geänderten Host-Key
automatisch annimmt.
- **Rechte** nur serverseitig über `darf()`; jede Seite und jeder Route Handler prüft selbst.
Rolle wird pro Anfrage aus der Datenbank gelesen, nicht aus dem Token.
- **Protokoll** ist append-only (Trigger) und über eine Hash-Kette verbunden.
- Zod immer über `@/lib/validierung` importieren (deutsche Meldungen).
## Werkzeuge und Versionen
Node 24 (`.nvmrc`), pnpm 12. Exakt gepinnt: `next@16.3.6`, `react@19.3.0`,
`prisma`/`@prisma/client`/`@prisma/adapter-pg` `7.10.0`, `vitest@5.0.1`, `vite@8.3.0`,
`@playwright/test@1.63.0`. `eslint` bleibt auf 9.x, `typescript` auf `~6.0.3`
(Gründe siehe Laufzettel/CLAUDE.md).
**Next 16:** `middleware.ts` heißt `proxy.ts`. `cookies()`, `headers()`, `params`,
`searchParams` sind async.
**Prisma 7:** Generator `prisma-client` nach `src/generated/prisma`, Zugriff über
`@prisma/adapter-pg`, Lazy-Proxy in `src/lib/db.ts`. Typen aus `@/generated/prisma/client`,
Enum-Werte aus `@/generated/prisma/enums`.
## Entwicklung
```bash
pnpm db:up # PostgreSQL auf 127.0.0.1:5436
pnpm db:migrate && pnpm db:seed
pnpm dev # http://localhost:3400
pnpm worker # zweites Terminal
```
Oberflächen immer gegen den **gebauten Stand** prüfen (`pnpm build && pnpm start`) – siehe
Laufzettel: `next dev` hydriert in dieser Umgebung nicht zuverlässig.
## Vor jedem Commit
```bash
pnpm lint && pnpm typecheck && pnpm format:pruefen && pnpm test
```
Vor jedem Merge zusätzlich `pnpm test:integration` (braucht Docker).