# 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. ## Tests brauchen die Testdatenbank für sich allein `tests/hilfen/db.ts` leert vor jedem Test alle Tabellen. Zwei gleichzeitige Läufe (z. B. ein Sub-Agent und die Hauptsitzung) räumen sich gegenseitig die Daten weg – das sieht aus wie ein echter Fehler („No record was found for an update“). Parallel Prüfende bekommen deshalb eine **eigene** Datenbank: ```bash docker exec sshkv-dev-db psql -U sshkv -c "create database sshkv_test_" TEST_DATABASE_URL=postgresql://sshkv:sshkv@localhost:5436/sshkv_test_?schema=public pnpm test ``` ## Vor jedem Commit ```bash pnpm lint && pnpm typecheck && pnpm format:pruefen && pnpm test ``` Vor jedem Merge zusätzlich `pnpm test:integration` (braucht Docker).