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>
101 lines
4.5 KiB
Markdown
101 lines
4.5 KiB
Markdown
# 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).
|