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

12 KiB
Raw Blame History

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)

# 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.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. 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.