Files
certvia/docs/HANDOVER-DEV.md
msolarczekandClaude Opus 4.8 2ec0230f57 Doku: Konsolidierte Übergabe des dev-Stands (PM + neue Entwickler)
Neues Dokument docs/STAND-dev-branch.md fasst alle Entwicklungstätigkeiten
auf dev zusammen: Produktionshärtung (Pakete 1-3), Benutzer-/Rollenverwaltung
(A/B/C), Freigabe-Workflow + Aufgaben-Modul, Richtlinien-Governance und
GAP-Report (WP1-4, E2). Enthält fachlichen Status für PM, technische
Landkarte (neue Modelle, 6 Migrationen, Auth-Architektur, Modul-Guards,
Fallstricke), Commit-Übersicht und nächste Schritte.

HANDOVER-DEV.md und HANDOVER-PM.md verweisen prominent darauf.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 17:25:45 +02:00

198 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Entwickler-Übergabe — ISMS-Tool
> 📌 **Aktueller Gesamtstand des `dev`-Branches (alle Entwicklungstätigkeiten, PM + Dev):** siehe **`docs/STAND-dev-branch.md`**.
> Stand: 2026-07-22 · Branch `dev` (Produktionshärtung + Benutzerverwaltung) · Basis `main`
> Zweck: Kontext, Setup und Konventionen, damit ein neuer Entwickler direkt weiterarbeiten kann.
> Fachlicher Status (fertig/offen) siehe **`docs/HANDOVER-PM.md`**. Neue Härtungs-/Verwaltungspakete: §10.
---
## 1. Repository & Zugriff
- **Lokaler Pfad:** `~/Projects/ISMS-Tool`
- **Git-Remote (Gitea, nur HTTP):**
`http://gitea-vkbhbn2qdkz5ppk9q4qgb0tn.192.168.1.207.sslip.io/msolarczek/ISMS-Tool.git`
(interner Server; kein SSH). **Zugangstoken** liegt im macOS-**Schlüsselbund** (nicht im Repo, nicht in Klartext weitergeben). Für `git push` wird der Token als HTTP-Passwort verwendet.
- **Default-Branch:** `main` (es wird direkt auf `main` committet; Commits sind fein granular je Thema).
- **Commit-Konvention:** deutschsprachige, aussagekräftige Messages; Referenz auf Spec-Abschnitte (z. B. „§7b"). Co-Authored-By-Trailer für KI-Beiträge.
---
## 2. Tech-Stack (verifizierte Versionen)
| Bereich | Technologie |
|--------|-------------|
| Runtime | **Node.js 26** |
| Framework | **Next.js 16** (App Router, React 19, Server Components + Server Actions, Turbopack im Dev) |
| Sprache | TypeScript (strict) |
| DB / ORM | **PostgreSQL** (mit **pgvector**) · **Prisma 7** (`@prisma/client` + `@prisma/adapter-pg`, `prisma.config.ts`) |
| Auth | **NextAuth v5** (Credentials, JWT-Session) · Passwörter mit `@node-rs/argon2` |
| i18n | **next-intl** (Default `de`, `en` vorbereitet; Catalog in `messages/de.json`/`en.json`) |
| UI | Tailwind **v4** + shadcn/ui (**Base-UI-Variante**), Dark-Theme über zentrale CSS-Tokens in `src/app/globals.css` |
| Spezial | Handlebars + `marked` (Richtlinien-Rendering), `@xyflow/react` + `@dagrejs/dagre` (Abhängigkeitsgraph), `zod` (Validierung) |
**Scripts** (`package.json`): `dev` (`next dev`), `build`, `start`, `lint` (`eslint`). Seed: `npx tsx prisma/seed.ts`.
---
## 3. Setup (von Null)
```bash
# 1. Repo klonen (Token als HTTP-Passwort)
git clone http://gitea-…/msolarczek/ISMS-Tool.git
cd ISMS-Tool
# 2. Abhängigkeiten
npm install
# 3. .env anlegen (Vorlage vorhanden)
cp .env.example .env
# Wichtige Variablen: DATABASE_URL (Postgres inkl. pgvector), AUTH_SECRET, AUTH_URL,
# optional REDIS_URL, AI_PROVIDER/AI_API_KEY, SMTP_* (noch ungenutzt).
# 4. Infrastruktur starten (docker-compose.yml im Repo-Root)
docker compose up -d postgres # Postgres mit pgvector (Image pgvector/pgvector:pg16)
# Weitere Services im Compose: app, worker, redis, minio (Objektspeicher, für späteren
# Logo-Upload), mailhog (SMTP-Dev). Für lokale Entwicklung reicht i. d. R. 'postgres'.
# 5. Prisma-Client + Migrationen
npx prisma generate
npx prisma migrate deploy # wendet alle Migrationen an (inkl. RLS-Policies)
# 6. Seed (Demo-Mandant, Kataloge, Richtlinienpaket, Admin-Konsole)
npx tsx prisma/seed.ts
# 7. Dev-Server
npm run dev # http://localhost:3000 (Port 3000, siehe .claude/launch.json)
```
**Demo-Logins** (Passwort `Demo1234!`): `admin@demo.example` (Mandanten-Admin + ISB), `bea.approver@demo.example` (ISB, zweiter Freigeber für den Vier-Augen-Workflow), `auditor@demo.example`, `owner@demo.example`, `user@demo.example` — alle über den **Mandanten-Login** `/login`.
**Plattform-Admin (Betrieb):** getrennter Store + eigener Login `/platform/login` (TOTP-MFA-Pflicht, Enrollment beim ersten Login). Demo-Konto: `admin@demo.example` / `Demo1234!` (gleiche Adresse, aber getrennte Session ohne Mandantenkontext). Das frühere `isPlatformAdmin`-Flag ist abgelöst; die Admin-Konsole `/admin` ist nur mit Plattform-Session erreichbar. Siehe **Paket 2** der Produktionshärtung.
---
## 4. Architektur & tragende Konventionen
### Mandantenfähigkeit (kritisch!)
- Jede Fachtabelle hat `tenant_id`. **Nie ohne Mandantenkontext queren.**
- Zentraler Guard **`dbForTenant(tenantId)`** in `src/server/db.ts`: filtert reads automatisch nach `tenantId`, injiziert ihn bei `create`, prüft Ownership bei `findUnique`/`update`/`delete`. Neue tenant-bezogene Modelle **müssen in `TENANT_MODELS`** (in `db.ts`) eingetragen werden.
- Zusätzlich **Postgres Row Level Security** je Tabelle (Policy `tenant_isolation`, gesetzt in den Migrationen). Superadmin/plattformweite Reads laufen über den **rohen `prisma`**-Client (nicht `dbForTenant`).
- Session (`src/server/auth.ts`) trägt `tenantId`, `roles`, `permissions`, `isPlatformAdmin`.
### RBAC
- Katalog + Rollen-Blueprints in **`src/server/rbac.ts`** (`PERMISSIONS`, `ROLE_DEFS`). Serverseitige Durchsetzung: `requirePermission(session, "x:y")` / `hasPermission(...)`. UI-Verstecken ist nur Komfort.
### Modul-Gating (§3.4)
- Modul-Katalog in **`src/lib/modules.ts`**. Je Mandant `TenantModule`-Zeilen (enabled). Navigation blendet deaktivierte Module aus (`layout.tsx`).
- **Serverseitige Durchsetzung:** `requireModule("key")` in `src/server/modules.ts`, angewandt als **Modul-`layout.tsx`** je Routenordner (`assets/`, `processes/`, `risks/`, `measures/`, `policies/`, `suppliers/`, `dependencies/`) → schützt auch Unterrouten. In Server-Actions läuft der Layout-Guard erst nach der Mutation, daher zusätzlich `requireModule` im Action-`guard()` (bisher exemplarisch nur `policies.ts`**auf übrige Action-Dateien nachzuziehen**).
### UI-Muster
- **Detail/Bearbeiten/Anlegen** überwiegend als **URL-gesteuerte Popups** (`?detail=`/`?edit=`/`?new=1`, `src/components/modal.tsx`) — Ausnahme: **Richtlinien-Dokumente** wurden bewusst auf **eigene Seiten** (`/policies/[code]`, `.../edit`) umgestellt.
- Dark-Theme: **keine hartkodierten Hex-Werte** in Komponenten — zentrale Tokens verwenden (`--bg-0`, `--panel`, `--surface-soft`, `--band`, `--ok/--warn/--risk/--info`, …).
- Formulare mit „einem Speichern-Button" nutzen HTML-`form`-Attribut-Assoziation (`form="id"`).
- Alle sichtbaren Texte über den next-intl-Catalog (`messages/*.json`) — Admin-/Register-Detailtexte teils bewusst inline-Deutsch.
### Prisma-7-Migrationen (Eigenheit)
Nicht-interaktiv, in zwei Schritten:
```bash
npx prisma migrate diff --from-config-datasource prisma.config.ts \
--to-schema prisma/schema.prisma --script > prisma/migrations/<ts>_name/migration.sql
# RLS-DO-Block manuell an die migration.sql anhängen (siehe bestehende Migrationen)
npx prisma migrate deploy
```
(Die interaktiven `migrate dev`-Prompts sind in dieser Umgebung blockiert; Flag-Namen in Prisma 7 geändert: `--from-config-datasource`/`--to-schema`.)
---
## 5. Verzeichnisstruktur (Auszug)
```
src/
app/(app)/ # geschützter App-Bereich (Sidebar-Shell = layout.tsx)
dashboard/ assets/ processes/ risks/ measures/ dependencies/ suppliers/
policies/ # Richtlinien: page + [code]/(page,edit) + layout.tsx (Modul-Guard)
admin/ admin/[id]/ # Plattform-Admin-Konsole (Superadmin)
settings/ # Kunden-Einstellungen (tenant:manage)
app/login/ # Login
components/ # UI + Fach-Modals (asset-, supplier-, service-, policy-*.tsx …)
server/
auth.ts db.ts rbac.ts modules.ts provision.ts audit.ts
risk-calc.ts dependency-graph.ts
actions/ # Server Actions je Modul (assets, risks, measures, suppliers,
# services, policies, admin, tenant-settings)
lib/ # modules, policy-render, supplier(+include), risk, control-titles,
# isa-controls, levels, measure, utils
prisma/
schema.prisma seed.ts import-policies.ts import-managed.ts migrations/
messages/ de.json en.json
seed/isms-vorlagenpaket-v2/ # VDA-ISA-Vorlagenpaket (Richtlinien/Verfahren, mapping.json, Baseline …)
docs/ SPEC.md HANDOVER-PM.md HANDOVER-DEV.md *.html (Mockups)
```
---
## 6. Modul-Kurzreferenz (wo liegt was)
- **Richtlinien:** Rendering-Engine `src/lib/policy-render.ts` (Handlebars, Flags, BL-Entfernung, `applyProtection` für TISAX-Level), Import `prisma/import-policies.ts` + `prisma/import-managed.ts`, UI `src/app/(app)/policies/**` + `src/components/policy-*.tsx`, Actions `src/server/actions/policies.ts`. Control-Titel `src/lib/control-titles.ts`.
- **Lieferanten/IT-Service:** Engine `src/lib/supplier.ts`, Includes `src/lib/supplier-include.ts`, UI `src/components/supplier-modals.tsx`/`service-modals.tsx`/`supplier-cockpit.tsx`, Actions `suppliers.ts`/`services.ts`.
- **Admin/Mandanten:** Provisionierung `src/server/provision.ts` (von Seed **und** `actions/admin.ts` genutzt, idempotent), `actions/tenant-settings.ts` (Stammdaten → ISMS-Variablen via `syncPolicyVariablesFromSettings`).
- **Risiko/Graph:** `src/server/risk-calc.ts`, `src/server/dependency-graph.ts`, `src/lib/risk.ts`.
---
## 7. Datenmodell — zentrale Modelle
`Tenant`, `TenantSettings` (Quelle der ISMS-Variablen), `TenantModule`, `User` (`isPlatformAdmin`), `Role`/`Permission`/`RolePermission`/`UserRole`, `AuditLog` (`scope: tenant|platform`).
Fachlich: `Asset`/`AssetRelation`, `Process`/`ProcessAsset`/`BiaEntry`, `Risk`/`RiskAsset`/`Measure`/`RiskMeasure`, `Threat`/`Vulnerability`, `SupplierProfile`/`ITServiceProfile` (+ Assessments/Contracts/Ndas/Evidence/Raci/Maturity), Richtlinien: `PolicyDocument`/`PolicyRequirement`/`PolicyVariable`/`PolicyBaselineParam`/`PolicyEvidence` + verwaltete Register (`CryptoEntry`, `ClassificationClass`/`HandlingAspect`/`HandlingRule`, `RiskMatrixClass`/`RiskEwLevel`/`RiskDamageDimension`, `HandbookTopic`).
---
## 8. Verifikations-Workflow
Nach jeder Änderung: **`npx tsc --noEmit`** → **`npm run lint`** → **`npm run build`**. Danach wo relevant Browser-Verifikation (Dev-Server + Login `admin@demo.example`). Bei DB-Änderungen: Migration erzeugen/anwenden + `npx tsx prisma/seed.ts` neu laufen lassen. Für das Richtlinien-Rendering existiert ein Residue-Check-Muster (rückstandsfrei über Flag-Kombinationen, angelehnt an `seed/.../_verify.py`).
---
## 9. Bekannte Fallstricke
1. **Beschädigte Seed-Tokens:** Das VDA-ISA-Paket enthält in einigen VA-RACI-Tabellen (VA-05/08/09/10/12/13) abgeschnittene `{{VAR |`-Tokens. Bei jedem Paket-Update **erneut prüfen & reparieren** (sonst bricht Handlebars). Scan: unbalancierte `{{`/`}}` je Zeile.
2. **Richtlinien-Re-Import ist nicht-destruktiv** (Phase-1-Härtung Paket 3, `prisma/import-policies.ts`): Diff/Upsert über stabile Schlüssel (`code`/`reqId`/`key`/`blId`/`nr`). Vorhandenes wird inhaltlich aktualisiert, aber **Status/Override/Freigabe** (PolicyDocument) und **nutzergepflegte Variablenwerte** bleiben erhalten; entfernte Paket-Einträge werden **deaktiviert** (`archivedAt`) statt gelöscht (aktive Ansichten filtern `archivedAt: null`). Verwaltete Register aus `import-managed.ts` (CRYPTO/RISKMATRIX/CLASSIFICATION/HANDBUCH) liegen außerhalb des Paket-Namensraums und werden nicht angetastet. Jeder Lauf liefert einen Änderungsreport (Audit-Log, Entity `policy_package`); `{ dryRun: true }` erzeugt die Vorschau ohne Schreibzugriff. Akzeptanztest: `npx tsx scripts/test-reimport.ts`.
3. **RLS-Kontext:** RLS-Policies erwarten `current_setting('app.tenant_id')`. Die App nutzt primär den `dbForTenant`-Guard; wenn direkte DB-Zugriffe hinzukommen, `app.tenant_id` in der Transaktion setzen.
4. **Turbopack-HMR** kann veraltete Fehler/`MISSING_MESSAGE` zeigen, nachdem `messages/*.json` geändert wurde → Dev-Server neu starten. Produktions-Build ist maßgeblich.
5. **Prisma-7-Migrationsflow** wie in §4 (kein `migrate dev`).
6. **`.next`-Cache** nicht löschen, während der Dev-Server läuft (Turbopack-Korruption) → Server stoppen, `rm -rf .next`, neu starten.
7. **TISAX-Flags:** `FLAG_HIGH_PROTECTION` ist im Modell stets aktiv, `FLAG_ELEVATED_PROTECTION` wird **abgeleitet** (`applyProtection`) — nie manuell setzen. Effektiver Level = Dokument-Override sonst global.
---
## 10. Produktionshärtung & Benutzerverwaltung (umgesetzt, Branch `dev`)
Aufbauend auf dem Fundament wurden mehrere Härtungspakete umgesetzt (feingranulare Commits auf `dev`):
- **API-Modul-Durchsetzung (§3.4):** zentraler `moduleGuard("<key>")` in `src/server/action-guard.ts`; jede mutierende Action eines gegateten Moduls läuft über `guard(...)` (Session → `assertModuleEnabled` → RBAC). Vollständigkeitscheck `scripts/check-module-guards.ts` (Registry Action→Modul) als `prebuild` — Build failt bei nicht zugeordneter Action-Datei. Neue Action-Datei ⇒ dort eintragen (Modul-Key oder `EXEMPT`).
- **Plattform-Admins getrennt:** Store `PlatformAdmin` (kein `tenant_id`), eigene NextAuth-Instanz `src/server/platform-auth.ts` (eigener Cookie/basePath `/api/platform-auth`, Session ohne Tenant), Login `/platform/login`, Bereich unter `src/app/(platform)/…`. **MFA (TOTP, `src/server/mfa.ts`) ist optional** — Enrollment nur erzwungen, wenn `PlatformSetting.mfaRequired` (Singleton) an ist; Umschaltung + Self-Service unter `/platform/profile`. Rate-Limit/Lockout am Login bleiben. Audit `scope=platform` via `writePlatformAudit`.
- **Nicht-destruktiver Richtlinien-Re-Import:** siehe §9 Punkt 2.
- **Benutzer- & Rollenverwaltung (ohne E-Mail-Flow):**
- Plattform-Admin je Mandant: `src/server/actions/platform-users.ts` + `components/platform-tenant-users.tsx`, eingebettet in `/admin/[id]`. Anlegen mit **Initial-/Einmal-Passwort** (selbst setzen oder generiert, einmalig angezeigt), Rollen, Deaktivieren/Reaktivieren, Passwort-Reset.
- Mandanten-Admin intern: `src/server/actions/tenant-users.ts` + `components/tenant-users-manager.tsx`/`role-manager.tsx`, Seite `/settings/users` (nur `user:manage`/`role:manage`). Benutzer-CRUD **und** Rollen-CRUD (eigene Rollen + Permissions; Standardrollen schreibgeschützt/klonbar). Strikt `dbForTenant(session)` → kein Cross-Tenant. **Lockout-Schutz** für den letzten aktiven Mandanten-Admin.
- **Force-Change:** neue Nutzer starten mit `mustChangePassword=true`; das `(app)`-Layout leitet autoritativ (DB) auf `/change-password` und sperrt deaktivierte Konten. Passwort-Policy: `src/lib/password-policy.ts` (Validierung, client-safe) + `src/server/password.ts` (Argon2id-Hash + Generator); Quelle `TenantSettings.securityPolicy.password`.
- **Nutzer-MFA optional:** Tenant-Login (`auth.ts`) verlangt TOTP nur bei eingerichteter MFA; Self-Service unter `/account`. `role:manage` ist neu im RBAC-Katalog (Mandanten-Admin).
- **Bearbeiten:** je Nutzer sind **Name & E-Mail** (E-Mail eindeutig je Mandant), Rollen, Aktiv/Deaktiviert und Passwort-Reset editierbar — in beiden Konsolen.
- **Zuständigkeit Einstellungen (Superadmin vs. Tenant-Admin):** **Kern-Einstellungen** (aktive Module, TISAX-/Schutzbedarf-**Tiefe**, Richtlinienpaket) steuert ausschließlich der **Superadmin** in der Admin-Konsole (`/admin/[id]`, u. a. `setTenantTisaxLevel`). Der **Tenant-Admin** pflegt in `/settings` nur seinen Bereich (Stammdaten/Branding → ISMS-Variablen) + Benutzer/Rollen; die TISAX-Tiefe ist dort nur noch als Read-only-Anzeige.
- **Zukunftssicher:** `createTenantUser`/`createUser` kapseln die Aktivierung über Initial-/Einmal-Passwort — der spätere **E-Mail-Einladungs-Flow (Paket 4)** lässt sich als alternative Aktivierung (Token statt Passwort) einhängen, ohne die UI umzubauen.
- **Benutzer-UI als Popup:** Anlegen/Bearbeiten über URL-gesteuerte Modals (`?new`/`?edit`, generische `components/user-forms.tsx` + `user-table.tsx`) in `/settings/users` und `/admin/[id]`; die Tabelle zeigt nur.
- **Aufgaben-/Freigabe-Modul (`tasks`):** generisches `Task`/`TaskComment` (RLS, in `TENANT_MODELS`). Erster Typ `policy_approval`: beim Einreichen wählt der Autor einen **konkreten Freigeber** (aktiver Nutzer mit `policy:approve`, ≠ Einreicher) → Aufgabe. Freigeben/Ablehnen (mit Grund)/Kommentieren im Bereich **`/tasks`** (nur der zugewiesene Freigeber; Vier-Augen), Verlauf historisiert; **Dashboard-Kachel** zählt offene Freigaben. Actions: `server/actions/tasks.ts` (+ `submitForApproval` in `policies.ts`). Der Editor zeigt nur noch Status/Freigeber + Link zur Aufgabe.
- **Richtlinien-Governance zentralisiert:** zentrale Variablen (Organisation/Rollen/Schutzbedarf-Flags, `lib/policy-variables.ts`) sind im Editor gesperrt (nur Einstellungen); **Schutzbedarf/TISAX** ausschließlich Superadmin (kein Per-Doc-Override, kein globaler Schalter im Modul); **Coverage-Matrix** filtert nach aktivem Assessment-Level (AL2 ohne „sehr hoch").
## 11. Nächste sinnvolle Aufgaben (Einstiegspunkte)
- **SMTP + Einladungs-/Aktivierungs-/Reset-Flow (Paket 4, M):** transaktionale Mails (Nodemailer), signierte Einladungs-/Reset-Tokens; ersetzt/ergänzt den Initial-Passwort-Weg.
- **Admin Phase 2 — Impersonation (M):** neues Modell `ImpersonationSession`, Cookie-basierter effektiver Tenant + Banner, Ablauf, Audit.
- **Tenant-weite MFA-Pflicht scharfschalten (S):** `securityPolicy.mfaRequired` wird von `disableOwnMfa` bereits respektiert; Enrollment-Erzwingung analog zum Force-Change-Gate (Seite außerhalb der `(app)`-Shell) nachziehen.
- **NIS2-Modul (L):** eigenes Modul inkl. Incident-Reporting mit Fristen-Timern.
- **Richtlinien-Versionierung/Diff (ML)** und **DOCX/PDF-Export (M)**.
Weitere Details, Priorisierung und Aufwände: **`docs/HANDOVER-PM.md`**. Projekt-Spec: **`docs/SPEC.md`** + Modul-Prompts/Mockups.