Files
certvia/docs/HANDOVER-DEV.md
T
msolarczekandClaude Opus 4.8 e07dcd9f2a Nicht-destruktiver Richtlinien-Re-Import (Phase-1-Härtung Paket 3)
Der Re-Import löschte bisher alle Policy-Zeilen und legte sie neu an — das setzte
per-Dokument-Status, TISAX-Override, Freigabe/Version und nutzergepflegte
Variablenwerte zurück. Jetzt Diff/Upsert über stabile Schlüssel, verlustfrei.

- Schema: PolicyDocument.archivedAt + PolicyRequirement.archivedAt (Lifecycle,
  orthogonal zum Freigabe-status). Migration additiv/nullable.
- import-policies.ts komplett auf Reconcile umgebaut:
  - Dokumente (code): neu→anlegen; vorhanden→nur Inhaltsfelder aktualisieren,
    Status/Version/Owner/Freigabe/Override bleiben; fehlend→archivedAt setzen
    (deaktivieren, nicht löschen); Wiederauftauchen→reaktivieren.
  - Anforderungen (reqId): analog inkl. Deaktivierung entfernter Anforderungen.
  - Variablen (key): Metadaten aktualisieren, aber value NIE überschreiben
    (Kundenpflege); fehlende bleiben bestehen (als obsolet ausgewiesen).
  - Baseline (blId) und Nachweise (nr): Upsert; fehlende bleiben erhalten.
  - Deaktivierung greift nur im Paket-Namensraum (L00/R*/VA-*/BASELINE/NACHWEIS)
    — verwaltete Register aus import-managed (CRYPTO/RISKMATRIX/CLASSIFICATION/
    HANDBUCH) werden nicht angetastet.
- Änderungsreport (added/updated/archived/reactivated/unchanged/obsolete) wird
  zurückgegeben und ins Audit-Log geschrieben (Entity policy_package). Option
  { dryRun: true } liefert die Vorschau ohne Schreibzugriff. Idempotent.
- Aktive Ansichten (Bibliothek/Coverage, Dokument-Detail) filtern archivedAt: null;
  Historie bleibt per Direktlink erreichbar.

Akzeptanztest scripts/test-reimport.ts: Status/Override/Einreicher + Variablenwert
bleiben nach Re-Import erhalten, entfernte Anforderung wird deaktiviert (nicht
gelöscht), verwaltete Register unberührt, zweiter Lauf idempotent. Browser: /policies
rendert unverändert (30 Dokumente). tsc + lint + build + Guard-Check grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 13:46:42 +02:00

176 lines
12 KiB
Markdown
Raw 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
> Stand: 2026-07-20 · Branch `main` · letzter Commit `6ddeedf`
> Zweck: Kontext, Setup und Konventionen, damit ein neuer Entwickler direkt weiterarbeiten kann.
> Fachlicher Status (fertig/offen) siehe **`docs/HANDOVER-PM.md`**.
---
## 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), `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. Nächste sinnvolle Aufgaben (Einstiegspunkte)
- **API-Modul-Enforcement vervollständigen (S):** `await requireModule("<key>")` in den `guard()`/Action-Einstiegen der übrigen Action-Dateien ergänzen (Vorlage: `actions/policies.ts`).
- **Admin Phase 2 — Impersonation (M):** neues Modell `ImpersonationSession`, Cookie-basierter effektiver Tenant + Banner, Ablauf, Audit.
- **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.