Plattform-Administratoren sind nicht länger isPlatformAdmin-Nutzer innerhalb eines Mandanten, sondern ein getrennter Store mit eigener Auth-Domäne — Voraussetzung für den sicheren Betrieb beim ersten echten Kunden. Store & Migration - Neues Modell PlatformAdmin (kein tenant_id): Argon2id-Hash, TOTP-Secret, Recovery-Codes (nur SHA-256-Hashes), Fehlversuchszähler + Sperre, lastLogin. - AuditLog.tenant_id nullable → mandantenlose Plattform-Ereignisse (scope=platform). - Datenmigration: bestehende isPlatformAdmin-Nutzer in den neuen Store übernommen (gleicher Hash → Login sofort möglich), Flag mandantenweit auf false gesetzt. Getrennter Login + MFA - Zweite NextAuth-Instanz (server/platform-auth.ts) mit eigenem Cookie und eigenem basePath /api/platform-auth; Session trägt bewusst KEINEN tenantId. - TOTP-MFA (otplib): Enrollment beim ersten Login (/platform/enroll-mfa, QR + Klartext-Secret), danach bei jedem Login erzwungen; 10 einmalige Recovery-Codes. - Härtung: Konto-Sperre nach 5 Fehlversuchen (15 min), Audit aller Anmeldungen, Fehlversuche und Sperren (scope=platform). Autorisierung / Trennung - Admin-Konsole nach (platform)/admin verschoben; (platform)/layout.tsx erzwingt Plattform-Session + aktivierte MFA. Mandanten-Session hat KEINEN Zugriff auf /admin. - Mandanten-Shell zeigt keinen /admin-Link mehr; admin-Actions prüfen die Plattform-Session statt des abgelösten Flags. - provision/seed setzen isPlatformAdmin nicht mehr; Seed legt den Demo-Plattform- Admin (admin@demo.example) im getrennten Store an. Browser-verifiziert: Plattform-Login → erzwungenes MFA-Enrollment → Recovery-Codes → /admin; Login ohne Code scheitert (?error=1); Mandanten-Session auf /admin wird auf /platform/login umgeleitet. tsc + lint + build + Guard-Check grün. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
11 KiB
Entwickler-Übergabe — ISMS-Tool
Stand: 2026-07-20 · Branch
main· letzter Commit6ddeedfZweck: Kontext, Setup und Konventionen, damit ein neuer Entwickler direkt weiterarbeiten kann. Fachlicher Status (fertig/offen) siehedocs/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ürgit pushwird der Token als HTTP-Passwort verwendet. - Default-Branch:
main(es wird direkt aufmaincommittet; 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)
# 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)insrc/server/db.ts: filtert reads automatisch nachtenantId, injiziert ihn beicreate, prüft Ownership beifindUnique/update/delete. Neue tenant-bezogene Modelle müssen inTENANT_MODELS(indb.ts) eingetragen werden. - Zusätzlich Postgres Row Level Security je Tabelle (Policy
tenant_isolation, gesetzt in den Migrationen). Superadmin/plattformweite Reads laufen über den rohenprisma-Client (nichtdbForTenant). - Session (
src/server/auth.ts) trägttenantId,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 MandantTenantModule-Zeilen (enabled). Navigation blendet deaktivierte Module aus (layout.tsx). - Serverseitige Durchsetzung:
requireModule("key")insrc/server/modules.ts, angewandt als Modul-layout.tsxje 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ätzlichrequireModuleim Action-guard()(bisher exemplarisch nurpolicies.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:
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,applyProtectionfür TISAX-Level), Importprisma/import-policies.ts+prisma/import-managed.ts, UIsrc/app/(app)/policies/**+src/components/policy-*.tsx, Actionssrc/server/actions/policies.ts. Control-Titelsrc/lib/control-titles.ts. - Lieferanten/IT-Service: Engine
src/lib/supplier.ts, Includessrc/lib/supplier-include.ts, UIsrc/components/supplier-modals.tsx/service-modals.tsx/supplier-cockpit.tsx, Actionssuppliers.ts/services.ts. - Admin/Mandanten: Provisionierung
src/server/provision.ts(von Seed undactions/admin.tsgenutzt, idempotent),actions/tenant-settings.ts(Stammdaten → ISMS-Variablen viasyncPolicyVariablesFromSettings). - 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
- 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. - Richtlinien-Re-Import ist destruktiv (delete+recreate): setzt per-Dokument-Status/Override/Freigabe zurück. „Deaktivieren statt löschen" ist offene Anforderung.
- RLS-Kontext: RLS-Policies erwarten
current_setting('app.tenant_id'). Die App nutzt primär dendbForTenant-Guard; wenn direkte DB-Zugriffe hinzukommen,app.tenant_idin der Transaktion setzen. - Turbopack-HMR kann veraltete Fehler/
MISSING_MESSAGEzeigen, nachdemmessages/*.jsongeändert wurde → Dev-Server neu starten. Produktions-Build ist maßgeblich. - Prisma-7-Migrationsflow wie in §4 (kein
migrate dev). .next-Cache nicht löschen, während der Dev-Server läuft (Turbopack-Korruption) → Server stoppen,rm -rf .next, neu starten.- TISAX-Flags:
FLAG_HIGH_PROTECTIONist im Modell stets aktiv,FLAG_ELEVATED_PROTECTIONwird 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 denguard()/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 (M–L) und DOCX/PDF-Export (M).
Weitere Details, Priorisierung und Aufwände: docs/HANDOVER-PM.md. Projekt-Spec: docs/SPEC.md + Modul-Prompts/Mockups.