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

17 KiB
Raw Permalink Blame History

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)

# 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.tsauf ü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, 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 --noEmitnpm run lintnpm 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.