Infra: Worker/Garage/Test-Runner
- docker-compose.yml: explizite Build-Targets (runner/migrate) — Ursache für "npx not found" bei garage-provision war das Default-Target (letzte Stage = Garage-Image ohne Node); worker startet npm run worker:mail; Defaults craftvia - Coolify-Compose: incident-inbound-worker und sync-policy-templates entfernt, Rollen-/Bucket-/Image-Namen auf craftvia - Dockerfile: seed/ und docs/wizard-uebergabe entfernt, messages/ im Runner - npm: Name craftvia, Scripts test (scripts/run-tests.ts) und gate, ISMS-Pakete entfernt (handlebars, marked, sanitize-html, @xyflow/react, @dagrejs/dagre, html-to-image, imapflow, mailparser, exceljs, @dnd-kit/core) - .env-Beispiele, launch.json (craftvia-dev), CI-Kommentare umbenannt Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@
|
||||
"version": "0.0.1",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "isms-dev",
|
||||
"name": "craftvia-dev",
|
||||
"runtimeExecutable": "npm",
|
||||
"runtimeArgs": ["run", "dev"],
|
||||
"port": 3000
|
||||
|
||||
+10
-10
@@ -1,13 +1,13 @@
|
||||
# Referenz für die Coolify-Environment-Variablen (Testserver, intern).
|
||||
# ECHTE Secrets NUR in Coolify eintragen â diese Datei enthält nur Platzhalter.
|
||||
# In Coolify: Ressource -> Environment Variables (Bulk-Paste möglich).
|
||||
# Referenz für die Coolify-Environment-Variablen (Testserver, intern).
|
||||
# ECHTE Secrets NUR in Coolify eintragen – diese Datei enthält nur Platzhalter.
|
||||
# In Coolify: Ressource -> Environment Variables (Bulk-Paste möglich).
|
||||
# Hostnamen sind die Compose-Service-Namen (postgres/redis/garage), NICHT localhost.
|
||||
|
||||
# --- Datenbank (Service "postgres") ---
|
||||
POSTGRES_USER=isms
|
||||
POSTGRES_USER=craftvia
|
||||
POSTGRES_PASSWORD=CHANGE_ME_db_password
|
||||
POSTGRES_DB=isms
|
||||
DATABASE_URL=postgresql://isms:CHANGE_ME_db_password@postgres:5432/isms?schema=public
|
||||
POSTGRES_DB=craftvia
|
||||
DATABASE_URL=postgresql://craftvia:CHANGE_ME_db_password@postgres:5432/craftvia?schema=public
|
||||
|
||||
# --- Redis (Service "redis") ---
|
||||
# F-18: Redis läuft mit requirepass. NUR REDIS_PASSWORD setzen — REDIS_URL wird in der
|
||||
@@ -24,7 +24,7 @@ REDIS_PASSWORD=CHANGE_ME_redis_password
|
||||
S3_ENDPOINT=http://garage:3900
|
||||
S3_ACCESS_KEY=GK000000000000000000000000
|
||||
S3_SECRET_KEY=CHANGE_ME_openssl_rand_hex_32
|
||||
S3_BUCKET=isms-documents
|
||||
S3_BUCKET=craftvia-documents
|
||||
S3_REGION=us-east-1
|
||||
# Garage-Secrets: der Daemon liest sie aus der Env (NICHT in deploy/garage.toml).
|
||||
# In Coolify LITERAL setzen, NICHT via ${...} referenzieren (Interpolationsfalle).
|
||||
@@ -47,12 +47,12 @@ BACKUP_LOCAL_DIR=/app/.backups
|
||||
|
||||
# --- Auth (NextAuth) ---
|
||||
# AUTH_SECRET: openssl rand -base64 32
|
||||
# AUTH_URL: exakt die Coolify-Domain des app-Service (http:// für intern)
|
||||
# AUTH_URL: exakt die Coolify-Domain des app-Service (http:// für intern)
|
||||
AUTH_SECRET=CHANGE_ME_openssl_rand_base64_32
|
||||
# PASSWORD_PEPPER (Härtung §1): openssl rand -hex 32 — frisch je Umgebung, NICHT rotierbar, nie ins Artefakt.
|
||||
PASSWORD_PEPPER=CHANGE_ME_openssl_rand_hex_32
|
||||
AUTH_URL=http://REPLACE-WITH-COOLIFY-SSLIP-DOMAIN
|
||||
# Hinter Reverse-Proxy (Coolify/Traefik) für Auth.js v5 zwingend, sonst UntrustedHost:
|
||||
# Hinter Reverse-Proxy (Coolify/Traefik) für Auth.js v5 zwingend, sonst UntrustedHost:
|
||||
AUTH_TRUST_HOST=true
|
||||
|
||||
# --- Demo-Seed (NUR Testserver!) ---
|
||||
@@ -69,4 +69,4 @@ SMTP_HOST=
|
||||
SMTP_PORT=1025
|
||||
SMTP_USER=
|
||||
SMTP_PASSWORD=
|
||||
SMTP_FROM=isms@example.com
|
||||
SMTP_FROM=craftvia@example.com
|
||||
|
||||
+18
-18
@@ -1,21 +1,21 @@
|
||||
# --- Datenbank ---
|
||||
POSTGRES_USER=isms
|
||||
POSTGRES_PASSWORD=isms
|
||||
POSTGRES_DB=isms
|
||||
DATABASE_URL=postgresql://isms:isms@localhost:5432/isms?schema=public
|
||||
POSTGRES_USER=craftvia
|
||||
POSTGRES_PASSWORD=craftvia
|
||||
POSTGRES_DB=craftvia
|
||||
DATABASE_URL=postgresql://craftvia:craftvia@localhost:5432/craftvia?schema=public
|
||||
|
||||
# --- Row Level Security (F-04) â lokal AUS (Owner-Betrieb) ---
|
||||
# Lokal bleibt RLS aus: Der Owner isms ist Superuser/BYPASSRLS und sieht trotz
|
||||
# --- Row Level Security (F-04) – lokal AUS (Owner-Betrieb) ---
|
||||
# Lokal bleibt RLS aus: Der Owner craftvia ist Superuser/BYPASSRLS und sieht trotz
|
||||
# FORCE alle Daten. Zum scharfen Testen die beiden Zeilen aktivieren (die Rolle
|
||||
# isms_app zuvor mit LOGIN+Passwort versehen, s. scripts/test-rls-enforcement.ts):
|
||||
# craftvia_app zuvor mit LOGIN+Passwort versehen, s. scripts/test-rls-enforcement.ts):
|
||||
# RLS_ENFORCED=true
|
||||
# RLS_DATABASE_URL=postgresql://isms_app:isms_app_local@localhost:5432/isms?schema=public
|
||||
# RLS_DATABASE_URL=postgresql://craftvia_app:craftvia_app_local@localhost:5432/craftvia?schema=public
|
||||
|
||||
# --- Redis (BullMQ) ---
|
||||
# F-18: Redis läuft mit requirepass. REDIS_PASSWORD muss zum docker-compose-Default
|
||||
# passen; das Passwort steht zusätzlich in der REDIS_URL (redis://:<pw>@host:port).
|
||||
REDIS_PASSWORD=isms-redis
|
||||
REDIS_URL=redis://:isms-redis@localhost:6379
|
||||
# F-18: Redis läuft mit requirepass. REDIS_PASSWORD muss zum docker-compose-Default
|
||||
# passen; das Passwort steht zusätzlich in der REDIS_URL (redis://:<pw>@host:port).
|
||||
REDIS_PASSWORD=craftvia-redis
|
||||
REDIS_URL=redis://:craftvia-redis@localhost:6379
|
||||
|
||||
# --- Objektspeicher (Garage / S3-kompatibel) ---
|
||||
# Sind alle vier S3_*-Pflichtvariablen gesetzt, nutzt der Storage-Adapter das echte
|
||||
@@ -28,7 +28,7 @@ REDIS_URL=redis://:isms-redis@localhost:6379
|
||||
S3_ENDPOINT=http://localhost:3900
|
||||
S3_ACCESS_KEY=GKdead0000beef0000cafe0000
|
||||
S3_SECRET_KEY=0000000000000000000000000000000000000000000000000000000000000001
|
||||
S3_BUCKET=isms-documents
|
||||
S3_BUCKET=craftvia-documents
|
||||
# Region beidseitig us-east-1 (deckt sich mit garage.toml s3_region). forcePathStyle ist
|
||||
# im Code fest gesetzt - Garage bedient ausschliesslich Path-Style.
|
||||
S3_REGION=us-east-1
|
||||
@@ -61,9 +61,9 @@ AUTH_URL=http://localhost:3000
|
||||
AI_PROVIDER=anthropic
|
||||
AI_API_KEY=
|
||||
|
||||
# --- Anthropic (KI-Entwurf Control-Beschreibungen, Audit-Vorbereitung) ---
|
||||
# --- Anthropic (Lotse KI-Assistent, Auftragsimport) ---
|
||||
# Ohne ANTHROPIC_API_KEY ist die KI-Anbindung deaktiviert (graceful degradation):
|
||||
# kein Entwurf, Status bleibt âmanuell zu erfassen", die UI funktioniert weiter.
|
||||
# kein Entwurf, Status bleibt –manuell zu erfassen", die UI funktioniert weiter.
|
||||
ANTHROPIC_API_KEY=
|
||||
# Optionale Modell-ID; Default: claude-opus-5
|
||||
ANTHROPIC_MODEL=claude-opus-5
|
||||
@@ -71,7 +71,7 @@ ANTHROPIC_MODEL=claude-opus-5
|
||||
# --- E-Mail / SMTP (SEC1) ---
|
||||
# Dev: Mailpit oder Mailhog (docker-compose Service `mailhog`, SMTP auf 1025,
|
||||
# Weboberflaeche auf 8025). Gegen localhost wird TLS bewusst nicht erzwungen.
|
||||
# Prod: dedizierte Absenderdomain mit SPF, DKIM und DMARC â Vorbedingung vor
|
||||
# Prod: dedizierte Absenderdomain mit SPF, DKIM und DMARC – Vorbedingung vor
|
||||
# dem ersten Produktivversand. Secrets ausschliesslich aus dem Secret-Store.
|
||||
SMTP_HOST=localhost
|
||||
SMTP_PORT=1025
|
||||
@@ -82,8 +82,8 @@ SMTP_USER=
|
||||
SMTP_PASSWORD=
|
||||
# Absenderadresse und Anzeigename. MAIL_FROM/MAIL_FROM_NAME werden als Alias
|
||||
# ebenfalls akzeptiert.
|
||||
SMTP_FROM=no-reply@certvia.de
|
||||
MAIL_FROM_NAME=Certvia
|
||||
SMTP_FROM=no-reply@craftvia.de
|
||||
MAIL_FROM_NAME=Craftvia
|
||||
# Optionale Antwortadresse (sonst keine Reply-To-Kopfzeile).
|
||||
MAIL_REPLY_TO=
|
||||
# Basis fuer absolute Links in Mails. Faellt auf AUTH_URL zurueck.
|
||||
|
||||
+26
-26
@@ -1,37 +1,37 @@
|
||||
# Referenz für die PRODUKTIV-Env-Variablen (Contabo-VPS + Coolify).
|
||||
# ECHTE Secrets NUR in Coolify eintragen â diese Datei enthält nur Platzhalter.
|
||||
# Referenz für die PRODUKTIV-Env-Variablen (Contabo-VPS + Coolify).
|
||||
# ECHTE Secrets NUR in Coolify eintragen – diese Datei enthält nur Platzhalter.
|
||||
# Unterschiede zum Testserver: HTTPS-AUTH_URL, KEIN Demo-Seed, stattdessen Bootstrap-Admin.
|
||||
|
||||
# --- Datenbank (Service "postgres") ---
|
||||
POSTGRES_USER=isms
|
||||
POSTGRES_USER=craftvia
|
||||
POSTGRES_PASSWORD=CHANGE_ME_starkes_db_passwort
|
||||
POSTGRES_DB=isms
|
||||
DATABASE_URL=postgresql://isms:CHANGE_ME_starkes_db_passwort@postgres:5432/isms?schema=public
|
||||
POSTGRES_DB=craftvia
|
||||
DATABASE_URL=postgresql://craftvia:CHANGE_ME_starkes_db_passwort@postgres:5432/craftvia?schema=public
|
||||
|
||||
# --- Row Level Security scharfschalten (F-04) ---
|
||||
# RLS_ENFORCED=true â die App verbindet sich als eingeschränkte Rolle isms_app
|
||||
# RLS_ENFORCED=true – die App verbindet sich als eingeschränkte Rolle craftvia_app
|
||||
# (NOBYPASSRLS) und setzt app.tenant_id pro Transaktion; FORCE ROW LEVEL SECURITY
|
||||
# macht die Policies dann scharf. Ist der Kontext nicht gesetzt, sieht isms_app
|
||||
# NULL Zeilen â daher NUR mit korrekt gesetztem RLS_DATABASE_URL einschalten.
|
||||
# macht die Policies dann scharf. Ist der Kontext nicht gesetzt, sieht craftvia_app
|
||||
# NULL Zeilen – daher NUR mit korrekt gesetztem RLS_DATABASE_URL einschalten.
|
||||
# WICHTIG: Die Owner-/Migrate-Rolle in DATABASE_URL MUSS BYPASSRLS/Superuser sein
|
||||
# (Migrationen, Seed und der mandantenübergreifende Login-Lookup laufen darüber),
|
||||
# sonst sähe der Login keine Nutzer. isms_app in Prod EINMALIG mit LOGIN + starkem
|
||||
# Passwort versehen: ALTER ROLE isms_app WITH LOGIN PASSWORD '<stark>';
|
||||
# (Migrationen, Seed und der mandantenübergreifende Login-Lookup laufen darüber),
|
||||
# sonst sähe der Login keine Nutzer. craftvia_app in Prod EINMALIG mit LOGIN + starkem
|
||||
# Passwort versehen: ALTER ROLE craftvia_app WITH LOGIN PASSWORD '<stark>';
|
||||
RLS_ENFORCED=true
|
||||
RLS_DATABASE_URL=postgresql://isms_app:CHANGE_ME_starkes_isms_app_passwort@postgres:5432/isms?schema=public
|
||||
RLS_DATABASE_URL=postgresql://craftvia_app:CHANGE_ME_starkes_craftvia_app_passwort@postgres:5432/craftvia?schema=public
|
||||
|
||||
# --- Redis ---
|
||||
# F-18: Redis läuft mit requirepass. REDIS_PASSWORD setzen (stark!) und identisch
|
||||
# F-18: Redis läuft mit requirepass. REDIS_PASSWORD setzen (stark!) und identisch
|
||||
# in die REDIS_URL einsetzen (redis://:<pw>@redis:6379).
|
||||
REDIS_PASSWORD=CHANGE_ME_starkes_redis_passwort
|
||||
REDIS_URL=redis://:CHANGE_ME_starkes_redis_passwort@redis:6379
|
||||
|
||||
# --- Objektspeicher (MinIO) â S3_* muss zu MINIO_ROOT_* passen ---
|
||||
# --- Objektspeicher (MinIO) – S3_* muss zu MINIO_ROOT_* passen ---
|
||||
S3_ENDPOINT=http://minio:9000
|
||||
S3_ACCESS_KEY=isms
|
||||
S3_ACCESS_KEY=CHANGE_ME_GK_plus_24_hex
|
||||
S3_SECRET_KEY=CHANGE_ME_starkes_minio_passwort
|
||||
S3_BUCKET=isms-documents
|
||||
MINIO_ROOT_USER=isms
|
||||
S3_BUCKET=craftvia-documents
|
||||
MINIO_ROOT_USER=craftvia
|
||||
MINIO_ROOT_PASSWORD=CHANGE_ME_starkes_minio_passwort
|
||||
|
||||
# --- Backup-Zielspeicher (optional) ---
|
||||
@@ -41,13 +41,13 @@ MINIO_ROOT_PASSWORD=CHANGE_ME_starkes_minio_passwort
|
||||
# die DB-Config Vorrang. Fuer „Lokal" auf ein gemountetes, persistentes Volume zeigen.
|
||||
BACKUP_LOCAL_DIR=/app/.backups
|
||||
|
||||
# --- Auth (NextAuth) â Produktiv über HTTPS ---
|
||||
# --- Auth (NextAuth) – Produktiv über HTTPS ---
|
||||
# AUTH_SECRET: openssl rand -base64 32 (frisch, NICHT der Testwert)
|
||||
AUTH_SECRET=CHANGE_ME_openssl_rand_base64_32
|
||||
# PASSWORD_PEPPER (Härtung §1): openssl rand -hex 32 — frisch je Umgebung, NICHT rotierbar, nie ins Artefakt.
|
||||
PASSWORD_PEPPER=CHANGE_ME_openssl_rand_hex_32
|
||||
AUTH_URL=https://app.certvia.de
|
||||
# AUTH_TRUST_HOST ist im Compose fest auf true (hinter dem Coolify-Proxy) â nicht nötig.
|
||||
AUTH_URL=https://app.craftvia.de
|
||||
# AUTH_TRUST_HOST ist im Compose fest auf true (hinter dem Coolify-Proxy) – nicht nötig.
|
||||
|
||||
# --- KI-Provider (optional) ---
|
||||
AI_PROVIDER=anthropic
|
||||
@@ -58,7 +58,7 @@ SMTP_HOST=
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=
|
||||
SMTP_PASSWORD=
|
||||
SMTP_FROM=noreply@certvia.de
|
||||
SMTP_FROM=noreply@craftvia.de
|
||||
|
||||
# --- Demo-Seed: in PROD AUS lassen! ---
|
||||
RUN_DEMO_SEED=false
|
||||
@@ -67,10 +67,10 @@ RUN_DEMO_SEED=false
|
||||
# Beim ersten Deploy true setzen -> migrate-Job legt Admin + Mandant an (idempotent).
|
||||
# Danach kann true bleiben (tut nichts, wenn der Admin existiert) oder auf false.
|
||||
BOOTSTRAP_ADMIN=true
|
||||
BOOTSTRAP_ADMIN_EMAIL=admin@certvia.de
|
||||
BOOTSTRAP_ADMIN_EMAIL=admin@craftvia.de
|
||||
BOOTSTRAP_ADMIN_PASSWORD=CHANGE_ME_initiales_admin_passwort
|
||||
BOOTSTRAP_ADMIN_NAME=Certvia Admin
|
||||
BOOTSTRAP_TENANT_NAME=Certvia
|
||||
BOOTSTRAP_TENANT_SLUG=certvia
|
||||
BOOTSTRAP_TENANT_SHORT=Certvia
|
||||
BOOTSTRAP_ADMIN_NAME=Craftvia Admin
|
||||
BOOTSTRAP_TENANT_NAME=Craftvia
|
||||
BOOTSTRAP_TENANT_SLUG=craftvia
|
||||
BOOTSTRAP_TENANT_SHORT=Craftvia
|
||||
BOOTSTRAP_TENANT_SECTOR=
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# CI-Pipeline (Gitea Actions — GitHub-Actions-kompatibel).
|
||||
#
|
||||
# WICHTIG: Braucht einen aktivierten Gitea-Actions-Runner (git.certvia.de ->
|
||||
# WICHTIG: Braucht einen aktivierten Gitea-Actions-Runner (Gitea ->
|
||||
# Settings -> Actions -> Runners). Ohne registrierten Runner wird dieser Workflow
|
||||
# NICHT ausgeführt (er schlägt nicht fehl, er läuft schlicht nicht an).
|
||||
# Inhaltlich identisch zu .github/workflows/ci.yml (Spiegel für Nicht-Gitea-Remotes).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# CI-Pipeline — Spiegel von .gitea/workflows/ci.yml (identischer Job-Inhalt).
|
||||
# Primäres Remote ist Gitea (git.certvia.de); diese Datei greift nur, falls das
|
||||
# Primäres Remote ist Gitea (Gitea); diese Datei greift nur, falls das
|
||||
# Repo (auch) auf einem GitHub-Actions-Remote gespiegelt wird.
|
||||
#
|
||||
# WICHTIG: Braucht einen aktivierten Actions-Runner. Ohne Runner läuft der
|
||||
|
||||
+4
-20
@@ -1,4 +1,4 @@
|
||||
# ISMS-Tool — Next.js App (Multi-Stage-Build)
|
||||
# Craftvia — Next.js App (Multi-Stage-Build)
|
||||
#
|
||||
# Base-Image: node:22-slim (Debian/glibc) statt node:22-alpine (musl).
|
||||
# Begründung (F-11): Mit einem glibc-Base greifen die im Lockfile hinterlegten
|
||||
@@ -57,19 +57,6 @@ COPY package.json package-lock.json prisma.config.ts tsconfig.json ./
|
||||
COPY prisma ./prisma
|
||||
COPY scripts ./scripts
|
||||
COPY src ./src
|
||||
# seed/ trägt das Richtlinien-Vorlagenpaket (mapping.json + Quelldateien), das der
|
||||
# Demo-Seed (prisma/seed.ts) bzw. Bootstrap über importPolicies liest. Ohne diesen COPY
|
||||
# bricht der migrate-Job mit ENOENT auf seed/isms-vorlagenpaket-v2/mapping.json ab.
|
||||
# Einige Quelldateien liegen als 0600 vor → a+rX, damit der non-root app-User sie lesen kann.
|
||||
COPY seed ./seed
|
||||
RUN chmod -R a+rX ./seed
|
||||
# docs/wizard-uebergabe/: Fachcontent-Quelldateien, aus denen der Demo-Seed den
|
||||
# Risikokatalog (C4, import-risks.ts) und die Umsetzungshinweise (C6, import-hints.ts)
|
||||
# liest. Nur im migrate-Image nötig — die Laufzeit/runner ruft diese Importer nicht auf
|
||||
# (importManaged in provision.ts liest keine Dateien). Ohne diesen COPY bricht der
|
||||
# Demo-Seed mit ENOENT auf docs/wizard-uebergabe/.../C6_Umsetzungshinweise.md ab.
|
||||
COPY docs/wizard-uebergabe ./docs/wizard-uebergabe
|
||||
RUN chmod -R a+rX ./docs
|
||||
# Prisma-Client für Seed/Bootstrap generieren (migrate deploy selbst braucht nur schema+migrations).
|
||||
ENV DATABASE_URL="postgresql://build:build@localhost:5432/build?schema=public"
|
||||
RUN npx prisma generate
|
||||
@@ -94,12 +81,9 @@ RUN groupadd --system --gid 1001 app \
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
COPY --from=builder /app/.next/static ./.next/static
|
||||
COPY --from=builder /app/public ./public
|
||||
# Richtlinien-Vorlagenpaket für den Laufzeit-Import: Modul „policies" aktivieren
|
||||
# (toggleTenantModule), Mandant mit Seed anlegen (createTenant), manueller Paket-Import
|
||||
# (importPolicyPackageForTenant) lesen alle aus seed/isms-vorlagenpaket-v2/. Fehlt es,
|
||||
# wirft die App zur Laufzeit ENOENT. a+rX wegen der 0600-Quelldateien (non-root app-User).
|
||||
COPY seed ./seed
|
||||
RUN chmod -R a+rX ./seed
|
||||
# i18n-Kataloge (messages/<locale>/<namespace>.json) liegen über outputFileTracingIncludes
|
||||
# bereits im standalone-Output; der explizite COPY hält sie auch bei Tracing-Änderungen vor.
|
||||
COPY --from=builder /app/messages ./messages
|
||||
# Backup-/Restore-/DSGVO-Topologie (src/server/backup/topology.ts) liest zur Laufzeit
|
||||
# prisma/schema.prisma: Prisma 7 entfernt relationFromFields aus dem Laufzeit-DMMF,
|
||||
# die FK-Relationen kommen daher aus der Schema-Datei. Der Inline-Export (Direkt-
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Coolify-Deployment (PREBUILT-Variante) — zieht fertige Images aus der Registry
|
||||
# statt auf dem Host zu bauen (Plan B: langsamer/timeoutender Host-Build umgehen).
|
||||
# Images vorher bauen+pushen: scripts/build-and-push-images.sh
|
||||
# Registry/Tag via Coolify-Env: REGISTRY (Default git.certvia.de/msolarczek), IMAGE_TAG (Default main).
|
||||
# Registry/Tag via Coolify-Env: REGISTRY (Default registry.example.com/craftvia), IMAGE_TAG (Default main).
|
||||
# Abgeleitet von docker-compose.coolify.yml.
|
||||
# Unterschiede zum lokalen Dev-Compose:
|
||||
# - keine host "ports": Coolify-Proxy routet die Domain intern auf app:3000
|
||||
@@ -24,8 +24,8 @@ services:
|
||||
# Optionaler Demo-Seed nur, wenn RUN_DEMO_SEED=true (Testserver). Idempotent (upserts).
|
||||
# In Produktion die Variable NICHT setzen; stattdessen BOOTSTRAP_ADMIN.
|
||||
migrate:
|
||||
image: ${REGISTRY:-git.certvia.de/msolarczek}/certvia-migrate:${IMAGE_TAG:-main}
|
||||
command: sh -c "npx prisma migrate deploy && echo '>> Rollen-Rechte-Sync läuft…' && npx tsx scripts/sync-role-permissions.ts && echo '>> Vorlagen-Sync läuft…' && npx tsx scripts/sync-policy-templates.ts && if [ \"$$RUN_DEMO_SEED\" = \"true\" ]; then echo '>> Demo-Seed läuft…'; npx tsx prisma/seed.ts; fi && if [ \"$$BOOTSTRAP_ADMIN\" = \"true\" ]; then echo '>> Bootstrap-Admin läuft…'; npx tsx scripts/bootstrap-admin.ts; fi"
|
||||
image: ${REGISTRY:-registry.example.com/craftvia}/craftvia-migrate:${IMAGE_TAG:-main}
|
||||
command: sh -c "npx prisma migrate deploy && echo '>> Rollen-Rechte-Sync läuft…' && npx tsx scripts/sync-role-permissions.ts && if [ \"$$RUN_DEMO_SEED\" = \"true\" ]; then echo '>> Demo-Seed läuft…'; npx tsx prisma/seed.ts; fi && if [ \"$$BOOTSTRAP_ADMIN\" = \"true\" ]; then echo '>> Bootstrap-Admin läuft…'; npx tsx scripts/bootstrap-admin.ts; fi"
|
||||
environment:
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
# Härtung §1: Passwort-Pepper (Argon2 `secret`). Seed/Bootstrap hashen Passwörter
|
||||
@@ -59,12 +59,12 @@ services:
|
||||
restart: "no"
|
||||
|
||||
app:
|
||||
image: ${REGISTRY:-git.certvia.de/msolarczek}/certvia-app:${IMAGE_TAG:-main}
|
||||
image: ${REGISTRY:-registry.example.com/craftvia}/craftvia-app:${IMAGE_TAG:-main}
|
||||
environment:
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
# F-04: Row Level Security scharf. Der migrate-Job oben läuft bewusst
|
||||
# weiter mit der Owner-DATABASE_URL (BYPASSRLS). Nur der App-Prozess
|
||||
# verbindet als eingeschränkte Rolle isms_app (NOBYPASSRLS) über
|
||||
# verbindet als eingeschränkte Rolle craftvia_app (NOBYPASSRLS) über
|
||||
# RLS_DATABASE_URL und setzt app.tenant_id pro Transaktion.
|
||||
RLS_ENFORCED: ${RLS_ENFORCED:-false}
|
||||
RLS_DATABASE_URL: ${RLS_DATABASE_URL}
|
||||
@@ -148,7 +148,7 @@ services:
|
||||
# Owner-DATABASE_URL (kein RLS): der Worker arbeitet mandantenübergreifend.
|
||||
# Im default-Netz (Egress), damit der externe SMTP-Server erreichbar ist.
|
||||
worker:
|
||||
image: ${REGISTRY:-git.certvia.de/msolarczek}/certvia-migrate:${IMAGE_TAG:-main}
|
||||
image: ${REGISTRY:-registry.example.com/craftvia}/craftvia-migrate:${IMAGE_TAG:-main}
|
||||
command: ["npx", "tsx", "scripts/mail-worker.ts"]
|
||||
environment:
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
@@ -192,7 +192,7 @@ services:
|
||||
# Braucht das S3/MinIO-Backup-Bucket (S3_*) und den Backup-Schlüssel (BACKUP_ENC_KEY,
|
||||
# Fallback AUTH_SECRET). concurrency ist im Worker seriell (destruktiv).
|
||||
backup-worker:
|
||||
image: ${REGISTRY:-git.certvia.de/msolarczek}/certvia-migrate:${IMAGE_TAG:-main}
|
||||
image: ${REGISTRY:-registry.example.com/craftvia}/craftvia-migrate:${IMAGE_TAG:-main}
|
||||
command: ["npx", "tsx", "scripts/backup-worker.ts"]
|
||||
environment:
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
@@ -238,47 +238,6 @@ services:
|
||||
condition: service_completed_successfully
|
||||
restart: unless-stopped
|
||||
|
||||
# IM-D — Inbound-Mail-Worker (E-Mail-to-Ticket). Holt Mails vom Catch-all-Postfach
|
||||
# (vorfall-<token>@in.certvia.de) per IMAP ab und legt daraus Vorfälle an bzw. reiht
|
||||
# unklare Mails in die Betreiber-Review. Kein Redis nötig (IMAP-Poller, keine Queue).
|
||||
# Ohne INCIDENT_IMAP_* beendet sich der Prozess sauber („nicht konfiguriert").
|
||||
incident-inbound-worker:
|
||||
image: ${REGISTRY:-git.certvia.de/msolarczek}/certvia-migrate:${IMAGE_TAG:-main}
|
||||
command: ["npx", "tsx", "scripts/incident-inbound-worker.ts"]
|
||||
environment:
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
AUTH_SECRET: ${AUTH_SECRET}
|
||||
# Pepper wird von der Fail-Secure-Startprüfung erwartet (assertSecureEnv).
|
||||
PASSWORD_PEPPER: ${PASSWORD_PEPPER}
|
||||
# IMAP-Zugang des Catch-all-Postfachs. Fehlt es, beendet sich der Worker sauber.
|
||||
INCIDENT_IMAP_HOST: ${INCIDENT_IMAP_HOST:-}
|
||||
INCIDENT_IMAP_PORT: ${INCIDENT_IMAP_PORT:-993}
|
||||
INCIDENT_IMAP_USER: ${INCIDENT_IMAP_USER:-}
|
||||
INCIDENT_IMAP_PASSWORD: ${INCIDENT_IMAP_PASSWORD:-}
|
||||
INCIDENT_IMAP_TLS: ${INCIDENT_IMAP_TLS:-true}
|
||||
INCIDENT_IMAP_MAILBOX: ${INCIDENT_IMAP_MAILBOX:-INBOX}
|
||||
INCIDENT_IMAP_POLL_MS: ${INCIDENT_IMAP_POLL_MS:-60000}
|
||||
# Muss zur Catch-all-Subdomain passen (Ableitung der Intake-Adressen).
|
||||
INCIDENT_INTAKE_DOMAIN: ${INCIDENT_INTAKE_DOMAIN:-in.certvia.de}
|
||||
AUTH_URL: ${AUTH_URL}
|
||||
networks:
|
||||
- backend
|
||||
- default
|
||||
security_opt:
|
||||
- "no-new-privileges:true"
|
||||
cap_drop:
|
||||
- ALL
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "0.5"
|
||||
memory: 512M
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
restart: unless-stopped
|
||||
|
||||
postgres:
|
||||
image: pgvector/pgvector:0.8.0-pg16
|
||||
@@ -346,7 +305,7 @@ services:
|
||||
# Image mit eingebackener deploy/garage.toml (Dockerfile-Stage „garage"). KEIN
|
||||
# Bind-Mount der Config: Coolify legt relative Bind-Quellen sonst als Verzeichnis an
|
||||
# → Garage bekäme /etc/garage.toml als Ordner („IO error: Is a directory").
|
||||
image: ${REGISTRY:-git.certvia.de/msolarczek}/certvia-garage:${IMAGE_TAG:-main}
|
||||
image: ${REGISTRY:-registry.example.com/craftvia}/craftvia-garage:${IMAGE_TAG:-main}
|
||||
# Secrets stehen NICHT in der eingebackenen deploy/garage.toml — der Daemon liest
|
||||
# rpc_secret/admin_token aus der Env (in Coolify literal setzen, nicht via ${…}).
|
||||
environment:
|
||||
@@ -383,7 +342,7 @@ services:
|
||||
# Läuft bei JEDEM Deploy; "already exists" = Erfolg. Ohne GARAGE_ADMIN_TOKEN No-op.
|
||||
# Nutzt das schlanke "migrate"-Image (Node/tsx) — kein Garage-Binary nötig.
|
||||
garage-provision:
|
||||
image: ${REGISTRY:-git.certvia.de/msolarczek}/certvia-migrate:${IMAGE_TAG:-main}
|
||||
image: ${REGISTRY:-registry.example.com/craftvia}/craftvia-migrate:${IMAGE_TAG:-main}
|
||||
command: ["npx", "tsx", "scripts/garage-provision.ts"]
|
||||
environment:
|
||||
GARAGE_ADMIN_URL: http://garage:3903
|
||||
@@ -391,7 +350,7 @@ services:
|
||||
# Der zu importierende Garage-Key = App-Key (App-Env und Garage synchron).
|
||||
S3_ACCESS_KEY: ${S3_ACCESS_KEY}
|
||||
S3_SECRET_KEY: ${S3_SECRET_KEY}
|
||||
S3_BUCKET: ${S3_BUCKET:-isms-documents}
|
||||
S3_BUCKET: ${S3_BUCKET:-craftvia-documents}
|
||||
# Optionaler separater Backup-Bucket (nur falls Backup-Store auf S3 statt lokal).
|
||||
BACKUP_S3_BUCKET: ${BACKUP_S3_BUCKET:-}
|
||||
# Single-Node-Layout (nominale Kapazität/Zone; für Prod ggf. anheben).
|
||||
|
||||
@@ -23,7 +23,7 @@ services:
|
||||
build:
|
||||
context: .
|
||||
target: migrate
|
||||
command: sh -c "npx prisma migrate deploy && echo '>> Rollen-Rechte-Sync läuft…' && npx tsx scripts/sync-role-permissions.ts && echo '>> Vorlagen-Sync läuft…' && npx tsx scripts/sync-policy-templates.ts && if [ \"$$RUN_DEMO_SEED\" = \"true\" ]; then echo '>> Demo-Seed läuft…'; npx tsx prisma/seed.ts; fi && if [ \"$$BOOTSTRAP_ADMIN\" = \"true\" ]; then echo '>> Bootstrap-Admin läuft…'; npx tsx scripts/bootstrap-admin.ts; fi"
|
||||
command: sh -c "npx prisma migrate deploy && echo '>> Rollen-Rechte-Sync läuft…' && npx tsx scripts/sync-role-permissions.ts && if [ \"$$RUN_DEMO_SEED\" = \"true\" ]; then echo '>> Demo-Seed läuft…'; npx tsx prisma/seed.ts; fi && if [ \"$$BOOTSTRAP_ADMIN\" = \"true\" ]; then echo '>> Bootstrap-Admin läuft…'; npx tsx scripts/bootstrap-admin.ts; fi"
|
||||
environment:
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
# Härtung §1: Passwort-Pepper (Argon2 `secret`). Seed/Bootstrap hashen Passwörter
|
||||
@@ -64,7 +64,7 @@ services:
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
# F-04: Row Level Security scharf. Der migrate-Job oben läuft bewusst
|
||||
# weiter mit der Owner-DATABASE_URL (BYPASSRLS). Nur der App-Prozess
|
||||
# verbindet als eingeschränkte Rolle isms_app (NOBYPASSRLS) über
|
||||
# verbindet als eingeschränkte Rolle craftvia_app (NOBYPASSRLS) über
|
||||
# RLS_DATABASE_URL und setzt app.tenant_id pro Transaktion.
|
||||
RLS_ENFORCED: ${RLS_ENFORCED:-false}
|
||||
RLS_DATABASE_URL: ${RLS_DATABASE_URL}
|
||||
@@ -242,49 +242,6 @@ services:
|
||||
condition: service_completed_successfully
|
||||
restart: unless-stopped
|
||||
|
||||
# IM-D — Inbound-Mail-Worker (E-Mail-to-Ticket). Holt Mails vom Catch-all-Postfach
|
||||
# (vorfall-<token>@in.certvia.de) per IMAP ab und legt daraus Vorfälle an bzw. reiht
|
||||
# unklare Mails in die Betreiber-Review. Kein Redis nötig (IMAP-Poller, keine Queue).
|
||||
# Ohne INCIDENT_IMAP_* beendet sich der Prozess sauber („nicht konfiguriert").
|
||||
incident-inbound-worker:
|
||||
build:
|
||||
context: .
|
||||
target: migrate
|
||||
command: ["npx", "tsx", "scripts/incident-inbound-worker.ts"]
|
||||
environment:
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
AUTH_SECRET: ${AUTH_SECRET}
|
||||
# Pepper wird von der Fail-Secure-Startprüfung erwartet (assertSecureEnv).
|
||||
PASSWORD_PEPPER: ${PASSWORD_PEPPER}
|
||||
# IMAP-Zugang des Catch-all-Postfachs. Fehlt es, beendet sich der Worker sauber.
|
||||
INCIDENT_IMAP_HOST: ${INCIDENT_IMAP_HOST:-}
|
||||
INCIDENT_IMAP_PORT: ${INCIDENT_IMAP_PORT:-993}
|
||||
INCIDENT_IMAP_USER: ${INCIDENT_IMAP_USER:-}
|
||||
INCIDENT_IMAP_PASSWORD: ${INCIDENT_IMAP_PASSWORD:-}
|
||||
INCIDENT_IMAP_TLS: ${INCIDENT_IMAP_TLS:-true}
|
||||
INCIDENT_IMAP_MAILBOX: ${INCIDENT_IMAP_MAILBOX:-INBOX}
|
||||
INCIDENT_IMAP_POLL_MS: ${INCIDENT_IMAP_POLL_MS:-60000}
|
||||
# Muss zur Catch-all-Subdomain passen (Ableitung der Intake-Adressen).
|
||||
INCIDENT_INTAKE_DOMAIN: ${INCIDENT_INTAKE_DOMAIN:-in.certvia.de}
|
||||
AUTH_URL: ${AUTH_URL}
|
||||
networks:
|
||||
- backend
|
||||
- default
|
||||
security_opt:
|
||||
- "no-new-privileges:true"
|
||||
cap_drop:
|
||||
- ALL
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "0.5"
|
||||
memory: 512M
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
restart: unless-stopped
|
||||
|
||||
postgres:
|
||||
image: pgvector/pgvector:0.8.0-pg16
|
||||
@@ -401,7 +358,7 @@ services:
|
||||
# Der zu importierende Garage-Key = App-Key (App-Env und Garage synchron).
|
||||
S3_ACCESS_KEY: ${S3_ACCESS_KEY}
|
||||
S3_SECRET_KEY: ${S3_SECRET_KEY}
|
||||
S3_BUCKET: ${S3_BUCKET:-isms-documents}
|
||||
S3_BUCKET: ${S3_BUCKET:-craftvia-documents}
|
||||
# Optionaler separater Backup-Bucket (nur falls Backup-Store auf S3 statt lokal).
|
||||
BACKUP_S3_BUCKET: ${BACKUP_S3_BUCKET:-}
|
||||
# Single-Node-Layout (nominale Kapazität/Zone; für Prod ggf. anheben).
|
||||
|
||||
+29
-18
@@ -1,12 +1,18 @@
|
||||
# Lokales Dev-Compose. Härtung ggü. Backlog-Findings:
|
||||
# Craftvia — lokales Dev-Compose. Härtung:
|
||||
# - F-11: alle Images auf konkrete Tags gepinnt (kein :latest / rollender Tag)
|
||||
# - F-18: Host-Ports NUR auf 127.0.0.1 gebunden (nicht auf allen Interfaces des
|
||||
# Entwicklerrechners); Redis mit Passwort (requirepass);
|
||||
# - F-18: Host-Ports NUR auf 127.0.0.1 gebunden; Redis mit Passwort (requirepass);
|
||||
# security_opt no-new-privileges auf allen Services.
|
||||
# Für Prod/Testserver gilt docker-compose.coolify.yml (Netzsegmentierung, Limits etc.).
|
||||
#
|
||||
# Build-Targets (Dockerfile ist multi-stage; die LETZTE Stage ist das Garage-Image —
|
||||
# ohne explizites target würde `build: .` dieses Image bauen, das weder node noch npx hat):
|
||||
# runner → Next-Standalone-App
|
||||
# migrate → Node + tsx + src (Worker, Provisioning-/Seed-Jobs)
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
build:
|
||||
context: .
|
||||
target: runner
|
||||
ports:
|
||||
- "127.0.0.1:3000:3000"
|
||||
env_file: .env
|
||||
@@ -23,11 +29,13 @@ services:
|
||||
condition: service_completed_successfully
|
||||
restart: unless-stopped
|
||||
|
||||
# Wird in Iteration 4 aktiviert (BullMQ-Scheduler, siehe docs/SPEC.md §4.5)
|
||||
# Mail-Worker (BullMQ): Zustellung + täglicher Erinnerungslauf.
|
||||
worker:
|
||||
profiles: ["worker"]
|
||||
build: .
|
||||
command: ["npm", "run", "worker"]
|
||||
build:
|
||||
context: .
|
||||
target: migrate
|
||||
command: ["npm", "run", "worker:mail"]
|
||||
env_file: .env
|
||||
security_opt:
|
||||
- "no-new-privileges:true"
|
||||
@@ -41,9 +49,9 @@ services:
|
||||
postgres:
|
||||
image: pgvector/pgvector:0.8.0-pg16
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-isms}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-isms}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-isms}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-craftvia}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-craftvia}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-craftvia}
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
ports:
|
||||
@@ -51,7 +59,7 @@ services:
|
||||
security_opt:
|
||||
- "no-new-privileges:true"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-isms}"]
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-craftvia}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
@@ -60,7 +68,7 @@ services:
|
||||
image: redis:7.4.2-alpine
|
||||
# F-18: Redis mit Passwort. REDIS_URL in .env muss das Passwort tragen, z. B.
|
||||
# redis://:${REDIS_PASSWORD}@localhost:6379
|
||||
command: ["redis-server", "--requirepass", "${REDIS_PASSWORD:-isms-redis}"]
|
||||
command: ["redis-server", "--requirepass", "${REDIS_PASSWORD:-craftvia-redis}"]
|
||||
volumes:
|
||||
- redisdata:/data
|
||||
ports:
|
||||
@@ -68,9 +76,8 @@ services:
|
||||
security_opt:
|
||||
- "no-new-privileges:true"
|
||||
|
||||
# Objektspeicher: Garage (S3-kompatibel) — ersetzt MinIO (EOL). S3-API auf 3900,
|
||||
# Admin-API auf 3903 (nur lokal gebunden). Dev-Secrets kommen aus .env (siehe
|
||||
# .env.example: GARAGE_RPC_SECRET/GARAGE_ADMIN_TOKEN, S3_ACCESS_KEY/S3_SECRET_KEY).
|
||||
# Objektspeicher: Garage (S3-kompatibel). S3-API auf 3900, Admin-API auf 3903 (nur lokal
|
||||
# gebunden). Dev-Secrets kommen aus .env (siehe .env.example).
|
||||
garage:
|
||||
image: dxflrs/garage:v1.2.0
|
||||
environment:
|
||||
@@ -93,16 +100,20 @@ services:
|
||||
start_period: 5s
|
||||
|
||||
# Idempotenter Provisioning-Job (Layout + Bucket + Key + Rechte via Admin-API).
|
||||
# Nutzt das App-Image (tsx vorhanden); läuft einmalig vor der app.
|
||||
# Läuft im migrate-Target (Node + tsx vorhanden); einmalig vor der app.
|
||||
# Alternative ohne Image-Build (Host-Node):
|
||||
# GARAGE_ADMIN_URL=http://localhost:3903 npx tsx scripts/garage-provision.ts
|
||||
garage-provision:
|
||||
build: .
|
||||
build:
|
||||
context: .
|
||||
target: migrate
|
||||
command: ["npx", "tsx", "scripts/garage-provision.ts"]
|
||||
environment:
|
||||
GARAGE_ADMIN_URL: http://garage:3903
|
||||
GARAGE_ADMIN_TOKEN: ${GARAGE_ADMIN_TOKEN:-0000000000000000000000000000000000000000000000000000000000000003}
|
||||
S3_ACCESS_KEY: ${S3_ACCESS_KEY:-GKdead0000beef0000cafe0000}
|
||||
S3_SECRET_KEY: ${S3_SECRET_KEY:-0000000000000000000000000000000000000000000000000000000000000001}
|
||||
S3_BUCKET: ${S3_BUCKET:-isms-documents}
|
||||
S3_BUCKET: ${S3_BUCKET:-craftvia-documents}
|
||||
GARAGE_CAPACITY_BYTES: ${GARAGE_CAPACITY_BYTES:-10000000000}
|
||||
security_opt:
|
||||
- "no-new-privileges:true"
|
||||
|
||||
@@ -1,290 +0,0 @@
|
||||
# Feindesign B1 — Assessment und Readiness für zwei Frameworks
|
||||
|
||||
**Stand:** 2026-08-27 · **Branch:** `feature/iso27001-framework-mapping` · **Status:** Entwurf zur Abnahme
|
||||
|
||||
> **Ausgangslage:** AP1–AP5 sind umgesetzt. Ein ISO-Mandant hat Dokumente, SoA-Modell, Kennzahlen,
|
||||
> Managementbewertung und Korrekturmaßnahmen. Was fehlt, ist die **Bewertungs- und Readiness-Sicht**:
|
||||
> `maturity.ts`, `scope-filter.ts`, `assessment-level.ts` und `readiness.ts` kennen kein Framework und
|
||||
> rechnen durchgängig VDA ISA — AL2/AL3, Prüfziele, Reifegrad 0–3, MUSS/SOLL.
|
||||
>
|
||||
> **Belegter Bruch:** `soa-context.ts:151` und `export-context.ts:49` lesen `controlAssessment`.
|
||||
> **Keine einzige Stelle liest `soaEntry`.** Das in AP3 gebaute SoA-Modul ist von der Auswertung
|
||||
> abgekoppelt — die Daten liegen da, die Readiness greift nicht darauf zu.
|
||||
|
||||
Grundlage: `docs/KONZEPT-framework-iso27001.md` (Lane 3), `docs/FRAMEWORK-MAPPING-ISO27001.md`,
|
||||
`docs/UEBERGABE-framework-iso27001.md`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Leitentscheidung: die Belegbasis liegt **unterhalb** der Framework-Strategie
|
||||
|
||||
Es werden **nicht zwei Engines** gebaut. Der Belegstatus eines Controls — ist die zuständige Richtlinie
|
||||
freigegeben, existiert das Verfahren, hängt ein Asset dran, gibt es einen Wirksamkeitsnachweis — ist
|
||||
eine **Tatsache über die Organisation**, keine Frage der Norm. Ob R08 freigegeben ist, ändert sich
|
||||
nicht dadurch, ob ISO oder VDA ISA danach fragt.
|
||||
|
||||
Würde man die Belegbasis mitparallelisieren, entstünden zwei Bewertungen derselben Realität, die
|
||||
auseinanderlaufen können. Im Audit steht dann „Berechtigungsvergabe: TISAX Reifegrad 3" neben
|
||||
„ISO: teilweise umgesetzt" — ein Widerspruch über denselben Sachverhalt.
|
||||
|
||||
**Regel: eine Belegbasis, zwei Bewertungen.**
|
||||
|
||||
```
|
||||
Schicht 3 Sichten /soa · /audit-readiness · Exporte · Wizard-Schritte → Reiter je Framework
|
||||
Schicht 2 Strategie Scope · Zielwert · Bewertung · Vokabular → je Framework
|
||||
Schicht 1 Belegbasis loadEvidenceResolver → ControlEvidence → GETEILT
|
||||
Schicht 0 Fachdaten PolicyDocument · Evidence · Asset · Risk · Measure → GETEILT
|
||||
```
|
||||
|
||||
Das ist derselbe Schnitt wie bei den Richtlinien: ein Umsetzungstext, zwei Anforderungssichten.
|
||||
|
||||
---
|
||||
|
||||
## 2. Was generalisiert wird (Schicht 1)
|
||||
|
||||
`ControlEvidence` (`src/lib/maturity.ts:54`) ist bereits **framework-neutral** — Richtlinienstatus,
|
||||
Verfahrensstatus, Asset-/Risiko-Verknüpfung, operativer Wirksamkeitsnachweis. Nur der *Eingabetyp* des
|
||||
Resolvers ist TISAX-spezifisch.
|
||||
|
||||
**Änderung:** `C5ControlSpec` (`maturity.ts:16`) wird auf ein neutrales `ControlSpec` reduziert:
|
||||
|
||||
```ts
|
||||
export interface ControlSpec {
|
||||
control: string; // "4.1.2" | "A.8.5"
|
||||
title: string;
|
||||
policy: string[]; // ["R08"]
|
||||
verfahren: string[]; // ["VA-03"]
|
||||
needsAsset: boolean;
|
||||
needsRisk: boolean;
|
||||
}
|
||||
// C5ControlSpec extends ControlSpec { target: number } — TISAX-Zusatzfeld bleibt dort
|
||||
```
|
||||
|
||||
`loadEvidenceResolver(db, completeControls)` nimmt künftig `ControlSpec`. **Für TISAX ändert sich
|
||||
nichts** — `C5ControlSpec` erfüllt das Interface.
|
||||
|
||||
### ISO-Specs kommen aus dem Mapping, nicht von Hand
|
||||
|
||||
`mapping-iso.json` trägt je Anforderung bereits `policy` (R-Code) und `verfahren` (VA-Codes). Daraus
|
||||
lässt sich der ISO-`ControlSpec` erzeugen. `needsAsset`/`needsRisk` werden über den vorhandenen
|
||||
Crosswalk `ISO_TO_ISA` (`src/lib/iso-isa-crosswalk.ts`, 87 der 120) vom ISA-Spec **geerbt**; für die
|
||||
33 ISO-eigenen Abschnitte werden sie explizit gesetzt — sinnvoll nur bei A.5.9 (`needsAsset`) sowie
|
||||
6.1.2/6.1.3/8.2/8.3 (`needsRisk`).
|
||||
|
||||
**Umsetzung:** `_generate_iso.py` erzeugt zusätzlich `src/lib/control-specs-iso.ts` — analog zu
|
||||
`control-titles-iso.ts` und `iso-isa-crosswalk.ts`. Damit bleibt das Mapping die einzige Quelle und
|
||||
niemand pflegt eine zweite Liste.
|
||||
|
||||
---
|
||||
|
||||
## 3. Die Strategie-Schnittstelle (Schicht 2)
|
||||
|
||||
```ts
|
||||
export type FrameworkKey = "TISAX" | "ISO_27001";
|
||||
|
||||
/** Bewertung eines Controls — je Framework ein eigener Typ, nie gemischt. */
|
||||
export type Verdict =
|
||||
| { kind: "maturity"; suggested: 0 | 1 | 2 | 3; confirmed: number | null; target: 2 | 3 }
|
||||
| { kind: "status"; applicable: boolean; suggested: ImplStatus; confirmed: ImplStatus | null };
|
||||
|
||||
export type ImplStatus = "umgesetzt" | "teilweise" | "geplant";
|
||||
|
||||
export interface AssessmentRow {
|
||||
control: string;
|
||||
title: string;
|
||||
spec: ControlSpec;
|
||||
evidence: ControlEvidence; // aus Schicht 1, identisch für beide Frameworks
|
||||
verdict: Verdict; // je Framework interpretiert
|
||||
gaps: OpenPoint[];
|
||||
}
|
||||
|
||||
export interface FrameworkStrategy {
|
||||
key: FrameworkKey;
|
||||
/** Anzeigename für Reiter und Berichte. */
|
||||
label: string; // "TISAX / VDA ISA 2027" | "ISO/IEC 27001:2022"
|
||||
/** Datei im Vorlagenpaket. */
|
||||
mappingFile: string; // "mapping.json" | "mapping-iso.json"
|
||||
/** Controls im Geltungsbereich — TISAX: AL + Prüfziele · ISO: Anwendbarkeit aus der SoA. */
|
||||
controlsInScope(db: TenantDb): Promise<ControlSpec[]>;
|
||||
/** Bewertung eines Controls aus geteiltem Beleg + framework-eigener Regel. */
|
||||
evaluate(spec: ControlSpec, ev: ControlEvidence, ctx: EvalContext): Verdict;
|
||||
/** Offene Punkte, die aus der Lücke zum Zielwert folgen. */
|
||||
gaps(spec: ControlSpec, ev: ControlEvidence, v: Verdict): OpenPoint[];
|
||||
/** Kennzahl und Textband — framework-eigenes Vokabular, kein gemeinsamer Nenner. */
|
||||
summarise(rows: AssessmentRow[]): ReadinessSummary;
|
||||
}
|
||||
```
|
||||
|
||||
`buildControlRows` (`soa-context.ts:146`) wird zu `buildAssessment(db, tenantId, framework)` und
|
||||
delegiert an die Strategie. Die Belegauflösung bleibt, wo sie ist.
|
||||
|
||||
### TisaxStrategy — verhaltensgleich extrahieren
|
||||
|
||||
Reine Umverdrahtung, **kein** neues Verhalten: `loadScopeInput` + `controlsInScope` → `controlsInScope`,
|
||||
`suggestMaturity` + `targetMaturity` → `evaluate`, `openPoints` → `gaps`, `computeReadiness` →
|
||||
`summarise`. Regressionsschutz: Snapshot-Test gegen die heutige Ausgabe (siehe §7).
|
||||
|
||||
### IsoStrategy — neu
|
||||
|
||||
| Aspekt | Regel |
|
||||
|---|---|
|
||||
| **Scope** | `SoaEntry.applicable = true`. Kein AL, keine Prüfziele. Klauseln 4–10 sind **immer** im Scope (nicht Gegenstand der Anwendbarkeit). |
|
||||
| **Zielwert** | `implementationStatus = "umgesetzt"` für jedes anwendbare Control. Keine Stufung. |
|
||||
| **Vorschlag** | aus `ControlEvidence`: Richtlinie *und* Verfahren `validiert` + geforderte Verknüpfungen vorhanden → `umgesetzt`; teilweise belegt → `teilweise`; sonst `geplant`. |
|
||||
| **Bestätigung** | `SoaEntry.implementationStatus` ist der bestätigte Wert; der Vorschlag überschreibt ihn nie (Muster wie `ControlAssessment.suggested` / `confirmedValue`). |
|
||||
| **Lücken** | fehlende Begründung, fehlender Nachweis, Status ≠ „umgesetzt" bei anwendbarem Control. |
|
||||
|
||||
---
|
||||
|
||||
## 4. Vorbelegung bei Doppel-Framework — gegen Doppelerfassung
|
||||
|
||||
Führt ein Mandant beide Normen, darf der ISB **nicht zweimal dasselbe beantworten**. Über
|
||||
`ISO_TO_ISA` ist bekannt, welches ISA-Control denselben Bibliotheksabschnitt trägt.
|
||||
|
||||
**Regel:** Ist das zugehörige ISA-Control bestätigt und erreicht seinen Zielreifegrad, schlägt die
|
||||
ISO-Sicht `umgesetzt` vor — mit Verweis auf denselben Nachweis. Der ISB **bestätigt**, das System
|
||||
setzt nichts automatisch.
|
||||
|
||||
Für die 33 ISO-Anforderungen ohne ISA-Gegenstück (Managementsystem-Klauseln, Clear Desk, DLP,
|
||||
Kapazität, Zeitsynchronisation …) gibt es keine Vorbelegung — sie werden regulär bewertet. Das ist
|
||||
zugleich die ehrliche Aussage an den Kunden: **das ist die Delta-Arbeit, die ISO gegenüber TISAX
|
||||
zusätzlich verlangt.** Diese Liste ist ein verkaufbares Ergebnis für sich.
|
||||
|
||||
---
|
||||
|
||||
## 5. Sichten und Reiter (Schicht 3)
|
||||
|
||||
| Bereich | Reiter ISO / TISAX | Begründung |
|
||||
|---|:--:|---|
|
||||
| Controls- / SoA-Sicht (`/soa`) | **ja** | zwei Kataloge, zwei Zielsysteme |
|
||||
| Readiness (`/audit-readiness`) | **ja** | je Norm eine eigene Aussage und ein eigenes Vokabular |
|
||||
| Exporte | **ja** | VDA-ISA-Export bleibt TISAX; SoA und Annex-A-Gap sind ISO |
|
||||
| Richtlinien (`/policies`) | **nein** | ein Dokumentensatz; Parallelanzeige im Dokument ist gebaut |
|
||||
| Nachweise | **nein** | ein Beleg belegt eine Tatsache, unabhängig von der fragenden Norm |
|
||||
| Assets, Risiken, Vorfälle, Lieferanten, Aufgaben | **nein** | framework-neutral |
|
||||
|
||||
**Reiter-Verhalten:** ein aktives Framework → kein Reiter, direkte Anzeige. Zwei aktive Frameworks →
|
||||
Reiter, Vorauswahl `TenantFramework.isPrimary`. Die Auswahl gehört in die URL (`?fw=iso`), damit
|
||||
Deep-Links und Berichte reproduzierbar sind.
|
||||
|
||||
**Harte Regel: keine gemischte Gesamtzahl.** Ein „Erfüllungsgrad 87 %" über beide Normen ist fachlich
|
||||
sinnlos — ein Reifegrad 0–3 und ein Umsetzungsstatus lassen sich nicht mitteln. Je Norm eine Kennzahl,
|
||||
immer getrennt ausgewiesen.
|
||||
|
||||
---
|
||||
|
||||
## 6. Vokabular
|
||||
|
||||
`REIFEGRAD_BANDS` (`readiness.ts:16`) ist TISAX-Sprache („Assessment-reif", „AL-Ziel"). Für ISO
|
||||
gehören eigene Bänder auf Basis des Umsetzungsgrads — Vorschlag:
|
||||
|
||||
| Anteil „umgesetzt" | Band | Aussage |
|
||||
|---|---|---|
|
||||
| < 50 % | Aufbau | wesentliche Maßnahmen noch offen |
|
||||
| 50–79 % | In Umsetzung | Struktur steht, Nachweise fehlen |
|
||||
| 80–99 % | Zertifizierungsnah | wenige offene Punkte, Wirksamkeitsnachweise ergänzen |
|
||||
| 100 % | Zertifizierungsreif | alle anwendbaren Controls umgesetzt und belegt |
|
||||
|
||||
**Ein ISO-Auditbericht darf nicht mit „Reifegrad 2,4" argumentieren.** Der Nachweis lautet
|
||||
„umgesetzt, hier ist der Beleg". Der Reifegrad bleibt unter ISO ein optionales Beratungsinstrument —
|
||||
sichtbar als Zusatzspalte, nie als Erfüllungsaussage (Entscheidung aus dem Fachgespräch, Variante 3).
|
||||
|
||||
---
|
||||
|
||||
## 7. Regressionsschutz
|
||||
|
||||
Die Extraktion der `TisaxStrategy` ist der riskanteste Teil. Absicherung **vor** dem Umbau:
|
||||
|
||||
1. **Snapshot erzeugen:** `buildControlRows` für den Demo-Mandanten (321 Anforderungen, 45 Controls)
|
||||
als JSON festhalten — Reifegradvorschlag, Zielwert, Belegstatus und offene Punkte je Control.
|
||||
2. **Nach dem Umbau vergleichen:** `buildAssessment(db, tenantId, "TISAX")` muss denselben Snapshot
|
||||
liefern. Abweichung = Regression, kein „ist besser geworden".
|
||||
3. Als `scripts/test-framework-assessment.ts` in der Hausform der übrigen `test-*.ts` ablegen.
|
||||
|
||||
Ergänzend unverändert gültig: `_verify.py`, `_verify_iso.py --lang de|en`, `_render_diff.py HEAD`,
|
||||
`test-framework-dryrun.ts`.
|
||||
|
||||
---
|
||||
|
||||
## 7a. Priorisierung nach Kundenlage (Nachtrag 2026-08-27)
|
||||
|
||||
**Ist-Lage:** Die Mehrzahl der Mandanten führt TISAX, **ein** Mandant ISO, **keiner beide**.
|
||||
|
||||
Daraus folgt zweierlei:
|
||||
|
||||
1. **Das Regressionsrisiko dominiert.** Der riskanteste Teil ist nicht die ISO-Logik, sondern die
|
||||
verhaltensgleiche Extraktion der `TisaxStrategy` — sie betrifft alle Bestandsmandanten. Schritt 1
|
||||
(Snapshot) ist damit nicht Kür, sondern die wichtigste Einzelmaßnahme des ganzen Pakets.
|
||||
2. **Zwei Themen lassen sich zurückstellen** — beide betreffen ausschließlich den Doppel-Mandanten,
|
||||
den es heute nicht gibt:
|
||||
|
||||
| Zurückgestellt | Was entfällt vorerst | Wieder aufnehmen, wenn |
|
||||
|---|---|---|
|
||||
| **Schritt 7** — Vorbelegung über `ISO_TO_ISA` | Übernahmevorschlag aus dem jeweils anderen Framework | ein Mandant beide Normen führt |
|
||||
| **Schritt 8b** — Reiter-UI | Umschalter in `/soa` und `/audit-readiness`; bei einem aktiven Framework wird direkt angezeigt | ein Mandant beide Normen führt |
|
||||
|
||||
**Was dabei nicht zurückgestellt werden darf:** die **Strategie-Schnittstelle** und der
|
||||
**Framework-Parameter** in `buildAssessment`. Beide kosten jetzt fast nichts und sind später teuer
|
||||
nachzurüsten, weil sonst 7 Aufrufstellen erneut angefasst werden müssen. Die Architektur bleibt
|
||||
zweigleisig, nur die Oberfläche zeigt vorerst ein Gleis.
|
||||
|
||||
Erwartete Wirkung auf den Aufwand: **5–8 PT → 4–6 PT.**
|
||||
|
||||
---
|
||||
|
||||
## 8. Arbeitsschritte
|
||||
|
||||
| # | Schritt | Ergebnis |
|
||||
|---|---|---|
|
||||
| **1** | Snapshot-Test der heutigen TISAX-Ausgabe | Regressionsnetz steht, **vor** jedem Umbau |
|
||||
| **2** | `ControlSpec` einführen, `loadEvidenceResolver` darauf umstellen | Belegbasis framework-neutral, TISAX unverändert |
|
||||
| **3** | `_generate_iso.py` erzeugt `control-specs-iso.ts` | ISO-Specs aus dem Mapping, keine Zweitpflege |
|
||||
| **4** | `FrameworkStrategy` + `TisaxStrategy` (reine Extraktion) | Snapshot grün |
|
||||
| **5** | `IsoStrategy` (Scope aus SoA, Status statt Reifegrad) | ISO-Bewertung rechnet |
|
||||
| **6** | `buildAssessment(db, tenantId, framework)` ersetzt `buildControlRows` | 7 Dateien rufen es direkt, 13 hängen an der Assessment-Logik insgesamt |
|
||||
| ~~**7**~~ | ~~Vorbelegung über `ISO_TO_ISA`~~ | **zurückgestellt** — betrifft nur Doppel-Mandanten (§7a) |
|
||||
| **8a** | ISO-Readiness-Bänder und framework-richtige Beschriftung | ISO-Mandant sieht ISO-Vokabular |
|
||||
| ~~**8b**~~ | ~~Reiter in `/soa` und `/audit-readiness`~~ | **zurückgestellt** (§7a) |
|
||||
| **9** | ISO-Exporte: SoA + Annex-A-Gap | Managementbewertung hat ihre Eingabe |
|
||||
|
||||
Schritte 1–4 sind Pflicht und hängen aneinander. 5–9 sind danach teilbar.
|
||||
|
||||
---
|
||||
|
||||
## 9. Definition of Done
|
||||
|
||||
| Prüfung | Erwartung |
|
||||
|---|---|
|
||||
| Snapshot-Test TISAX | 0 Abweichungen zur Ausgabe vor dem Umbau |
|
||||
| Reiner ISO-Mandant | Readiness und SoA rechnen; keine AL-, Prüfziel- oder Reifegrad-Begriffe in der Oberfläche |
|
||||
| Reiner TISAX-Mandant | Verhalten und Beschriftung unverändert |
|
||||
| Doppel-Mandant | *zurückgestellt* — Architektur trägt es, Oberfläche zeigt es noch nicht (§7a) |
|
||||
|
||||
| ISO-Delta | die 33 Anforderungen ohne ISA-Gegenstück sind als eigene Liste ausweisbar |
|
||||
| Gate | `tsc`, `lint`, `build`, `_verify*`, `_render_diff`, beide Testskripte grün |
|
||||
|
||||
---
|
||||
|
||||
## 10. Aufwand und Risiken
|
||||
|
||||
**Aufwand:** 4–6 PT im vorgezogenen Umfang (§7a), 5–8 PT vollständig. Schwerpunkt liegt auf Schritt 4 (verhaltensgleiche Extraktion) und Schritt 8
|
||||
(zwei Sichten statt einer), nicht auf der ISO-Logik selbst — die ist schlank.
|
||||
|
||||
| Risiko | Gegenmaßnahme |
|
||||
|---|---|
|
||||
| TISAX-Regression bei der Extraktion | Snapshot-Test **vor** Schritt 2 anlegen, als Merge-Gate setzen |
|
||||
| Belegbasis wandert versehentlich in die Strategie | Review-Kriterium: `loadEvidenceResolver` darf `FrameworkKey` nicht kennen |
|
||||
| Gemischte Kennzahlen schleichen sich in die UI | `ReadinessSummary` je Framework typisieren, keine Aggregation über beide |
|
||||
| ISO-Scope hängt an gepflegter SoA | leere SoA → Readiness meldet „Anwendbarkeit noch nicht erklärt" statt 0 % |
|
||||
| Doppelte Datenpflege beim Doppel-Mandanten | Schritt 7 ist nicht optional |
|
||||
|
||||
---
|
||||
|
||||
## 11. Was ausdrücklich **nicht** gebaut wird
|
||||
|
||||
- Kein Reiter über Richtlinien, Nachweisen, Assets, Risiken oder Aufgaben.
|
||||
- Keine gemeinsame Kennzahl über beide Frameworks.
|
||||
- Kein Reifegrad als ISO-Erfüllungsaussage (optionale Zusatzspalte ja, Bewertungsgrundlage nein).
|
||||
- Keine Änderung an der VDA-ISA-Logik über die reine Extraktion hinaus.
|
||||
- Kein Umbau von `readiness.ts`/`gap-consolidation.ts` — die Rechen-Engines sind numerisch
|
||||
standard-agnostisch und werden von beiden Strategien gefüttert.
|
||||
@@ -1,150 +0,0 @@
|
||||
# ISO/IEC 27001:2022 auf der gemeinsamen Dokumentenbibliothek (Variante A)
|
||||
|
||||
**Stand:** 2026-08-27 · **Paket:** `seed/isms-vorlagenpaket-v2` (+ `-en`) · **Status:** umgesetzt, ISB-Freigabe offen
|
||||
|
||||
> **Entscheidung:** Ein Dokumentensatz, zwei Framework-Mappings. Die bestehenden Richtlinien und
|
||||
> Verfahren bleiben die einzige Quelle; ISO/IEC 27001 wird als zweites Mapping darübergelegt.
|
||||
> Damit ersetzt diese Umsetzung die ursprüngliche Annahme aus `KONZEPT-framework-iso27001.md`
|
||||
> (D4: zweites Seed-Paket `seed/isms-iso27001-v1/`).
|
||||
|
||||
---
|
||||
|
||||
## 1. Warum nicht zwei Pakete
|
||||
|
||||
`PolicyDocument` ist über `@@unique([tenantId, code])` eindeutig. Zwei Pakete mit denselben
|
||||
Dokument-Codes (`L00`, `R01`…`R14`, `VA-01`…`VA-20`) können in einem Mandanten nicht nebeneinander
|
||||
existieren — der zweite Import überschreibt beim Upsert den Inhalt des ersten und archiviert die
|
||||
Dokumente, die im anderen Paket fehlen. Für einen Mandanten mit ISO **und** TISAX wäre das Ergebnis
|
||||
das Gegenteil der Absicht.
|
||||
|
||||
Hinzu kommt der fachliche Punkt: Die Umsetzungsbeschreibung („Umsetzung bei {{ORG_NAME}}") ist
|
||||
normunabhängig. Wie eine Organisation Berechtigungen vergibt, ändert sich nicht dadurch, ob ISO oder
|
||||
VDA ISA danach fragt. Sie zweimal zu pflegen erzeugt Widersprüche.
|
||||
|
||||
## 2. Aufbau
|
||||
|
||||
| Bestandteil | Rolle |
|
||||
|---|---|
|
||||
| `richtlinien/`, `verfahren/` | **gemeinsame** Dokumente — ein Umsetzungstext je Thema |
|
||||
| `mapping.json` | Framework-Mapping **VDA ISA 2027** (321 Anforderungen) |
|
||||
| `mapping-iso.json` | Framework-Mapping **ISO/IEC 27001:2022** (120 Anforderungen) |
|
||||
| `_iso_crosswalk.json` | fachliche Zuordnung ISO-Anforderung → Dokument + Abschnitt (redaktionell) |
|
||||
| `_iso_sections.json` / `_iso_sections_en.json` | Texte der ISO-only-Abschnitte (redaktionell, je Sprache) |
|
||||
| `_iso_texts_en.json` | englische Anforderungstexte (Struktur bleibt im Crosswalk) |
|
||||
| `_generate_iso.py` | erzeugt aus beidem die Dokument-Patches, `mapping-iso.json` und die SoA |
|
||||
| `_verify.py` / `_verify_iso.py` | prüfen je eine Framework-Sicht |
|
||||
| `Statement-of-Applicability-ISO.md` | SoA-Gerüst mit den Pflichtangaben aus 6.1.3 d) |
|
||||
|
||||
### Sichtbarkeitssteuerung über Platzhalter
|
||||
|
||||
Zwei neue Flags in `variables.schema.json` steuern, welche Anforderungssicht ein Mandant sieht:
|
||||
|
||||
| Flag | Default | Wirkung |
|
||||
|---|---|---|
|
||||
| `FLAG_FW_TISAX` | `true` | VDA-ISA-Anforderungsblöcke sichtbar |
|
||||
| `FLAG_FW_ISO27001` | `false` | ISO-Anforderungsblöcke und ISO-only-Abschnitte sichtbar |
|
||||
|
||||
Im Dokument sieht das so aus — der Umsetzungstext steht **einmal** und gilt für beide:
|
||||
|
||||
```markdown
|
||||
### 3.2 Sichere Anmeldung
|
||||
|
||||
*Anforderungsbezug:* {{#if FLAG_FW_TISAX}}VDA ISA 4.1.2{{/if}}{{#if FLAG_FW_ISO27001}}{{#if FLAG_FW_TISAX}} · {{/if}}ISO/IEC 27001 A.8.5{{/if}}
|
||||
|
||||
**Anforderung**
|
||||
|
||||
{{#if FLAG_FW_TISAX}}
|
||||
- **[MUSS]** Verfahren zur Benutzerauthentifizierung nach dem Stand der Technik werden angewandt.
|
||||
{{/if}}
|
||||
{{#if FLAG_FW_ISO27001}}
|
||||
- **[ISO A.8.5]** Sichere Authentisierungstechnologien und -verfahren sind einzusetzen.
|
||||
{{/if}}
|
||||
|
||||
**Umsetzung bei {{ORG_NAME}}**
|
||||
|
||||
<!-- IMPL 4.1.2 -->
|
||||
Die Authentifizierungsverfahren sind risikobasiert ausgewählt … Passwortvorgaben nach BL-IAM-01 …
|
||||
```
|
||||
|
||||
Beide Mappings zeigen mit `impl_anchor` auf denselben Block `IMPL 4.1.2`.
|
||||
|
||||
## 3. Abdeckung
|
||||
|
||||
- **120 ISO-Anforderungen:** 27 Klauseln (Kap. 4–10, inkl. 6.3 aus Amd 1:2024) + 93 Anhang-A-Controls
|
||||
in der Verteilung 37/8/14/34.
|
||||
- **43 Abschnitte** der Bibliothek werden von beiden Frameworks genutzt.
|
||||
- **19 ISO-only-Abschnitte** wurden ergänzt, wo VDA ISA kein Gegenstück hat:
|
||||
|
||||
| Dokument | Neue Abschnitte | ISO-Bezug |
|
||||
|---|---|---|
|
||||
| L00 | Politik, Ziele, Kommunikation | 5.2, 6.2, 7.4, A.5.1 |
|
||||
| R01 | Kontext/Scope · Änderungsplanung · Dokumentenlenkung · Behördenkontakte | 4.1–4.4, 6.3, 7.5.1–7.5.3, A.5.5, A.5.6 |
|
||||
| R02 | Datenmaskierung | A.8.11 |
|
||||
| R03 | SoA · Betriebliche Planung · Messung · Managementbewertung · CAPA | 6.1.3, 8.1, 9.1, 9.3, 10.1, 10.2 |
|
||||
| R05 | Vorgehen bei Verstößen | A.6.4 |
|
||||
| R07 | Umgebungsschutz/Versorgung/Verkabelung/Wartung · Clear Desk | A.7.5, A.7.7, A.7.8, A.7.11–A.7.13 |
|
||||
| R10 | Bedrohungsinformationen · Betriebsabläufe · Kapazität · Datenabfluss · Zeitsynchronisation | A.5.7, A.5.37, A.8.6, A.8.12, A.8.17 |
|
||||
|
||||
Die neuen Abschnitte sind ausschließlich über Platzhalter individualisierbar — wie die
|
||||
Bestandstexte. Dafür kamen elf Variablen und acht Baseline-Parameter hinzu
|
||||
(`BL-OPS-10/11/12`, `BL-NET-03`, `BL-PHY-03/04`, `BL-GOV-02/03`).
|
||||
|
||||
**Ohne ISO-Bezug** bleibt nur der Abschnitt „Nutzung von KI-/GenAI-Diensten" (eigene Ergänzung) sowie
|
||||
die Dokumente `P01` (Prototypenschutz) und `D01` (Datenschutz-Prüfziel) — beides TISAX-spezifisch.
|
||||
|
||||
## 4. Änderungen am Anwendungscode
|
||||
|
||||
Zwei Stellen, beide klein und rückwärtskompatibel:
|
||||
|
||||
1. **`prisma/import-policies.ts`** — der Umsetzungstext wird jetzt über `impl_anchor` aufgelöst
|
||||
(`IMPL 4.1.2`), mit Rückfall auf die Anforderungs-ID und auf ein `implementation`-Feld im Mapping.
|
||||
*Nebeneffekt:* Das behebt einen Bestandsfehler. Bisher wurde `implMap.get(a.id)` gesucht — die
|
||||
Anforderungs-IDs (`4.1.2-M1`) haben aber keinen eigenen IMPL-Block, sodass **alle 321**
|
||||
VDA-ISA-Anforderungen mit leerem Umsetzungstext importiert wurden. Sichtbar war das u. a. in der
|
||||
Spalte „Umsetzung" unter `/policies` und in der Plattform-Vorlagenverwaltung. Nach der Korrektur
|
||||
bleiben 12 leere Einträge (L00 — die Leitlinie hat bewusst keine IMPL-Blöcke).
|
||||
2. **`src/lib/policy-render.ts`** — `buildContext` belegt fehlende Framework-Flags vor
|
||||
(`FLAG_FW_TISAX = true`, `FLAG_FW_ISO27001 = false`). Ohne das würden Bestandsmandanten, deren
|
||||
Vorlagenpaket noch nicht neu importiert wurde, die VDA-ISA-Anforderungsblöcke leer sehen.
|
||||
|
||||
## 5. Prüfung
|
||||
|
||||
```bash
|
||||
cd seed/isms-vorlagenpaket-v2
|
||||
python3 _generate_iso.py # deutsche Fassung, idempotent
|
||||
python3 _generate_iso.py --lang en # englische Fassung
|
||||
python3 _verify.py # TISAX-Sicht → OK
|
||||
python3 _verify_iso.py # ISO-Sicht DE → OK
|
||||
python3 _verify_iso.py --lang en # ISO-Sicht EN → OK
|
||||
```
|
||||
|
||||
`_verify_iso.py` prüft Vollständigkeit (27 + 93), Auflösbarkeit aller Anker, nicht leere
|
||||
Umsetzungsblöcke, das Rendering **beider** Sichten ohne offene Platzhalter sowie die Verknüpfung zu
|
||||
den Verfahren.
|
||||
|
||||
## 6. Was noch fehlt (Anwendungsseite)
|
||||
|
||||
Das Paket ist fertig; die Anwendung kennt das zweite Mapping noch nicht. Offen bleibt aus
|
||||
`KONZEPT-framework-iso27001.md`:
|
||||
|
||||
- **Lane 1** — `Framework`-Enum, `TenantFramework`, `framework` an `PolicyTemplateVersion` und
|
||||
`PolicyPackageState`. Erst damit lässt sich `mapping-iso.json` überhaupt importieren; heute liest
|
||||
`parsePackageFiles` fest `mapping.json`.
|
||||
- **Lane 3/4** — ISO-Assessment (Applicability statt Reifegrad) und das **SoA-Modul**. Bis dahin wird
|
||||
die SoA als gelenktes Dokument geführt (`Statement-of-Applicability-ISO.md`).
|
||||
- **Setzen der Flags** — beim Provisionieren eines ISO-Mandanten müssen `FLAG_FW_ISO27001 = true`
|
||||
und, falls kein TISAX, `FLAG_FW_TISAX = false` gesetzt werden.
|
||||
|
||||
Ebenfalls offen und unabhängig davon: `REVIEW_CYCLE` wird weiterhin für fünf verschiedene Zyklen
|
||||
verwendet. Die neuen Abschnitte nutzen bereits die getrennten Variablen
|
||||
(`POLICY_REVIEW_CYCLE`, `MGMT_REVIEW_CYCLE`, `RISK_REVIEW_CYCLE`); die Bestandstexte umzustellen ist
|
||||
eine eigene, kleine Änderung.
|
||||
|
||||
## 7. Urheberrechtlicher Hinweis
|
||||
|
||||
Die ISO-Anforderungstexte in `mapping-iso.json` und in den Dokumenten sind **eigene Paraphrasen**;
|
||||
die Referenzen sind exakt, damit in der erworbenen Norm nachgeschlagen werden kann. Wörtliche
|
||||
Normzitate sind bewusst unterlassen. Das VDA-ISA-Mapping übernimmt die Anforderungen laut eigenem
|
||||
Hinweis in `mapping.json` „1:1 aus ISA" — auch dieser Katalog ist geschützt. Bei der weiteren Pflege
|
||||
der gemeinsamen Bibliothek sollte die vorsichtigere Linie des ISO-Mappings die gemeinsame werden
|
||||
(vgl. `SPEC.md` §12).
|
||||
@@ -1,83 +0,0 @@
|
||||
# Handbuch Kundenbetreuung — certvia (ISMS-Tool)
|
||||
|
||||
**Stand:** 2026-09-03 · **Zielgruppe:** Kundenbetreuung / Customer Success · **Zweck:** Schneller, praxisnaher Einstieg für die Betreuung von certvia-Kunden — was das Produkt kann, wie ein Kunde aufgesetzt/betreut wird und wie typische Support-Fälle gelöst werden.
|
||||
|
||||
> Dieses Handbuch ist bewusst **produkt- und supportorientiert**. Technische Tiefe steht in `docs/SPEC.md`, `docs/HANDOVER-PM.md` und den `docs/KONZEPT-*.md`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Was ist certvia (in einem Absatz)
|
||||
|
||||
certvia ist ein **Multi-Mandanten-ISMS-Tool** (Informationssicherheits-Managementsystem als SaaS). Jeder Kunde ist ein **Mandant** mit strikt getrennten Daten. Das Tool führt einen Kunden vom Onboarding über Strukturanalyse (Assets/Prozesse/Lieferanten), Risikomanagement, Richtlinien und Maßnahmen bis zur **Audit-Vorbereitung** — wahlweise nach **TISAX (VDA-ISA)** und/oder **ISO 27001**.
|
||||
|
||||
## 2. Zugang, Rollen, Anmeldung
|
||||
|
||||
- **Kunden-Login:** `https://<kunde-domain>/login` — E-Mail + Passwort, danach ggf. MFA (TOTP) und, bei mehreren Mandanten, Mandantenauswahl.
|
||||
- **Plattform-/Superadmin:** `…/platform/login` — **getrennter Login** für die Betreiber-Administration (Mandanten anlegen, Module, Stammdaten). MFA-Einrichtung beim ersten Login.
|
||||
- **Rollen (mandantenintern):** z. B. Mandanten-Admin, ISB (Informationssicherheitsbeauftragter), Auditor, Owner, User. Rechte hängen an Rollen; der **Mandanten-Admin** verwaltet Benutzer & Rollen unter **Einstellungen → Benutzer & Rollen**.
|
||||
- **Passwort/MFA:** Initial-/Reset-Passwörter erzwingen einen Wechsel beim nächsten Login. MFA und Passkeys sind an die **Person (Identity)** gebunden, nicht an den Mandanten.
|
||||
|
||||
## 3. Einen neuen Kunden aufsetzen (Provisionierung)
|
||||
|
||||
Ein Kunde wird als **Mandant** angelegt (über die Plattform-/Superadmin-Konsole bzw. beim ersten Deployment per Bootstrap-Admin). Beim Anlegen wird automatisch:
|
||||
- ein **Mandanten-Admin** erzeugt,
|
||||
- die **Standard-Module** aktiviert,
|
||||
- das **Richtlinien-Vorlagenpaket** importiert (inkl. Anforderungen, Variablen, Nachweisregister),
|
||||
- das **Framework** gesetzt (Default **TISAX**; ISO 27001 ist zusätzlich/alternativ wählbar).
|
||||
|
||||
Die **Stammdaten** des Mandanten (Firmenname, Kürzel, Rollen wie ISB/IT-Leitung/DSB, Scope) pflegt der Kunde unter **Einstellungen** — diese speisen automatisch die ISMS-Variablen in den Richtlinien.
|
||||
|
||||
## 4. Framework-Wahl: ISO 27001 und/oder TISAX
|
||||
|
||||
- Ein Mandant kann **ein oder beide** Frameworks führen. Der Umsetzungstext der Richtlinien ist normunabhängig; je Framework gibt es eine eigene Katalog-/Anforderungssicht.
|
||||
- **TISAX (VDA-ISA):** Reifegrad-Modell, Schutzbedarf/Assessment-Level (AL2/AL3), Prüfziele (Informationssicherheit/Prototypen/Datenschutz), VDA-ISA-Export.
|
||||
- **ISO 27001:** Anwendbarkeitserklärung (SoA, Annex A 2022, 93 Controls) mit „anwendbar/ausgeschlossen + Begründung", Managementklauseln (Kennzahlen 9.1, Managementbewertung 9.3, Korrekturmaßnahmen 10.2) und Dokumentenlenkung.
|
||||
- **Umschalten:** In der Admin-Konsole lassen sich die Normen je Mandant **nachträglich aktivieren/deaktivieren**.
|
||||
|
||||
## 5. Die Module (Kurzüberblick)
|
||||
|
||||
| Modul | Zweck |
|
||||
|---|---|
|
||||
| **Assets** | Informationswerte/Systeme/Anwendungen etc. inkl. Schutzbedarf (C/I/V) |
|
||||
| **Prozesse** | Geschäftsprozesse + Verknüpfung zu Assets (Strukturanalyse) |
|
||||
| **Risiken** | Risiko-Register (Eintritt × Auswirkung), Behandlung, Verknüpfung zu Assets/Prozessen |
|
||||
| **Lieferanten** | Lieferanten-/Dienstleistersteuerung (Kritikalität, NIS2, TISAX-Label, Verträge/NDAs) |
|
||||
| **Maßnahmen** | Maßnahmen zur Risikobehandlung, Wirksamkeit |
|
||||
| **Richtlinien** | Richtlinien-/Verfahrensbibliothek aus Vorlagen, Freigabe, Coverage |
|
||||
| **SoA** | ISO-Anwendbarkeitserklärung bzw. TISAX-Control-Assessment |
|
||||
| **Audit-Readiness** | Reifegrad/Gap-Analyse, Nachweise, Abgabe/Export |
|
||||
| **Vorfälle** | Incident-Management (inkl. NIS2-/DSGVO-Meldevorlagen) |
|
||||
| **Aufgaben** | Kanban-Aufgaben, Fristen |
|
||||
|
||||
Module lassen sich je Mandant **ein-/ausschalten** (Admin-Konsole).
|
||||
|
||||
## 6. Onboarding-Wizard
|
||||
|
||||
Neue Mandanten durchlaufen einen geführten Wizard: **Kontext → Scope → Richtlinien → Rollen → Risikokriterien → Prozesse → Controls**. Er baut das ISMS Schritt für Schritt auf; der Fortschritt wird gespeichert.
|
||||
|
||||
## 7. Typische Support-Fälle
|
||||
|
||||
- **„Login klappt nicht / Anmeldung fehlgeschlagen":** falsche E-Mail/Passwort, oder Account nach mehreren Fehlversuchen kurz gesperrt (15 Min). Prüfen: richtige Seite (`/login` vs `/platform/login`), Passwort exakt. Bei Reset ein Initial-Passwort setzen (erzwingt Wechsel).
|
||||
- **„MFA-Gerät verloren":** über Recovery-Codes anmelden; sonst MFA administrativ zurücksetzen (Mandanten-Admin/Betreiber).
|
||||
- **„Ein Modul fehlt in der Navigation":** Modul ist für den Mandanten deaktiviert → in der Admin-Konsole aktivieren.
|
||||
- **„Falsche Norm / ISO fehlt":** Framework des Mandanten prüfen und ggf. ISO 27001 aktivieren (Admin-Konsole).
|
||||
- **„E-Mails kommen nicht an":** SMTP-Konfiguration prüfen (Betreiber); Postfach/From-Adresse.
|
||||
|
||||
## 8. Wo finde ich vertiefende Infos?
|
||||
|
||||
- **Produkt/Funktionsumfang:** `docs/SPEC.md`, `docs/HANDOVER-PM.md`
|
||||
- **Kundennahe Mockups (im Browser):** `docs/ISMS-Prototyp-GEFIM.html`, `ISMS-Lieferantenmanagement-GEFIM.html`
|
||||
- **Feature-Konzepte:** `docs/KONZEPT-framework-iso27001.md` (ISO/TISAX), `KONZEPT-incidents.md`, `KONZEPT-backup-restore.md`, `KONZEPT-identity-mandanten.md` (Login/Mandanten/MFA)
|
||||
- **Aktueller Stand/Änderungen:** `docs/STAND-dev-branch.md`
|
||||
- **Am besten:** die **Demo-/Testinstanz** durchklicken (Login `admin@demo.example` / `Demo1234!`).
|
||||
|
||||
## 9. Betrieb & Grenzen (gut zu wissen)
|
||||
|
||||
- **Test- vs. Produktivumgebung:** Änderungen werden erst auf einer Testinstanz erprobt, dann produktiv ausgerollt. Support arbeitet auf der Produktivumgebung nur mit Bedacht.
|
||||
- **Backups:** Datenbank + Objektspeicher werden gesichert (Betrieb). Restore ist möglich; keine eigenmächtigen Löschaktionen an Produktivdaten.
|
||||
- **Datenschutz/Mandantentrennung:** Jeder Mandant sieht nur seine eigenen Daten — niemals Kundendaten zwischen Mandanten kopieren.
|
||||
- **Secrets/Zugänge:** niemals per E-Mail/Chat weitergeben; Passwörter setzt der Kunde selbst bzw. als Initial-Passwort mit Wechselzwang.
|
||||
|
||||
---
|
||||
|
||||
*Fehlt etwas oder ist ein Support-Fall unklar? Ergänze dieses Handbuch — es ist als lebendes Dokument gedacht.*
|
||||
@@ -1,197 +0,0 @@
|
||||
# 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 (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.
|
||||
@@ -1,98 +0,0 @@
|
||||
# Projektübergabe — ISMS-Tool (Stand für Projektmanagement)
|
||||
|
||||
> 📌 **Konsolidierter Gesamtstand aller Entwicklungstätigkeiten auf `dev` (PM + Dev):** siehe **`docs/STAND-dev-branch.md`**.
|
||||
|
||||
> Stand: 2026-07-22 · Branch `dev` (Produktionshärtung + Benutzerverwaltung; noch nicht nach `main` gemerged)
|
||||
> Zweck: Statusüberblick für die Weiterplanung — was ist umgesetzt, was ist offen (mit Priorität & grobem Aufwand).
|
||||
|
||||
## 🆕 Neu auf `dev` (Produktionshärtung Phase 1 + Benutzerverwaltung)
|
||||
|
||||
| Thema | Status | Kurz |
|
||||
|-------|:------:|------|
|
||||
| **API-seitige Modul-Durchsetzung** | ✅ | Deaktiviertes Modul sperrt jetzt auch Writes serverseitig; automatischer Vollständigkeitscheck (Build-Gate). |
|
||||
| **Separater Superadmin-Store + eigener Login** | ✅ | Eigener Store/Login (`/platform/login`), Session ohne Mandantenbezug; `isPlatformAdmin`-Umweg abgelöst. |
|
||||
| **MFA für Superadmins** | ✅ (optional) | Zunächst als Pflicht gebaut, dann auf **optional** umgestellt; Policy-Flag „MFA-Pflicht" (aus) stellt die Erzwingung wieder her. |
|
||||
| **Nicht-destruktiver Richtlinien-Re-Import** | ✅ | Diff/Upsert; Status/Override/Freigabe/Variablenwerte bleiben, entfernte Einträge werden deaktiviert; Änderungsreport + Vorschau. |
|
||||
| **Benutzer- & Rollenverwaltung** | ✅ | Plattform-Admin legt je Kunde Nutzer an (Initial-/Einmal-Passwort); Mandanten-Admin verwaltet Nutzer **und** Rollen intern (eigene Rollen + Rechte, Standardrollen klonbar), mandantengetrennt + Lockout-Schutz. Force-Change beim ersten Login, Passwort-Policy. |
|
||||
| **Nutzer-MFA (Mandant)** | ✅ (optional) | Je Nutzer aktivierbar (`/account`); Login verlangt Code nur bei aktiver MFA. |
|
||||
| **SMTP + Einladungs-/Aktivierungs-/Reset-Flow (Paket 4)** | ⏸️ zurückgestellt | E-Mail-Versand bewusst später; die Nutzer-Aktivierung läuft vorerst über Initial-/Einmal-Passwort und ist so gekapselt, dass der Einladungs-Flow ohne Umbau ergänzt werden kann. |
|
||||
|
||||
## Was ist das Produkt
|
||||
|
||||
Multi-Tenant-**SaaS für Informationssicherheits-Management (ISMS)**, ausgerichtet auf **ISO/IEC 27001:2022** und **TISAX / VDA-ISA 2027**. Web-App (Deutsch, EN vorbereitet), Dark-Theme, mandantenfähig (mehrere Kunden, Nutzer, Rollen). Mehrere fachliche Module + Plattform-/Kundenverwaltung.
|
||||
|
||||
**Aufwands-Legende:** **S** = klein (≤ 1 Tag) · **M** = mittel (2–4 Tage) · **L** = groß (> 1 Woche).
|
||||
|
||||
---
|
||||
|
||||
## ✅ Umgesetzt (produktiv nutzbar)
|
||||
|
||||
| # | Modul | Umfang (Kurz) |
|
||||
|---|-------|---------------|
|
||||
| 1 | **Fundament** | Login/Auth (lokale Accounts, NextAuth v5, JWT), **RBAC** (granulare Rechte, Rollen je Mandant), **Mandanten-Isolation** (tenant_id + Postgres-RLS + zentraler App-Guard), i18n (de/en), Dark-Theme (zentrale Tokens), Audit-Log. |
|
||||
| 2 | **Assets & BIA** | Asset-Inventar + Geschäftsprozesse/BIA als ein Modul; C/I/A-Schutzbedarf, Vererbung, Abhängigkeiten; Detail/Bearbeiten/Anlegen als Popups; zugeordnete Risiken. |
|
||||
| 3 | **Risikoanalyse** | 5×5-Heatmap, Risikoregister, Risiko-Detail mit Maßnahmen (dezimale Minderung, Brutto→Rest visualisiert), Bedrohungs-/Schwachstellen-Kataloge, Control-Verknüpfung. |
|
||||
| 4 | **Maßnahmen** | Kanban-Board (Drag & Drop), berechnetes Restrisiko aus Maßnahmen. |
|
||||
| 5 | **Abhängigkeiten & kritische Pfade** | Interaktiver Graph (React Flow + dagre), Single Points of Failure, kritische Pfade. |
|
||||
| 6 | **Lieferanten- & IT-Service-Management** | Asset-basiert (Lieferant/IT-Service **sind** Assets); Anforderungs-Engine (Schutzbedarf→Stufen), Gate-Logik (erzeugt echte Risiken), ISB-Reifegrad-Freigabe; **RACI-Matrix** über ISA-Controls (VDA-ISA 6.1.3); Cockpit direkt aus dem Asset-Inventar öffenbar. |
|
||||
| 7 | **Richtlinien & Verfahren (VDA-ISA 2027)** | Siehe Detailblock unten — größtes Modul. |
|
||||
| 8 | **Admin-Konsole & Mandantenverwaltung (Phase 1)** | Plattform-Admin (`/admin`): Kunden anlegen + **automatisch provisionieren**, Module-Toggles, Lebenszyklus (aktiv/gesperrt/archiviert). Kunden-Einstellungen (`/settings`): Stammdaten → speisen ISMS-Variablen, Branding, TISAX-Level. **Serverseitige Modul-Durchsetzung** (deaktivierte Module gesperrt, nicht nur ausgeblendet). |
|
||||
|
||||
### Modul 7 „Richtlinien & Verfahren" im Detail (umgesetzt)
|
||||
- **Import** des VDA-ISA-2027-Vorlagenpakets: **28 Dokumente** (Leitlinie L00, R01–R14, VA-01–VA-13), **316 Anforderungen** (122 MUSS · 132 SOLL · 43 HOHER · 19 SEHR HOHER Schutzbedarf) über **45 Controls**; Baseline-Parameter, Variablen, Nachweisregister.
|
||||
- **Rendering-Engine**: Handlebars (verschachtelte `{{#if}}`-Flags), Variablen aus einer Pflegestelle, Deep-Links, BL-Referenzen im Lesemodus entfernt; rückstandsfrei über alle Flag-Kombinationen.
|
||||
- **Bibliothek** + **Referenz-/Coverage-Matrix** (zwei Richtungen: nach Control / nach Dokument).
|
||||
- **Lesemodus** als eigene Seite (kein Popup); **Bearbeitungsmodus** variablenbasiert + **Vier-Augen-Freigabe** (Entwurf → In Freigabe → Freigegeben); **Experten-Modus** (Rohtext-Editor + Formatier-/Einfügehilfen + Auto-Anlage neuer Variablen).
|
||||
- **Verwaltete Register** (editierbar): Verschlüsselungsregister (mit Ablaufüberwachung), Risiko-Bewertungsmatrix (FB-80-04-Defaults), Klassifizierungs-Handhabungsmatrix (AA-80-20). **Anwender-Handbuch** (kuratiert, Baseline-synchron, Deep-Links).
|
||||
- **Schutzbedarf-/TISAX-Level-Schalter (AL2/AL3)** global + **Override je Richtlinie**.
|
||||
|
||||
---
|
||||
|
||||
## 🟥 Offen — Hohe Priorität
|
||||
|
||||
| Thema | Aufwand | Anmerkung |
|
||||
|-------|:------:|-----------|
|
||||
| **NIS2-Modul** (nie begonnen) | **L** | Framework Art. 20/21 + Control-Mapping, Einrichtungs-Einstufung + BSI-Registrierung, **Incident-Reporting-Workflow mit Fristen-Timern (24 h / 72 h / 1 Monat)**, NIS2-Dashboard. War „Teil C" der ursprünglichen Planung. |
|
||||
| **Admin-Konsole Phase 2 — Impersonation** | **M** | Zeitlich begrenzter, protokollierter Support-Zugriff in einen Mandanten; „Support-Sitzung aktiv"-Banner; automatischer Ablauf. |
|
||||
| **Admin-Konsole Phase 2 — Plan/Limits** | **M** | Lizenzstufen, Limits (Nutzer/Speicher/Assets), Warnung/Sperre bei Überschreitung. |
|
||||
| **Separater Superadmin-Store + eigener Login + MFA-Pflicht** | **M–L** | Aktuell ist der Superadmin ein `isPlatformAdmin`-Nutzer im Mandanten (Demo). Spec fordert getrennte Accounts + eigenen Login-Pfad. |
|
||||
| **Richtlinien: echte Versionierung + Diff** | **M–L** | Aktuell ändert die Freigabe nur den Status (ohne Versionshistorie/Diff). Entwurf-neben-Freigegeben, block-/klauselgenauer Diff. |
|
||||
| **Richtlinien: DOCX/PDF-Export** | **M** | Voll gerendert im GEFIM-Corporate-Design; Referenz-/Nachweisdoku separat. |
|
||||
|
||||
---
|
||||
|
||||
## 🟧 Offen — Mittlere Priorität
|
||||
|
||||
| Thema | Aufwand | Anmerkung |
|
||||
|-------|:------:|-----------|
|
||||
| **Richtlinien: Status „Revoked" + Auto-Version** | **S** | Vom Kunden ausdrücklich für später gemerkt: Status-Auswahl inkl. Revoked (manuell), Version zählt bei jedem Speichern automatisch hoch. |
|
||||
| **Richtlinien: Word-Upload (.docx-Import)** | **M** | Eigene Dokumente hochladen → Block-Modell + Original als Anhang, versioniert, im Freigabeprozess. |
|
||||
| **Richtlinien: KI-Wizard** | **L** | Geführte Erstellung/Anpassung (control-getrieben, Feature-Flags/Reifegrad), KI formuliert Blocktext. |
|
||||
| **Richtlinien: KI-Formulierungshilfe im Experten-Modus** | **M** | Braucht Anthropic-API-Anbindung. |
|
||||
| **Zentrale Baseline-/Variablen-Einstellseite** | **S–M** | Eine Pflegestelle mit Freigabe-Durchlauf. |
|
||||
| **Admin Phase 2 — Logo-Upload / Objektspeicher je Mandant** | **M** | Für UI-Kopf + Export (Branding/Whitelabel). |
|
||||
| **Admin Phase 2 — SMTP/Benachrichtigungen + Einladungs-/Aktivierungs-Flow** | **M** | E-Mail-Einladung, Passwort-Setzen, Benachrichtigungsregeln (Fristen/Freigaben/Vorfälle). |
|
||||
| **Lieferanten Phase 2** | **M–L** | Fragebogen-Builder, Self-Service-Portal (externer Lieferantenzugang), Scheduler (Review-/Ablauf-Erinnerungen). |
|
||||
| **Risikomatrix zusammenführen** | **M** | Bewertungsmatrix im Richtlinienmodul ist eigene 4×4-Pflegestelle (FB-80-04); Risikoanalyse nutzt 5×5. Auf eine gemeinsame, zentrale Skala vereinheitlichen. |
|
||||
| **Platzhalter-Module ausbauen** | je **M–L** | Sidebar-Punkte vorhanden, aber nicht gebaut: **SoA & Controls**, **Vorfälle**, **Nachweise**, **Management-Review**, **KI-Chat**. |
|
||||
|
||||
---
|
||||
|
||||
## 🟩 Offen — Niedrige Priorität / Technische Schulden
|
||||
|
||||
| Thema | Aufwand | Anmerkung |
|
||||
|-------|:------:|-----------|
|
||||
| **Modul-Durchsetzung auf API-Ebene vervollständigen** | **S** | Route-Zugriff (GET) ist für alle Module gesperrt; der `requireModule`-Guard in Server-Actions ist bisher **exemplarisch nur für Richtlinien** gesetzt. Einzeiler je Action-Guard nachziehen. |
|
||||
| **Richtlinien-Re-Import ist destruktiv** | **M** | Re-Import löscht + legt Dokumente/Anforderungen neu an (setzt per-Dokument-Status/Override/Freigabe zurück). Spec wünscht „deaktivieren statt löschen" + Historie erhalten. |
|
||||
| **Coverage zeigt alle statt nur aktive Anforderungen** | **S** | Referenzmatrix listet vollständig (gut für Audit); optional Filter „nur aktive" nach effektiven Flags. |
|
||||
| **Admin Phase 2 — Datenexport/Löschung/Retention (DSGVO)** | **L** | Mandantenvollständiger Export, Löschkonzept, Aufbewahrungsfristen. |
|
||||
| **Optionale Zusatzfeatures** | je **M** | SSO (OIDC/SAML), API-Keys/Webhooks, Onboarding-Wizard, E-Mail-Domain-Allowlist, Wartungs-/Status-Banner. |
|
||||
|
||||
---
|
||||
|
||||
## Hinweise für die Planung
|
||||
|
||||
- **Spezifikationen** liegen im Repo: `docs/SPEC.md` (Gesamt-Spec) sowie die Übergabe-Prompts und Mockups je Modul (Richtlinien, Admin-Konsole). Neue Anforderungen kamen bisher als „Delta-Prompts" (z. B. TISAX-Level-Update).
|
||||
- **Nächster logischer Block:** entweder **NIS2** (letztes großes Framework, hängt am Incident-/Vorfälle-Modul) oder **Admin-Konsole Phase 2** (Impersonation + Plan/Limits + Superadmin-Login), je nach Vertriebs-/Compliance-Priorität.
|
||||
- **Demo-Umgebung:** Mandant „demo", Login `admin@demo.example` (ist Superadmin + Mandanten-Admin), Passwort im Seed. 4 Demo-Rollen vorhanden.
|
||||
- **Qualität:** Jede Iteration wurde mit `tsc` + `lint` + `build` und – wo möglich – Browser-Verifikation abgeschlossen; Commits sind fein granular und je Thema.
|
||||
@@ -1,238 +0,0 @@
|
||||
# Implementierungsfaden — TISAX-Onboarding-Wizard Neustruktur
|
||||
|
||||
> Status: Entwurf · Grundlage: Konzept v2 (4 Ebenen, nach TISAX-Fachprüfung) + IST-Analyse des Task-Moduls (Branch `dev-tasks-kanban`, `ce1e847`).
|
||||
> Ziel: Aus dem linearen 9-Schritt-Monolithen `/onboarding` werden vier Ebenen — **Fundament → Strukturanalyse → Cockpit → Audit** — informationszentriert, prozessgeführt erhoben, bereichsbasiert umgesetzt.
|
||||
|
||||
---
|
||||
|
||||
## 0. Ausgangslage & Auswirkung der Kanban-Anpassung
|
||||
|
||||
Das Task-Modul wurde zwischenzeitlich auf ein **Kanban-Board** umgestellt (`src/components/kanban-board.tsx`, `src/app/(app)/tasks/page.tsx`, Action `updateTaskStatus`, Status `IN_PROGRESS`). Das ist die Basis für Ebene 3 — das Bereichs-Board wird **additiv** darauf gebaut, nicht neu.
|
||||
|
||||
**Bereits vorhanden (nutzbar):** generisches Task-Modell, Kanban mit DnD-Statuswechsel, `assigneeId` + `createdById` + Vier-Augen-Freigabe, PROPOSED→OPEN/DISCARDED-Vorschlagsmechanik, Wizard-Trigger (`task-triggers.ts`, `proposeTasksFromTriggers`), polymorphe `links`-Json + harte `entityType/entityId`-Kopplung, Teil-Sync Task→Objekt bei Policy-Freigabe (`approveTask`).
|
||||
|
||||
**Fehlt (dieser Plan liefert es):** `domain`/Bereich, RACI/Mitwirkende, `orderIdx`, Recurrence/Wiedervorlage, Auto-Completion-Deckel, Bereichs-/Personen-Filter, harte Control-/Evidence-Verknüpfung, Information als Kernobjekt.
|
||||
|
||||
**Altlasten (Vorarbeit M0):**
|
||||
- `TASK_STATUSES` in `src/lib/tasks.ts` enthält `IN_PROGRESS` nicht, obwohl Board/Actions ihn nutzen → Inkonsistenz beheben.
|
||||
- `src/app/(app)/tasks/page.tsx:166` referenziert `open` — im File nicht definiert (nur `myOpen`/`active`/`proposals`/`terminal`). Verifizieren & fixen.
|
||||
|
||||
---
|
||||
|
||||
## 1. Datenmodell (Prisma-Migrationen)
|
||||
|
||||
Konventionen wie im Bestand: `cuid()`-IDs, `tenantId`, `@@map(snake_case)`, `@@unique([tenantId, …])`. Enums additiv; freie `String`-Statusfelder brauchen keine Migration.
|
||||
|
||||
### 1.1 Werte-Modell: Information IST ein (primärer) Asset — kein Extra-Objekt
|
||||
|
||||
**Korrektur ggü. erstem Entwurf.** Ein Informationswert ist kein neues Objekt neben dem Asset, sondern ein **primärer Asset** (ISO 27005 / TISAX: primäre Werte = Informationen + Prozesse; sekundäre = Träger). Euer Schema bildet das bereits ab:
|
||||
- `AssetType.INFORMATION` / `DATA` = primäre Werte; `SYSTEM/APPLICATION/LOCATION/SUPPLIER/IT_SERVICE/SOFTWARE/PERSON` = sekundär/Träger.
|
||||
- `ProcessAsset.role = PRIMARY | SECONDARY` trennt primär/sekundär je Prozess-Beziehung.
|
||||
- `AssetRelation` bildet Träger-Abhängigkeiten ab; `confidentiality/integrity/availability` liegen schon am `Asset`.
|
||||
|
||||
→ **Kein** `InformationValue`/`ProcessInformation`/`InformationAsset`. Stattdessen kleine Ergänzungen am Bestand:
|
||||
|
||||
```prisma
|
||||
enum InfoLabel { NONE INFO_HIGH INFO_VERY_HIGH PROTOTYPE PERSONAL_DATA }
|
||||
|
||||
model Asset {
|
||||
// … Bestand (type, C/I/A, ownerId, status, tags) …
|
||||
normalizedName String? // Dedup-Schlüssel (s. 2.1)
|
||||
label InfoLabel @default(NONE) // Info hoch/sehr hoch, Prototyp, personenbezogen → steuert Scope/Bereiche
|
||||
@@unique([tenantId, normalizedName]) // verhindert Exakt-Duplikate (v.a. type INFORMATION/DATA)
|
||||
}
|
||||
```
|
||||
|
||||
**Primär/sekundär** bleibt über `ProcessAsset.role`. Optional als intrinsische Klassifikation `Asset.tier (PRIMARY|SUPPORTING)`, ableitbar aus `type` — nur einführen, falls die Rolle je Prozess nicht ausreicht (s. offene Entscheidung 4.1).
|
||||
**Schutzbedarf:** bleibt am `Asset`. Primäre Informations-Assets tragen den echten C/I/A-Wert; sekundäre erben per **Maximum** der von ihnen getragenen primären Assets.
|
||||
**„Erhebung über den Prozess":** Im Prozess-Schritt werden primäre Informations-Assets erfasst (Dedup/Autocomplete gegen bestehende Assets, 2.1), dann Träger-Assets via `ProcessAsset(SECONDARY)` + `AssetRelation` verknüpft. Anker = das primäre Informations-Asset. **Keine Datenmigration nötig** — nur additive Spalten.
|
||||
|
||||
### 1.2 Standard-Prozess-Katalog (Ebene 2)
|
||||
|
||||
```prisma
|
||||
model ProcessCatalogEntry { // global, kein tenantId
|
||||
id String @id @default(cuid())
|
||||
code String @unique
|
||||
name String
|
||||
category ProcessCategory // CORE | MANAGEMENT | SUPPORT (Neben→SUPPORT)
|
||||
suggestedAssetTypes AssetType[]
|
||||
suggestedRiskCodes String[] // → RiskCatalogEntry.code
|
||||
suggestedInfoLabels InfoLabel[]
|
||||
@@map("process_catalog")
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3 Team / Funktionszuordnung (Ebene 1)
|
||||
|
||||
Heute sind ISMS-Rollen read-only Variablen. Neu: echte Zuordnung Funktion→User(n) inkl. „unbesetzt".
|
||||
|
||||
```prisma
|
||||
model ProjectFunctionAssignment {
|
||||
id String @id @default(cuid())
|
||||
tenantId String
|
||||
functionKey String // ISB, PM, HR_LEAD, IT_LEAD, BCM, AUDITOR_INT, DPO …
|
||||
userId String? // null = unbesetzt → erzeugt Task „Funktion besetzen"
|
||||
domain Domain? // Default-Bereich dieser Funktion (Sichtbarkeit)
|
||||
invitedEmail String? // Einladung, falls Account noch nicht existiert
|
||||
createdAt DateTime @default(now())
|
||||
@@index([tenantId, functionKey])
|
||||
@@map("project_function_assignments")
|
||||
}
|
||||
```
|
||||
|
||||
### 1.4 Bereich (Domain) & Control→RACI-Mapping (Ebene 3)
|
||||
|
||||
```prisma
|
||||
enum Domain { GOVERNANCE HR PHYSICAL BCM IT PROCUREMENT COMPLIANCE DATA_PROTECTION PROTOTYPE }
|
||||
enum RaciKind { RESPONSIBLE ACCOUNTABLE CONSULTED INFORMED }
|
||||
|
||||
model ControlDomainMap { // global default; tenant-Override via tenantId
|
||||
id String @id @default(cuid())
|
||||
tenantId String? // null = globaler Default
|
||||
control String // "3.1.4" oder Kapitel-Präfix "3"
|
||||
domain Domain
|
||||
raci RaciKind @default(RESPONSIBLE)
|
||||
functionKey String? // Default-Verantwortliche Funktion
|
||||
@@map("control_domain_map")
|
||||
}
|
||||
```
|
||||
|
||||
Seed-Defaults (Kapitel → Bereich), fachlich korrigiert:
|
||||
| Kapitel | Domain | Anmerkung |
|
||||
|---|---|---|
|
||||
| 1 | GOVERNANCE | ISB + Management |
|
||||
| 2 | HR | |
|
||||
| 3 (phys.) | PHYSICAL | |
|
||||
| 3 (BCM) | BCM | **aus K3 gelöst** — eigener Bereich |
|
||||
| 4 IAM | IT + **HR (CONSULTED)** | Joiner-Mover-Leaver |
|
||||
| 5 | IT | |
|
||||
| 6 | PROCUREMENT + **ISB/Recht (CONSULTED)** | |
|
||||
| 7 | COMPLIANCE + **DPO/IT (CONSULTED)** | |
|
||||
| Prototyp | PROTOTYPE | nur bei Label |
|
||||
| Datenschutz | DATA_PROTECTION | nur bei Label |
|
||||
|
||||
### 1.5 Task-Erweiterungen (Ebene 3)
|
||||
|
||||
```prisma
|
||||
model Task {
|
||||
// … Bestand …
|
||||
domain Domain? // Bereich (Default aus ControlDomainMap)
|
||||
orderIdx Int @default(0) // manuelle Sortierung je Bereich
|
||||
recurrence String? // ISO-8601-Dauer/RRULE, z.B. "P1Y"
|
||||
remindAt DateTime?
|
||||
effectiveUntil DateTime? // Wirksamkeitsintervall (Wiedervorlage)
|
||||
participants TaskParticipant[]
|
||||
@@index([tenantId, domain, status])
|
||||
}
|
||||
|
||||
model TaskParticipant { // RACI zusätzlich zu assigneeId (=primär Responsible)
|
||||
id String @id @default(cuid())
|
||||
tenantId String
|
||||
taskId String
|
||||
userId String
|
||||
raci RaciKind
|
||||
@@unique([tenantId, taskId, userId, raci])
|
||||
@@map("task_participants")
|
||||
}
|
||||
```
|
||||
|
||||
### 1.6 Nachweis-/Evidence-Register (Ebene 3+4)
|
||||
|
||||
```prisma
|
||||
model Evidence {
|
||||
id String @id @default(cuid())
|
||||
tenantId String
|
||||
title String
|
||||
kind String // record | protocol | screenshot | export
|
||||
fileRef String?
|
||||
taskId String?
|
||||
control String?
|
||||
validFrom DateTime?
|
||||
validUntil DateTime? // koppelt an Task.effectiveUntil
|
||||
createdAt DateTime @default(now())
|
||||
@@index([tenantId, control])
|
||||
@@map("evidence")
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Querschnitts-Bausteine
|
||||
|
||||
### 2.1 Dedup-Erkennung & Autovervollständigung für Informationswerte
|
||||
|
||||
Kernanforderung: Menschen erfassen über den Prozess, sollen aber denselben Wert nicht doppelt anlegen (auch nicht bei abweichender Groß-/Kleinschreibung).
|
||||
|
||||
- **Normalisierung → `normalizedName`:** `trim` → Mehrfach-Whitespace kollabieren → Unicode-NFC → `toLowerCase` (locale-aware `de`) → Umlaut-Faltung (ä→ae, ö→oe, ü→ue, ß→ss) → Satzzeichen entfernen. Ergebnis ist der `@@unique`-Schlüssel.
|
||||
- Beispiel: „Kundendaten", „kundendaten", „ Kundendaten " → alle `kundendaten`.
|
||||
- **Exakt-Duplikate:** durch `@@unique([tenantId, normalizedName])` unmöglich; bei Kollision wird das bestehende Asset *verknüpft* (`ProcessAsset`) statt neu angelegt.
|
||||
- **Autovervollständigung:** As-you-type-Suche im Server (`searchAssets(query)`, gefiltert auf `type INFORMATION/DATA`) gegen (a) das Tenant-Asset-Register und (b) globale Katalog-Vorschläge. Treffer zeigen „bereits erfasst in Prozess X" → ein Klick verknüpft.
|
||||
- **Fuzzy-Nah-Duplikate (weiche Warnung):** Trigramm-/Levenshtein-Ähnlichkeit auf `normalizedName`; ab Schwelle „Meintest du *Kundendaten*?" **vor** dem Anlegen. Bei Postgres optional `pg_trgm` (`similarity()`), sonst in-app Levenshtein auf der Kandidatenliste.
|
||||
- **UI:** Combobox (bestehendes `components.json`/shadcn-Setup) mit Vorschlagsliste, Badge „neu" vs. „verknüpfen".
|
||||
|
||||
### 2.2 Auto-Completion-Engine — gedeckelt
|
||||
|
||||
Zentrale Funktion `syncTaskFromObject(entityType, entityId)`, aufgerufen bei Statuswechsel von Policy/Risk/Control/Asset. Fachprüfungs-Regel: **Existenz ≠ Wirksamkeit.**
|
||||
|
||||
| Auslöser | Task geht auf … | Deckel |
|
||||
|---|---|---|
|
||||
| `PolicyDocument.status = FREIGEGEBEN` | `DONE` (dokumentiert) | Reifegrad 3 / audit-ready nur mit verknüpftem `Evidence` + Vier-Augen |
|
||||
| Asset C/I/A + Owner gesetzt | `DONE` | — |
|
||||
| `Risk.status = ACCEPTED/CLOSED` | `DONE` | Restrisiko gesetzt |
|
||||
| `ControlImplementation.status = erledigt` | `DONE` (umgesetzt) | Reifegrad-Anhebung getrennt bestätigen |
|
||||
|
||||
- Kein Auto-`DONE` ohne mindestens dokumentierten Zustand; „audit-ready" ist ein **separater, manueller** Schritt mit Nachweis.
|
||||
- **Wiedervorlage:** Tasks mit `recurrence` erzeugen bei `DONE` automatisch eine Folge-Task mit neuem `dueDate`/`effectiveUntil` (Serienlogik).
|
||||
|
||||
### 2.3 Bereichs-Sichtbarkeit & RACI
|
||||
|
||||
- Default-Sicht: **eigene Bereiche** (aus `ProjectFunctionAssignment.domain` des Users) + eigene/zugewiesene Tasks + Pool.
|
||||
- **PM + ISB:** `task:read_all` (existiert bereits) → alle Bereiche.
|
||||
- Gezielte Mitwirkung: Eintrag in `TaskParticipant` (CONSULTED/INFORMED) macht Task für die Person sichtbar, ohne ihr den ganzen Bereich zu öffnen.
|
||||
- Kanban erhält einen **Bereichs-Selektor** (Lane-Filter) zusätzlich zu den Status-Spalten; Sortierung je Bereich nach `orderIdx`, dann Priorität.
|
||||
|
||||
---
|
||||
|
||||
## 3. Meilenstein-Faden (jeder Schritt einzeln lauffähig)
|
||||
|
||||
### M0 · Vorarbeit & Bereinigung
|
||||
- `TASK_STATUSES` um `IN_PROGRESS` ergänzen (`src/lib/tasks.ts`); `open`-Bug in `tasks/page.tsx:166` verifizieren/fixen.
|
||||
- Enums `Domain`, `RaciKind`, `InfoLabel`, `InfoProcessRole` + Task-Felder `domain`/`orderIdx` (nullable) migrieren — noch ohne UI-Wirkung.
|
||||
- *Risiko: minimal. Kein Verhaltensbruch.*
|
||||
|
||||
### M1 · Ebene 1 „Fundament" (Wizard-Umbau Teil 1)
|
||||
- Onboarding-Steps in `src/lib/onboarding/register-steps.ts` neu ordnen/ergänzen: `context` → `scope` (einfrieren) → `policy` (Leitlinie, verlinkt Richtlinien-Modul) → `roles`(Team) → `criteria` (Risikoakzeptanz + C/I/A-Skala).
|
||||
- **Team-Entität** `ProjectFunctionAssignment` + Zuweisen/Einladen-Flow (Schritt `roles`). Neue Funktionen: BCM, unabhängiger interner Auditor, DPO, Asset-/Risk-Owner-Kennzeichnung.
|
||||
- Leitlinie als Fundament-Artefakt (nicht als Cockpit-Task).
|
||||
- *Betroffen: `src/app/(app)/onboarding/steps/*`, `src/server/roles.ts`, `src/server/actions/onboarding*.ts`.*
|
||||
|
||||
### M2 · Ebene 2 „Strukturanalyse" (Information = primärer Asset)
|
||||
- Additive `Asset`-Spalten (`normalizedName`, `label`) + `ProcessCatalogEntry` migrieren. **Keine** Datenmigration — Bestand bleibt gültig.
|
||||
- Wizard-Fluss **prozessgeführt**: Prozesse wählen (Katalog) → je Prozess primäre Informations-Assets erfassen (Combobox mit Dedup/Autocomplete, 2.1) → Träger-Assets (`ProcessAsset SECONDARY`: System/Anwendung/Raum/Person/Dienstleister/Standort) → Schutzbedarf am Asset (Maximum/Kumulation/Verteilung) → Risiken aus Katalog.
|
||||
- *Betroffen: neue Steps `processes`/`assets`/`protection`/`risks`, `RiskCatalogEntry`-Matching (existiert).*
|
||||
|
||||
### M3 · Ebene 3 „Cockpit" auf bestehendem Kanban
|
||||
- `ControlDomainMap` seeden (Tabelle 1.4); Task-Erzeugung (`soa.ts`, `task-triggers.ts`, `gap.ts`) setzt `domain` + Default-RACI.
|
||||
- Kanban erweitern: Bereichs-Lane/-Filter + Personen-Filter; Default „meine Bereiche"; `orderIdx`-Sortierung (DnD persistiert Reihenfolge).
|
||||
- `TaskParticipant` (RACI) + Sichtbarkeitslogik (2.3).
|
||||
- **Auto-Completion-Engine** (2.2) + Recurrence/Wiedervorlage; `Evidence`-Register.
|
||||
- Fragebogen (`context`) auf Bereiche verteilen → Fragen erzeugen Tasks im jeweiligen Bereich.
|
||||
- *Betroffen: `kanban-board.tsx`, `tasks/page.tsx`, `src/server/actions/tasks.ts`, `soa.ts`, `policies.ts` (Sync-Hook).*
|
||||
|
||||
### M4 · Ebene 4 „Audit-Wizard" abtrennen
|
||||
- Neuer, aktivierbarer Wizard aus heutigen Steps `gap` + `readiness`; **internes Audit** (unabhängig, AL3-Pflicht) als eigener Schritt ≠ Readiness-Snapshot.
|
||||
- Reifegrad + Nachweise laufen bereits kontinuierlich (M3) → hier nur Konsolidierung + Management-Review.
|
||||
- *Betroffen: neue Route `/audit-readiness` o. ä., Auslagern aus `onboarding/register-steps.ts`.*
|
||||
|
||||
---
|
||||
|
||||
## 4. Offene Entscheidungen
|
||||
1. **Primär/sekundär — intrinsisch oder relational?** Reicht `ProcessAsset.role` (Rolle je Prozess), oder soll ein intrinsisches `Asset.tier (PRIMARY|SUPPORTING)` als Wahrheit ergänzt werden (ableitbar aus `type`)? → Vorschlag: mit `role` starten, `tier` nur bei Bedarf. *(C/I/A-Ablageort ist entschieden: bleibt am `Asset`, sekundär erbt per Maximum.)*
|
||||
2. **Fuzzy-Matching-Technik:** `pg_trgm` (DB-nah, schnell) vs. in-app Levenshtein (DB-agnostisch). → Abhängig davon, ob Postgres-Extension im Coolify-Deployment verfügbar ist.
|
||||
3. **RACI-Tiefe:** volle RACI oder zunächst nur Responsible + Consulted (Sichtbarkeit)? → Vorschlag: klein starten (R + C), A = ISB/PM implizit.
|
||||
4. **Audit-Wizard-Aktivierung:** manuell vs. ab Coverage-Schwelle.
|
||||
|
||||
---
|
||||
|
||||
## 5. Reihenfolge-Logik (warum dieser Faden)
|
||||
M0 legt risikolos das Datenfundament. M1–M2 bauen die *sequenziellen* Ebenen (Setup/Strukturanalyse), auf denen alles Weitere aufsetzt — inkl. der informationszentrierten Struktur, dem größten Modell-Hebel. M3 nutzt maximal das bereits vorhandene Kanban (additiv statt Neubau). M4 ist die saubere Abtrennung am Ende. Jeder Meilenstein ist für sich lauffähig und liefert sichtbaren Nutzen.
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,162 +0,0 @@
|
||||
# KONZEPT: Mehr-Framework-Fähigkeit — ISO 27001 neben TISAX (pro Mandant wählbar)
|
||||
|
||||
**Stand:** 2026-08-21 · **Zielgruppe:** mehrköpfiges Entwicklerteam + PM · **Status:** Entwurf zur Abnahme
|
||||
|
||||
> **Nachtrag 2026-08-21 — D4 und Lane 2 sind entschieden und umgesetzt:** Nicht zwei Seed-Pakete,
|
||||
> sondern **ein Dokumentensatz mit zwei Framework-Mappings** (Variante A). Umsetzung und Begründung:
|
||||
> `docs/FRAMEWORK-MAPPING-ISO27001.md`. Die übrigen Lanes bleiben unverändert gültig.
|
||||
|
||||
> **Ziel:** Kunden sollen pro Mandant **ISO 27001 und/oder TISAX** wählen können. Je Framework gibt es u. a. ein eigenes Vorlagenpaket, einen eigenen Control-Katalog und eine eigene Audit-/Readiness-Logik. Heute ist das Tool durchgängig **implizit auf VDA-ISA 2027 / TISAX** verdrahtet.
|
||||
|
||||
---
|
||||
|
||||
## 1. Ausgangslage (Ist-Analyse, belegt)
|
||||
|
||||
Das Fachmodell kennt **kein** „Framework/Standard" pro Mandant. Alles ist implizit VDA-ISA/TISAX:
|
||||
- **Kein Framework-Feld:** `Tenant` (`prisma/schema.prisma:31`) hat nur `sector` + generisches `config Json`; `TenantSettings` (`:52`) hat als einzigen Standard-Anker `tisaxLevel` (`:70`, „AL2|AL3"). ISO 27001 erscheint nur als Marketing-Text (`src/lib/brand.ts:57`) und in einem Kommentar (`src/server/actions/tenant-users.ts:197`).
|
||||
- **Control-Katalog** liegt als **String-ID** vor (kein Enum): `ControlAssessment.control` (`:967`, z. B. „1.3.1"/„5.3.4-KI", Werte 0–3), `ControlImplementation.reqId` (`:988`), `ControlDescription` (`:1217`, „VDA-ISA-Spalte 4"). Titel/IDs kommen aus VDA-ISA (`src/lib/control-titles.ts:1`). `Domain`-Enum (`:1029`) enthält TISAX-only `PROTOTYPE`.
|
||||
- **Ein** Vorlagenpaket verdrahtet: Parser `prisma/import-policies.ts` (Codes L00/R../VA-, `:115`), globale Ablage `PolicyTemplateVersion` (`:1637`, **ohne** Framework-Dimension), Auflösung `prisma/template-store.ts` (`resolvePackageForTenant` wählt nur nach Locale die *eine* neueste PUBLISHED-Version, `:147`), Sync-Skript `scripts/sync-policy-templates.ts:20` (fest `seed/isms-vorlagenpaket-v2` de/en, `meta.standard:"VDA ISA 2027"`, `version:"2.1"`).
|
||||
- **Readiness/Reifegrad** ist TISAX: Reifegrad **0–3** (`src/lib/maturity.ts:11`), Zielgrad aus AL2/AL3 + Schutzbedarf (`src/server/assessment-level.ts`), Anforderungsschema MUSS/SOLL/HOCH/SEHR-HOCH + Prüfziele IS/Prototyp(8.)/Datenschutz(9.) (`src/lib/scope-filter.ts`, `src/lib/export/vda-isa.ts:9`). Die reinen Rechen-Engines `src/lib/readiness.ts` und `src/lib/gap-consolidation.ts` sind numerisch **standard-agnostisch**.
|
||||
- **SoA** existiert als Modul-Key `soa` (`src/lib/modules.ts:19`), ist faktisch aber ein **VDA-ISA-Reifegrad-Assessment** (`src/server/actions/soa.ts`, Werte 0–3), **nicht** die ISO-typische Applicability-Erklärung (anwendbar/ausgeschlossen + Begründung je Annex-A-Control).
|
||||
- **Provisionierung**: `provisionTenant` (`src/server/provision.ts:53`) ist die zentrale Stelle — schreibt `tisaxLevel`, aktiviert alle Module, importiert das *eine* Paket, setzt TISAX-Schutzbedarf-Flags. `ProvisionOpts` kennt kein `framework`.
|
||||
|
||||
**Bereits standard-agnostisch (wiederverwendbar):** Multi-Tenancy/RLS, Modul-Toggle (`TenantModule`), Vorlagen-**Mechanik** (Parser-Struktur, nicht-destruktiver `reconcilePackage`, DB-Versionsablage, Locale-Fallback), Control-Speicherung als String-ID, Onboarding-Registry/Progress, die Rechen-Engines readiness/gap.
|
||||
|
||||
**Hart an TISAX gekoppelt (abstrahieren/duplizieren):** AL2/AL3-Schutzbedarf + Flags, Reifegrad 0–3 + C5-Belegtabelle, MUSS/SOLL-Schema + Prüfziele 8./9., der eine Vorlagenpaket-Pfad + single-published-Auflösung, VDA-ISA-Exporte/Labels, Control-Titel, `Domain.PROTOTYPE`, die SoA-Semantik, zahlreiche i18n-Labels „TISAX"/„VDA-ISA".
|
||||
|
||||
---
|
||||
|
||||
## 2. Zielbild
|
||||
|
||||
Ein **Framework als First-Class-Dimension**: Mandant wählt ein oder mehrere Frameworks (`ISO_27001`, `TISAX`). Je Framework werden Vorlagenpaket, Control-Katalog, Scope-/Assessment-Modell, Readiness/SoA-Sicht und Export **framework-spezifisch** aufgelöst — über eine **Strategie-Schicht**, damit die generische Mechanik (Tenancy, Vorlagen-Import, Wizard-Shell, Rechen-Engines) unverändert bleibt.
|
||||
|
||||
Leitprinzipien:
|
||||
- **Additiv / Expand-Contract**: bestehende (Test-)Mandanten laufen unverändert als TISAX weiter; neue Spalten/Tabellen additiv, keine Datenmigration von Inhalten (nur Testdaten).
|
||||
- **TISAX-Verhalten bleibt bit-genau erhalten** (Regressionsschutz) — ISO wird *daneben* gebaut, nicht *statt*.
|
||||
- **Ein Mandant kann beide Frameworks führen** (n:m) — geteilte Belege/Policies, aber getrennte Katalog-/SoA-Sichten.
|
||||
- **Feature-Flag**: ISO bleibt hinter einem Schalter, bis Katalog + Readiness + SoA abgenommen sind.
|
||||
|
||||
---
|
||||
|
||||
## 3. Entscheidungen (D) — vom Team/PO zu bestätigen
|
||||
|
||||
| # | Entscheidung | Empfehlung | Begründung |
|
||||
|---|--------------|-----------|------------|
|
||||
| **D1** | Framework-Kardinalität | **n:m** (Mandant kann ISO **und** TISAX) via eigener Tabelle `TenantFramework` | Nutzeranforderung „oder/und"; erlaubt per-Framework-Attribute (z. B. TISAX-Level, ISO-Zertifizierungsziel). |
|
||||
| **D2** | `tisaxLevel` | bleibt vorerst auf `TenantSettings`, wird als **TISAX-scoped** dokumentiert (nur relevant, wenn TISAX aktiv); optional später in `TenantFramework.config` verschieben | Minimiert Migration + die ~356 dbForTenant-Aufrufstellen; kein Umbau bestehender Reads. |
|
||||
| **D3** | Control-Speicherung | **String-ID beibehalten**, Framework als zusätzliche Dimension (kein Enum-Umbau) | `ControlAssessment.control` etc. nehmen ISO-Annex-A-IDs (A.5.1 …) ohne Schema-Bruch auf. |
|
||||
| **D4** | Vorlagenpaket | ~~zweites Seed-Paket~~ → **entschieden 2026-08-21: ein Dokumentensatz, zwei Mappings** (`mapping.json` + `mapping-iso.json` in `seed/isms-vorlagenpaket-v2`). `framework`-Dimension auf `PolicyTemplateVersion` bleibt nötig (+ Unique `(framework, version)`). | Gleiche Dokument-Codes können in einem Mandanten nicht zweimal existieren (`@@unique([tenantId, code])`); der Umsetzungstext ist ohnehin normunabhängig. Siehe `FRAMEWORK-MAPPING-ISO27001.md`. |
|
||||
| **D5** | Assessment-Modell | **Strategie-Interface** je Framework (Scope/Reifegrad/Ziel/SoA), TISAX = heutige 0–3/AL-Logik, ISO = SoA-Applicability + Umsetzungsstatus | ISO kennt kein AL2/AL3 und keine VDA-ISA-Reifegrade; saubere Trennung ohne TISAX-Regression. |
|
||||
| **D6** | ISO-SoA | echte **Statement of Applicability** (Annex-A-Liste, anwendbar/ausgeschlossen + Begründung, Verknüpfung Policy/Evidence) — neu für ISO; TISAX behält sein Reifegrad-Assessment | ISO-27001-Kernartefakt fehlt heute fachlich. |
|
||||
| **D7** | Rollout | **Feature-Flag** „ISO" + erst Test-Instanz; TISAX unverändert | Risikoarme Einführung; TISAX-Kunden unberührt. |
|
||||
| **D8** | Katalog-Grundlage ISO | **Annex A (ISO/IEC 27001:2022, 93 Controls, 4 Themen)** + Klauseln 4–10 als Managementsystem-Anforderungen | Aktueller Normstand; 2022er Struktur. |
|
||||
|
||||
---
|
||||
|
||||
## 4. Zielarchitektur
|
||||
|
||||
### 4.1 Datenmodell (additiv)
|
||||
- **`enum Framework { ISO_27001, TISAX }`**.
|
||||
- **`model TenantFramework`** (n:m): `tenantId`, `framework`, `isPrimary Boolean`, `config Json` (per-Framework-Attribute, z. B. `{ tisaxLevel: "AL3" }` bzw. `{ certScope, certBodyTarget }`), Unique `(tenantId, framework)`. → in `TENANT_MODELS` (RLS) aufnehmen.
|
||||
- **`PolicyTemplateVersion`**: neue Spalte `framework Framework`; Unique `(framework, version)` statt nur `version`; Default-Backfill `TISAX`.
|
||||
- **`PolicyPackageState`** (Mandanten-Merker, `schema:1612`): um `framework` erweitern (je Framework eine importierte Version).
|
||||
- **ISO-SoA** (neu): `model SoaEntry { tenantId, framework=ISO_27001, control (A.x.y), applicable Boolean, justification String, implementationStatus enum, linkedPolicyCode?, linkedEvidenceId? }` — RLS-scoped.
|
||||
- **`Domain`-Enum**: ISO-Themen ergänzen bzw. `PROTOTYPE` als TISAX-only markieren; ISO-Controls mappen auf die 4 Annex-A-Themen (Organizational/People/Physical/Technological) → entweder neue Enum-Werte oder eine framework-abhängige Domain-Auflösung.
|
||||
|
||||
### 4.2 Strategie-Schicht (Kernstück)
|
||||
Ein `FrameworkStrategy`-Interface kapselt alle TISAX-spezifischen Annahmen; je Framework eine Implementierung:
|
||||
```
|
||||
interface FrameworkStrategy {
|
||||
key: Framework
|
||||
resolvePackage(locale): PublishedPackage // template-store, framework-parametrisiert
|
||||
loadCatalog(): { controls, titles, scope } // c1/c5/mapping bzw. Annex-A/Klauseln
|
||||
scopeFilter(settings): ControlRow[] // TISAX: AL/Prüfziel · ISO: Applicability
|
||||
targetFor(control, settings): AssessmentTarget // TISAX: Reifegrad 0–3 · ISO: Umsetzungsstatus/SoA
|
||||
readinessView(rows): ReadinessSummary // nutzt generische readiness/gap-Engines
|
||||
export(): ExportArtifact // TISAX: VDA-ISA · ISO: SoA + Annex-A-Gap
|
||||
wizardSteps(): StepKey[] // framework-abhängige Sichtbarkeit/Inhalte
|
||||
}
|
||||
```
|
||||
Bestehende Dateien werden hinter diese Schnittstelle gezogen: `assessment-level.ts`, `maturity.ts`, `scope-filter.ts`, `control-titles.ts`, `export/vda-isa*.ts` → `TisaxStrategy`. Die generischen Engines `readiness.ts`/`gap-consolidation.ts` bleiben und werden von beiden Strategien gefüttert.
|
||||
|
||||
### 4.3 Auflösung zur Laufzeit
|
||||
- `template-store.ts`: `resolvePackageForTenant(tenant, framework, locale)` — wählt PUBLISHED-Version je `(framework, locale)`.
|
||||
- `provisionTenant`: `ProvisionOpts.frameworks: Framework[]` → schreibt `TenantFramework`-Zeilen, importiert **je Framework** das passende Paket + Katalog, setzt nur bei TISAX die AL-Flags.
|
||||
- UI/Server lösen die aktive Framework-Sicht über die Mandanten-`TenantFramework` + eine aktive Auswahl (bei Mehr-Framework: Umschalter, analog Mandantenwahl).
|
||||
|
||||
---
|
||||
|
||||
## 5. Workstreams / Lanes für das Team
|
||||
|
||||
Fünf Lanes + PM. Abhängigkeiten in Klammern.
|
||||
|
||||
### Lane 1 — Framework-Kern (Datenmodell, Provision, Auflösung) *(Fundament, zuerst)*
|
||||
- `Framework`-Enum, `TenantFramework`-Tabelle (+ RLS/`TENANT_MODELS`), `PolicyTemplateVersion.framework` (+ Unique), `PolicyPackageState.framework` — additive Expand-Migrationen + Backfill bestehender Daten auf `TISAX`.
|
||||
- `ProvisionOpts.frameworks` + framework-abhängige Paket-/Katalog-Auflösung in `provision.ts`.
|
||||
- `template-store.ts` framework-parametrisieren.
|
||||
- **DoD:** bestehende Mandanten laufen unverändert (framework=TISAX), neuer Mandant kann mit `frameworks:[ISO_27001]` **oder** `[TISAX]` **oder** beiden provisioniert werden; Gate grün.
|
||||
|
||||
### Lane 2 — ISO-Mapping & -Katalog *(inhaltlicher Teil erledigt; Rest braucht L1)*
|
||||
- ✅ **erledigt (2026-08-21):** `mapping-iso.json` (27 Klauseln + 93 Annex-A-Controls) auf der bestehenden
|
||||
Bibliothek; 19 ISO-only-Abschnitte ergänzt; Sichtbarkeit über `FLAG_FW_ISO27001`/`FLAG_FW_TISAX`;
|
||||
SoA-Gerüst mit den Pflichtangaben aus 6.1.3 d); `_verify_iso.py` grün.
|
||||
- ⬜ ISO-`control-titles`, ISO-Scope-/Control-Kataloge (Pendants zu `c1-scope.json`/`c5-controls.json`).
|
||||
- ⬜ `parsePackageFiles`/`sync-policy-templates.ts` über **Frameworks × Sprachen** iterieren — heute ist
|
||||
`mapping.json` fest verdrahtet, `mapping-iso.json` wird noch nicht gelesen.
|
||||
- ✅ **erledigt:** Englische Fassung `isms-vorlagenpaket-v2-en` nachgezogen (eigene Texte, `--lang en`).
|
||||
- **DoD:** ISO-Mapping importiert als eigene `PolicyTemplateVersion(framework=ISO_27001)`; ein ISO-Mandant
|
||||
erhält Annex-A-Controls und sieht die ISO-Anforderungssicht.
|
||||
|
||||
### Lane 3 — Assessment-/Readiness-Abstraktion *(braucht L1; parallel zu L2)*
|
||||
- `FrameworkStrategy`-Interface; heutige TISAX-Logik als `TisaxStrategy` extrahieren (verhaltensgleich!).
|
||||
- `IsoStrategy`: Scope = Applicability; Ziel = Umsetzungsstatus (statt Reifegrad 0–3); Readiness/Gap über die bestehenden generischen Engines.
|
||||
- `readiness.ts`/`gap-consolidation.ts` framework-parametrisiert füttern; keine TISAX-Regression.
|
||||
- **DoD:** TISAX-Readiness identisch zu heute (Snapshot-Test); ISO liefert eine erste Readiness-/Gap-Sicht auf Annex-A-Basis.
|
||||
|
||||
### Lane 4 — ISO-SoA + Exporte *(braucht L2+L3)*
|
||||
- Echte **SoA-Sicht** (`SoaEntry`): Annex-A-Liste, anwendbar/ausgeschlossen + Begründung, Verknüpfung Policy/Evidence, Umsetzungsstatus; Modul-Key `soa` beherbergt beide Sichten (TISAX-Reifegrad bleibt).
|
||||
- ISO-Export: SoA-Dokument + Annex-A-Gap-Report; VDA-ISA-Export bleibt TISAX-only.
|
||||
- **DoD:** ISO-Mandant kann eine vollständige SoA pflegen und exportieren.
|
||||
|
||||
### Lane 5 — Wizard, Settings/Admin & i18n *(braucht L1; UI-Feinschliff am Ende)*
|
||||
- Framework-Auswahl in Admin (Mandant anlegen) + `/settings`; `setTenantTisaxLevel` → TISAX-scoped, ISO-Zertifizierungsziel analog.
|
||||
- Onboarding-Registry framework-aware (`getVisibleSteps` guard je Framework): TISAX behält Scope/AL/Prüfziel + Controls-Reifegrad; ISO ersetzt AL-Schritt durch Applicability/SoA-Schritt.
|
||||
- i18n: framework-neutrale Labels + per-Framework-Overrides; „TISAX/VDA-ISA"-Strings entkoppeln (`messages/de.json`/`en.json`, `settings/page.tsx`, `audit-readiness/*`, `admin/page.tsx`).
|
||||
- **DoD:** Kunde wählt im Admin ISO und/oder TISAX; der Wizard zeigt die passenden Schritte; keine „TISAX"-Labels bei reinen ISO-Mandanten.
|
||||
|
||||
**PM:** Reihenfolge L1 → (L2 ∥ L3) → L4 → L5; Abnahme je Lane; Regressions-Gate für TISAX (Snapshot der heutigen Readiness/Exporte) als Pflicht vor jedem Merge.
|
||||
|
||||
---
|
||||
|
||||
## 6. Migration & Rollout
|
||||
- **Expand:** additive Migrationen (Enum, `TenantFramework`, Spalten); Backfill: für jeden bestehenden Mandanten `TenantFramework(framework=TISAX, isPrimary=true)`; `PolicyTemplateVersion.framework=TISAX`.
|
||||
- **Feature-Flag** „ISO 27001" (Plattform-Setting) gated Admin-Auswahl + Provisionierung, bis L2–L4 abgenommen.
|
||||
- **Keine Inhaltsmigration** (nur Testdaten); neue ISO-Mandanten frisch provisioniert.
|
||||
- **Contract (später):** ungenutzte TISAX-only-Felder erst nach stabilem Mehr-Framework-Betrieb aufräumen (z. B. `tisaxLevel` → `TenantFramework.config`).
|
||||
|
||||
## 7. Risiken & Gegenmaßnahmen
|
||||
| Risiko | Gegenmaßnahme |
|
||||
|--------|---------------|
|
||||
| TISAX-Regression durch Refactoring | `TisaxStrategy` verhaltensgleich extrahieren; Snapshot-Tests der heutigen Readiness/Exporte als Merge-Gate. |
|
||||
| ISO-Katalog-Qualität (Annex-A ↔ Policies) | Fachliches Mapping-Review (ISMS-Experte) vor L4; `mapping.json` als Single Source. |
|
||||
| SoA-Semantik ist fachlich neu | Eigene Lane (L4) mit klarer Definition applicable/exclusion + Begründungspflicht. |
|
||||
| Mehr-Framework-Komplexität in UI | Aktive-Framework-Umschalter analog Mandantenwahl; getrennte Katalog-Sichten. |
|
||||
| `Domain.PROTOTYPE`/AL nur TISAX | Framework-abhängige Domain-/Scope-Auflösung; ISO ignoriert AL/Prototyp. |
|
||||
| i18n-Wildwuchs „TISAX" | Zentrale framework-neutrale Keys + Overrides; Lint auf verbleibende Hardcodes. |
|
||||
|
||||
## 8. Grobe Aufwandsschätzung
|
||||
| Lane | Aufwand (PT, grob) |
|
||||
|------|--------------------|
|
||||
| L1 Framework-Kern | 4–6 |
|
||||
| L2 ISO-Paket & Katalog (inkl. fachliches Mapping) | 8–12 |
|
||||
| L3 Assessment-Abstraktion | 5–8 |
|
||||
| L4 ISO-SoA + Exporte | 5–8 |
|
||||
| L5 Wizard/Settings/i18n | 4–6 |
|
||||
| PM/Fachreview | durchgehend |
|
||||
| **Summe** | **~26–40 PT**, L2/L3 parallelisierbar |
|
||||
|
||||
## 9. Offene Punkte (vom PO/Fachexperten zu klären)
|
||||
- Umfang ISO-Vorlagenpaket: nur Annex-A-Controls oder auch Managementsystem-Klauseln 4–10 als geführte Artefakte? (Empfehlung: beides.)
|
||||
- ~~Wie stark sollen ISO- und TISAX-Sicht bei Doppel-Framework **Belege/Policies teilen**?~~ → **entschieden:** ein gemeinsames Policy-Set, zwei Mappings (Variante A, 2026-08-21).
|
||||
- ISO-Reifegrad optional zusätzlich zur Applicability (manche Kunden wollen Reifegrade auch unter ISO)?
|
||||
- Zielformat ISO-Exporte (SoA-Dokument als Word/PDF/XLSX; Annex-A-Gap als XLSX).
|
||||
@@ -1,121 +0,0 @@
|
||||
# Incident-Management — Fachkonzept (Certvia)
|
||||
|
||||
Modul „Vorfälle" (Placeholder im Bestand). Umfang: **Standard** — erfassen → kategorisieren/bewerten → bearbeiten (Verantwortliche, Aufgaben, Maßnahmen) → abschließen + Lessons Learned. Rahmen: **ISO 27001** (A.5.24–5.28), **NIS2** (Meldepflicht-Bewusstsein + Fristen), **TISAX/VDA-ISA** (1.6.x). Kanäle: **intern manuell** + **E-Mail-to-Ticket**. **Keine Behörden-API** — NIS2-/DSGVO-Meldung wird **vorbereitet** (Fristen-Timer + Meldevorlage/Export), Übermittlung erfolgt manuell.
|
||||
|
||||
---
|
||||
|
||||
## 1. Rollen (RACI-Kurz)
|
||||
| Rolle | Aufgabe |
|
||||
|---|---|
|
||||
| **Melder** (intern / E-Mail) | Meldet den Verdacht/Vorfall (Titel, Beschreibung, was/wann). |
|
||||
| **ISB / Incident-Manager** | Triage, Kategorisierung, Bewertung, Steuerung, **Meldepflicht-Entscheidung**, Abschluss. |
|
||||
| **IT / Bearbeiter** | Sofort-/Behebungsmaßnahmen umsetzen (als Aufgaben). |
|
||||
| **Geschäftsführung** | Eskalation, Freigabe externer Meldungen. |
|
||||
| **DSB** (optional) | Bei Personenbezug (DSGVO Art. 33/34). |
|
||||
|
||||
## 2. Kanäle (Intake)
|
||||
- **Intern manuell:** berechtigte Rollen legen Vorfall über die UI an (Popup wie bei Assets/Aufgaben).
|
||||
- **E-Mail-to-Ticket:** Zustellung an ein **Certvia-seitiges Eingangspostfach** (nicht an ein Kundenpostfach). Certvia betreibt eine Inbound-Domain und vergibt **je Mandant eine eindeutige, nicht erratbare Adresse** (z. B. `vorfall-<token>@in.certvia.de`); der Kunde nutzt sie direkt **oder** leitet von seiner eigenen Adresse (`vorfall@kunde.de`) dorthin **weiter**. Über die Zieladresse erfolgt die **Mandantenzuordnung**. Eingehende Mail → Vorfall im Status **Neu/Triage** (Betreff→Titel, Text→Beschreibung, Absender→Melder). Dedupe über Message-Header; **Absender-Allowlist** (nur interne Kundendomänen erzeugen Tickets) + SPF/DKIM/DMARC-Prüfung + Spam-Filter; externe/unbekannte Absender werden „extern" markiert (Triage). Anhänge später (Storage-Paket).
|
||||
- **Inbound ist ein eigener Kanal:** SEC1 deckte nur den **Ausgang** (SMTP) ab; für den Empfang braucht es einen Empfangsweg. **Warum kein Kundenpostfach:** kein Speichern/Pollen von Kunden-IMAP/OAuth-Credentials → weniger Aufwand, robuster, DSGVO-/sicherheitsseitig sauberer.
|
||||
- **Konkrete Umsetzung (All-inkl · einfachster Weg, gewählt):** Subdomain **`in.certvia.de`** bei All-inkl mit **Catch-all-Postfach** — alle `vorfall-<token>@in.certvia.de` landen in **einem** Postfach. *(Catch-all in All-inkl KAS: E-Mail → E-Mail-Postfach → „Neues Postfach anlegen", das **Adressfeld leer lassen**. Catch-all ist spam-anfällig → eigene, nirgends veröffentlichte Intake-Subdomain hält die Spam-Fläche klein; zusätzlich Allowlist/DKIM/Review-Pfad.)* Certvia holt die Mails per **IMAP** (kurzes Polling/IDLE, BullMQ-Job), parst sie (mailparser), ermittelt den **Token aus dem Empfänger-Header** (`Delivered-To`/`X-Envelope-To` — **nicht** `To`, da dort bei Weiterleitung die Kundenadresse steht), ordnet dem Mandanten zu, legt den Vorfall an und verschiebt die Mail nach „Verarbeitet"/„Fehler". Idempotenz über `Message-ID`; unbekannter/kein Token → **Betreiber-Review** statt Drop. **Kein Postfach je Kunde** (Catch-all + **Auto-Token**), keine KAS-API nötig; einmaliger globaler Setup (Subdomain + Catch-all + IMAP-Zugang als Plattform-Secret).
|
||||
- **Weiterleitungs-Fallstricke:** Weiterleitung bricht i. d. R. **SPF** (DKIM bleibt meist gültig) → **nicht** hart auf SPF-Fail ablehnen; Vertrauen über **Absender-Allowlist + DKIM**, SPF nur als Signal. Auto-Reply/Bounce-Schleifen über `Auto-Submitted`/Precedence-Header erkennen und ignorieren. Größenlimit/Spam-Filter beachten.
|
||||
- **Mail-Einstellungen:** die **mandantenspezifischen** Einstellungen (Intake-Adresse/Routing, Benachrichtigungspräferenzen, Absender-Anzeige) werden im **Einstellungs-Modul** gepflegt. Die **SMTP-Zugangsdaten/der Transport** bleiben aus Sicherheitsgründen auf **Plattform-/Secret-Store-Ebene** (SEC1) — kein Mandant legt Server-Credentials selbst an.
|
||||
|
||||
## 3. Lebenszyklus / Statusmodell
|
||||
**Primärfluss:**
|
||||
`Neu/Eingegangen → Triage → In Bearbeitung → Eingedämmt (contained) → Behoben → Abgeschlossen` · (+ `Wiedereröffnet`)
|
||||
- Jeder Übergang: Pflichtfelder-Check, Zeitstempel, Akteur, Audit-Eintrag.
|
||||
- **Parallel-Track „Meldung"** (nur wenn meldepflichtig): `Meldepflicht geprüft → Erstmeldung (24 h) → Folgemeldung (72 h) → Abschlussbericht (1 Monat)` — als **Status + Timer**, Übermittlung manuell.
|
||||
|
||||
## 4. Datenmodell (Incident-Objekt)
|
||||
- **Kennung:** `refNo` (z. B. `INC-2026-0042`), `tenantId` (RLS).
|
||||
- **Basis:** Titel, Beschreibung, **Kanal/Quelle** (manuell/E-Mail), Melder (+Kontakt).
|
||||
- **Zeiten:** `occurredAt` (Eintritt), `detectedAt` (Entdeckung), `reportedAt` (interne Meldung), Timeline.
|
||||
- **Kategorie** (Taxonomie): Schadsoftware · Phishing/Social Engineering · Unbefugter Zugriff · Datenabfluss/-verlust · Systemausfall/Verfügbarkeit · Physisch (Zutritt/Diebstahl) · Fehlbedienung/Konfiguration · Lieferant/Drittpartei · **Prototyp/Kundendaten** (TISAX) · Sonstiges.
|
||||
- **Betroffenheit:** verknüpfte **Assets/Prozesse (BIA)**, Schutzziel-Impact **C/I/A**, Datenkategorien, **Personenbezug** (→ DSGVO-Flag), **Prototyp/Kundendaten** (→ TISAX-Flag).
|
||||
- **Bewertung:** **Schweregrad/Priorität** (siehe §5).
|
||||
- **Steuerung:** `owner` (Incident-Manager), Bearbeiter, Status.
|
||||
- **Meldepflicht:** `nis2Relevant`, `dsgvoRelevant` (bool) + Meldestatus + Fristen (§6).
|
||||
- **Behebung:** Sofortmaßnahmen, **Ursache (Root Cause)**, Lösung/Resolution.
|
||||
- **Abschluss:** Abschlussnotiz, **Lessons Learned**, verknüpfte **CAPA-Aufgaben**.
|
||||
- **Verknüpfungen:** **Maßnahmen** (im zentralen Maßnahmen-Modul, §9), **Risiken** (bestätigt/neu), **Controls** (welche versagten/betroffen), **Nachweise**.
|
||||
- **Kommentare/Notizen:** **Kommentar-Thread** am Vorfall (Autor, Zeitstempel, editierbar nach Regel) für die Zusammenarbeit — **getrennt** von der automatischen, manipulationssicheren **Audit-Timeline** (§8/§9). Interne vs. sichtbare Kommentare optional.
|
||||
- **Anhänge:** Belege (Screenshots/Logs) — Modell vorbereiten, Datei-Persistenz mit Storage-Paket.
|
||||
|
||||
## 5. Schweregrad / Priorisierung
|
||||
- **Schweregrad** aus **Auswirkung** (C/I/A-Verletzung × Umfang: einzelnes System … unternehmensweit … Kunde/Lieferkette) und **Dringlichkeit** → Klassen **niedrig · mittel · hoch · kritisch**.
|
||||
- Treibt **interne SLA** (Reaktion/Behebung), **Eskalation** und **Benachrichtigungen**. Matrix mandantenkonfigurierbar (Default vorgegeben).
|
||||
|
||||
## 6. Fristen & Timer (vorbereitet, ohne Behörden-API)
|
||||
| Auslöser | Frist | Umsetzung im Tool |
|
||||
|---|---|---|
|
||||
| **NIS2** – Früh-/Erstmeldung | **24 h** ab Kenntnis | Timer/Countdown + Erinnerung (SEC1) + Meldevorlage |
|
||||
| **NIS2** – Meldung | **72 h** | Timer + Vorlage (Aktualisierung) |
|
||||
| **NIS2** – Abschlussbericht | **1 Monat** | Timer + Abschluss-Vorlage/Export |
|
||||
| **DSGVO** Art. 33 (bei Personenbezug) | **72 h** | Timer + Datenschutz-Meldevorlage |
|
||||
| **Interne SLA** (je Severity) | konfigurierbar | Reaktions-/Behebungs-Timer |
|
||||
- Timer nur, wenn **Meldepflicht = ja** (NIS2-Betroffenheit des Mandanten aus den Einstellungen). Countdown im Vorfall + Dashboard-Kachel; **Eskalation** bei drohender/verpasster Frist. **Übermittlung an die Behörde erfolgt manuell** (Vorlage/Export bereitgestellt).
|
||||
|
||||
## 7. Benachrichtigungen (SEC1)
|
||||
Neuer Vorfall → ISB/Incident-Manager; Zuweisung → Bearbeiter; Statuswechsel → Beteiligte; **Fristen-Erinnerung/Eskalation**; Abschluss → Melder/GF. Respektiert Benachrichtigungspräferenzen + Mandantenisolation.
|
||||
|
||||
## 8. Abschluss & Lessons Learned
|
||||
- Pflicht beim Abschluss: **Ursache**, **Lösung**, Wirksamkeit der Maßnahmen, **Lessons Learned**.
|
||||
- **CAPA**: korrigierende/präventive Maßnahmen als **Aufgaben** anlegen; **Risikoregister** aktualisieren (Risiko bestätigt/neu); Bezug zu betroffenen **Controls**.
|
||||
- Optionaler **Post-Incident-Review** (Kurzbericht) → speist **Management-Review**.
|
||||
|
||||
## 9. Verknüpfung zu bestehenden Modulen
|
||||
- **Maßnahmen-Modul** (vorhanden): Sofort- und CAPA-Maßnahmen werden **im zentralen Maßnahmen-Modul angelegt/gepflegt** (nicht doppelt im Vorfall) und mit dem Vorfall **verknüpft**; im Vorfall erscheinen sie als verknüpfte Liste mit „Maßnahme direkt aus dem Vorfall anlegen". Verantwortliche/Fristen/Status kommen aus dem Maßnahmen-Modul; Bezug zu Risiken/Controls möglich. *(Hinweis: falls „Maßnahmen"/„Aufgaben" heute getrennt sind, an **eine** zentrale Maßnahmen-/Aufgaben-Backbone andocken.)*
|
||||
- **Kommentare** dagegen liegen **am Vorfall** (Thread, §4) — sie sind Zusammenarbeit, keine trackbare Maßnahme.
|
||||
- **Assets/BIA · Risiken · Controls**: Betroffenheit und Wirkung verknüpfen; Vorfall kann Risiko bestätigen/erzeugen.
|
||||
- **Audit-Log**: Vorfall-Timeline (wer/wann/was) manipulationssicher (getrennt von den Kommentaren).
|
||||
- **Nachweise/Export**: Vorfallregister + Einzelbericht (DOCX/PDF über Export-Layer), NIS2-/DSGVO-Meldevorlagen (vorbefüllt) für die manuelle Übermittlung.
|
||||
|
||||
## 10. Framework-Mapping
|
||||
| Rahmen | Bezug |
|
||||
|---|---|
|
||||
| **ISO 27001:2022** | A.5.24 Planung/Vorbereitung · A.5.25 Bewertung/Entscheidung · A.5.26 Reaktion · A.5.27 Lernen · A.5.28 Beweissicherung |
|
||||
| **TISAX / VDA-ISA** | 1.6.x Incident-/Ereignismanagement; Prototyp-/Kundendaten-Bezug |
|
||||
| **NIS2** (Art. 23) | Meldekette 24 h/72 h/1 Monat — im Tool als Timer/Vorlage vorbereitet |
|
||||
| **DSGVO** | Art. 33/34 Datenpanne (72 h) — Timer/Vorlage |
|
||||
|
||||
## 11. Rechte / Sicherheit
|
||||
- Strikt **mandantengebunden (RLS)**; rollenbasierte Rechte (melden vs. bearbeiten vs. abschließen/melden).
|
||||
- **Vertraulichkeit:** sensible Vorfälle optional auf einen eingeschränkten Personenkreis begrenzbar.
|
||||
- Meldevorlagen/Exports datensparsam; jede Aktion auditiert.
|
||||
|
||||
## 12. Technische Einordnung
|
||||
- **Eigenes Modul „Vorfälle"** (`incidents`), modul-gated (Superadmin-Toggle); **Maßnahmen** über das zentrale **Maßnahmen-Modul** (verknüpft); **Kommentare** als eigener Thread am Vorfall; **Mail** über SEC1; **Timeline** über Audit; Verknüpfungen zu Assets/Risiken/Controls.
|
||||
- **Mail-Einstellungen:** mandantenseitig im **Einstellungs-Modul** (Intake-Adresse, Benachrichtigungen); SMTP-Transport plattformseitig (SEC1).
|
||||
- Popups/Bedienung im etablierten Muster (wie Assets/Maßnahmen).
|
||||
|
||||
## 12a. Provisionierung des Intake-Postfachs (Betreiberportal & Onboarding)
|
||||
Das Anlegen der Inbound-Route (`vorfall-<token>@in.certvia.de`) ist zunächst ein **manueller Betreiber-Schritt** — dafür braucht es die richtigen Infos beim Onboarding und einen sichtbaren Status.
|
||||
|
||||
**Beim Kunden-Onboarding erfassen** (Admin-Konsole „Kunde anlegen", nur wenn Modul „Vorfälle" + E-Mail-to-Ticket aktiv):
|
||||
- **Absender-/Weiterleitungs-Domäne(n)** des Kunden (z. B. `kunde.de`) → **Allowlist**.
|
||||
- optional konkrete **Quelladresse** (`vorfall@kunde.de`), von der weitergeleitet wird.
|
||||
- **Intake-Adresse** wird von Certvia **automatisch generiert** (`vorfall-<token>@in.certvia.de`) und angezeigt (der Kunde richtet die Weiterleitung darauf ein).
|
||||
- optional Benachrichtigungsempfänger/Sprache.
|
||||
|
||||
**Provisionierungs-Status je Kunde** (Betreiberportal): `Postfach anzulegen → angelegt → verifiziert`.
|
||||
- Solange „anzulegen": **Hinweis-Badge** am Kundendatensatz („⚠ Intake-Postfach anlegen") **und** eine **Sammelliste offener Provisionierungen** auf dem Betreiber-Dashboard.
|
||||
- **Betreiber-Schritt:** Inbound-Route/Alias im Inbound-Dienst anlegen (manuell **oder** per Provider-API) → Status „angelegt". **Verifizierung** per Test-Mail (analog SEC1-Testversand) → „verifiziert".
|
||||
- **Ausbau:** bei Inbound-Providern mit API kann die Route beim Modul-Aktivieren **automatisch** angelegt werden → Status springt direkt auf „angelegt"; bis dahin bleibt es der manuelle Hinweis-Schritt.
|
||||
- Alle Provisionierungs-Aktionen im **Plattform-Audit** (`scope=platform`).
|
||||
|
||||
> **Mit der gewählten Variante (All-inkl Catch-all + Auto-Token):** Es muss **kein Postfach je Kunde** angelegt werden; der **Token wird automatisch generiert**. Der einmalige Setup (Subdomain `in.certvia.de` + Catch-all-Postfach + IMAP-Zugang) ist ein **globaler** Betreiber-Schritt, nicht je Kunde. Der **per-Kunde-Schritt reduziert sich** darauf, die **Weiterleitung des Kunden per Test-Mail zu verifizieren** → vereinfachter Status je Kunde: `Weiterleitung ausstehend → verifiziert`. Der Onboarding-Datenbedarf bleibt (Allowlist-Domänen, Quelladresse); die Intake-Adresse wird automatisch erzeugt/angezeigt.
|
||||
|
||||
## 13. Abgrenzung / spätere Ausbaustufen
|
||||
- **Direkte Behörden-Übermittlung** (BSI-Meldeportal/-API) — jetzt bewusst **nicht** (nur Vorlage/Export).
|
||||
- Automatische Erkennung/**SIEM-Integration**, **externe/anonyme** Meldung, SLA-Automationen, KI-gestützte Klassif/Zusammenfassung — spätere Stufen.
|
||||
|
||||
## 14. Offene Entscheidungen
|
||||
1. **NIS2-Betroffenheit je Mandant** — woher (Mandanten-Einstellungen: „wichtige/wesentliche Einrichtung"?), steuert die Timer.
|
||||
2. **Severity-Matrix** — fester Default oder mandantenkonfigurierbar?
|
||||
3. **Inbound (entschieden):** All-inkl **Catch-all-Postfach** auf `in.certvia.de` + **IMAP-Abholung**, **Auto-Token**, kein Postfach je Kunde. Rest-Details: Polling-Intervall vs. IMAP-IDLE, welcher Header trägt den Token (`Delivered-To`/`X-Envelope-To` — beim ersten Test verifizieren), Ordner-/Fehler-Handling.
|
||||
4. **Anhänge** — abhängig vom Storage-Paket (bis dahin nur Referenz/Text).
|
||||
5. **Vertraulichkeits-Stufen** für sensible Vorfälle — jetzt oder später?
|
||||
|
||||
---
|
||||
*Nächster Schritt auf Wunsch: Entwickler-Task-Paket (Branches, Stories, DoD) — Maßnahmen auf das Task-Modul aufsetzend, Mail über SEC1, Timer/Meldevorlagen NIS2/DSGVO.*
|
||||
@@ -1,355 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>certvia – BIA-Prozessübersicht (Mockup)</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root{
|
||||
--violet:#5d52a3; --violet2:#7d6fd6; --magenta:#812d80; --blue:#8dc4e0; --ink:#3b3b3a;
|
||||
--violet-050:#f2f0f9; --violet-100:#e6e2f3; --blue-050:#eef7fb;
|
||||
--grad-soft:linear-gradient(135deg,#5d52a3 0%,#8dc4e0 100%);
|
||||
--bg:#f5f6fa; --card:#ffffff; --line:#e7e8ef; --line2:#eff0f5; --muted:#7a7b86;
|
||||
--soft:#fafbfd;
|
||||
--ok:#2e9e6b; --warn:#e0982e; --risk:#d64c4c; --info:#3a86c8;
|
||||
--ok-bg:#e9f6ef; --warn-bg:#fdf3e2; --risk-bg:#fbe9e9; --info-bg:#e9f2fb; --gray-bg:#eef0f4;
|
||||
--shadow:0 1px 3px rgba(30,25,60,.06),0 6px 20px rgba(30,25,60,.05);
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
html,body{margin:0}
|
||||
body{font-family:"Open Sans",system-ui,sans-serif;color:var(--ink);background:var(--bg);font-size:14px}
|
||||
h1,h2,h3,h4{font-family:"Poppins",sans-serif;font-weight:600;margin:0}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:26px 26px 60px}
|
||||
|
||||
/* Page head */
|
||||
.crumb{font-size:12px;color:var(--muted);margin-bottom:3px}
|
||||
.pagehead{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap}
|
||||
.pagehead h1{font-size:23px}
|
||||
.pagehead .sub{color:var(--muted);margin-top:5px;font-size:13px;max-width:640px;line-height:1.5}
|
||||
.head-actions{display:flex;align-items:center;gap:10px}
|
||||
.toggle{display:flex;background:#fff;border:1px solid var(--line);border-radius:10px;padding:3px;gap:2px}
|
||||
.toggle button{border:0;background:transparent;font-family:Poppins;font-weight:600;font-size:12.5px;color:var(--muted);padding:6px 12px;border-radius:8px;cursor:pointer;display:flex;align-items:center;gap:6px}
|
||||
.toggle button.active{background:var(--violet-100);color:var(--violet)}
|
||||
.btn{border:0;border-radius:10px;padding:9px 15px;font-weight:600;font-family:Poppins;font-size:13px;cursor:pointer;display:inline-flex;align-items:center;gap:7px}
|
||||
.btn.primary{background:var(--grad-soft);color:#fff}
|
||||
|
||||
/* KPI */
|
||||
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin:20px 0 6px}
|
||||
.kpi{background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);padding:15px 16px}
|
||||
.kpi .lbl{color:var(--muted);font-size:12px;font-weight:600}
|
||||
.kpi .val{font-family:Poppins;font-weight:700;font-size:27px;margin:5px 0 0;line-height:1}
|
||||
.kpi .val small{font-size:14px;color:var(--muted);font-weight:600}
|
||||
.kpi .bar{height:6px;border-radius:6px;background:#eef0f6;overflow:hidden;margin-top:11px}
|
||||
.kpi .bar>i{display:block;height:100%;border-radius:6px}
|
||||
|
||||
/* Legend */
|
||||
.legend{display:flex;flex-wrap:wrap;gap:16px;align-items:center;margin:16px 2px 4px;font-size:12px;color:var(--muted)}
|
||||
.legend .grp{display:flex;align-items:center;gap:8px}
|
||||
.legend .sw{width:12px;height:12px;border-radius:3px;display:inline-block}
|
||||
.legend .dot{width:10px;height:10px;border-radius:50%;display:inline-block}
|
||||
.legend b{color:var(--ink);font-weight:600}
|
||||
|
||||
/* Lanes */
|
||||
.lane{margin-top:22px}
|
||||
.lane-head{display:flex;align-items:center;gap:10px;margin:0 2px 12px}
|
||||
.lane-head .tag{font-family:Poppins;font-weight:600;font-size:14px}
|
||||
.lane-head .cnt{font-size:11.5px;color:var(--muted);background:#fff;border:1px solid var(--line);border-radius:999px;padding:2px 9px;font-weight:600}
|
||||
.lane-head .rule{flex:1;height:1px;background:var(--line)}
|
||||
.lane-mgmt .tag{color:var(--magenta)}
|
||||
.lane-core .tag{color:var(--violet)}
|
||||
.lane-supp .tag{color:var(--info)}
|
||||
|
||||
/* Main process card */
|
||||
.mp{background:var(--card);border:1px solid var(--line);border-left-width:4px;border-radius:14px;box-shadow:var(--shadow);margin-bottom:13px;overflow:hidden}
|
||||
.mp.st-komplett{border-left-color:var(--ok)}
|
||||
.mp.st-teilweise{border-left-color:var(--warn)}
|
||||
.mp.st-offen{border-left-color:#c4c8d2}
|
||||
.mp-head{display:flex;align-items:center;gap:14px;padding:14px 16px;cursor:pointer;user-select:none}
|
||||
.mp-head:hover{background:var(--soft)}
|
||||
.chev{width:16px;height:16px;flex:0 0 16px;color:var(--muted);transition:transform .18s}
|
||||
details[open] .chev{transform:rotate(90deg)}
|
||||
.mp-title{min-width:0;flex:1}
|
||||
.mp-title .nm{font-family:Poppins;font-weight:600;font-size:14.5px;display:flex;align-items:center;gap:9px;flex-wrap:wrap}
|
||||
.mp-title .meta{margin-top:4px;display:flex;align-items:center;gap:12px;flex-wrap:wrap;color:var(--muted);font-size:12px}
|
||||
.owner{display:inline-flex;align-items:center;gap:6px}
|
||||
.owner .av{width:19px;height:19px;border-radius:50%;background:var(--grad-soft);color:#fff;display:grid;place-items:center;font-size:9.5px;font-family:Poppins;font-weight:700}
|
||||
|
||||
/* metrics strip */
|
||||
.metrics{display:flex;gap:8px;flex:0 0 auto}
|
||||
.m{background:var(--soft);border:1px solid var(--line2);border-radius:9px;padding:5px 10px;text-align:center;min-width:58px}
|
||||
.m .k{font-size:9.5px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);font-weight:700}
|
||||
.m .v{font-family:Poppins;font-weight:600;font-size:13.5px;margin-top:1px}
|
||||
|
||||
/* pills */
|
||||
.pill{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:999px;font-size:11px;font-weight:700;white-space:nowrap}
|
||||
.pill .dot{width:7px;height:7px;border-radius:50%}
|
||||
.crit-1{background:var(--gray-bg);color:#5b6070}
|
||||
.crit-2{background:var(--info-bg);color:var(--info)}
|
||||
.crit-3{background:var(--warn-bg);color:#b9761b}
|
||||
.crit-4{background:var(--risk-bg);color:var(--risk)}
|
||||
.st-pill.komplett{background:var(--ok-bg);color:var(--ok)}
|
||||
.st-pill.teilweise{background:var(--warn-bg);color:#b9761b}
|
||||
.st-pill.offen{background:var(--gray-bg);color:#5b6070}
|
||||
.tag-cat{background:var(--violet-050);color:var(--violet);border:1px solid var(--violet-100);padding:2px 8px;border-radius:6px;font-size:10.5px;font-weight:700}
|
||||
|
||||
/* dependencies row */
|
||||
.deps{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:0 16px 12px 46px}
|
||||
.deps .lab{font-size:11px;color:var(--muted);font-weight:600;display:inline-flex;align-items:center;gap:5px}
|
||||
.dep{display:inline-flex;align-items:center;gap:6px;background:#fff;border:1px solid var(--line);border-radius:999px;padding:3px 10px;font-size:11.5px;font-weight:600;color:#4b4c57}
|
||||
.dep.crossref{border-style:dashed;border-color:var(--violet2);color:var(--violet)}
|
||||
.dep .ic{width:12px;height:12px;opacity:.7}
|
||||
|
||||
/* sub processes tree */
|
||||
.subs{padding:2px 16px 14px 30px;background:var(--soft);border-top:1px dashed var(--line)}
|
||||
.subs-h{font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);font-weight:700;margin:10px 0 8px 16px}
|
||||
.sub{position:relative;display:flex;align-items:center;gap:12px;padding:9px 12px 9px 16px;margin-left:16px;border-radius:10px}
|
||||
.sub:hover{background:#fff}
|
||||
/* tree connector */
|
||||
.sub::before{content:"";position:absolute;left:0;top:-6px;bottom:50%;width:1px;background:#d6dae3}
|
||||
.sub::after{content:"";position:absolute;left:0;top:50%;width:12px;height:1px;background:#d6dae3}
|
||||
.sub:last-child::before{bottom:50%}
|
||||
.sub .sdot{width:9px;height:9px;border-radius:50%;flex:0 0 9px;z-index:1;box-shadow:0 0 0 3px var(--soft)}
|
||||
.sdot.komplett{background:var(--ok)} .sdot.teilweise{background:var(--warn)} .sdot.offen{background:#c4c8d2}
|
||||
.sub .snm{flex:1;min-width:0}
|
||||
.sub .snm .t{font-weight:600;font-size:13px}
|
||||
.sub .snm .s{color:var(--muted);font-size:11.5px;margin-top:1px;display:flex;gap:10px;flex-wrap:wrap}
|
||||
.sub .metrics .m{background:#fff}
|
||||
.sub .right{display:flex;align-items:center;gap:8px}
|
||||
.mini{font-size:11px;color:var(--muted);display:inline-flex;align-items:center;gap:5px}
|
||||
|
||||
.note{margin-top:26px;background:var(--violet-050);border:1px solid var(--violet-100);border-radius:12px;padding:14px 16px;font-size:12.5px;color:#4b4c57;line-height:1.6}
|
||||
.note b{color:var(--violet)}
|
||||
.foot{margin-top:22px;color:var(--muted);font-size:11.5px;text-align:center}
|
||||
@media(max-width:820px){
|
||||
.kpis{grid-template-columns:repeat(2,1fr)}
|
||||
.metrics{display:none}
|
||||
.mp-head{flex-wrap:wrap}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
|
||||
<div class="pagehead">
|
||||
<div>
|
||||
<div class="crumb">Strukturanalyse · GEFIM (TISAX)</div>
|
||||
<h1>Business Impact Analyse — Prozessübersicht</h1>
|
||||
<div class="sub">Prozesse gegliedert nach Haupt- und Teilprozessen. Farbe = BIA-Status, Kritikalität nach Maximumprinzip aus den Teilprozessen abgeleitet. Abhängigkeiten zeigen, welche Prozesse voneinander bzw. von gemeinsamen Diensten abhängen.</div>
|
||||
</div>
|
||||
<div class="head-actions">
|
||||
<div class="toggle">
|
||||
<button class="active" title="Gruppierte Prozesshaus-Ansicht">▤ Prozesshaus</button>
|
||||
<button title="Klassische Tabelle">≣ Tabelle</button>
|
||||
</div>
|
||||
<button class="btn primary">+ Prozess</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KPIs -->
|
||||
<div class="kpis">
|
||||
<div class="kpi"><div class="lbl">Prozesse gesamt</div><div class="val">24 <small>/ 6 Haupt</small></div><div class="bar"><i style="width:100%;background:var(--grad-soft)"></i></div></div>
|
||||
<div class="kpi"><div class="lbl">Im Scope</div><div class="val">21 <small>/ 24</small></div><div class="bar"><i style="width:87%;background:var(--violet2)"></i></div></div>
|
||||
<div class="kpi"><div class="lbl">BIA vollständig</div><div class="val">13 <small>/ 21</small></div><div class="bar"><i style="width:62%;background:var(--ok)"></i></div></div>
|
||||
<div class="kpi"><div class="lbl">Kritische Prozesse</div><div class="val" style="color:var(--risk)">4</div><div class="bar"><i style="width:19%;background:var(--risk)"></i></div></div>
|
||||
</div>
|
||||
|
||||
<!-- Legend -->
|
||||
<div class="legend">
|
||||
<div class="grp"><b>BIA-Status:</b></div>
|
||||
<div class="grp"><span class="dot" style="background:var(--ok)"></span> komplett</div>
|
||||
<div class="grp"><span class="dot" style="background:var(--warn)"></span> teilweise</div>
|
||||
<div class="grp"><span class="dot" style="background:#c4c8d2"></span> offen</div>
|
||||
<div class="grp" style="margin-left:8px"><b>Kritikalität:</b></div>
|
||||
<div class="grp"><span class="sw crit-1" style="background:#d3d7e0"></span> 1 niedrig</div>
|
||||
<div class="grp"><span class="sw" style="background:var(--info)"></span> 2 mittel</div>
|
||||
<div class="grp"><span class="sw" style="background:var(--warn)"></span> 3 hoch</div>
|
||||
<div class="grp"><span class="sw" style="background:var(--risk)"></span> 4 kritisch</div>
|
||||
</div>
|
||||
|
||||
<!-- ============ MANAGEMENT ============ -->
|
||||
<div class="lane lane-mgmt">
|
||||
<div class="lane-head"><span class="tag">Managementprozesse</span><span class="cnt">1 Hauptprozess · 3 Teilprozesse</span><span class="rule"></span></div>
|
||||
|
||||
<details class="mp st-teilweise" open>
|
||||
<summary class="mp-head">
|
||||
<svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M9 6l6 6-6 6"/></svg>
|
||||
<div class="mp-title">
|
||||
<div class="nm">Unternehmenssteuerung & ISMS <span class="tag-cat">Management</span></div>
|
||||
<div class="meta">
|
||||
<span class="owner"><span class="av">GF</span> M. Geschäftsführung</span>
|
||||
<span>·</span><span>3 Teilprozesse</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metrics">
|
||||
<div class="m"><div class="k">RTO</div><div class="v">24 h</div></div>
|
||||
<div class="m"><div class="k">RPO</div><div class="v">24 h</div></div>
|
||||
<div class="m"><div class="k">MTD</div><div class="v">72 h</div></div>
|
||||
</div>
|
||||
<span class="pill crit-2"><span class="dot" style="background:var(--info)"></span> Krit. 2</span>
|
||||
<span class="pill st-pill teilweise">teilweise</span>
|
||||
</summary>
|
||||
|
||||
<div class="deps">
|
||||
<span class="lab">↳ benötigt:</span>
|
||||
<span class="dep crossref"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M13 6l6 6-6 6"/></svg> IT-Betrieb</span>
|
||||
<span class="dep"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M13 6l6 6-6 6"/></svg> Personalmanagement</span>
|
||||
</div>
|
||||
|
||||
<div class="subs">
|
||||
<div class="subs-h">Teilprozesse</div>
|
||||
<div class="sub">
|
||||
<span class="sdot komplett"></span>
|
||||
<div class="snm"><div class="t">Risikomanagement</div><div class="s"><span>Owner: ISB</span><span>Schnittstelle: Risiko-Modul</span></div></div>
|
||||
<div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">48 h</div></div><div class="m"><div class="k">RPO</div><div class="v">24 h</div></div><div class="m"><div class="k">MTD</div><div class="v">1 W</div></div></div>
|
||||
<div class="right"><span class="pill crit-2">Krit. 2</span></div>
|
||||
</div>
|
||||
<div class="sub">
|
||||
<span class="sdot teilweise"></span>
|
||||
<div class="snm"><div class="t">Interne Audits</div><div class="s"><span>Owner: ISB</span></div></div>
|
||||
<div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">1 W</div></div><div class="m"><div class="k">RPO</div><div class="v">1 W</div></div><div class="m"><div class="k">MTD</div><div class="v">2 W</div></div></div>
|
||||
<div class="right"><span class="pill crit-1">Krit. 1</span></div>
|
||||
</div>
|
||||
<div class="sub">
|
||||
<span class="sdot offen"></span>
|
||||
<div class="snm"><div class="t">Managementbewertung</div><div class="s"><span>Owner: GF</span><span style="color:var(--warn)">BIA offen</span></div></div>
|
||||
<div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">—</div></div><div class="m"><div class="k">RPO</div><div class="v">—</div></div><div class="m"><div class="k">MTD</div><div class="v">—</div></div></div>
|
||||
<div class="right"><span class="mini">BIA erfassen →</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<!-- ============ KERNPROZESSE ============ -->
|
||||
<div class="lane lane-core">
|
||||
<div class="lane-head"><span class="tag">Kernprozesse</span><span class="cnt">2 Hauptprozesse · 8 Teilprozesse</span><span class="rule"></span></div>
|
||||
|
||||
<details class="mp st-komplett" open>
|
||||
<summary class="mp-head">
|
||||
<svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M9 6l6 6-6 6"/></svg>
|
||||
<div class="mp-title">
|
||||
<div class="nm">Produktentwicklung / Engineering <span class="tag-cat">Kern</span></div>
|
||||
<div class="meta"><span class="owner"><span class="av">HE</span> H. Entwicklung</span><span>·</span><span>4 Teilprozesse</span></div>
|
||||
</div>
|
||||
<div class="metrics">
|
||||
<div class="m"><div class="k">RTO</div><div class="v">8 h</div></div>
|
||||
<div class="m"><div class="k">RPO</div><div class="v">4 h</div></div>
|
||||
<div class="m"><div class="k">MTD</div><div class="v">24 h</div></div>
|
||||
</div>
|
||||
<span class="pill crit-4"><span class="dot" style="background:var(--risk)"></span> Krit. 4</span>
|
||||
<span class="pill st-pill komplett">komplett</span>
|
||||
</summary>
|
||||
|
||||
<div class="deps">
|
||||
<span class="lab">↳ benötigt:</span>
|
||||
<span class="dep crossref"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M13 6l6 6-6 6"/></svg> IT-Betrieb · CAD-Systeme</span>
|
||||
<span class="dep"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M13 6l6 6-6 6"/></svg> Einkauf · Musterteile</span>
|
||||
<span class="dep" style="border-style:dashed;border-color:var(--magenta);color:var(--magenta)">◆ Prototypenschutz</span>
|
||||
</div>
|
||||
|
||||
<div class="subs">
|
||||
<div class="subs-h">Teilprozesse</div>
|
||||
<div class="sub"><span class="sdot komplett"></span><div class="snm"><div class="t">Konstruktion (CAD)</div><div class="s"><span>Owner: H. Entwicklung</span><span>Assets: CAD-Server, PLM</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">8 h</div></div><div class="m"><div class="k">RPO</div><div class="v">4 h</div></div><div class="m"><div class="k">MTD</div><div class="v">24 h</div></div></div><div class="right"><span class="pill crit-4">Krit. 4</span></div></div>
|
||||
<div class="sub"><span class="sdot komplett"></span><div class="snm"><div class="t">Prototypenbau</div><div class="s"><span>Owner: Werkstattleitung</span><span style="color:var(--magenta)">◆ Prototypenschutz</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">1 T</div></div><div class="m"><div class="k">RPO</div><div class="v">8 h</div></div><div class="m"><div class="k">MTD</div><div class="v">3 T</div></div></div><div class="right"><span class="pill crit-3">Krit. 3</span></div></div>
|
||||
<div class="sub"><span class="sdot komplett"></span><div class="snm"><div class="t">Anforderungsmanagement</div><div class="s"><span>Owner: Projektleitung</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">2 T</div></div><div class="m"><div class="k">RPO</div><div class="v">1 T</div></div><div class="m"><div class="k">MTD</div><div class="v">1 W</div></div></div><div class="right"><span class="pill crit-2">Krit. 2</span></div></div>
|
||||
<div class="sub"><span class="sdot teilweise"></span><div class="snm"><div class="t">Erprobung & Test</div><div class="s"><span>Owner: QS</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">2 T</div></div><div class="m"><div class="k">RPO</div><div class="v">1 T</div></div><div class="m"><div class="k">MTD</div><div class="v">1 W</div></div></div><div class="right"><span class="pill crit-2">Krit. 2</span></div></div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="mp st-teilweise">
|
||||
<summary class="mp-head">
|
||||
<svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M9 6l6 6-6 6"/></svg>
|
||||
<div class="mp-title">
|
||||
<div class="nm">Auftragsabwicklung <span class="tag-cat">Kern</span></div>
|
||||
<div class="meta"><span class="owner"><span class="av">VL</span> Vertriebsleitung</span><span>·</span><span>4 Teilprozesse</span></div>
|
||||
</div>
|
||||
<div class="metrics">
|
||||
<div class="m"><div class="k">RTO</div><div class="v">4 h</div></div>
|
||||
<div class="m"><div class="k">RPO</div><div class="v">1 h</div></div>
|
||||
<div class="m"><div class="k">MTD</div><div class="v">24 h</div></div>
|
||||
</div>
|
||||
<span class="pill crit-4"><span class="dot" style="background:var(--risk)"></span> Krit. 4</span>
|
||||
<span class="pill st-pill teilweise">teilweise</span>
|
||||
</summary>
|
||||
<div class="deps">
|
||||
<span class="lab">↳ benötigt:</span>
|
||||
<span class="dep crossref"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M13 6l6 6-6 6"/></svg> IT-Betrieb · ERP</span>
|
||||
<span class="dep"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M13 6l6 6-6 6"/></svg> Einkauf & Lieferanten</span>
|
||||
</div>
|
||||
<div class="subs">
|
||||
<div class="subs-h">Teilprozesse</div>
|
||||
<div class="sub"><span class="sdot komplett"></span><div class="snm"><div class="t">Fertigung</div><div class="s"><span>Owner: Produktionsleitung</span><span>Assets: MES, Maschinen</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">4 h</div></div><div class="m"><div class="k">RPO</div><div class="v">1 h</div></div><div class="m"><div class="k">MTD</div><div class="v">24 h</div></div></div><div class="right"><span class="pill crit-4">Krit. 4</span></div></div>
|
||||
<div class="sub"><span class="sdot teilweise"></span><div class="snm"><div class="t">Produktionsplanung</div><div class="s"><span>Owner: Arbeitsvorbereitung</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">8 h</div></div><div class="m"><div class="k">RPO</div><div class="v">4 h</div></div><div class="m"><div class="k">MTD</div><div class="v">2 T</div></div></div><div class="right"><span class="pill crit-3">Krit. 3</span></div></div>
|
||||
<div class="sub"><span class="sdot komplett"></span><div class="snm"><div class="t">Versand & Logistik</div><div class="s"><span>Owner: Logistik</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">1 T</div></div><div class="m"><div class="k">RPO</div><div class="v">8 h</div></div><div class="m"><div class="k">MTD</div><div class="v">3 T</div></div></div><div class="right"><span class="pill crit-2">Krit. 2</span></div></div>
|
||||
<div class="sub"><span class="sdot offen"></span><div class="snm"><div class="t">Angebot & Kalkulation</div><div class="s"><span>Owner: Vertrieb</span><span style="color:var(--warn)">BIA offen</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">—</div></div><div class="m"><div class="k">RPO</div><div class="v">—</div></div><div class="m"><div class="k">MTD</div><div class="v">—</div></div></div><div class="right"><span class="mini">BIA erfassen →</span></div></div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<!-- ============ UNTERSTÜTZEND ============ -->
|
||||
<div class="lane lane-supp">
|
||||
<div class="lane-head"><span class="tag">Unterstützende Prozesse</span><span class="cnt">3 Hauptprozesse · 8 Teilprozesse</span><span class="rule"></span></div>
|
||||
|
||||
<details class="mp st-komplett" open>
|
||||
<summary class="mp-head">
|
||||
<svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M9 6l6 6-6 6"/></svg>
|
||||
<div class="mp-title">
|
||||
<div class="nm">IT-Betrieb <span class="tag-cat">Support</span> <span class="pill" style="background:var(--violet-050);color:var(--violet);border:1px dashed var(--violet2)">▲ 3 Prozesse hängen hiervon ab</span></div>
|
||||
<div class="meta"><span class="owner"><span class="av">IT</span> IT-Leitung</span><span>·</span><span>4 Teilprozesse</span></div>
|
||||
</div>
|
||||
<div class="metrics">
|
||||
<div class="m"><div class="k">RTO</div><div class="v">4 h</div></div>
|
||||
<div class="m"><div class="k">RPO</div><div class="v">1 h</div></div>
|
||||
<div class="m"><div class="k">MTD</div><div class="v">24 h</div></div>
|
||||
</div>
|
||||
<span class="pill crit-4"><span class="dot" style="background:var(--risk)"></span> Krit. 4</span>
|
||||
<span class="pill st-pill komplett">komplett</span>
|
||||
</summary>
|
||||
<div class="deps">
|
||||
<span class="lab">▲ wird benötigt von:</span>
|
||||
<span class="dep crossref">Produktentwicklung</span>
|
||||
<span class="dep crossref">Auftragsabwicklung</span>
|
||||
<span class="dep crossref">Unternehmenssteuerung</span>
|
||||
</div>
|
||||
<div class="subs">
|
||||
<div class="subs-h">Teilprozesse</div>
|
||||
<div class="sub"><span class="sdot komplett"></span><div class="snm"><div class="t">Netzwerk & Infrastruktur</div><div class="s"><span>Owner: Netzwerkadmin</span><span>Assets: Core-Switch, FW</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">4 h</div></div><div class="m"><div class="k">RPO</div><div class="v">1 h</div></div><div class="m"><div class="k">MTD</div><div class="v">24 h</div></div></div><div class="right"><span class="pill crit-4">Krit. 4</span></div></div>
|
||||
<div class="sub"><span class="sdot komplett"></span><div class="snm"><div class="t">Backup & Recovery</div><div class="s"><span>Owner: IT-Betrieb</span><span>VA-08</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">8 h</div></div><div class="m"><div class="k">RPO</div><div class="v">1 h</div></div><div class="m"><div class="k">MTD</div><div class="v">24 h</div></div></div><div class="right"><span class="pill crit-4">Krit. 4</span></div></div>
|
||||
<div class="sub"><span class="sdot komplett"></span><div class="snm"><div class="t">Client-/Server-Betrieb</div><div class="s"><span>Owner: IT-Betrieb</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">8 h</div></div><div class="m"><div class="k">RPO</div><div class="v">4 h</div></div><div class="m"><div class="k">MTD</div><div class="v">2 T</div></div></div><div class="right"><span class="pill crit-3">Krit. 3</span></div></div>
|
||||
<div class="sub"><span class="sdot teilweise"></span><div class="snm"><div class="t">Berechtigungsverwaltung</div><div class="s"><span>Owner: IT + ISB</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">1 T</div></div><div class="m"><div class="k">RPO</div><div class="v">8 h</div></div><div class="m"><div class="k">MTD</div><div class="v">3 T</div></div></div><div class="right"><span class="pill crit-3">Krit. 3</span></div></div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="mp st-offen">
|
||||
<summary class="mp-head">
|
||||
<svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M9 6l6 6-6 6"/></svg>
|
||||
<div class="mp-title">
|
||||
<div class="nm">Einkauf & Lieferantenmanagement <span class="tag-cat">Support</span></div>
|
||||
<div class="meta"><span class="owner"><span class="av">EK</span> Einkaufsleitung</span><span>·</span><span>2 Teilprozesse</span><span>·</span><span style="color:var(--warn)">BIA offen</span></div>
|
||||
</div>
|
||||
<div class="metrics">
|
||||
<div class="m"><div class="k">RTO</div><div class="v">—</div></div>
|
||||
<div class="m"><div class="k">RPO</div><div class="v">—</div></div>
|
||||
<div class="m"><div class="k">MTD</div><div class="v">—</div></div>
|
||||
</div>
|
||||
<span class="pill crit-1"><span class="dot" style="background:#c4c8d2"></span> offen</span>
|
||||
<span class="pill st-pill offen">offen</span>
|
||||
</summary>
|
||||
<div class="subs">
|
||||
<div class="subs-h">Teilprozesse</div>
|
||||
<div class="sub"><span class="sdot offen"></span><div class="snm"><div class="t">Lieferantenauswahl</div><div class="s"><span>Owner: Einkauf</span><span style="color:var(--warn)">BIA offen</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">—</div></div><div class="m"><div class="k">RPO</div><div class="v">—</div></div><div class="m"><div class="k">MTD</div><div class="v">—</div></div></div><div class="right"><span class="mini">BIA erfassen →</span></div></div>
|
||||
<div class="sub"><span class="sdot offen"></span><div class="snm"><div class="t">Wareneingang / QS</div><div class="s"><span>Owner: QS</span><span style="color:var(--warn)">BIA offen</span></div></div><div class="metrics"><div class="m"><div class="k">RTO</div><div class="v">—</div></div><div class="m"><div class="k">RPO</div><div class="v">—</div></div><div class="m"><div class="k">MTD</div><div class="v">—</div></div></div><div class="right"><span class="mini">BIA erfassen →</span></div></div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div class="note">
|
||||
<b>Was ist neu ggü. der heutigen Ansicht?</b> Statt einer flachen Tabelle aller Prozesse werden sie nach <b>Prozesskategorie</b> (Management / Kern / Support) gruppiert und in <b>Haupt- → Teilprozesse</b> aufgeklappt. Jeder Hauptprozess rollt Kritikalität (Maximumprinzip) und die schärfsten RTO/RPO/MTD-Werte seiner Teilprozesse zusammen. <b>Abhängigkeiten</b> („↳ benötigt" / „▲ wird benötigt von") machen sichtbar, welche Prozesse auf gemeinsame Dienste wie den IT-Betrieb angewiesen sind — ein Ausfall dort trifft alle abhängigen Prozesse. Datenbasis ist bereits vorhanden (<code>Process.parentId</code>, <code>category</code>, <code>biaStatus</code>, <code>BiaEntry</code>); es ist reine Darstellung, kein Datenmodell-Umbau.
|
||||
</div>
|
||||
<div class="foot">Mockup · certvia BIA-Prozessübersicht · Beispieldaten (GEFIM) · nicht verbindlich</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,67 +0,0 @@
|
||||
# Onboarding-Prompt für einen neuen Claude-Code-Agenten
|
||||
|
||||
> Diesen Prompt dem neuen Agenten als erste Nachricht geben. Er enthält bewusst **keinen**
|
||||
> inhaltlichen Projektstand — der steht in `docs/STAND-dev-branch.md` und wird nur dort
|
||||
> gepflegt (kein doppelter, veraltender Stand im Prompt).
|
||||
|
||||
---
|
||||
|
||||
```text
|
||||
Du übernimmst die Weiterentwicklung des ISMS-Tools (Multi-Tenant-SaaS für
|
||||
ISO 27001:2022 / TISAX / VDA-ISA 2027). Mach dich zuerst mit dem Stand vertraut.
|
||||
Beginne noch KEINE Aufgabe — lies ein, bestätige dein Verständnis und warte dann
|
||||
auf meine Anweisung.
|
||||
|
||||
## Repo & Umgebung
|
||||
- Arbeitsverzeichnis: das lokale Repo `ISMS-Tool` (kein Gitea-/Remote-Zugang!).
|
||||
- Du kannst NICHT pushen. Arbeite auf Branch `dev`, committe lokal. Pushen mache ich selbst.
|
||||
Prüfe mit `git branch --show-current`, dass du auf `dev` bist (NICHT `main`).
|
||||
- Stack: Next.js 16 (App Router, Turbopack, Server Actions), React 19, TypeScript strict,
|
||||
Prisma 7 (+ @prisma/adapter-pg), PostgreSQL + pgvector, NextAuth v5, Tailwind.
|
||||
|
||||
## Zuerst lesen (in dieser Reihenfolge) — das ist die maßgebliche Statusquelle
|
||||
1. `docs/STAND-dev-branch.md` — konsolidierter Gesamtstand (PM + Technik): was fertig/offen
|
||||
ist, wo was liegt, Datenmodelle, Migrationen, Fallstricke, Demo-Logins.
|
||||
2. `docs/HANDOVER-DEV.md` — Setup, Stack, Konventionen, Migrations-Flow (§1–§10).
|
||||
3. `docs/SPEC.md` — fachliche Spezifikation.
|
||||
Verlasse dich auf diese Dokumente statt zu raten. Den inhaltlichen Projektstand NICHT aus
|
||||
diesem Prompt ableiten — er steht ausschließlich in der Doku (Single Source of Truth).
|
||||
|
||||
## Arbeitskonventionen (verbindlich)
|
||||
- Commits auf Deutsch, granular pro Thema, mit Trailer:
|
||||
`Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>`
|
||||
- Neue mutierende Server-Action → über `moduleGuard("<key>")` und in
|
||||
`scripts/check-module-guards.ts` eintragen (sonst failt der Build).
|
||||
- Neue mandantengebundene Prisma-Modelle → in `TENANT_MODELS` (`src/server/db.ts`)
|
||||
UND RLS-Policy in der Migration (`tenant_isolation` via `current_setting('app.tenant_id')`).
|
||||
- Migrations-Flow Prisma 7:
|
||||
`npx prisma migrate diff --from-config-datasource prisma.config.ts --to-schema prisma/schema.prisma --script`
|
||||
→ RLS-DO-Block manuell anhängen → `npx prisma migrate deploy` → `npx prisma generate`.
|
||||
(tsx-Skripte brauchen `import "dotenv/config"`.)
|
||||
- Zentrale Richtlinien-Variablen (Organisation/Rollen/Schutzbedarf) sind nur in `/settings`
|
||||
pflegbar und serverseitig geschützt — nicht im Richtlinien-Editor.
|
||||
- Editier-UIs immer als Popup/Modal (Muster: Assets/Lieferanten/Software/Projekte).
|
||||
- Doku mitpflegen: Nach jeder abgeschlossenen Arbeit `docs/STAND-dev-branch.md`
|
||||
aktualisieren (Executive Summary, PM-Statustabelle, ggf. neue Modelle/Migrationen,
|
||||
„Wo liegt was", Commit-Übersicht, offene Punkte). Das ist die Single Source of Truth —
|
||||
sie muss den `dev`-Stand jederzeit korrekt widerspiegeln. Der Doku-Update gehört in einen
|
||||
eigenen Commit (oder denselben Themen-Commit), nicht separat vergessen.
|
||||
|
||||
## Jede Iteration abschließen mit
|
||||
`npx tsc --noEmit` → `npm run lint` → `npm run build` (führt `prebuild`-Guard-Check aus).
|
||||
Bei Änderungen am Vorlagenpaket zusätzlich `python3 seed/isms-vorlagenpaket-v2/_verify.py`
|
||||
(muss `OK` liefern). Wo im Browser sichtbar: Dev-Server (`npm run dev`, Port 3000) und selbst
|
||||
verifizieren — nicht den Nutzer manuell prüfen lassen. Hinweis: geänderte Server-Actions
|
||||
greifen im Turbopack-Dev teils erst nach Neustart des Dev-Servers. Voraussetzung: lokale
|
||||
Postgres-DB läuft und `.env` mit `DATABASE_URL` ist vorhanden (siehe HANDOVER-DEV.md).
|
||||
|
||||
## Lokale Demo-Daten
|
||||
Seed: `npx tsx prisma/seed.ts` (idempotent). Demo-Logins Passwort `Demo1234!`:
|
||||
`admin@demo.example` (Mandanten-Admin+ISB), `bea.approver@demo.example` (2. Freigeber für
|
||||
Vier-Augen), `auditor@`, `owner@`, `user@`. Plattform-Login unter `/platform/login`.
|
||||
|
||||
## Ablauf jetzt
|
||||
Lies die drei Dokumente, fasse mir in wenigen Sätzen zusammen, was der aktuelle Stand ist
|
||||
und was als Nächstes offen wäre, und WARTE dann auf meine konkrete Aufgabe. Fang nichts
|
||||
Eigenes an. Bei Unklarheiten: gezielt nachfragen.
|
||||
```
|
||||
@@ -1,59 +0,0 @@
|
||||
# Kickoff-Prompt — Lane Konfigurierbarer Backup-Zielspeicher (certvia)
|
||||
|
||||
> Diesem Prompt einem Entwickler/Claude-Code-Agenten geben. Bootstrapt in certvia + diese Lane.
|
||||
|
||||
```text
|
||||
Du übernimmst die Lane „Konfigurierbarer Backup-Zielspeicher" am Produkt „certvia" (ISMS-Tool,
|
||||
Multi-Tenant Next.js-16 / Prisma-7 / Postgres+RLS / Auth.js-v5). Repo: ~/Projects/ISMS-Tool, Branch `dev`.
|
||||
|
||||
WICHTIG: certvia ist strikt getrennt von jedem anderen Produkt (insb. „visitvia"). Nichts vermischen.
|
||||
|
||||
BRANCH/CHECKOUT:
|
||||
Arbeits-Branch: `lane-backup-target` (KEIN `feature/`-Prefix — origin-Namespace-Konflikt).
|
||||
git fetch origin && git checkout dev && git checkout -b lane-backup-target.
|
||||
Remotes: origin = https://git.certvia.de/msolarczek/certvia.git · local-gitea (intern).
|
||||
|
||||
1) PFLICHTLEKTÜRE:
|
||||
- docs/HANDOVER-DEV.md, docs/SPEC.md, docs/STAND-dev-branch.md
|
||||
- docs/KONZEPT-backup-target.md ← dein Fahrplan
|
||||
- docs/KONZEPT-backup-restore.md §9 ← Verschlüsselung/Secrets-Kohärenz
|
||||
- Bestand ansehen: src/server/storage/backup-store.ts (BackupStore, S3-/Local-Store, createBackupStore)
|
||||
|
||||
2) AUFTRAG:
|
||||
Den Backup-Zielspeicher im Betreiber-Portal konfigurierbar machen + lokale (persistente) Option.
|
||||
a) DATENMODELL: PlatformSetting erweitern (backupTarget local|s3, backupLocalDir, backupS3Endpoint/
|
||||
Bucket/Region/AccessKey, backupS3SecretKeyEnc). Additive Migration (nullable, Default local).
|
||||
b) FACTORY: statisches `backupStore` → `getBackupStore(): Promise<BackupStore>`, liest PlatformSetting,
|
||||
entschlüsselt den S3-Key (secret-crypto). Präzedenz DB → Env (S3_*/BACKUP_LOCAL_DIR) → lokaler
|
||||
Default `.backups`. Cachen + bei Settings-Änderung invalidieren. Die 3 Nutzer umstellen:
|
||||
src/server/backup/export.ts, restore.ts, ops.ts.
|
||||
c) UI: Seite im Plattform-Portal (z. B. /admin/backup): Ziel wählen (Lokal/S3), Config, „Verbindung
|
||||
testen" (Probe put/get/remove). Gated requirePlatformFullAdmin + MFA-Step-up. Speichern via Action
|
||||
analog setPlatformMfaRequired (platformSetting.upsert); S3-Secret VOR dem Schreiben verschlüsseln.
|
||||
d) PERSISTENZ: docker-compose.coolify.yml — persistentes Volume `backups:` (wie pgdata/miniodata) in
|
||||
app+worker mounten (Pfad = backupLocalDir, z. B. /app/.backups).
|
||||
e) TESTS: scripts/test-backup-* erweitern (Store-Auflösung DB local/s3, Präzedenz, Test-Verbindung,
|
||||
fail-secure bei unvollständiger S3-Config, Export→Restore gegen beide Backends).
|
||||
|
||||
3) VERBINDLICHE REGELN:
|
||||
- S3-Secret NUR verschlüsselt in der DB (src/server/secret-crypto.ts: encryptSecret/decryptSecret) — nie Klartext.
|
||||
- Fail-secure: backupTarget=s3 mit unvollständiger Config → klarer Fehler, NICHT still auf lokal fallen.
|
||||
- Env-Fallback erhalten (Rückwärtskompatibilität bestehender Deployments).
|
||||
- BACKUP_ENC_KEY (Artefakt-Verschlüsselung) bleibt GETRENNT vom Zielspeicher — nicht vermischen.
|
||||
- RLS/Mandanten-Isolation der Artefakt-Keys (`<tenantId>/backups/…`) unverändert lassen.
|
||||
- Config-Bearbeitung nur Full-Admin + Step-up, auditiert.
|
||||
|
||||
4) ARBEITSWEISE:
|
||||
- Gate vor JEDEM Merge: npx tsc --noEmit · npm run lint · npm run build · ALLE scripts/test-*.ts.
|
||||
- migrate reset gegen lokale DB braucht Nutzer-Zustimmung (Prisma-Guard).
|
||||
- UI im Browser verifizieren: Ziel umschalten Lokal↔S3, „Verbindung testen", Export→Restore lokal.
|
||||
- DevOps: lane-backup-target → git merge --no-ff nach dev → Gate grün → Push auf BEIDE Remotes →
|
||||
docs/STAND-dev-branch.md pflegen.
|
||||
|
||||
5) NICHT TUN: kein Umbau am Auth-/RLS-Kern; keine Mehrfachziele/Offsite-Profile (Phase 2); Artefakt-
|
||||
Verschlüsselung (crypto.ts) nicht anfassen.
|
||||
|
||||
Erste Schritte: (a) Pflichtlektüre + backup-store.ts lesen, 10-Zeilen-Zusammenfassung + Fragen,
|
||||
(b) PR-Plan (Schema+Migration, getBackupStore-Refactor, UI, Compose-Volume, Tests), (c) nach Freigabe
|
||||
umsetzen. Warte nach (a)/(b) auf Bestätigung.
|
||||
```
|
||||
@@ -1,57 +0,0 @@
|
||||
# Kickoff-Prompt — Lane Backup/Restore/DSGVO (certvia)
|
||||
|
||||
> Diesem Prompt einem Entwickler/Claude-Code-Agenten geben. Bootstrapt in certvia + diese Lane.
|
||||
|
||||
```text
|
||||
Du übernimmst die Lane „Datensicherung, Wiederherstellung & DSGVO" am Produkt „certvia"
|
||||
(ISMS-Tool, Multi-Tenant Next.js-16 / Prisma-7 / Postgres+RLS / Auth.js-v5). Repo:
|
||||
~/Projects/ISMS-Tool, Integrationsbranch `dev`.
|
||||
|
||||
WICHTIG: certvia ist strikt getrennt von jedem anderen Produkt (insb. „visitvia"). Nichts vermischen.
|
||||
|
||||
BRANCH/CHECKOUT:
|
||||
Arbeits-Branch: `lane-backup` (KEIN `feature/`-Prefix — auf origin blockiert der Branch
|
||||
`feature` diesen Namespace). Aus `dev` erstellen: git fetch origin && git checkout dev &&
|
||||
git checkout -b lane-backup.
|
||||
Remotes: origin = https://git.certvia.de/msolarczek/certvia.git · local-gitea (intern).
|
||||
|
||||
1) PFLICHTLEKTÜRE (erst lesen, nicht sofort coden):
|
||||
- docs/HANDOVER-DEV.md, docs/SPEC.md, docs/STAND-dev-branch.md
|
||||
- docs/KONZEPT-backup-restore.md ← dein Fahrplan (Schicht A/B, Portal, DSGVO, §9 Verschlüsselung)
|
||||
- docs/KONZEPT-haertung.md §3 ← operativer Bezug „verschlüsselte Backups"
|
||||
|
||||
2) AUFTRAG (Phasen aus dem Konzept §11):
|
||||
(1) Schicht A: pgBackRest/wal-g + PITR, client-seitig AES-256 (§9) — Ops-nah, sofort möglich.
|
||||
(2) Tenant-scoped Export/Restore-Engine über TENANT_MODELS (FK-Reihenfolge), REPEATABLE READ.
|
||||
(3) Betreiber-Portal-Restore (Worker-Job, Kontrollen §4/§10).
|
||||
(4) DSGVO-Export (per-Mandant + per-Person).
|
||||
(5) DSGVO-Löschung (Anonymisieren vs. Hard-Delete + Löschnachweis + Tombstone-on-Restore).
|
||||
|
||||
3) VERBINDLICHE REGELN:
|
||||
- Engine läuft über den Owner-`prisma`-Client (BYPASSRLS), NIE den RLS-Client.
|
||||
- Jede Operation `tenant_id`-gescopt (Export SELECT, Restore DELETE+INSERT, Löschung) →
|
||||
beweisbar keine Fremdmandanten berührt. cuid-PKs: Reinsert kollisionsfrei.
|
||||
- `Identity` ist GLOBAL: Tenant-Restore holt Mitgliedschaften (`User`), NICHT den globalen
|
||||
Credential-Store (der liegt in Schicht A). Fehlende Identity beim Reinsert sauber behandeln.
|
||||
- Verschlüsselung = §9-Primitiv: client-seitig AES-256, Keys pro Umgebung. Backup-Artefakte
|
||||
enthalten KEINE Umgebungs-Secrets (Pepper/MFA_ENC_KEY) → Restore-Kohärenz dokumentieren.
|
||||
- MinIO-Dateien (Prefix je Mandant) gehören zu Export/Restore/Löschung dazu.
|
||||
- Destruktive Portal-Aktionen: requirePlatformFullAdmin + MFA-Step-up + getippte Bestätigung
|
||||
+ Mandant-Sperre + Pre-Restore-Snapshot + Audit.
|
||||
|
||||
4) ARBEITSWEISE:
|
||||
- Gate vor JEDEM Merge: npx tsc --noEmit · npm run lint · npm run build · ALLE scripts/test-*.ts.
|
||||
Jede Story bringt ihren Test mit (Isolation: Restore/Export/Löschung berührt nur den Zielmandanten).
|
||||
- DevOps: lane-backup → git merge --no-ff nach dev → Gate grün → Push auf BEIDE Remotes →
|
||||
docs/STAND-dev-branch.md pflegen.
|
||||
|
||||
5) KOORDINATION:
|
||||
- §9-Verschlüsselung ist gemeinsam mit Lane Härtung: Mechanismus/Keys sind entschieden
|
||||
(client-seitig AES-256, Keys pro Umgebung) — nur EINMAL abstimmen, dann unabhängig.
|
||||
- prisma migrate reset gegen Test/Coolify braucht Nutzer-Zustimmung (Prisma-Guard).
|
||||
|
||||
6) NICHT TUN: keine Änderung am Auth-/RLS-Kern; TENANT_MODELS bleibt Quelle der tenant-Tabellen.
|
||||
|
||||
Erste Schritte: (a) Pflichtlektüre + 10-Zeilen-Zusammenfassung/Fragen, (b) FK-Reihenfolge aus
|
||||
TENANT_MODELS ableiten + Engine-PR-Plan skizzieren, (c) nach Freigabe umsetzen. Warte nach (a)/(b).
|
||||
```
|
||||
@@ -1,120 +0,0 @@
|
||||
# Kickoff-Prompt — B1: Assessment und Readiness für zwei Frameworks
|
||||
|
||||
Du baust die **Bewertungs- und Readiness-Schicht** für ISO 27001 neben TISAX. Alles andere steht bereits: Der Dokumentensatz trägt beide Normen, `mapping-iso.json` liefert 120 ISO-Anforderungen, die Framework-Dimension im Datenmodell ist gebaut (AP1–AP5), ein ISO-Mandant hat SoA, Kennzahlen, Managementbewertung und Korrekturmaßnahmen.
|
||||
|
||||
**Was fehlt:** `maturity.ts`, `scope-filter.ts`, `assessment-level.ts` und `readiness.ts` kennen kein Framework und rechnen durchgängig VDA ISA — AL2/AL3, Prüfziele, Reifegrad 0–3, MUSS/SOLL. Der belegte Bruch: `src/server/soa-context.ts:151` und `src/server/export-context.ts:49` lesen `controlAssessment`; **keine einzige Stelle liest `soaEntry`**. Das SoA-Modul ist von der Auswertung abgekoppelt.
|
||||
|
||||
**Pflichtlektüre vor der ersten Zeile Code:** `docs/FEINDESIGN-framework-assessment.md` — vollständig, insbesondere §1 (Leitentscheidung) und §7a (Priorisierung). Hintergrund: `docs/FRAMEWORK-MAPPING-ISO27001.md`, `docs/UEBERGABE-framework-iso27001.md`.
|
||||
|
||||
## Repo & Branch
|
||||
- **origin:** `git.certvia.de/msolarczek/certvia`; zweiter Remote `local-gitea`.
|
||||
- **Basis ist `feature/iso27001-framework-mapping`**, nicht `dev`.
|
||||
- Arbeite auf `feature/framework-assessment`, PR gegen den Basis-Branch.
|
||||
|
||||
## Kundenlage — sie bestimmt, was jetzt gebaut wird
|
||||
|
||||
Die Mehrzahl der Mandanten führt **TISAX**, **ein** Mandant **ISO**, **keiner beide**.
|
||||
|
||||
Daraus folgt: **Das Regressionsrisiko dominiert dieses Paket.** Der gefährlichste Teil ist nicht die ISO-Logik — die ist schlank — sondern die verhaltensgleiche Extraktion der bestehenden TISAX-Logik. Sie betrifft jeden Bestandsmandanten. Schritt 1 ist deshalb keine Kür.
|
||||
|
||||
**Zurückgestellt** (betrifft ausschließlich den Doppel-Mandanten, den es heute nicht gibt):
|
||||
- Vorbelegung über `ISO_TO_ISA` (Übernahmevorschlag zwischen den Frameworks)
|
||||
- Reiter-UI in `/soa` und `/audit-readiness` — bei einem aktiven Framework wird direkt angezeigt
|
||||
|
||||
**Nicht zurückstellen:** die **Strategie-Schnittstelle** und den **Framework-Parameter** in `buildAssessment`. Beides kostet jetzt fast nichts und ist später teuer, weil sonst sieben Aufrufstellen erneut angefasst werden. Die Architektur bleibt zweigleisig, die Oberfläche zeigt vorerst ein Gleis.
|
||||
|
||||
## Die eine Leitentscheidung
|
||||
|
||||
**Die Belegbasis liegt unterhalb der Framework-Strategie.** Ob R08 freigegeben ist, ist eine Tatsache über die Organisation, keine Frage der Norm. `ControlEvidence` (`src/lib/maturity.ts:54`) wird geteilt; nur Scope, Zielwert, Bewertung und Vokabular sind framework-eigen.
|
||||
|
||||
```
|
||||
Schicht 3 Sichten /soa · /audit-readiness · Exporte → je Framework (Reiter später)
|
||||
Schicht 2 Strategie Scope · Zielwert · Bewertung → je Framework
|
||||
Schicht 1 Belegbasis loadEvidenceResolver → ControlEvidence → GETEILT
|
||||
Schicht 0 Fachdaten PolicyDocument · Evidence · Asset … → GETEILT
|
||||
```
|
||||
|
||||
**Review-Kriterium, hart:** `loadEvidenceResolver` darf `FrameworkKey` nicht kennen. Sobald die Belegauflösung anfängt, das Framework zu fragen, ist der Schnitt gerissen und wir bekommen zwei Bewertungen derselben Realität, die auseinanderlaufen.
|
||||
|
||||
## Nicht anfassen
|
||||
|
||||
- **`seed/isms-vorlagenpaket-v2/**` und `-en/**`** — generiert. Änderungen nur über `_iso_crosswalk.json` / `_iso_sections.json` / `_iso_texts_en.json` + `python3 _generate_iso.py [--lang en]`.
|
||||
- **Die VDA-ISA-Fachlogik inhaltlich** — `suggestMaturity`, `targetMaturity`, `openPoints`, `activeRequirements` werden **verschoben, nicht verändert**.
|
||||
- **`readiness.ts` und `gap-consolidation.ts`** — numerisch standard-agnostisch, werden von beiden Strategien gefüttert.
|
||||
|
||||
## Arbeitsschritte
|
||||
|
||||
### 1 — Snapshot der heutigen TISAX-Ausgabe *(zuerst, vor jeder Änderung)*
|
||||
`buildControlRows` für den Demo-Mandanten festhalten: Reifegradvorschlag, Zielwert, Belegstatus und offene Punkte je Control, als JSON im Repo. Ablage als `scripts/test-framework-assessment.ts` in der Hausform der übrigen `test-*.ts`.
|
||||
**DoD:** Test läuft grün gegen den unveränderten Stand und ist als Merge-Gate gesetzt.
|
||||
|
||||
### 2 — `ControlSpec` einführen
|
||||
`C5ControlSpec` (`src/lib/maturity.ts:16`) auf ein neutrales `ControlSpec` reduzieren (`control`, `title`, `policy[]`, `verfahren[]`, `needsAsset`, `needsRisk`); `C5ControlSpec` erweitert es um `target`. `loadEvidenceResolver` (`src/server/soa-context.ts:50`) nimmt künftig `ControlSpec`.
|
||||
**DoD:** Snapshot unverändert grün, `tsc` sauber.
|
||||
|
||||
### 3 — ISO-Specs generieren
|
||||
`_generate_iso.py` erzeugt zusätzlich `src/lib/control-specs-iso.ts` — analog zu `control-titles-iso.ts` und `iso-isa-crosswalk.ts`. Quelle ist `mapping-iso.json` (`policy` und `verfahren` stehen dort je Anforderung); `needsAsset`/`needsRisk` über `ISO_TO_ISA` vom ISA-Spec erben, für die 33 ISO-eigenen Abschnitte explizit setzen — sinnvoll nur bei A.5.9 (`needsAsset`) sowie 6.1.2/6.1.3/8.2/8.3 (`needsRisk`).
|
||||
**DoD:** Generator idempotent, `_verify_iso.py` DE und EN grün, keine handgepflegte Zweitliste.
|
||||
|
||||
### 4 — `FrameworkStrategy` + `TisaxStrategy` *(reine Extraktion)*
|
||||
Interface nach §3 des Feindesigns. `TisaxStrategy` verdrahtet die vorhandenen Funktionen um: `loadScopeInput` + `controlsInScope` → `controlsInScope`, `suggestMaturity` + `targetMaturity` → `evaluate`, `openPoints` → `gaps`, `computeReadiness` → `summarise`.
|
||||
**DoD:** Snapshot bitgenau grün. Jede Abweichung ist eine Regression, kein „ist besser geworden".
|
||||
|
||||
### 5 — `IsoStrategy`
|
||||
| Aspekt | Regel |
|
||||
|---|---|
|
||||
| Scope | `SoaEntry.applicable = true`; Klauseln 4–10 immer im Scope |
|
||||
| Zielwert | `implementationStatus = "umgesetzt"`, keine Stufung |
|
||||
| Vorschlag | Richtlinie *und* Verfahren `validiert` + geforderte Verknüpfungen → `umgesetzt`; teilweise → `teilweise`; sonst `geplant` |
|
||||
| Bestätigung | `SoaEntry.implementationStatus`; der Vorschlag überschreibt ihn nie |
|
||||
| Lücken | fehlende Begründung, fehlender Nachweis, Status ≠ „umgesetzt" bei anwendbarem Control |
|
||||
|
||||
**DoD:** ISO-Mandant bekommt eine Bewertung über alle anwendbaren Controls; leere SoA meldet „Anwendbarkeit noch nicht erklärt" statt 0 %.
|
||||
|
||||
### 6 — `buildAssessment(db, tenantId, framework)`
|
||||
Ersetzt `buildControlRows` (`src/server/soa-context.ts:146`) und delegiert an die Strategie. Sieben Dateien rufen es direkt; insgesamt hängen 13 an der Assessment-Logik.
|
||||
**DoD:** Alle Aufrufstellen umgestellt, Snapshot grün, `tsc`/`lint`/`build` grün.
|
||||
|
||||
### 7 — ISO-Readiness-Bänder und Beschriftung
|
||||
`REIFEGRAD_BANDS` (`src/lib/readiness.ts:16`) ist TISAX-Sprache („Assessment-reif", „AL-Ziel"). ISO bekommt eigene Bänder auf Basis des Umsetzungsgrads: < 50 % Aufbau · 50–79 % In Umsetzung · 80–99 % Zertifizierungsnah · 100 % Zertifizierungsreif.
|
||||
**DoD:** In der ISO-Sicht erscheint kein AL-, Prüfziel- oder Reifegradbegriff. Ein ISO-Bericht argumentiert mit „umgesetzt, hier ist der Beleg", nicht mit „Reifegrad 2,4".
|
||||
|
||||
### 8 — ISO-Exporte
|
||||
SoA-Export und Annex-A-Gap-Report. Der VDA-ISA-Export bleibt TISAX-only und unverändert.
|
||||
**DoD:** Der ISO-Mandant kann die Eingaben für seine Managementbewertung aus dem Tool ziehen.
|
||||
|
||||
**Zusatznutzen, bitte mitnehmen:** Die 33 ISO-Anforderungen ohne ISA-Gegenstück als eigene Liste ausweisbar machen. Das ist genau die Delta-Arbeit, die ISO gegenüber TISAX zusätzlich verlangt — die erste Frage jedes TISAX-Kunden, der über ISO nachdenkt.
|
||||
|
||||
## Validierungs-Gate vor jedem PR
|
||||
|
||||
```bash
|
||||
npx tsc --noEmit && npm run lint && npm run build
|
||||
npx tsx scripts/test-framework-assessment.ts # Snapshot TISAX → 0 Abweichungen
|
||||
npx tsx scripts/test-framework-dryrun.ts # Paket + Import → alle Prüfungen bestanden
|
||||
cd seed/isms-vorlagenpaket-v2
|
||||
python3 _generate_iso.py && python3 _generate_iso.py --lang en # beide idempotent
|
||||
python3 _verify.py && python3 _verify_iso.py && python3 _verify_iso.py --lang en
|
||||
python3 _render_diff.py HEAD # TISAX-Renderdiff → 0 Abweichungen
|
||||
```
|
||||
|
||||
Weitere Konventionen: Migrationsflow Prisma 7 mit manuell angehängtem RLS-DO-Block (`docs/HANDOVER-DEV.md:100`); neue mandantengebundene Modelle in `TENANT_MODELS` (`src/server/db.ts:81`) **und** RLS-Policy in der Migration; jede neue Datei unter `src/server/actions/` in `scripts/check-module-guards.ts` eintragen, sonst schlägt der Build fehl.
|
||||
|
||||
## Definition of Done (gesamt)
|
||||
|
||||
| Prüfung | Erwartung |
|
||||
|---|---|
|
||||
| Snapshot TISAX | 0 Abweichungen zur Ausgabe vor dem Umbau |
|
||||
| Bestandsmandant (TISAX) | Verhalten und Beschriftung unverändert |
|
||||
| ISO-Mandant | Readiness und SoA rechnen; kein TISAX-Vokabular in der Oberfläche |
|
||||
| Architektur | Strategie-Schnittstelle und Framework-Parameter vorhanden, auch wenn die UI nur ein Gleis zeigt |
|
||||
| Belegbasis | `loadEvidenceResolver` kennt `FrameworkKey` nicht |
|
||||
| Kennzahlen | je Framework eine eigene, **keine** gemischte Gesamtzahl |
|
||||
| Gate | alle Prüfungen oben grün |
|
||||
|
||||
## Aufwand
|
||||
|
||||
4–6 PT im vorgezogenen Umfang. Schritte 1–4 hängen aneinander und sind Pflicht; 5–8 sind danach teilbar. Schwerpunkt liegt auf Schritt 4, nicht auf der ISO-Logik.
|
||||
|
||||
## Nicht dein Scope
|
||||
|
||||
Vorbelegung zwischen den Frameworks und die Reiter-UI (siehe Kundenlage). Ebenso Paket- und Freigabearbeit: `REVIEW_CYCLE`-Split an 32 Bestandsstellen, ISB-Freigabe der 19 ISO-Abschnittstexte, Review des Crosswalks.
|
||||
@@ -1,151 +0,0 @@
|
||||
# Kickoff-Prompt — Framework-Dimension: ISO 27001 neben TISAX
|
||||
|
||||
Du übernimmst den **Anwendungsumbau** für die Mehr-Framework-Fähigkeit. Die **Inhaltsseite ist fertig**: `seed/isms-vorlagenpaket-v2` trägt seit Branch `feature/iso27001-framework-mapping` **zwei Framework-Mappings auf einem Dokumentensatz** — `mapping.json` (VDA ISA, 321 Anforderungen) und `mapping-iso.json` (ISO/IEC 27001:2022, 120 Anforderungen). Die Anwendung kennt das zweite Mapping nicht: `parsePackageFiles` liest `mapping.json` fest verdrahtet.
|
||||
|
||||
**Pflichtlektüre vor der ersten Zeile Code:** `docs/UEBERGABE-framework-iso27001.md` — insbesondere **§1 „Die vier Fallen"**. Hintergrund und Begründung der Entscheidung: `docs/FRAMEWORK-MAPPING-ISO27001.md`. Gesamtarchitektur: `docs/KONZEPT-framework-iso27001.md` (D4 und Lane 2 sind dort per Nachtrag korrigiert).
|
||||
|
||||
## Repo & Branch
|
||||
- **origin:** `git.certvia.de/msolarczek/certvia`; zweiter Remote `local-gitea`.
|
||||
- **Basis ist `feature/iso27001-framework-mapping`**, nicht `dev` — dort liegt die Vorarbeit (Commits `492d315`, `bbde804`, `7769908`, `b28d0f0`).
|
||||
- AP1 auf `feature/framework-core`, PR gegen den Basis-Branch. AP2–AP5 danach je eigener Branch, parallelisierbar.
|
||||
|
||||
## Nicht anfassen
|
||||
- **`seed/isms-vorlagenpaket-v2/**`** — generiert. Inhaltliche Änderungen laufen ausschließlich über `_iso_crosswalk.json` / `_iso_sections.json` + `python3 _generate_iso.py`, nie direkt in den Markdown-Dateien (der Generator überschreibt sentinel-begrenzte Blöcke).
|
||||
- **Die TISAX-Logik verhaltensgleich lassen:** `src/lib/maturity.ts`, `src/lib/scope-filter.ts`, `src/server/assessment-level.ts`, `src/lib/control-titles.ts`, `src/lib/export/vda-isa*.ts`. Wenn du sie hinter eine `FrameworkStrategy` ziehst, muss das Verhalten identisch bleiben.
|
||||
|
||||
## Vier Invarianten — hier geht es sonst schief
|
||||
|
||||
1. **`reconcilePackage` archiviert fremde Anforderungen.** `prisma/import-policies.ts:368-371` setzt `archivedAt` auf jede `PolicyRequirement`, deren `reqId` nicht im importierten Paket steht. Ein ISO-Import in einen TISAX-Mandanten legt damit **alle 321 VDA-ISA-Anforderungen still** — und umgekehrt. Lösung: `PolicyRequirement.framework` ergänzen (Backfill `TISAX`) und den Archivierungslauf auf `where: { tenantId, framework }` einschränken. Für Dokumente, Variablen, Baseline und Nachweisregister gilt das **nicht** — die sind geteilt und identisch, sie dürfen genau einmal je Mandant abgeglichen werden.
|
||||
2. **Zwei Unique-Constraints brechen.** `PolicyTemplateVersion.version @unique` (`prisma/schema.prisma:1639`) → `@@unique([framework, version])`, sonst kollidieren ISO 2.1 und TISAX 2.1. `PolicyPackageState.tenantId @unique` (`:1614`) → `@@unique([tenantId, framework])`, sonst merkt sich ein Mandant nur eine Paketversion.
|
||||
3. **TISAX darf sich nicht verändern.** Messlatte ist `python3 seed/isms-vorlagenpaket-v2/_render_diff.py HEAD` → 0 Abweichungen.
|
||||
4. **Den Fail-Safe in `src/lib/policy-render.ts` nicht entfernen.** `buildContext` belegt fehlende Framework-Flags vor (`FLAG_FW_TISAX = true`, `FLAG_FW_ISO27001 = false`), damit Bestandsmandanten vor dem Paket-Re-Import keine leeren Anforderungsblöcke sehen.
|
||||
|
||||
## AP1 — Framework-Dimension *(Fundament, blockiert alles)*
|
||||
|
||||
**Schema, additiv:**
|
||||
```prisma
|
||||
enum Framework { ISO_27001 TISAX }
|
||||
|
||||
model TenantFramework {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
framework Framework
|
||||
isPrimary Boolean @default(false) @map("is_primary")
|
||||
config Json? // z. B. { tisaxLevel: "AL3" } bzw. { certScope }
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
@@unique([tenantId, framework])
|
||||
@@index([tenantId])
|
||||
@@map("tenant_frameworks")
|
||||
}
|
||||
```
|
||||
Dazu `PolicyRequirement.framework`, `PolicyTemplateVersion.framework`, `PolicyPackageState.framework`. Backfill aller Bestandsdaten auf `TISAX`. `TenantFramework` gehört in **`TENANT_MODELS`** (`src/server/db.ts:81`) und braucht eine **RLS-Policy in der Migration**.
|
||||
|
||||
**Code:**
|
||||
| Datei | Änderung |
|
||||
|---|---|
|
||||
| `prisma/import-policies.ts` | `parsePackageFiles(seedDir, mappingFile = "mapping.json")`; Requirements framework-scoped reconcilen |
|
||||
| `prisma/template-store.ts:147` | `resolvePackageForTenant(prisma, tenantId, seedDir, framework)`; `loadPublishedPackage(prisma, locale, framework)`; `getAvailableVersion` ebenso |
|
||||
| `scripts/sync-policy-templates.ts:23` | über **Frameworks × Sprachen** iterieren |
|
||||
|
||||
Die vier Aufrufer bekommen den Parameter durchgereicht: `src/server/provision.ts:139`, `src/server/actions/policy-package.ts:28`, `src/server/actions/admin.ts`, `src/app/(app)/policies/updates/page.tsx:44`. **Das Seed-Verzeichnis bleibt für beide Frameworks dasselbe** — die fünf `SEED_DIR`-Konstanten ändern sich nicht, nur der Mapping-Dateiname.
|
||||
|
||||
**DoD:** Bestandsmandanten laufen unverändert als TISAX; ein Mandant lässt sich mit `["ISO_27001"]`, `["TISAX"]` oder beiden provisionieren; bei Doppel-Framework koexistieren 321 + 120 Anforderungen und **keine** ist fälschlich archiviert.
|
||||
|
||||
## AP2 — Provisionierung und Flags *(klein, direkt nach AP1)*
|
||||
|
||||
`ProvisionOpts` (`src/server/provision.ts:37`) um `frameworks: Framework[]`. `provisionTenant` schreibt die `TenantFramework`-Zeilen, importiert je Framework das passende Mapping und setzt die Sichtbarkeits-Flags als `PolicyVariable`: nur TISAX → `true/false`, nur ISO → `false/true`, beides → `true/true`.
|
||||
|
||||
**Reihenfolge beachten:** `reconcilePackage` erhält nutzergepflegte Variablenwerte und überschreibt sie nicht — die Flags also **nach** dem Import setzen, sonst bleibt der Schema-Default stehen und ein ISO-Mandant sieht die VDA-ISA-Sicht. `tisaxLevel` bleibt auf `TenantSettings`, ist aber TISAX-scoped; bei einem reinen ISO-Mandanten keine AL-Flags setzen.
|
||||
|
||||
**DoD:** Frisch provisionierter ISO-Mandant öffnet `/policies` und sieht je Abschnitt `*Anforderungsbezug:* ISO/IEC 27001 …` plus die 19 ISO-only-Abschnitte; keine VDA-ISA-Anforderungen.
|
||||
|
||||
## AP3 — SoA-Modul *(das fehlende ISO-Kernartefakt)*
|
||||
|
||||
Der Modul-Key `soa` (`src/lib/modules.ts:19`) zeigt auf `/soa`, **die Route existiert nicht**; die heutige Logik liegt als Wizard-Schritt in `src/server/actions/soa.ts` und ist ein VDA-ISA-Reifegrad-Assessment (0–3), nicht die ISO-Anwendbarkeitserklärung.
|
||||
|
||||
```prisma
|
||||
model SoaEntry {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
framework Framework
|
||||
control String // "A.5.15"
|
||||
applicable Boolean @default(true)
|
||||
justification String // Begründung Einbeziehung ODER Ausschluss
|
||||
source String? // Risiko-ID / gesetzliche / vertragliche Anforderung
|
||||
implementationStatus String @default("geplant") // umgesetzt | teilweise | geplant
|
||||
ownerId String? @map("owner_id")
|
||||
policyCode String? @map("policy_code")
|
||||
evidenceId String? @map("evidence_id")
|
||||
@@unique([tenantId, framework, control])
|
||||
@@index([tenantId])
|
||||
@@map("soa_entries")
|
||||
}
|
||||
```
|
||||
|
||||
`applicable`, `justification`, `implementationStatus` und die Ausschlussbegründung sind **normative Pflichtangaben** (ISO/IEC 27001:2022, 6.1.3 d) — ohne sie ist die SoA im Zertifizierungsaudit angreifbar. Vorbefüllung aus `mapping-iso.json` (93 Controls); das Feld `condition` steuert die Default-Anwendbarkeit. Fachliche Vorlage für Aufbau und Spalten: `seed/isms-vorlagenpaket-v2/Statement-of-Applicability-ISO.md`.
|
||||
|
||||
**DoD:** SoA vollständig pflegbar und als PDF/XLSX exportierbar; ein Control ohne Begründung wird als unvollständig markiert.
|
||||
|
||||
## AP4 — Kennzahlen, Managementbewertung, Korrekturmaßnahmen
|
||||
|
||||
| Klausel | Modell | Inhalt |
|
||||
|---|---|---|
|
||||
| 9.1 | `Kpi` / `KpiValue` | Kennzahl, Datenquelle, Zielwert, Turnus, Verantwortlicher, Messwerte je Periode |
|
||||
| 9.3 | `ManagementReview` | Datum, Eingaben nach 9.3.2, Ergebnisse nach 9.3.3, Beschlüsse mit Verantwortlichem und Termin |
|
||||
| 10.2 | `Nonconformity` + `CorrectiveAction` | Herkunft, Sofortkorrektur, Ursachenanalyse, Maßnahme, Wirksamkeitsbewertung |
|
||||
|
||||
Aufsetzen auf Vorhandenes: `Task.recurrence` (RRULE), `Task.remindAt`, `Task.effectiveUntil` (Wirksamkeitsintervall, gekoppelt an `Evidence.validUntil`), `TaskParticipant` (RACI), `AuditLog`. Datenquellen für Kennzahlen liegen bereits im Tool: Aufgabenfristen und Überfälligkeit, Incident-SLA und Meldefristen (`src/lib/incident-deadlines.ts`), Reifegrade je Control, Maßnahmenstatus. Die Feldinhalte stehen fachlich in R03 der Bibliothek (`ISO-MS-MESSUNG`, `ISO-MS-MGMTREVIEW`, `ISO-MS-CAPA`).
|
||||
|
||||
**DoD:** Kennzahlenblatt mit Zielwerten über zwei Perioden auswertbar; Management-Review entlang der 9.3.2-Agenda protokollierbar; ein Maßnahmenfall inklusive dokumentierter Wirksamkeitsprüfung abschließbar.
|
||||
|
||||
## AP5 — Dokumentenlenkung *(klein, hohe Auditwirkung)*
|
||||
|
||||
- `PolicyDocument.reviewCycle` + `nextReviewAt` — heute führt nur `ManagedRegister` einen `reviewCycle`; A.5.1 verlangt die Überprüfung „in geplanten Abständen".
|
||||
- `PolicyAcknowledgement { tenantId, policyDocumentId, version, userId, acknowledgedAt }` — Lesebestätigung, in `SPEC.md` §4.6 vorgesehen und bis heute nicht gebaut. Zugleich der einfachste Nachweis für Klausel 7.3 und Control A.6.3.
|
||||
- Änderungshistorie je Dokumentversion — aus `AuditLog` (Vorher/Nachher) ableitbar oder eigene Tabelle.
|
||||
|
||||
**DoD:** Übersicht „Prüfung fällig"; Auswertung der Lesebestätigungen je Richtlinienversion; Dokumenthistorie über mindestens zwei Versionen sichtbar.
|
||||
|
||||
## Validierungs-Gate vor jedem PR
|
||||
|
||||
```bash
|
||||
npx tsc --noEmit && npm run lint && npm run build
|
||||
cd seed/isms-vorlagenpaket-v2
|
||||
python3 _verify.py # TISAX-Sicht → OK
|
||||
python3 _verify_iso.py # ISO-Sicht → OK (0 Befunde)
|
||||
python3 _render_diff.py HEAD # TISAX-Regression → 0 Abweichungen
|
||||
```
|
||||
|
||||
Zusätzlich beachten:
|
||||
- **Migrationsflow Prisma 7** (`docs/HANDOVER-DEV.md:100`): `migrate diff --from-config-datasource … --to-schema … --script`, danach den **RLS-DO-Block manuell** an die `migration.sql` anhängen, dann `migrate deploy`.
|
||||
- **`scripts/check-module-guards.ts`** läuft als `prebuild`-Gate: jede neue Datei unter `src/server/actions/` dort eintragen (Modul-Key oder `EXEMPT`), sonst schlägt der Build fehl.
|
||||
- Bei paralleler Lane-Entwicklung teilen sich die Worktrees dieselbe lokale Postgres-DB: beim Erzeugen einer Migration nur die **eigenen** DDL-Blöcke übernehmen, Fremd-Drops von Hand entfernen.
|
||||
|
||||
## Definition of Done (gesamt)
|
||||
|
||||
| Prüfung | Erwartung |
|
||||
|---|---|
|
||||
| Bestandsmandant (TISAX) nach Deploy | Readiness und Exporte identisch zum Snapshot vor dem Umbau |
|
||||
| Import ISO in Mandant mit TISAX | 120 neue Anforderungen, **0 archivierte** ISA-Anforderungen |
|
||||
| Import ISO, Umsetzungstexte | 120 von 120 gefüllt |
|
||||
| Dokumente bei Doppel-Framework | 39 Dokumente, **nicht** doppelt |
|
||||
| Parallelbetrieb im Dokument | beide Anforderungssichten unter einem gemeinsamen Umsetzungstext |
|
||||
| Gate | tsc, lint, build, beide `_verify*`, `_render_diff` grün |
|
||||
|
||||
`parsePackageFiles` ist reine Dateiarbeit und ohne Datenbank testbar; für den Mandanten-Import gibt es `reconcilePackage(..., { dryRun: true })` — Änderungsreport ohne Schreibzugriff, geeignet als Freigabebedingung.
|
||||
|
||||
## Reihenfolge und Aufwand
|
||||
|
||||
```
|
||||
AP1 Framework-Dimension 4–6 PT ← blockiert alles
|
||||
├─ AP2 Provisionierung 1–2 PT
|
||||
├─ AP3 SoA-Modul 5–8 PT
|
||||
├─ AP4 Managementkl. 5–8 PT
|
||||
└─ AP5 Dok.-Lenkung 2–3 PT
|
||||
```
|
||||
|
||||
AP3–AP5 sind nach AP1 parallelisierbar. **Feature-Flag:** ISO bleibt laut Entscheidung D7 hinter einem Plattform-Schalter, bis AP3 abgenommen ist.
|
||||
|
||||
## Nicht dein Scope
|
||||
|
||||
Diese Punkte gehören dem ISB bzw. der Redaktion: Nachweisregister um Zeilen für Kennzahlenblatt, Management-Review-Protokoll und Maßnahmenregister ergänzen; VA-15 trennen und ein Verfahren für Korrekturmaßnahmen ergänzen (**Nummer ab VA-21**, VA-20 ist belegt); `REVIEW_CYCLE` an den 33 Bestandsstellen auf die getrennten Zyklus-Variablen umstellen; ISB-Freigabe der 19 neuen Abschnittstexte.
|
||||
@@ -1,42 +0,0 @@
|
||||
# Kickoff-Prompt — Lane D: Test, Cutover & Abnahme
|
||||
|
||||
Du übernimmst **Lane D** (Integration/Abnahme) der Umstellung **MinIO → Garage**. Lies `docs/KONZEPT-garage-migration.md` (v. a. §7 Runbook, §8 Rollback, §9 Abnahmekriterien). **Randbedingung:** nur Test-Instanzen, keine Datenmigration — Neu-Deploy.
|
||||
|
||||
## Repo & Branch
|
||||
- **origin:** `git.certvia.de/msolarczek/certvia` — Basis-Branch **`dev`**.
|
||||
- Zweiter Remote (interner Coolify-Test): `local-gitea` = `gitea.192.168.1.155.sslip.io/msolarczek/ISMS-Tool`. Push auf `dev` löst den Test-Deploy aus.
|
||||
- Deploy-Ziel: interne Coolify-Instanz, `certvia.192.168.1.155.sslip.io`.
|
||||
|
||||
## Ziel
|
||||
Die integrierten Ergebnisse aus Lane A–C auf der Test-Instanz **per Neu-Deploy** in Betrieb nehmen und **formal abnehmen** — plus abgenommenes Runbook (auch für spätere Prod).
|
||||
|
||||
## Aufgaben
|
||||
1. **Cutover (Runbook §7)** an der Test-Instanz durchspielen:
|
||||
- Im Compose `minio` → `garage` + `garage-provision`; Volumes `garage_meta`/`garage_data`.
|
||||
- Coolify-Env: `S3_ENDPOINT=http://garage:3900`, `S3_REGION=us-east-1`, `GARAGE_RPC_SECRET`, `GARAGE_ADMIN_TOKEN` (literal!), `S3_ACCESS_KEY/S3_SECRET_KEY` = provisionierter Garage-Key.
|
||||
- Deploy; Garage „ready", `garage-provision` legt Bucket/Key/Rechte an.
|
||||
- Optional DB-Reset (wie in bisherigen Deploys), falls alte Objekt-Referenzen stören.
|
||||
2. **End-to-End-Abnahme (§9)** — alle grün:
|
||||
- Upload (Richtlinie/Nachweis) → Objekt in Garage, `<tenantId>/uploads/…`-Präfix korrekt.
|
||||
- Download (`/files/[...key]`) inkl. korrektem Dateinamen/Content-Type.
|
||||
- Backup-Export `.cvb` (CVB1-Header), Persistenz + Download.
|
||||
- DSGVO-ZIP erzeugt + lesbar.
|
||||
- Restore → Datenintegrität + **Mandanten-Isolation**.
|
||||
- Backup-Historie: List + Aufräumen (Delete-Prefix).
|
||||
- Negativfall: fehlender Bucket → sprechender Konfigfehler (kein stiller CreateBucket).
|
||||
- `scripts/test-backup-*.ts` + `scripts/test-garage-storage.ts` grün gegen die Instanz.
|
||||
3. **Runbook & Rollback** in `docs/DEPLOY-COOLIFY.md` finalisieren (Schritt-für-Schritt, inkl. „`garage_meta` sichern").
|
||||
4. **`minio`-Service + Volumes** erst nach erfolgreicher Abnahme entfernen (bis dahin Rollback-Sicherheitsnetz).
|
||||
|
||||
## Vorgaben
|
||||
- **Keine echten Secrets in Chat/Repo/Logs** (`GARAGE_*`, S3-Key). In Coolify **literal** setzen (Interpolationsfalle).
|
||||
- Bei „Container weg ohne Logs" die bekannte **Log-Capture-Technik** nutzen (Logs während des Deploys in Dateien mitschreiben; siehe Deployment-Erfahrungen).
|
||||
- Gefundene Bugs an die jeweilige Lane (A/B/C) zurückspielen, nicht selbst quer patchen.
|
||||
|
||||
## Definition of Done
|
||||
- Test-Instanz läuft auf Garage, alle Abnahmekriterien (§9) abgehakt.
|
||||
- Runbook + Rollback dokumentiert und einmal real durchgespielt.
|
||||
- `minio` entfernt (oder bewusst als Netz belassen, dokumentiert). Freigabe für spätere Prod.
|
||||
|
||||
## Abhängigkeiten
|
||||
Integriert **Lane A + B + C**. PM koordiniert Reihenfolge (A→B, C parallel) und Go für die Abnahme.
|
||||
@@ -1,36 +0,0 @@
|
||||
# Kickoff-Prompt — Lane C: App-Code Garage-tauglich
|
||||
|
||||
Du übernimmst **Lane C** der Umstellung **MinIO → Garage**. Lies `docs/KONZEPT-garage-migration.md` (v. a. §3 und §4 D3). **Kern:** Der S3-Code bleibt inhaltlich gleich (AWS SDK v3, `forcePathStyle`), aber die Selbstheilung `ensureBucket()` (HeadBucket→**CreateBucket**) muss weg — Garage unterstützt S3-`CreateBucket` nicht; Buckets werden von Lane B vorab provisioniert.
|
||||
|
||||
## Repo & Branch
|
||||
- **origin:** `git.certvia.de/msolarczek/certvia` — Basis-Branch **`dev`**.
|
||||
- Zweiter Remote: `local-gitea` = `gitea.192.168.1.155.sslip.io/msolarczek/ISMS-Tool`.
|
||||
- Arbeite auf `feature/garage-code` (aus `dev`), PR nach `dev`. **Unabhängig von Lane A/B** entwickelbar (gegen einen lokalen Garage-Container testen).
|
||||
|
||||
## Scope (genau diese Dateien)
|
||||
- `src/server/storage/adapter.ts` — `ensureBucket()` anpassen.
|
||||
- `src/server/storage/backup-store.ts` — `ensureBucket()` anpassen.
|
||||
- `.env.coolify.example` + `.env.example` — Kommentare MinIO → Garage, `S3_ENDPOINT`-Beispiel `http://garage:3900`, `forcePathStyle`-Begründung bleibt gültig.
|
||||
- Tests unter `scripts/` (neuer Smoke-Test).
|
||||
- **Nicht anfassen:** Compose/Infra (Lane A), Provisioning (Lane B), Fachlogik/UI.
|
||||
|
||||
## Aufgaben
|
||||
1. **`ensureBucket()` in beiden Stores** von „HeadBucket→CreateBucket" auf **nur prüfend** umstellen:
|
||||
- `HeadBucketCommand` → wenn ok, weiter.
|
||||
- Wenn Bucket fehlt/kein Zugriff → **klarer Konfigurationsfehler** werfen: „Bucket `<name>` nicht provisioniert/kein Zugriff — Garage-Provisioning (Lane B) ausführen." **Kein** `CreateBucketCommand` mehr.
|
||||
- `CreateBucketCommand`-Import entfernen, wenn ungenutzt (tsc/lint sauber halten).
|
||||
- Beachte: `backup-store.ts` schluckt heute den Fehler still — das durch die neue, sprechende Variante ersetzen.
|
||||
2. **Region/Endpoint-Doku** aktualisieren (Default `S3_REGION=us-east-1` bleibt, passend zu Garage-`s3_region`).
|
||||
3. **Smoke-Test** (`scripts/test-garage-storage.ts` o. ä.): gegen einen lokalen Garage-Container Put→Get→(List/Delete beim Backup-Store) grün; plus Negativfall „Bucket fehlt → sprechender Fehler".
|
||||
|
||||
## Vorgaben
|
||||
- **API der Storage-Abstraktion unverändert** (`StorageAdapter`/`BackupStore`-Interfaces, Key-Schema, Local-/Stub-Fallback bleiben).
|
||||
- Keine neuen Pflicht-Env; `S3_*`-Kontrakt bleibt.
|
||||
- **Validierungs-Gate vor PR:** `npx tsc --noEmit`, Lint, `npm run build`, alle `scripts/test-*.ts` grün (inkl. neuem Test). Denk an die bekannte Falle: **nichts, was Secrets liest, auf Modulebene aufrufen** (Build-Kompatibilität).
|
||||
|
||||
## Definition of Done
|
||||
- Beide `ensureBucket()` prüfen nur noch, mit sprechendem Fehler bei fehlendem Bucket.
|
||||
- Doku aktualisiert; Smoke-Test grün gegen lokale Garage; Gate grün.
|
||||
|
||||
## Abhängigkeiten
|
||||
Zur **Laufzeit** auf **Lane B** angewiesen (Bucket muss existieren), aber **Code + Tests unabhängig** entwickelbar (lokaler Garage-Container).
|
||||
@@ -1,35 +0,0 @@
|
||||
# Kickoff-Prompt — Lane A: Garage Infra & Deployment
|
||||
|
||||
Du übernimmst **Lane A** der Objektspeicher-Umstellung **MinIO → Garage**. Lies zuerst das Gesamtkonzept: `docs/KONZEPT-garage-migration.md` (v. a. §3 Reibungspunkt, §5 Zielarchitektur, §6 Lane A, §7 Runbook). **Randbedingung:** nur Test-Instanzen, keine Datenmigration — kompletter Neu-Deploy.
|
||||
|
||||
## Repo & Branch
|
||||
- **origin:** `git.certvia.de/msolarczek/certvia` — Basis-Branch **`dev`**.
|
||||
- Zweiter Remote (interner Coolify-Test): `local-gitea` = `gitea.192.168.1.155.sslip.io/msolarczek/ISMS-Tool`. Ein Push auf `dev` löst den Test-Deploy aus.
|
||||
- Arbeite auf `feature/garage-infra` (aus `dev`), PR nach `dev`. Nach Merge `dev` auf **beide** Remotes pushen.
|
||||
|
||||
## Ziel
|
||||
Garage als Compose-Service, der `minio` in `docker-compose.coolify.yml` ersetzt — lauffähig auf der Test-Instanz, Admin-API erreichbar, Single-Node-Layout „ready".
|
||||
|
||||
## Scope (nur diese Dateien/Bereiche)
|
||||
- `docker-compose.coolify.yml`: `minio`-Service durch `garage` ersetzen (nicht sofort löschen — auskommentiert/parallel lassen, bis Lane D abnimmt).
|
||||
- `garage.toml` (neu, als Config-Mount oder über Env) + ggf. `docs/DEPLOY-COOLIFY.md` ergänzen.
|
||||
- Keine App-Code-Änderung (das ist Lane C).
|
||||
|
||||
## Vorgaben
|
||||
- **Image pinnen** auf eine aktuelle stabile Garage-Version (`dxflrs/garage:vX.Y.Z`), nicht `latest`.
|
||||
- **Ports:** 3900 = S3-API (von der App genutzt), 3903 = Admin-API (clusterintern, für Healthcheck/Provisioning), 3902 = Web optional. **Nichts nach außen (Traefik) freigeben** — genau wie MinIO bisher.
|
||||
- **`garage.toml`:** `replication_factor = 1` (Single-Node), `metadata_dir`, `data_dir`, `rpc_secret` (aus `GARAGE_RPC_SECRET`), Block `[s3_api] s3_region = "us-east-1"`, `api_bind_addr = "[::]:3900"`, Block `[admin] api_bind_addr = "[::]:3903"`, `admin_token` (aus `GARAGE_ADMIN_TOKEN`).
|
||||
- **Volumes:** `garage_meta → /var/lib/garage/meta` (KRITISCH), `garage_data → /var/lib/garage/data`.
|
||||
- **Security analog Bestand:** `security_opt: no-new-privileges`, `cap_drop: ALL`, Resource-Limits, `restart: unless-stopped`.
|
||||
- **Healthcheck** gegen Admin-API `/health` (3903).
|
||||
- **Layout-Bootstrap** dokumentieren: nach erstem Start Node einer Zone mit Kapazität zuweisen (`garage layout assign …` → `garage layout apply`). Falls möglich, an Lane B (Provisioning-Job) delegieren — dann hier nur vorbereiten.
|
||||
- **Secrets:** `GARAGE_RPC_SECRET` (32-byte hex) und `GARAGE_ADMIN_TOKEN` als Coolify-Env, **literal** setzen (nicht über `${…}` referenzieren — bekannte Coolify-Interpolationsfalle). **Keine echten Secrets ins Repo oder in Logs.**
|
||||
|
||||
## Definition of Done
|
||||
- Garage-Container startet in der Test-Instanz, Admin-`/health` grün, Layout „ready".
|
||||
- `S3_ENDPOINT=http://garage:3900` intern erreichbar (kurzer `aws s3 ls`/curl-Nachweis).
|
||||
- `garage_meta` als zu sicherndes Volume in `docs/DEPLOY-COOLIFY.md` vermerkt.
|
||||
- Übergabepunkt an Lane B (Provisioning) klar dokumentiert (wie CLI/Admin-API erreichbar ist).
|
||||
|
||||
## Abhängigkeiten
|
||||
Lane B (Provisioning) baut direkt auf dir auf. Stimme das CLI-/Admin-API-Zugriffsmodell mit Lane B ab.
|
||||
@@ -1,37 +0,0 @@
|
||||
# Kickoff-Prompt — Lane B: Garage Provisioning (Bucket/Key/Rechte)
|
||||
|
||||
Du übernimmst **Lane B** der Umstellung **MinIO → Garage**. Lies `docs/KONZEPT-garage-migration.md` (v. a. §3 „einziger Reibungspunkt", §4 D3, §6 Lane B). **Kern:** Garage legt Buckets/Keys **nicht** über S3-`CreateBucket` an, sondern über **Admin-API/CLI** — das automatisieren wir hier, idempotent.
|
||||
|
||||
## Repo & Branch
|
||||
- **origin:** `git.certvia.de/msolarczek/certvia` — Basis-Branch **`dev`**.
|
||||
- Zweiter Remote: `local-gitea` = `gitea.192.168.1.155.sslip.io/msolarczek/ISMS-Tool` (Push auf `dev` = Test-Deploy).
|
||||
- Arbeite auf `feature/garage-provision` (aus `dev`), PR nach `dev`.
|
||||
|
||||
## Ziel
|
||||
Ein **idempotenter Init-Job `garage-provision`** (Compose-Service, `restart: no`, analog `migrate`), der aus einer frisch gestarteten Garage reproduzierbar den betriebsbereiten Zustand herstellt.
|
||||
|
||||
## Scope
|
||||
- Neuer Compose-Service `garage-provision` in `docker-compose.coolify.yml` (mit Lane A abstimmen; `depends_on: garage`).
|
||||
- Provisioning-Skript (`scripts/garage-provision.*` oder Shell im Job) — CLI **oder** Admin-API (HTTP). Entscheidung im Skript-Kommentar begründen.
|
||||
- Doku in `docs/DEPLOY-COOLIFY.md`.
|
||||
|
||||
## Aufgaben (alle idempotent — mehrfach ausführbar ohne Fehler)
|
||||
1. **Layout** sicherstellen (falls Lane A das nicht schon macht): Node zuweisen + `layout apply`.
|
||||
2. **Bucket(s)** anlegen: `isms-documents` (Uploads); Backup-Bucket nur, falls Backup-Store auf S3 statt `BACKUP_LOCAL_DIR` läuft.
|
||||
3. **Access-Key** bereitstellen — **deterministisch**: bevorzugt vorhandenen Key **importieren** (`garage key import` mit den Werten aus `S3_ACCESS_KEY`/`S3_SECRET_KEY` der Coolify-Env), damit App-Env und Garage garantiert synchron sind. (Alternative: Key erzeugen und Ausgabe in Coolify-Secrets übernehmen — nur wenn Import nicht praktikabel; Trade-off dokumentieren.)
|
||||
4. **Rechte** setzen: Key → Bucket read/write (owner nach Bedarf).
|
||||
5. **Verifikation:** am Ende prüfen, dass Bucket existiert und der Key Schreib-/Leserecht hat; bei Fehlkonfiguration mit klarer Meldung + Exit ≠ 0 abbrechen.
|
||||
|
||||
## Vorgaben
|
||||
- **Idempotenz zwingend:** vor jedem `create` Existenz prüfen; „already exists" als Erfolg werten (der Job läuft bei JEDEM Deploy).
|
||||
- **Kein Secret in Logs** (Key/Secret nicht ausgeben). `GARAGE_ADMIN_TOKEN` aus Env.
|
||||
- Nicht crash-loopen bei fehlender Config: klare Fehlermeldung, definierter Exit (der Job ist `restart:no`, kein Dauerdienst).
|
||||
- **Keine App-Code-Änderung** (Lane C).
|
||||
|
||||
## Definition of Done
|
||||
- Aus „leerer Garage" stellt ein einziger Job-Lauf Bucket + Key + Rechte her; zweiter Lauf ist ein sauberer No-Op.
|
||||
- Danach greift `HeadBucket` der App erfolgreich (Übergabe an Lane C/D).
|
||||
- Runbook-Schritt in `docs/DEPLOY-COOLIFY.md` dokumentiert.
|
||||
|
||||
## Abhängigkeiten
|
||||
Braucht **Lane A** (Garage-Service + Admin-Zugriff). Liefert die Vorbedingung für **Lane C** (`ensureBucket` prüft nur) und **Lane D** (Abnahme).
|
||||
@@ -1,55 +0,0 @@
|
||||
# Kickoff-Prompt — Lane Sicherheitshärtung (certvia)
|
||||
|
||||
> Diesem Prompt einem Entwickler/Claude-Code-Agenten geben. Bootstrapt in certvia + diese Lane.
|
||||
|
||||
```text
|
||||
Du übernimmst die Lane „Sicherheitshärtung" am Produkt „certvia" (ISMS-Tool, Multi-Tenant
|
||||
Next.js-16 / Prisma-7 / Postgres+RLS / Auth.js-v5). Repo: ~/Projects/ISMS-Tool, Branch `dev`.
|
||||
|
||||
WICHTIG: certvia ist strikt getrennt von jedem anderen Produkt (insb. „visitvia"). Nichts vermischen.
|
||||
|
||||
BRANCH/CHECKOUT:
|
||||
Arbeits-Branch: `lane-haertung` (KEIN `feature/`-Prefix — origin-Namespace-Konflikt).
|
||||
git fetch origin && git checkout dev && git checkout -b lane-haertung.
|
||||
Remotes: origin = https://git.certvia.de/msolarczek/certvia.git · local-gitea (intern).
|
||||
|
||||
1) PFLICHTLEKTÜRE:
|
||||
- docs/HANDOVER-DEV.md, docs/SPEC.md, docs/STAND-dev-branch.md
|
||||
- docs/KONZEPT-haertung.md ← dein Fahrplan
|
||||
- docs/KONZEPT-backup-restore.md §9 ← das gemeinsame Verschlüsselungs-Primitiv
|
||||
|
||||
2) AUFTRAG (Phasen aus dem Konzept §7):
|
||||
(1) PEPPER (App) — JETZT, solange test/dev-DBs frisch/leer sind.
|
||||
(2) Host-Encryption (LUKS/Volume) + verschlüsselte Backups (Ops, mit Backup-Lane).
|
||||
(3) Secrets-Register formalisieren.
|
||||
(4) DB-TLS (sslmode) + Vault/KMS = Phase 2.
|
||||
|
||||
3) VERBINDLICHE REGELN:
|
||||
- PEPPER: über Argon2-`secret` bei hash() UND jeder verify()-Stelle. Env `PASSWORD_PEPPER`
|
||||
(32-Byte hex). Nach Option C ist der verify-Pfad zentral (Login gegen Identity) → wenn nötig
|
||||
einen verifyPassword(hash,pw)-Wrapper einführen, damit Pepper EINE Stelle ist.
|
||||
- ⚠ Pepper ist NICHT rotierbar ohne Passwort-Reset für alle (wie MFA_ENC_KEY) → bewusst
|
||||
JETZT setzen, leere DBs nutzen. Restore-Kohärenz: Pepper ist Umgebungs-Secret, nicht im Artefakt.
|
||||
- Argon2-PARAMETER sind ERLEDIGT (src/server/password.ts, ARGON2_OPTIONS) — nicht anfassen,
|
||||
nur den `secret` ergänzen.
|
||||
- Host-Encryption/Backup-Verschlüsselung sind OPS-Runbook (kein App-Code) → in
|
||||
docs/DEPLOY-PROD-CONTABO.md als Go-Live-Punkte ergänzen; §9-Mechanismus (AES-256 client-seitig,
|
||||
Keys pro Umgebung) verwenden.
|
||||
- Secrets-Register: AUTH_SECRET · MFA_ENC_KEY · PASSWORD_PEPPER · pgBackRest-Key · age-Keypair;
|
||||
je Umgebung getrennt, nie im Artefakt-Bucket, Offline-Kopie versiegelt.
|
||||
|
||||
4) ARBEITSWEISE:
|
||||
- Gate vor JEDEM Merge: tsc · lint · build · ALLE scripts/test-*.ts. Der Pepper braucht einen Test
|
||||
(hash+verify mit gesetztem Pepper; verify schlägt fehl bei falschem/fehlendem Pepper).
|
||||
- DevOps: lane-haertung → git merge --no-ff nach dev → Gate grün → Push auf BEIDE Remotes →
|
||||
STAND pflegen.
|
||||
|
||||
5) KOORDINATION: §9-Verschlüsselung gemeinsam mit Lane Backup (Mechanismus/Keys entschieden — einmal
|
||||
abstimmen). Pepper-Rollout NUR auf Umgebungen mit leerer/frischer DB (sonst Passwort-Reset nötig).
|
||||
|
||||
6) NICHT TUN: keine Auth-Logik-Änderung außer dem Pepper; keine Rotation eines gesetzten Peppers/
|
||||
MFA_ENC_KEY ohne expliziten Reset-Plan; Argon2-Parameter unverändert lassen.
|
||||
|
||||
Erste Schritte: (a) Pflichtlektüre + Fragen, (b) Pepper-PR-Plan (Env, verify-Wrapper, Test) +
|
||||
Bestätigung „Pepper jetzt setzen, DBs leer" einholen, (c) umsetzen. Warte nach (a)/(b).
|
||||
```
|
||||
@@ -1,58 +0,0 @@
|
||||
# Kickoff-Prompt — Lane Betreiber-Konsole-UX + i18n (certvia)
|
||||
|
||||
> Diesem Prompt einem Entwickler/Claude-Code-Agenten geben. Bootstrapt in certvia + diese Lane.
|
||||
|
||||
```text
|
||||
Du übernimmst die Lane „Betreiber-Konsole-UX + vollständige i18n" am Produkt „certvia" (ISMS-Tool,
|
||||
Multi-Tenant Next.js-16 / Prisma-7 / Postgres+RLS / Auth.js-v5). Repo: ~/Projects/ISMS-Tool, Branch `dev`.
|
||||
|
||||
WICHTIG: certvia ist strikt getrennt von jedem anderen Produkt (insb. „visitvia"). Nichts vermischen.
|
||||
|
||||
BRANCH/CHECKOUT:
|
||||
Arbeits-Branch: `lane-ui-i18n` (KEIN `feature/`-Prefix — origin-Namespace-Konflikt).
|
||||
git fetch origin && git checkout dev && git checkout -b lane-ui-i18n.
|
||||
Remotes: origin = https://git.certvia.de/msolarczek/certvia.git · local-gitea (intern).
|
||||
|
||||
1) PFLICHTLEKTÜRE:
|
||||
- docs/HANDOVER-DEV.md, docs/SPEC.md, docs/STAND-dev-branch.md
|
||||
- docs/KONZEPT-ui-i18n.md ← dein Fahrplan (Bugfix 1+2, Ergänzungen A/B)
|
||||
|
||||
2) AUFTRAG:
|
||||
BUGFIX 1 — Betreiber-Konsole (src/app/(platform)/admin/[id]/page.tsx):
|
||||
- Module → Popup (searchParam `?modules=1`, <Modal>); Benutzer → Popup (`?users=1`).
|
||||
Muster existiert bereits auf der Seite (?new/?edit/?audit) — analog kapseln.
|
||||
- Hauptfenster stattdessen: Stammdaten (aus TenantSettings) + Hauptkontakt sichtbar.
|
||||
Offene Kleinentscheidung: Hauptkontakt = neue Felder in TenantSettings vs. Ableitung aus
|
||||
tenant-admin — mit PM klären.
|
||||
BUGFIX 2 — Vollständige UI-Sprache + per-Mitarbeiter-Umschaltung:
|
||||
- BEFUND: messages/en.json existiert (~95%), aber src/i18n/request.ts ist HART auf "de"
|
||||
(Zeile 8). TenantSettings.locale steuert nur die Richtlinien-Import-Sprache, NICHT die UI.
|
||||
- Neu: Identity.uiLocale (de|en, Default de) — persönliche Präferenz, folgt der Person.
|
||||
- request.ts liest uiLocale der aktiven Session-Identity (Fallback de).
|
||||
- Umschalter im Nutzer-Menü (Header/Profil) → Server-Action setUiLocale → speichern + reload.
|
||||
- messages/en.json auf 100% prüfen/auffüllen; hartkodierte deutsche Strings in Komponenten
|
||||
aufspüren und in den Katalog überführen.
|
||||
ERGÄNZUNG A — Login: Organisationsfeld (`tenant`) aus src/app/login/page.tsx ENTFERNEN
|
||||
(nach Option C überflüssig; Mandant kommt über /select-tenant). login-ticket-Signaturen entschlacken.
|
||||
|
||||
3) VERBINDLICHE REGELN:
|
||||
- UI-Sprache (Identity.uiLocale, Person) und Vorlagen-Import-Sprache (TenantSettings.locale,
|
||||
Inhalt) sind ZWEI getrennte Achsen — nicht vermischen.
|
||||
- Popups über das bestehende searchParam/<Modal>-Muster, KEINE neue Modal-Infrastruktur.
|
||||
- Stammdaten haben EINE Quelle (TenantSettings) — keine Doppelpflege einführen.
|
||||
- RLS/Datenpfade unverändert; das ist eine reine UI-/Präferenz-Lane.
|
||||
|
||||
4) ARBEITSWEISE:
|
||||
- Gate vor JEDEM Merge: tsc · lint · build · ALLE scripts/test-*.ts.
|
||||
- UI-Verifikation im Browser: Betreiber-Popups (Module/Benutzer), Sprachumschaltung DE↔EN
|
||||
(Menü + Beschreibungen wechseln), Login ohne Organisationsfeld, /select-tenant unverändert.
|
||||
- DevOps: lane-ui-i18n → git merge --no-ff nach dev → Gate grün → Push auf BEIDE Remotes →
|
||||
STAND pflegen.
|
||||
|
||||
5) NICHT TUN: keine Änderung am Auth-Kern/an /select-tenant-Logik; Identity.uiLocale nur als
|
||||
Präferenzfeld ergänzen (keine Auth-Semantik).
|
||||
|
||||
Erste Schritte: (a) Pflichtlektüre + Fragen (v.a. Hauptkontakt-Feld), (b) PR-Plan je Bugfix
|
||||
(Migration Identity.uiLocale, request.ts, Menü-Switcher; Popup-Umbau admin/[id]), (c) umsetzen.
|
||||
Warte nach (a)/(b).
|
||||
```
|
||||
@@ -1,71 +0,0 @@
|
||||
# Übergabe-Prompt — Auth-Umbau „Zentrale Identität + Mandanten-Mitgliedschaften"
|
||||
|
||||
> Diesen Prompt einem neuen Entwickler bzw. dessen Claude-Code-Agenten geben. Er bootstrapt in certvia und diese Aufgabe. Zugehörige Dokumente liegen im selben Branch.
|
||||
|
||||
```text
|
||||
Du übernimmst Entwicklungsarbeit am Produkt „certvia" (ISMS-Tool, Multi-Tenant-
|
||||
Next.js-16 / Prisma-7 / Postgres+RLS / Auth.js-v5 SaaS). Repo: ~/Projects/ISMS-Tool,
|
||||
Integrationsbranch `dev`. Deine Aufgabe: den Auth-Umbau „Zentrale Identität mit
|
||||
Mandanten-Mitgliedschaften" (Option C) umsetzen.
|
||||
|
||||
BRANCH / CHECKOUT:
|
||||
Arbeits-/Doku-Branch: `identity-mandanten`
|
||||
- origin = https://git.certvia.de/msolarczek/certvia.git (Branch: identity-mandanten)
|
||||
- local-gitea = interner Spiegel (Branch: identity-mandanten)
|
||||
Auschecken: git fetch origin && git checkout identity-mandanten
|
||||
Die unten genannten docs/ liegen auf genau diesem Branch.
|
||||
|
||||
WICHTIG: certvia ist strikt getrennt von jedem anderen Produkt (insb. „visitvia").
|
||||
Nichts vermischen.
|
||||
|
||||
1) PFLICHTLEKTÜRE — erst lesen, nicht sofort coden, in dieser Reihenfolge:
|
||||
- docs/HANDOVER-DEV.md, docs/SPEC.md (Projektgrundlagen)
|
||||
- docs/STAND-dev-branch.md (aktueller Entwicklungsstand)
|
||||
- docs/UEBERGABE-identity-mandanten.md (Kurzübergabe zu genau dieser Aufgabe)
|
||||
- docs/FEINDESIGN-identity-mandanten.md (der umsetzbare Bauplan — dein Fahrplan)
|
||||
- docs/KONZEPT-identity-mandanten.md (Warum/was, getroffene Entscheidungen A–E)
|
||||
|
||||
2) AUFTRAG:
|
||||
Setze Option C um. Reihenfolge = die Workstreams/Meilensteine aus dem FEINDESIGN.
|
||||
Beginne mit WS0 (Fundament): neues globales `Identity`-Modell, Schema-Recut von
|
||||
`User` zur Mitgliedschaft (+identityId), Migration, `TENANT_MODELS` anpassen,
|
||||
Reseed. WS0 ist Blocker — bau es als Pairing und lass es reviewen.
|
||||
|
||||
3) VERBINDLICHE REGELN (aus dem FEINDESIGN, nicht verhandelbar):
|
||||
- `User.id` = Mitgliedschaft, STABIL lassen; Auth-Felder wandern auf `Identity`.
|
||||
- `Identity` ist GLOBAL: NICHT in `TENANT_MODELS`, kein tenant_id, keine RLS-Policy.
|
||||
- Genau EIN aktiver Mandant pro Session; `session.user.tenantId` = aktiver Mandant;
|
||||
server-autoritativ; bei Mandantenwechsel Membership+MFA re-validieren.
|
||||
- Nutzeranlage NUR per Einladung (kein „Passwort direkt setzen" mehr).
|
||||
- MFA/Passwort gehören der Identity — KEIN Mandanten-Admin-Reset.
|
||||
- MFA beim Login als 2. Schritt (erst E-Mail+Passwort, dann MFA); dazwischen KEINE
|
||||
volle Session (kurzlebiger MFA-pending-State).
|
||||
- Plattform-Admins (`platform_admins`) bleiben getrennt — nicht anfassen.
|
||||
|
||||
4) ARBEITSWEISE:
|
||||
- Validierungs-Gate vor JEDEM PR/Merge: `npx tsc --noEmit`, `npm run lint`,
|
||||
`npm run build`, und ALLE `scripts/test-*.ts` müssen grün sein. Jede Story bringt
|
||||
ihren eigenen Test mit (Identity-Login, Tenant-Switch-Isolation, MFA-Enforcement
|
||||
multi-tenant, Einladung, Two-Step-Bypass).
|
||||
- DevOps: Feature-Branch → `git merge --no-ff` nach `dev` → Gate grün →
|
||||
Push auf BEIDE Remotes (origin=git.certvia.de, local-gitea) →
|
||||
docs/STAND-dev-branch.md pflegen.
|
||||
- Definition of Done: siehe FEINDESIGN §9.
|
||||
|
||||
5) KOORDINATION:
|
||||
Parallel läuft „Richtlinien-Upload im Adminportal". Funktional unabhängig, ABER
|
||||
beide editieren src/app/(platform)/admin/[id]/page.tsx (Policy-Upload = Module-Karte,
|
||||
Identity-Umbau = Benutzerverwaltung). Reihenfolge auf dieser Datei abstimmen.
|
||||
|
||||
6) NICHT TUN:
|
||||
- Getroffene Entscheidungen A–E nicht umwerfen (bei echtem Problem eskalieren, nicht
|
||||
eigenmächtig ändern).
|
||||
- Phase-2-Punkte (per-Mandant „immer Step-up", E-Mail-Änderung als Identity-Op,
|
||||
PlatformAdmin-Konsolidierung) sind bewusst ausgeklammert — nicht mitbauen.
|
||||
- Keine Datenmigration bauen: es gibt nur Testdaten → Schema-Recut + Reseed.
|
||||
|
||||
Erste Schritte: (a) Pflichtlektüre lesen und mir eine 10-Zeilen-Zusammenfassung +
|
||||
offene Fragen zurückgeben, (b) WS0 als PR-Plan skizzieren (Schema-Diff, Migrationen,
|
||||
TENANT_MODELS-Änderung, Reseed), (c) nach Freigabe umsetzen. Warte nach (a)/(b) auf
|
||||
Bestätigung, bevor du WS0 mergst.
|
||||
```
|
||||
@@ -1,43 +0,0 @@
|
||||
# Übergabe-Prompt: Kundenbetreuung certvia
|
||||
|
||||
**Zweck:** Onboarding eines neuen Kundenbetreuers (Customer Success/Support). Kann direkt gelesen oder einem KI-Assistenten (z. B. Claude) als Kontext-Prompt gegeben werden. Hauptquelle im Detail: `docs/HANDBUCH-KUNDENBETREUUNG.md`.
|
||||
|
||||
---
|
||||
|
||||
Rolle: Du übernimmst die Kundenbetreuung (Customer Success/Support) für „certvia" — ein Multi-Mandanten-ISMS-Tool (Informationssicherheits-Managementsystem als SaaS). Ziel: certvia-Kunden onboarden, betreuen und im Alltag unterstützen.
|
||||
|
||||
Was ist certvia (in einem Satz):
|
||||
Jeder Kunde ist ein eigener Mandant mit strikt getrennten Daten. Das Tool führt Kunden von der Strukturanalyse (Assets/Prozesse/Lieferanten) über Risikomanagement, Richtlinien und Maßnahmen bis zur Audit-Vorbereitung — wahlweise nach TISAX (VDA-ISA) und/oder ISO 27001.
|
||||
|
||||
Deine ersten Schritte (Woche 1):
|
||||
1. Lies das Handbuch: docs/HANDBUCH-KUNDENBETREUUNG.md (im Projekt-Repo). Es ist deine Hauptquelle.
|
||||
2. Klick die Demo-/Testinstanz komplett durch — am besten lernt man das Produkt hands-on:
|
||||
- Mandanten-Login /login: admin@demo.example / Demo1234!
|
||||
- Superadmin /platform/login (MFA-Einrichtung beim ersten Login).
|
||||
- Schau alle Module an: Assets, Prozesse, Risiken, Lieferanten, Maßnahmen, Richtlinien, SoA, Audit-Readiness, Vorfälle, Aufgaben.
|
||||
3. Verstehe die Framework-Wahl: ein Mandant kann ISO 27001 und/oder TISAX führen (in der Admin-Konsole je Mandant aktivierbar). Unterschiede stehen im Handbuch (TISAX = Reifegrad/AL2/AL3; ISO = Anwendbarkeitserklärung/SoA + Managementklauseln).
|
||||
|
||||
Deine Kernaufgaben:
|
||||
- Neue Kunden beim Onboarding begleiten (Stammdaten, Framework-Wahl, Onboarding-Wizard, Erfassung der Bestandsdaten).
|
||||
- Support im Alltag: Login/MFA/Passwort, Rollen & Rechte, Module, Vorlagen/Richtlinien.
|
||||
- Fachliche Beratung „welche Norm passt" (ISO vs. TISAX) auf Basis des Handbuchs.
|
||||
|
||||
Typische Support-Fälle (Details im Handbuch §7):
|
||||
- „Anmeldung fehlgeschlagen": richtige Seite (/login vs /platform/login), Passwort exakt, ggf. kurze Sperre nach 5 Fehlversuchen (15 Min).
|
||||
- „MFA-Gerät verloren": Recovery-Codes; sonst MFA administrativ zurücksetzen.
|
||||
- „Modul fehlt": in der Admin-Konsole für den Mandanten aktivieren.
|
||||
- „ISO/TISAX fehlt": Framework des Mandanten prüfen/aktivieren.
|
||||
|
||||
Grenzen & Eskalation (wichtig):
|
||||
- Niemals Kundendaten zwischen Mandanten kopieren (Mandantentrennung/Datenschutz).
|
||||
- Keine eigenmächtigen Löschungen an Produktivdaten; keine Secrets per E-Mail/Chat weitergeben.
|
||||
- Bei technischen Themen (Deployment, Fehlermeldungen im Betrieb, Backups, TLS/Domain, Datenbank) an das DevOps-/Entwicklerteam eskalieren — nicht selbst am Produktivsystem eingreifen.
|
||||
|
||||
Wo du alles findest:
|
||||
- Handbuch: docs/HANDBUCH-KUNDENBETREUUNG.md
|
||||
- Produkt/Funktionsumfang: docs/SPEC.md, docs/HANDOVER-PM.md
|
||||
- Feature-Konzepte: docs/KONZEPT-framework-iso27001.md (ISO/TISAX)
|
||||
- Kundennahe Mockups (im Browser): docs/ISMS-Prototyp-GEFIM.html, docs/ISMS-Lieferantenmanagement-GEFIM.html
|
||||
- Aktueller Stand: docs/STAND-dev-branch.md
|
||||
|
||||
Arbeitsweise: Wenn du unsicher bist, prüfe zuerst im Handbuch und in der Demo-Instanz. Dokumentiere wiederkehrende Support-Fälle, damit das Handbuch wächst.
|
||||
-310
@@ -1,310 +0,0 @@
|
||||
# ISMS-Plattform – Umsetzungsspezifikation
|
||||
|
||||
> **Version 1.2** · Ergänzt gegenüber 1.1: **Assets & BIA als ein gemeinsames Modul**, zugeordnete Risiken in Asset-/Prozess-Detailansichten, ausgearbeitete **Risiko-Detailansicht** (Maßnahmen, betroffene Assets, Control-Verknüpfung, Verlauf).
|
||||
>
|
||||
> Diese Datei ist die Projekt-Spec für die Umsetzung durch Claude Code.
|
||||
> Sie beschreibt **Architektur, Datenmodell, Module, Rollen, API und Akzeptanzkriterien**.
|
||||
> Sprache der Anwendung: **Deutsch (i18n-fähig, EN vorbereitet)**.
|
||||
|
||||
## 0. Kontext & Leitentscheidungen
|
||||
|
||||
Es wird eine Web-Applikation zum Betrieb eines Informationssicherheits-Managementsystems (ISMS) entwickelt, die von mehreren Kunden (Mandanten) mit mehreren Nutzern und Rollen genutzt wird. Ausrichtung auf **ISO/IEC 27001:2022** und **TISAX / VDA-ISA 6.0**.
|
||||
|
||||
Getroffene Entscheidungen (aus Anforderungsklärung):
|
||||
|
||||
| Thema | Entscheidung |
|
||||
|---|---|
|
||||
| Betriebsmodell | Zentrale SaaS, **Multi-Tenant** (gemeinsame DB, Mandanten-ID + strikte Row-Level-Trennung) |
|
||||
| Container | Betrieb in Docker (Compose), horizontal skalierbar |
|
||||
| KI / Assistent + Chat | **Cloud-LLM** (Anthropic/OpenAI) über austauschbaren Provider-Adapter |
|
||||
| Tech-Stack | Modernes Web-Frontend, Technologie offen → **empfohlener Stack unten** |
|
||||
| Authentifizierung | **Lokale Accounts (MVP)** mit RBAC; SSO (OIDC/SAML) als spätere Erweiterung vorbereiten |
|
||||
| Umfang | Alle Module gleichwertig (kein hartes Phasing), aber sinnvolle Iterationsreihenfolge |
|
||||
| Norm-Inhalte | **ISO 27001:2022 Annex A (93 Controls)** vorbefüllt + SoA; **VDA-ISA** Struktur/Mapping vorbereitet, Katalog-Inhalte per Import (lizenzrechtlich, siehe §12) |
|
||||
| Sprache | Deutsch, i18n-ready |
|
||||
| UX | Modern, einfach, geringe Komplexität, Drag-and-Drop, grafische Oberflächen |
|
||||
|
||||
## 1. Empfohlener Tech-Stack
|
||||
|
||||
Ziel: **eine** Codebasis, geringe Betriebs- und Wartungskomplexität, moderne UX.
|
||||
|
||||
- **Frontend & Backend:** Next.js 15 (App Router, React 19, TypeScript) — SSR + API in einem Deployment.
|
||||
- **API-Layer:** tRPC (typsicher) oder REST (OpenAPI). Empfehlung: tRPC intern, zusätzlich schlanke REST-Endpunkte für Integrationen/Webhooks.
|
||||
- **ORM/DB:** Prisma + **PostgreSQL 16**. Vektorsuche für den Chat/RAG über **pgvector** (kein zusätzlicher Vektor-DB-Dienst nötig).
|
||||
- **Auth:** Auth.js (NextAuth) mit Credentials-Provider (lokale Accounts), Argon2id-Hashing, TOTP-2FA. OIDC/SAML-Provider als Feature-Flag vorbereitet.
|
||||
- **Hintergrundjobs / wiederkehrende Aufgaben:** BullMQ + Redis (Scheduler für Reviews, Audits, Fristen, Erinnerungen).
|
||||
- **Dateispeicher:** S3-kompatibel (MinIO im Compose-Stack), verschlüsselt.
|
||||
- **UI-Kit:** Tailwind CSS + shadcn/ui, Icons via lucide-react, Diagramme via Recharts.
|
||||
- **Drag-and-Drop:** dnd-kit (Kanban-Boards, Risiko-Matrix-Einordnung, Aufgaben, Datei-Uploads).
|
||||
- **KI-Anbindung:** Provider-Adapter (`AiProvider`-Interface) für Anthropic/OpenAI; RAG-Pipeline auf Dokumenten des Mandanten.
|
||||
- **E-Mail:** SMTP (Benachrichtigungen, Fristen, Eskalationen).
|
||||
- **Tests:** Vitest (Unit), Playwright (E2E). Linting: ESLint + Prettier.
|
||||
|
||||
> Alternative bei starkem KI-/Analytics-Fokus: zusätzlicher **Python-FastAPI-Microservice** nur für RAG/Embedding. Für geringe Komplexität zunächst **nicht** empfohlen — alles in Next.js.
|
||||
|
||||
## 2. Architektur (High-Level)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
Browser ───▶ │ Next.js (App Router) │
|
||||
(DE UI) │ - React UI (Tailwind + shadcn/ui, dnd-kit) │
|
||||
│ - tRPC/REST API │
|
||||
│ - Auth.js (RBAC, Mandanten-Guard) │
|
||||
└───────┬───────────────┬──────────────┬───────┘
|
||||
│ │ │
|
||||
Prisma BullMQ AiProvider
|
||||
│ (Worker) (Adapter)
|
||||
┌───────▼───────┐ ┌───▼────┐ ┌────▼─────────┐
|
||||
│ PostgreSQL 16 │ │ Redis │ │ Anthropic / │
|
||||
│ + pgvector │ │ │ │ OpenAI API │
|
||||
└───────────────┘ └────────┘ └──────────────┘
|
||||
┌───────────────┐
|
||||
│ MinIO (S3) │ Dokumente, Nachweise, Uploads
|
||||
└───────────────┘
|
||||
```
|
||||
|
||||
**Mandantenfähigkeit (Multi-Tenant):** Jede fachliche Tabelle trägt `tenant_id`. Zugriff ausschließlich über einen zentralen Prisma-Middleware-/Query-Guard, der `tenant_id` aus der Session erzwingt (Row-Level-Isolation). Zusätzlich Postgres **Row Level Security (RLS)** als zweite Verteidigungslinie. Kein Query ohne Mandantenkontext.
|
||||
|
||||
## 3. Rollen- und Rechtemodell (RBAC)
|
||||
|
||||
Rollen sind pro Mandant vergeben. Ein Nutzer kann mehrere Rollen haben.
|
||||
|
||||
| Rolle | Beschreibung | Kernrechte |
|
||||
|---|---|---|
|
||||
| **Plattform-Admin** (mandantenübergreifend) | Betreiber der SaaS | Mandanten anlegen/sperren, globale Kataloge pflegen, keine Einsicht in Kundendaten außer für Support (protokolliert) |
|
||||
| **Mandanten-Admin** | Kundenadministrator | Nutzer/Rollen im Mandanten verwalten, Stammdaten, Konfiguration |
|
||||
| **ISB / CISO** | Informationssicherheitsbeauftragter | Vollzugriff fachlich: Risiken, Assets, BIA, Maßnahmen, Vorfälle, Freigaben, Chat-Eskalationsziel |
|
||||
| **Auditor** (intern/extern) | Prüfer | Lesezugriff + Audit-Durchführung, Findings anlegen, keine Bearbeitung der Fachdaten |
|
||||
| **Asset-/Risk-Owner** | Fachverantwortliche | Bearbeitung zugewiesener Assets/Risiken/Maßnahmen |
|
||||
| **Mitarbeiter / User** | Standardnutzer | Chat nutzen, Richtlinien lesen, Vorfälle melden, eigene Aufgaben |
|
||||
|
||||
Rechte werden als granulare **Permissions** (`asset:read`, `risk:write`, `incident:manage`, …) implementiert und über Rollen gebündelt. UI blendet nicht-erlaubte Aktionen aus; API prüft serverseitig.
|
||||
|
||||
## 4. Module (funktionaler Kern)
|
||||
|
||||
### 4.1 Assets & BIA (ein gemeinsames Modul)
|
||||
|
||||
Asset-Inventar und Business Impact Analyse bilden **ein zusammenhängendes Modul** (gemeinsamer Navigationsbereich, durchgängige Detailansichten). Assets, Prozesse und deren Kritikalität werden im selben Kontext gepflegt.
|
||||
|
||||
#### 4.1.1 Asset-Inventar
|
||||
Zentrales Verzeichnis aller Werte (Assets): Informationen, Systeme, Anwendungen, Standorte, Lieferanten, Personen/Rollen, Datenkategorien.
|
||||
|
||||
- Attribute: Name, Typ, Owner, Standort/Prozesszuordnung, Klassifizierung (C/I/A — Vertraulichkeit/Integrität/Verfügbarkeit als Schutzbedarf 1–4), Lieferanten/Verantwortliche, Status, Tags.
|
||||
- Beziehungen zwischen Assets (Abhängigkeiten) modellierbar → speist BIA und Risiko.
|
||||
- Import/Export (Excel/CSV), Bulk-Bearbeitung, Versionshistorie.
|
||||
- **Grafische Ansicht:** filterbare Tabelle + optionale Abhängigkeits-/Netzwerkgrafik.
|
||||
- **Asset-Detailansicht** zeigt neben Stammdaten und Beziehungen auch:
|
||||
- **Zugeordnete Risiken** (mit Risikowert, Status, Behandlung) inkl. Absprung in die Risiko-Detailansicht,
|
||||
- zugeordnete Prozesse (mit Rolle primär/sekundär) und daraus vererbter Schutzbedarf,
|
||||
- verknüpfte Maßnahmen, Vorfälle und Nachweise.
|
||||
|
||||
#### 4.1.2 Business Impact Analyse (BIA)
|
||||
Ermittelt Kritikalität von Prozessen/Assets und Wiederanlaufparameter.
|
||||
|
||||
- Erfassung von Geschäftsprozessen, Zuordnung zu Assets.
|
||||
- **Asset-Rollen je Prozess (Detailansicht):** In der Prozess-Detailansicht werden die zugeordneten Assets nach Rolle unterschieden:
|
||||
- **Primäres Asset** = das im Prozess erzeugte/verantwortete Ergebnis-Asset (z. B. der erzeugte Datensatz/das Informationsobjekt). Genau ein oder wenige je Prozess.
|
||||
- **Sekundäre Assets** = alle unterstützenden Assets, die zur Prozessdurchführung benötigt werden (Systeme, Anwendungen, Infrastruktur, Personen/Rollen, Lieferanten).
|
||||
- Die Rollenzuordnung speist die Abhängigkeitsanalyse (siehe 4.11) und die Schutzbedarfsvererbung: Der Schutzbedarf des primären Assets/Prozesses vererbt sich auf die sekundären Assets (max. Prinzip).
|
||||
- Schadensszenarien und Schadenshöhe je Schutzziel und Zeitverlauf.
|
||||
- Kennzahlen: **RTO, RPO, MTD/MTPD**, maximal tolerierbarer Ausfall.
|
||||
- Ergebnis: Kritikalitätsstufe je Prozess/Asset → priorisiert Risikoanalyse und Maßnahmen.
|
||||
- **Prozess-Detailansicht** zeigt zusätzlich die **zugeordneten Risiken** des Prozesses und seiner Assets (aggregiert, mit Risikowert und Status).
|
||||
- Geführter Wizard (Schritt-für-Schritt), Ergebnis als Report exportierbar.
|
||||
|
||||
### 4.2 Risikoanalyse & -behandlung
|
||||
Aufbauend auf Assets + BIA.
|
||||
|
||||
- Risiken = (Asset/Prozess) × Bedrohung × Schwachstelle.
|
||||
- Bewertung: Eintrittswahrscheinlichkeit × Auswirkung → Risikowert; konfigurierbare Skalen (z. B. 5×5).
|
||||
- **Interaktive Risiko-Matrix (Heatmap)** mit Drag-and-Drop-Einordnung/Filter.
|
||||
- Risikobehandlung: Vermeiden / Vermindern / Übertragen / Akzeptieren; Maßnahmen (Controls) verknüpfen.
|
||||
- Rest-Risiko nach Maßnahme, Risikoakzeptanz mit Freigabe-Workflow (ISB/Leitung).
|
||||
- Vererbung: Schutzbedarf aus Asset/BIA wird vorbelegt.
|
||||
- Verknüpfung zu ISO-27001-Annex-A-Controls und VDA-ISA-Zielen (SoA-Bezug).
|
||||
- **Risiko-Detailansicht (vollständig):**
|
||||
- Stammdaten: Beschreibung, Bedrohung/Schwachstelle, Owner, Status, Termine/Reviews.
|
||||
- Bewertung: Brutto-Risiko (Wahrscheinlichkeit × Auswirkung), **Rest-Risiko** nach Maßnahmen, Bewertungshistorie (Verlauf des Risikowerts über Zeit).
|
||||
- **Notwendige/verknüpfte Maßnahmen:** Liste der behandelnden Maßnahmen mit Status, Fälligkeit und Owner; neue Maßnahme direkt aus dem Risiko heraus anlegbar.
|
||||
- **Betroffene Assets/Prozesse:** alle verknüpften Assets und Prozesse mit Schutzbedarf/Kritikalität, Absprung in deren Detailansichten.
|
||||
- Verknüpfte Annex-A-Controls / VDA-ISA-Ziele (SoA-Bezug) und ggf. auslösende Vorfälle.
|
||||
- Freigabe-/Akzeptanz-Workflow mit Kommentar und Audit-Trail.
|
||||
|
||||
### 4.3 Control-Kataloge & Statement of Applicability (SoA)
|
||||
- **ISO 27001:2022 Annex A** mit 93 Controls in 4 Themen (Organisatorisch 37, Personenbezogen 8, Physisch 14, Technologisch 34) **vorbefüllt**.
|
||||
- **SoA:** je Control Anwendbarkeit (ja/nein + Begründung), Umsetzungsstatus, Verweise auf Maßnahmen/Nachweise, Verantwortliche.
|
||||
- **VDA-ISA 6.0**: 9 Kapitel/Prüfziele als Struktur + Mapping-Tabelle ISO↔VDA-ISA (siehe §12 zur Lizenz).
|
||||
- Reifegrad-Bewertung (VDA-ISA-Reifegradmodell 0–5) je Prüfziel.
|
||||
|
||||
### 4.4 Maßnahmenverwaltung (Controls/Tasks)
|
||||
- Maßnahmen mit Owner, Fälligkeit, Status, Priorität, Nachweisen (Dateien).
|
||||
- **Kanban-Board (Drag-and-Drop)** und Listen-/Kalenderansicht.
|
||||
- Verknüpfung zu Risiken, Controls, Vorfällen, Audits.
|
||||
- **Maßnahmen-Detailansicht** zeigt die **zugeordneten Risiken** (welche Risiken behandelt diese Maßnahme, mit Risikowert vor/nach) sowie verknüpfte Controls, Vorfälle und Nachweise.
|
||||
|
||||
### 4.5 Wiederkehrende Aufgaben & Fristen (Scheduler)
|
||||
Automatische Erzeugung/Erinnerung für u. a.:
|
||||
- **Benutzer-/Zugriffs-Review** (z. B. quartalsweise),
|
||||
- **Interne Audits** und **externe Audits/Re-Zertifizierung** (Zyklen),
|
||||
- **Management-Review**, Richtlinien-Review, Risiko-Review, Lieferanten-Review.
|
||||
- Konfigurierbare Wiederholung (cron-artig), Zuweisung, Eskalation bei Überfälligkeit, E-Mail-Benachrichtigung, Dashboard-Fälligkeitsanzeige.
|
||||
|
||||
### 4.6 Richtlinien-Management & Implementierungs-Assistent
|
||||
- Richtlinien-Bibliothek mit Versionierung, Freigabe- und Lese-Bestätigungs-Workflow.
|
||||
- **KI-Assistent** führt Nutzer durch die Anpassung von Muster-Richtlinien an das eigene Unternehmen.
|
||||
- **Zwei Individualisierungs-Ebenen:**
|
||||
1. **Basisdaten/Metadaten:** Firmenname, verantwortliche Rollen, Geltungsbereich, Platzhalter.
|
||||
2. **Inhaltliche Anpassung der Klauseln:** Die KI formuliert und passt die eigentlichen Richtlinientexte (Klauseln/Abschnitte) auf Basis der Unternehmensangaben an (z. B. erlaubte Geräte, Fristen, Verantwortlichkeiten, branchenspezifische Anforderungen). Vorschläge sind akzeptier-/verwerfbar.
|
||||
- **Inline-Editor (WYSIWYG):** Nutzer bearbeiten die generierten Klauseltexte direkt im Tool; KI-Assistenz („umformulieren", „kürzen", „an Control X ausrichten") auf Absatzebene.
|
||||
- **In-Tool-Darstellung:** Die Richtlinie wird innerhalb der Anwendung gerendert lesbar dargestellt (formatierte Ansicht, Inhaltsverzeichnis, verknüpfte Controls), nicht nur als Download.
|
||||
- **Governance:** Versionierung mit Änderungsverlauf/Diff, Freigabe-Workflow, Lesebestätigung durch Mitarbeiter, Verknüpfung zu ISO-/VDA-Controls.
|
||||
- Export als PDF/DOCX; Ablage in der Richtlinien-Bibliothek; Anbindung an den Chat (RAG) als Wissensquelle.
|
||||
|
||||
### 4.7 Interaktiver Chat (RAG + Eskalation)
|
||||
- Nutzer stellen Fragen; der Chat sucht per **RAG** in der Dokumentation/Richtlinien des Mandanten (pgvector) und antwortet mit Quellenangabe.
|
||||
- Wenn keine belastbare Antwort/Berechtigung → **Eskalation/Ticket an den ISB** (Weiterleitung, Benachrichtigung, Nachverfolgung).
|
||||
- Nur mandanten-eigene Dokumente im Kontext; keine mandantenübergreifende Vermischung.
|
||||
|
||||
### 4.8 Sicherheitsvorfall-Management (Incident)
|
||||
- Meldung von Vorfällen (auch niedrigschwellig durch Mitarbeiter, Formular + Chat).
|
||||
- Workflow: Erfassung → Triage/Kategorisierung → Bearbeitung → Eskalation → Abschluss → Lessons Learned.
|
||||
- Schweregrad, betroffene Assets, SLA/Fristen, Aufgaben, Zeitleiste, Nachweise.
|
||||
- Verknüpfung zu Risiken (neue/erhöhte Risiken) und ggf. Meldepflichten-Hinweis.
|
||||
|
||||
### 4.9 Dashboards & Reporting
|
||||
- Rollenbezogene Dashboards (ISB, Auditor, Owner): offene Risiken, überfällige Aufgaben, SoA-Erfüllungsgrad, Reifegrade, Vorfälle.
|
||||
- Exporte: SoA, Risikoregister, Maßnahmenplan, Audit-Report, Management-Review — als PDF/Excel.
|
||||
|
||||
### 4.10 Audit-Management
|
||||
- Audit-Plan (intern/extern), Scope, Prüfpunkte (aus Katalogen), Findings, Maßnahmen aus Findings, Nachverfolgung, Audit-Report.
|
||||
|
||||
### 4.11 Abhängigkeits- & Kritische-Pfade-Analyse
|
||||
Visualisiert die Verkettung von Prozessen und Assets, um Single Points of Failure und kritische Pfade sichtbar zu machen.
|
||||
|
||||
- **Netzwerkgraph:** Knoten = Prozesse und Assets (primär/sekundär), Kanten = Abhängigkeiten (aus Asset-Relationen und BIA-Rollenzuordnung).
|
||||
- **Kritische Pfade** werden anhand von Kritikalität/Schutzbedarf (aus BIA) berechnet und farblich hervorgehoben; Engstellen (Assets, von denen viele kritische Prozesse abhängen) werden markiert.
|
||||
- Interaktiv: Filtern nach Prozess/Kritikalität, Knoten anklicken → Detail/Sprung zum Asset, Hervorheben aller abhängigen Elemente.
|
||||
- Speist Risikoanalyse (Konzentrationsrisiken) und BCM/Notfallplanung.
|
||||
- Umsetzungshinweis: Rendering mit einer Graph-Bibliothek (z. B. Cytoscape.js oder D3-Force); Datenbasis sind `AssetRelation` und die BIA-Primär-/Sekundär-Zuordnung.
|
||||
|
||||
### 4.12 Nachweis- & Dokumentenmanagement
|
||||
- Zentrale, auditfeste Ablage für Nachweise/Evidenzen (Dateien, Screenshots, Protokolle).
|
||||
- Verknüpfung eines Nachweises mit Controls (SoA), Maßnahmen, Audits, Risiken und Vorfällen.
|
||||
- Metadaten: Gültigkeit/Ablaufdatum, Verantwortliche, Version, Vertraulichkeit; Erinnerung bei ablaufenden Nachweisen.
|
||||
- Volltext-/Metadatensuche; Nachweise sind Quelle für den RAG-Chat.
|
||||
|
||||
### 4.13 Lieferanten- & Dienstleister-Management (Third-Party)
|
||||
Für TISAX besonders relevant.
|
||||
|
||||
- Verzeichnis externer Dienstleister/Lieferanten mit Kontakt, Leistungen, Kritikalität.
|
||||
- Sicherheitsbewertung/Fragebögen, Zertifikatsnachweise (z. B. ISO 27001/TISAX-Label), Ablaufüberwachung.
|
||||
- Vertrags-/AV-Verwaltung (DSGVO Art. 28), Wiedervorlage/Review-Zyklen (siehe wiederkehrende Aufgaben).
|
||||
- Verknüpfung zu Assets (welcher Dienstleister betrifft welche Assets) und Risiken (Third-Party-Risiko).
|
||||
|
||||
### 4.14 Management-Review & Kennzahlen (KPIs)
|
||||
ISO-27001-Pflichtthemen zur Wirksamkeitsmessung.
|
||||
|
||||
- Definierbare Kennzahlen/Metriken (z. B. SoA-Erfüllungsgrad, offene Risiken, Reaktionszeiten Vorfälle, überfällige Aufgaben, Reifegradentwicklung) mit Zielwerten und Trend.
|
||||
- Strukturierte **Management-Review**-Vorlage (Eingaben, Ergebnisse, Beschlüsse, Verantwortliche, Termine) mit Historie.
|
||||
- Wirksamkeitsbewertung von Maßnahmen; Export als Management-Report (PDF).
|
||||
|
||||
## 5. Datenmodell (Kern-Entitäten, vereinfacht)
|
||||
|
||||
Alle fachlichen Tabellen enthalten `tenant_id`, `created_at`, `updated_at`, `created_by`.
|
||||
|
||||
- **Tenant**(id, name, status, config)
|
||||
- **User**(id, tenant_id, email, password_hash, name, status, mfa_secret)
|
||||
- **Role**(id, tenant_id, key, name) / **Permission** / **UserRole** / **RolePermission**
|
||||
- **Asset**(id, tenant_id, name, type, owner_id, classification_c/i/a, status, tags)
|
||||
- **AssetRelation**(asset_id, related_asset_id, type)
|
||||
- **Process**(id, tenant_id, name, owner_id) — BIA-Bezug
|
||||
- **ProcessAsset**(id, tenant_id, process_id, asset_id, **role** = `primary` | `secondary`) — Asset-Rolle je Prozess (BIA)
|
||||
- **BiaEntry**(id, tenant_id, process_id, rto, rpo, mtd, impact_scores, criticality)
|
||||
- **Threat** / **Vulnerability** (Kataloge, teils global)
|
||||
- **Risk**(id, tenant_id, asset_id/process_id, threat_id, likelihood, impact, score, treatment, residual_score, owner_id, status)
|
||||
- **RiskAsset**(risk_id, asset_id) — n:m betroffene Assets je Risiko (zusätzlich zum Hauptbezug)
|
||||
- **RiskMeasure**(risk_id, measure_id) — n:m Risiko ↔ behandelnde Maßnahmen
|
||||
- **Control**(id, framework, ref, title, theme) — global (ISO/VDA)
|
||||
- **Soa**(id, tenant_id, control_id, applicable, justification, status, maturity, owner_id)
|
||||
- **Measure/Task**(id, tenant_id, title, owner_id, due_date, status, priority, links[])
|
||||
- **RecurringTask**(id, tenant_id, type, schedule_cron, next_run, assignee)
|
||||
- **Policy**(id, tenant_id, title, version, status, body, ack_required)
|
||||
- **Document/Evidence**(id, tenant_id, name, storage_key, embedding[] via pgvector)
|
||||
- **ChatSession/ChatMessage**(…, sources[], escalated_to_isb)
|
||||
- **Incident**(id, tenant_id, title, severity, status, category, affected_assets[], timeline[])
|
||||
- **Audit**(id, tenant_id, type, scope, planned_date) / **Finding**(…)
|
||||
- **Supplier**(id, tenant_id, name, criticality, contract_ref, av_status, cert_status, cert_expiry, review_cron) / **SupplierAsset**(supplier_id, asset_id)
|
||||
- **Kpi**(id, tenant_id, name, target, unit) / **KpiValue**(kpi_id, period, value)
|
||||
- **ManagementReview**(id, tenant_id, date, inputs, results, decisions, owner_id)
|
||||
- **AuditLog**(id, tenant_id, actor, action, entity, before/after, timestamp)
|
||||
|
||||
## 6. API-Design (Auszug)
|
||||
|
||||
REST-/tRPC-Ressourcen je Modul mit CRUD + Aktionen:
|
||||
`/assets`, `/bia`, `/risks`, `/controls`, `/soa`, `/measures`, `/recurring-tasks`, `/policies`, `/chat`, `/incidents`, `/audits`, `/reports`, `/admin/tenants`, `/admin/users`.
|
||||
|
||||
Querschnitt: `GET /export/{modul}` (Excel/PDF), `POST /import/{modul}` (Excel/CSV), Webhooks für Fristen/Eskalationen. Jede Anfrage: Auth-Guard → Mandanten-Guard → Permission-Check → Handler → AuditLog.
|
||||
|
||||
## 7. Nicht-funktionale Anforderungen
|
||||
|
||||
- **Sicherheit:** Verschlüsselung at-rest (DB/Objektspeicher) und in-transit (TLS), Argon2id-Passwörter, TOTP-2FA, Session-Härtung, CSRF-/XSS-/SQLi-Schutz, striktes RBAC + Mandanten-Isolation (RLS), vollständiges Audit-Log.
|
||||
- **Datenschutz (DSGVO):** Auftragsverarbeitung, Löschkonzept, Datenminimierung; für Cloud-LLM: DPA mit KI-Anbieter, konfigurierbares Opt-out des Trainings, optionale Anonymisierung sensibler Felder vor KI-Aufruf.
|
||||
- **Performance:** Listen mit Server-Pagination/Filter; Zielantwortzeit < 300 ms für Standardabfragen.
|
||||
- **Verfügbarkeit:** Stateless App-Container (horizontal skalierbar), Backups DB + Objektspeicher, Health-/Readiness-Endpunkte.
|
||||
- **Barrierefreiheit & UX:** WCAG-AA-orientiert, responsive, konsistente Komponenten, geringe Klicktiefe.
|
||||
- **i18n:** Alle UI-Texte über Message-Katalog (de default, en vorbereitet).
|
||||
- **Nachvollziehbarkeit:** Versionierung von Richtlinien, Risiken, SoA; lückenloses Änderungsprotokoll (auditfest).
|
||||
|
||||
## 8. Deployment (Docker)
|
||||
|
||||
`docker-compose.yml` mit Services: `app` (Next.js), `worker` (BullMQ), `postgres` (pgvector-Image), `redis`, `minio`, optional `mailhog` (Dev). Konfiguration über `.env` (DB, Redis, S3, SMTP, `AI_PROVIDER`, `AI_API_KEY`). Migrations via Prisma. Seed-Skript befüllt globale Kataloge (ISO Annex A, VDA-ISA-Struktur, Threat-/Vuln-Beispiele) und einen Demo-Mandanten.
|
||||
|
||||
## 9. UX-Leitlinien
|
||||
|
||||
Modern, aufgeräumt, geringe Komplexität. Konsequenter Einsatz von: geführten Wizards (BIA, Richtlinien-Assistent), **Drag-and-Drop** (Kanban für Maßnahmen/Aufgaben, Risiko-Heatmap, Datei-Uploads), grafischen Auswertungen (Heatmaps, Reifegrad-Radar, Fortschrittsbalken), Inline-Bearbeitung und klaren, rollenbezogenen Startseiten. Fachbegriffe mit Tooltips erklärt.
|
||||
|
||||
Das HTML-Mockup (`docs/ISMS-Prototyp-GEFIM.html`) dient als **Orientierung** für Navigation, Layout und Views — die Module werden fachlich darüber hinaus vervollständigt (z. B. Risiko-Verknüpfungen in Detailansichten, siehe §4).
|
||||
|
||||
## 10. Akzeptanzkriterien (Definition of Done je Modul)
|
||||
|
||||
- Ein Nutzer eines Mandanten sieht **niemals** Daten eines anderen Mandanten (durch Test nachgewiesen: RLS + Guard).
|
||||
- RBAC serverseitig erzwungen; UI blendet unerlaubte Aktionen aus.
|
||||
- Asset → BIA → Risiko → SoA/Maßnahme bilden eine durchgängige, verknüpfte Kette — in beide Richtungen navigierbar (Asset zeigt Risiken, Risiko zeigt Maßnahmen/Assets, Maßnahme zeigt Risiken).
|
||||
- Wiederkehrende Aufgaben erzeugen automatisch Instanzen, benachrichtigen und eskalieren bei Überfälligkeit.
|
||||
- Chat beantwortet Fragen mit Quellen aus Mandanten-Dokumenten und eskaliert korrekt an den ISB.
|
||||
- Incident-Workflow von Meldung bis Abschluss inkl. Zeitleiste und Nachweisen.
|
||||
- Exporte (SoA, Risikoregister, Audit-Report) erzeugen valide PDF/Excel.
|
||||
- E2E-Tests (Playwright) für die Kernpfade grün; Audit-Log erfasst alle schreibenden Aktionen.
|
||||
|
||||
## 11. Empfohlene Umsetzungsreihenfolge (Iterationen)
|
||||
|
||||
Auch wenn Module gleichwertig sind, minimiert diese Reihenfolge das Risiko:
|
||||
|
||||
1. **Fundament:** Projektsetup, Docker-Compose, Auth (lokale Accounts), Mandanten-Isolation (RLS + Guard), RBAC, Audit-Log, i18n-Gerüst.
|
||||
2. **Kern-Fachdaten:** Assets & BIA (ein Modul) → Risikoanalyse (inkl. Heatmap + Detailansicht).
|
||||
3. **Compliance:** ISO-Annex-A-Katalog + SoA, VDA-ISA-Struktur + Mapping, Reifegrade.
|
||||
4. **Betrieb:** Maßnahmen-Kanban, wiederkehrende Aufgaben/Scheduler, Benachrichtigungen.
|
||||
5. **Vorfälle:** Incident-Management inkl. Meldeformular.
|
||||
6. **KI:** RAG-Chat mit Eskalation, Richtlinien-Implementierungs-Assistent.
|
||||
7. **Auswertung:** Dashboards, Reporting/Exporte, Audit-Management.
|
||||
8. **Härtung:** Sicherheits-/Datenschutz-Review, Tests, Doku.
|
||||
|
||||
## 12. Lizenz-/Rechtshinweis zu Katalog-Inhalten (empfohlenes Vorgehen)
|
||||
|
||||
- **ISO 27001:2022** Control-**Titel/Referenzen** (Annex A, A.5–A.8) können als Katalog abgebildet werden; der **volle Normtext** ist urheberrechtlich geschützt und darf nicht mitgeliefert werden. → Nur Kurzbezeichnungen + eigene Umsetzungshinweise, Volltext verweist der Kunde auf seine erworbene Norm.
|
||||
- **VDA-ISA 6.0 / TISAX:** Der ISA-Katalog wird vom VDA/ENX bereitgestellt (ISA6 als Excel). Empfehlung: **Struktur (9 Kapitel/Prüfziele) und Mapping** abbilden, die konkreten Katalog-Inhalte per **Import** aus der offiziellen ENX-Datei einspielen (Import-Funktion für `ISA6-EN.xlsx`). So bleibt die Anwendung lizenzkonform und aktualisierbar.
|
||||
- **Mapping ISO 27001 ↔ VDA-ISA** als pflegbare Tabelle vorsehen (Controls beeinflussen mehrere Prüfziele und umgekehrt).
|
||||
|
||||
## 13. Offene Punkte / spätere Erweiterungen
|
||||
|
||||
- SSO (OIDC/SAML, z. B. Entra ID) — Feature-Flag bereits vorgesehen.
|
||||
- Self-hosted-LLM-Option je Mandant (falls Datenschutzanforderungen es verlangen).
|
||||
- Meldepflichten-Assistent (NIS2/DSGVO-Fristen) im Incident-Modul.
|
||||
- Mobile App / PWA für Vorfallmeldung.
|
||||
|
||||
---
|
||||
|
||||
### Quellen
|
||||
- VDA-ISA / TISAX Katalog v6.0: https://portal.enx.com/en-us/TISAX/downloads/
|
||||
- VDA ISA 6.0 verpflichtend: https://vda-isa-berater.com/en/mandatory-vda-isa-catalog-version-6-0-for-all-those-who-order-the-tisax-assessment-now/
|
||||
- VDA Information Security: https://www.vda.de/en/topics/digitization/data/information-security
|
||||
@@ -1,404 +0,0 @@
|
||||
# Entwicklungsstand `dev` — Konsolidierte Übergabe (PM + neue Entwickler)
|
||||
|
||||
> Stand: 2026-07-30 · Branch **`dev`** · **Sync-Hinweis:** lokal **deutlich vor `origin/dev`** (`origin/dev` = `9b479ab`); enthält u. a. Prod-Deployment-Vorbereitung, Wizard-Kickoff + Story A1-1 und diese Doku. `dev` ist auf **`origin` (git.certvia.de)** und **`local-gitea` (intern)** gepusht. Vor dem nächsten Push zuerst `git fetch` und prüfen, ob niemand weitere Commits hat. **Alle Feature-Branches** (Dev A: A1–A8; Dev B: F1–F4, B1–B7 inkl. Prüfziel-Follow-up) sowie **Certvia-Branding**, der **Wizard-Parallelisierungs-Fix** und zuletzt das **Security-Härtungspaket P1/P2/P3 (F-01…F-20, u. a. RLS scharf F-04, moduleGuard-DB-Authz F-06, MFA-Replay, Container-/Supply-Chain-Härtung F-11/F-18)** sowie **SEC1 (Mailversand/Queue)**, **SEC2 (Auth-Self-Service: Passwort-Reset/-Wechsel/E-Mail-Änderung, Session-Invalidierung, Rate-Limit)** und zuletzt die **TISAX-Umstrukturierung (M0–M4: Fundament, Strukturanalyse, Cockpit mit RACI/Evidence, Audit-Wizard, TISAX-Tasks, Wizard-Neustruktur; v3: Prozesshaus + geführtes BIA je Prozess)** sowie **SEC3/SEC4 (MFA pro Mandant erzwingen, WebAuthn/Passkeys, TOTP-Verschlüsselung at rest, Plattform-Admin-Verwaltung)** sind per DevOps-Integration additiv nach `dev` konsolidiert (Gate grün); noch offene Feature-Branches rebasen auf `dev`. **Deployment-Pflichtschritte** aus dem Security-Paket siehe §1a (F-04 RLS scharfschalten, F-06×F-10 `scripts/sync-role-permissions.ts` nach `migrate`). **SEC1/SEC2 fürs Deployment:** eigener **Mail-Worker-Service** (`npm run worker:mail` = `scripts/mail-worker.ts`) nötig, echte **SMTP-Variablen** setzen, und die Queue nutzt **Redis** (`REDIS_URL` mit Passwort, BullMQ/ioredis) — der Worker fehlt noch in `docker-compose.coolify.yml`. · Basis-Doku: `docs/HANDOVER-DEV.md`, `docs/HANDOVER-PM.md`, `docs/SPEC.md`
|
||||
> Zweck: Ein Dokument, das den kompletten Stand der Weiterentwicklung auf `dev` zusammenfasst — fachlich (für PM) und technisch (für einen neuen Entwickler). `dev` ist noch **nicht** nach `main` gemergt.
|
||||
|
||||
> **Neu (2026-08-07):** `feature/settings-roles-platform-ui` integriert (Einstellungen umstrukturiert: Risikokriterien/Rollen als Menü-Karten + Link zur Plattform-Administration; neue Route `/settings/risk-criteria`). Zusätzlich **Audit-Trail einsehbar je Mandant**: wiederverwendbares server-gerendertes Popup (`src/components/audit-trail.tsx`, Muster wie die übrigen Popups über `?audit=1`) an **zwei** Stellen — Mandanten-Einstellungen `/settings` (eigener Mandant, TENANT_MODELS/RLS-gefiltert) und Plattform-Konsole `/admin/[id]` (Superadmin, cross-tenant über Owner-Client auf den Mandanten gefiltert). **Keine neue Migration.** Gate grün (tsc/lint/build + 17/17 Tests), Popup im Browser verifiziert.
|
||||
>
|
||||
> **Fix (2026-08-07):** `dev-fix-platform-admin` integriert — **Proxy-Gate für Plattform-Routen** (`src/proxy.ts`): `/platform/login` + `/api/platform-auth` sind jetzt public, und `/admin`, `/admins`, `/profile`, `/platform` gaten aufs Plattform-Session-Cookie und leiten anonyme Besucher auf **`/platform/login`** statt fälschlich auf die Mandanten-Login-Maske. Plus klarerer Modul-Toggle in `/admin/[id]` (Status-Pill + eigener „Aktivieren/Deaktivieren"-Button). Verifiziert: `/admin|/admins|/profile` → 307 `/platform/login`, `/dashboard` weiterhin → `/login`. Gate grün (17/17).
|
||||
>
|
||||
> **Fix (2026-08-07, 2):** Plattform-Auth bekommt **eigene Cookie-Namen für ALLE** Auth.js-Cookies, nicht nur `sessionToken` (`src/server/platform-auth.ts`): auch `csrfToken` (`__Host-platform-authjs.csrf-token`) und `callbackUrl` (`platform-authjs.callback-url`). Grund: zwei Auth.js-Instanzen auf derselben Domain teilten sich die Default-Cookies `authjs.csrf-token`/`authjs.callback-url`; da ein Nutzer zugleich Mandanten- und Plattform-Konto sein kann, überschrieb die zuletzt aktive Instanz das gemeinsame CSRF-Cookie → CSRF-Validierung der Plattform-Instanz schlug fehl (Sign-out warf, CSRF-POSTs/Session-Erneuerung landeten auf der Login-Maske). Getrennte Cookie-Namen isolieren beide Auth-Domänen vollständig. Gate grün (17/17).
|
||||
>
|
||||
> **Fix (2026-08-07, 3):** Plattform-Cookie-`secure`/Prefix folgt jetzt dem **AUTH_URL-Protokoll** (`https:`) statt `NODE_ENV` (`src/server/platform-auth.ts`, `PLATFORM_SECURE_COOKIES`), exakt wie Auth.js es für die Mandanten-Instanz tut (`useSecureCookies ?? url.protocol === "https:"`). Grund: im Container ist `NODE_ENV=production`, der interne Testserver wird aber ggf. über **http** bedient (AUTH_URL=http bzw. fehlendes `X-Forwarded-Proto`); ein hart auf `__Secure-`/`__Host-`/`secure` gesetztes Cookie wird vom Browser über http verworfen → Plattform-Session bleibt leer (jede Aktion → Login-Maske, Logout wirft), während die Mandanten-Session weiterläuft. **Betriebshinweis:** In Prod `AUTH_URL=https://…` setzen (dann greifen wieder secure-Cookies + `__Host-`/`__Secure-`-Prefixe). Gate grün (17/17).
|
||||
>
|
||||
> **Identity/Mandanten (Option C), WS0 (Fundament) — 2026-08-11:** globales `Identity`-Modell (kein `tenant_id`, **nicht** in `TENANT_MODELS`, keine RLS) + `User.identityId`; Migration `identity_foundation`; Reseed auf Identity+Membership inkl. 2. Mandant `demo2` + Multi-Membership-Fixture `multi@demo.example`. **Expand/Contract** (User-Auth-Felder bleiben vorerst Legacy; Contract-Migration droppt sie am Ende von WS1–WS4). Neuer Test `scripts/test-identity-schema.ts`. Grundlage/Fahrplan: `docs/FEINDESIGN-identity-mandanten.md`, `docs/KONZEPT-identity-mandanten.md`, `docs/UEBERGABE-identity-mandanten.md`, `docs/PROMPT-uebergabe-identity-mandanten.md`. Nächste Schritte: WS1 (Login gegen Identity, Two-Step + MFA-pending) → WS2 (`/select-tenant`), parallel WS3/WS4/WS6; Abschluss = Contract-Migration.
|
||||
>
|
||||
> **Identity/Mandanten (Option C), WS1/WS3/WS4/WS6 — 2026-08-11** (`feature/identity-auth-core` → `dev`, `--no-ff`, Gate grün: tsc/lint/build + **21/21** Tests; **noch nicht auf die Remotes gepusht**):
|
||||
> - **WS1 Auth-Kern:** `auth.ts` authentifiziert gegen die globale `Identity` (Passwort/MFA/Lockout an der Identity); Mitgliedschaften werden geladen, der aktive Mandant per Organisations-Slug oder Single-Membership gewählt (mehrere **ohne** Slug ⇒ noch kein Login → `/select-tenant` = WS2). Login-Kern als `authorizeTenantCredentials()` exportiert. Session/JWT (`next-auth.d.ts`) neu: `identityId`/`activeMembershipId`/`memberships[]` (optional, da Plattform-Auth dieselben Typen nutzt); `tenantId` = aktiver Mandant → **356 dbForTenant-Call-Sites unverändert**. Test `scripts/test-identity-login.ts`.
|
||||
> - **WS4 Passwort/MFA an Identity:** Passwortwechsel, MFA-Enroll/-Disable, Recovery-Codes und der **Session-Kill-Switch** (`sessionsValidAfter`) gehören der Identity (`account.ts`, `account/page.tsx`, `sessions.ts`). Guards (`action-guard.ts`, `(app)/layout.tsx`, `change-password`, `enroll-mfa`) lesen `mustChangePassword`/`sessionsValidAfter`/`mfaEnrolledAt` + globalen `identity.status` aus der Identity; Membership-Status/Rechte weiter aus `User`. Reset-Kette (`auth-recovery`/`auth-selfservice`/`auth-token`) auf `PrincipalType "identity"`. **Mandanten-Admin-Passwort-Reset entfernt** (goldene Regel 5). **E-Mail-Änderung für Mandanten-Konten deaktiviert = Phase 2.** Test `scripts/test-identity-account.ts`. **Abgetrennt (offen): WS4b WebAuthn→Identity** (Schema-Migration + `TENANT_MODELS` + `webauthn.ts`; Passkey-Login läuft bis dahin mandantengebunden).
|
||||
> - **WS3 Einladungs-Lifecycle:** Nutzeranlage **nur per Einladung** (goldene Regel 4) — `TokenType "invitation"` (7 Tage) + neue öffentliche Seite `/invite` + `redeemInvitation`. `createTenantUser`/`createUser`/`inviteFunctionHolder` ohne pwMode „set"; **bekannte Identity → nur Mitgliedschaft ergänzen** (kein Passwort-Reset), unbekannt → Identity + Einladung; **neutrale Rückmeldung** (kein Cross-Tenant-Leak). `user-forms.tsx` = reines Einladungsformular. Test `scripts/test-invitation.ts`.
|
||||
> - **WS6 Seed/Provision/Bootstrap:** bereits durch WS0 abgedeckt (`provisionTenant`/`seed.ts` Identity-fähig, `sync-role-permissions.ts` orthogonal) — kein Netto-neuer Code.
|
||||
> - **Keine neue Migration** (WS1/WS3/WS4/WS6 sind code-only; das WS0-Schema trägt).
|
||||
>
|
||||
> **Identity/Mandanten (Option C) — WS2/WS4b/WS5 + Contract, UMBAU KOMPLETT — 2026-08-11** (`feature/identity-tenant-context` → `dev`, `--no-ff`, Gate grün: tsc/lint/build + **23/23**; **noch nicht gepusht**):
|
||||
> - **WS2 Mandantenkontext:** Multi-Membership-Login ohne Organisations-Slug ergibt eine Session OHNE aktiven Mandanten → `(app)/layout` leitet auf **`/select-tenant`**. Wechsel server-autoritativ über **`setActiveTenant`** (`actions/tenant-switch.ts`, `unstable_update` + async jwt-`update`-Trigger → `resolveActiveMembership`: Rechte je Wechsel NEU aufgelöst). **Sidebar-`TenantSwitcher`** (nur bei >1 Mitgliedschaft). **Browser-verifiziert:** Wechsel demo↔demo2 inkl. Mandantenisolation (demo: 9 Assets, demo2: 0). Test `scripts/test-tenant-switch.ts`.
|
||||
> - **WS4b WebAuthn→Identity:** Passkeys sind identitätsgebunden (Migration `20260811140000_webauthn_identity`: `webauthn_credentials` verliert `tenant_id`/RLS, verweist auf `identities`); `WebAuthnCredential` **raus aus `TENANT_MODELS`**. Passkey-Login/-Verwaltung über `identityId`.
|
||||
> - **Contract-Migration** (`20260811150000_contract_user_auth_columns`): die 10 ungenutzten `User`-Auth-Spalten entfernt (`password_hash, must_change_password, failed_logins, locked_until, mfa_secret, mfa_enrolled_at, recovery_codes, last_totp_step, sessions_valid_after, is_platform_admin`) → **`User` = reine Mitgliedschaft** (`tenantId, identityId, email, name, status`). Expand/Contract abgeschlossen. DROP COLUMN → kein Reset.
|
||||
> - **WS5 Two-Step-Login (Entscheidung A):** `/login` Schritt 1 (E-Mail+Passwort) → bei aktiver MFA kurzlebiger, signierter, einzweckiger `mfa_pending`-Cookie (KEINE Session) → **`/login/mfa`** Schritt 2 → `login-ticket`-Provider prägt die Session. Bausteine `verifyIdentityPassword`/`verifyIdentityMfa`/`finalizeIdentityLogin` (kein Passwort-Orakel, Lockout wie beim vollen Login). `src/server/login-ticket.ts` (HMAC). Runtime-verifiziert. Test `scripts/test-two-step-login.ts`.
|
||||
> - **Damit ist der Umbau „Zentrale Identität mit Mandanten-Mitgliedschaften" vollständig** (alle 5 goldenen Regeln + Entscheidung A). Zwei neue Migrationen. **Offen: nur der Push auf beide Remotes** (origin + local-gitea) — bewusst zurückgehalten. Phase-2 (per-Mandant Step-up, E-Mail-Änderung als Identity-Op, PlatformAdmin-Konsolidierung) bleibt ausgeklammert.
|
||||
>
|
||||
> **Richtlinien-Vorlagen Plattform-Editor + EN-Paket — 2026-08-11:** `dev-fix-platform-admin` integriert — globale Vorlagen-Modelle + Migration `policy_templates`, Plattform-Editor (Entwurf/Veröffentlichen, Editoren für Anforderungen/Variablen), **Sprachwahl je Mandant** (`setTenantLocale`) und das **komplette EN-Übersetzungspaket** der Richtlinien-Vorlagen (Leitlinie, R01–R14, VA-01–VA-20, D01/P01, Baseline/Nachweisregister). Mandanten-Import liest die veröffentlichte DB-Version.
|
||||
>
|
||||
> **Härtung Argon2id — 2026-08-11:** Passwort-Hash-Parameter fixiert/dokumentiert (`src/server/password.ts`, `ARGON2_OPTIONS`: m=19456 KiB, t=2, p=1, outputLen=32; Argon2id = Lib-Default). Salt automatisch pro Hash (PHC-String), **kein** Pepper (dokumentiert). Nur neue Hashes betroffen.
|
||||
>
|
||||
> **Härtung Phase 2–3 (Ops-Doku) — 2026-08-11** (Lane `lane-haertung-ops`, **nur Markdown, kein App-Code/Migration, noch nicht nach `dev` gemergt**): **Phase 1 (Passwort-Pepper) ist erledigt** (Argon2-`secret`, zentral, in `dev`) — unverändert. Phasen 2–3 liegen jetzt als **Ops-Runbook** vor: `docs/DEPLOY-PROD-CONTABO.md` um **Host-Encryption at-rest** (LUKS/dm-crypt fürs Daten-Volume `pgdata`+MinIO, Boot-Unlock-Verfahren A/B, Passphrase im Passwortmanager) und **verschlüsselte Backups** (pgBackRest `aes-256-cbc` + `age` je Umgebung + restic für MinIO, Coolify-Cron/Retention/Restore-Test, Bezug zur App-Backup-Engine `BACKUP_ENC_KEY`/§9) ergänzt; neues **`docs/SECRETS-REGISTER.md`** (Ownership + Rotationsregel je Umgebung für `AUTH_SECRET`/`MFA_ENC_KEY`/`PASSWORD_PEPPER`/`BACKUP_ENC_KEY`/pgBackRest-Key/`age`-Keypair; `PASSWORD_PEPPER`+`MFA_ENC_KEY` als **nicht rotierbar** = Reset markiert). **Restore-Kohärenz-Regel** prominent in beiden Docs: Umgebungs-Secrets stehen nicht im Artefakt → Restore in fremde Umgebung bricht Passwort-/MFA-Prüfung bzw. Entschlüsselung. **DB-TLS (`sslmode`) + Vault/KMS bleiben Phase 2** (offen). Gate: nur `.md`, tsc/lint unberührt.
|
||||
>
|
||||
> **Merge-Zyklus 2026-08-11:** WS0 + Richtlinien/EN-Lane + Argon2 zusammen nach `dev` konsolidiert. Konflikt nur in `schema.prisma` (User-Relationsblock → Union mit `identity`) + `provision.ts` (auto-merge: Identity-Upsert **und** Policy-Variablen). DB neu gebaut (`migrate reset`, **52 Migrationen**, beide neuen koexistieren) + Seed. Gate grün: tsc/lint/build + **18/18 Tests**.
|
||||
>
|
||||
> **Konfigurierbarer Backup-Zielspeicher — 2026-08-17** (`lane-backup-target` → `dev`, `--no-ff`): Backup-/DSGVO-Zielspeicher jetzt **im Betreiber-Portal wählbar** (`/admin/backup`, Full-Admin + MFA-Step-up) — **Lokal** (persistentes Volume) oder **S3/MinIO**. `PlatformSetting` erweitert (`backupTarget`, `backupLocalDir`, `backupS3*`, `backupS3SecretKeyEnc` **verschlüsselt at-rest**), Migration `backup_target_config` (additiv). Statisches `backupStore` → **`getBackupStore()`** mit Präzedenz **DB → Env (`S3_*`/`BACKUP_LOCAL_DIR`) → lokaler Default `.backups`**, fail-secure bei unvollständiger S3-Config; alle Call-Sites umgestellt. **Persistentes `backups`-Volume** (app + backup-worker, `/app/.backups`) — Lokal überlebt Redeploys. Neuer Test `scripts/test-backup-target.ts`. Gate grün (tsc/lint/build + **28/28**), `/admin/backup` im Browser klickgeprüft (Lokal↔S3, Secret-Feld „nie Klartext"). Konzept/Prompt: `docs/KONZEPT-backup-target.md`, `docs/PROMPT-lane-backup-target.md`.
|
||||
>
|
||||
> **Modul „Vorfälle" (Incident-Management) IM-A — 2026-08-17** (`lane-incidents-a` → `dev`, vom Team): Fundament + Kern-Lifecycle/UI (Migration `incidents`, `src/app/(app)/incidents/*`, `src/server/actions/incidents.ts`, `docs/KONZEPT-incidents.md`, Test `scripts/test-incidents.ts`). IM-B (Meldefristen/Notifications) noch **in Arbeit** (eigener Branch `lane-incidents-b`).
|
||||
>
|
||||
> **Direkt-Download der Sicherung + S3-Bucket-Selbstheilung — 2026-08-17** (`lane-backup-download` @ `fe13a84` → `dev`, `--no-ff`): Neue Route `/api/platform/backup/download` (Full-Admin) — `exportTenant(persist:false)` streamt die verschlüsselte `.cvb` **inline in den Browser**, **ohne Worker/Redis/S3** („Sicherung herunterladen"-Button im Export-Popup). `S3BackupStore.ensureBucket()` legt einen fehlenden MinIO-Bucket beim ersten `put` **automatisch** an (behebt „The specified bucket does not exist"). Neuer Test `scripts/test-backup-download.ts`. Gate grün (tsc/lint/build + **30/30**). Merge über isoliertes Worktree (paralleler Team-Arbeitsbaum unberührt).
|
||||
>
|
||||
> **Modul „Vorfälle" IM-B/C/D (komplett) + Backup-Docker-Fix — 2026-08-18** (vom Team nach `dev` gemergt; von mir validiert + gepusht): **IM-B** (Meldefristen/Timer + Meldepflicht + Benachrichtigungen), **IM-C** (Verknüpfungen, Abschluss/Lessons-Learned, Export/Meldevorlagen), **IM-D** (E-Mail-to-Ticket Inbound + Provisionierung; Migration `incident_inbound_d`, Test `scripts/test-incident-inbound.ts`). Damit ist das Modul „Vorfälle" funktional komplett (IM-A…IM-D). **Docker-Fix:** `prisma/schema.prisma` wird jetzt auch in die `runner`-Stage kopiert — der Inline-Backup-Download läuft in der App (standalone), und die Backup-Topologie liest die Schema-Datei zur Laufzeit (Prisma 7 entfernt FK-Relationen aus dem Laufzeit-DMMF); sonst `ENOENT` → „Export fehlgeschlagen". Gate grün (tsc/lint/build + **33/33**).
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive Summary
|
||||
|
||||
Auf `main` lag das Fundament (Auth/RBAC/Mandanten-Isolation, Assets/BIA, Risiko, Maßnahmen, Abhängigkeiten, Lieferanten, Richtlinien Phase 1/2a, Admin-Konsole Phase 1). Der Branch **`dev`** ergänzt fünf große Blöcke — alle mit `tsc`+`lint`+`build`, Modul-Guard-Check und (wo relevant) Browser-Verifikation abgeschlossen:
|
||||
|
||||
1. **Produktionshärtung Phase 1** — API-seitige Modul-Durchsetzung, getrennter Superadmin-Store mit eigenem Login + MFA, nicht-destruktiver Richtlinien-Re-Import.
|
||||
2. **Benutzer- & Rollenverwaltung** (ohne E-Mail-Flow) — Plattform-Admin verwaltet Nutzer je Mandant; Mandanten-Admin verwaltet Nutzer **und** Rollen intern; Force-Change-Passwort, Passwort-Policy, optionale MFA je Nutzer; Popup-UI wie bei Assets.
|
||||
3. **Freigabe-Workflow + Aufgaben-Modul** — Richtlinien-Freigabe an eine konkrete Person, Bearbeitung im neuen Modul „Aufgaben", Dashboard-Kachel; plus zentralisierte Richtlinien-Governance (zentrale Variablen, Schutzbedarf, Coverage-Filter nach Assessment-Level).
|
||||
4. **GAP-Report-Umsetzung (Richtlinien-Vorlagenpaket)** — WP1–WP4 + E2: sechs neue Verfahrensanweisungen (ISB-Volltexte), Inline-VA-Verlinkung, Rendering-Fix, generisches editierbares Register-Datenmodell.
|
||||
5. **Register-Konsolidierung in Fachmodule** — vier generische Register in die Fachmodule überführt: **Software** und **Projekte** als eigene Asset-Typen (Popups wie bei Assets/Lieferanten), **kritische IT-Dienste** als schreibgeschützte Auto-Sicht aus BIA, REG-NET auf Referenzfeld reduziert; Richtlinien-Links zeigen jetzt auf die Module statt auf Register.
|
||||
6. **Produktions-Deployment-Vorbereitung** (Commits `cc8d486`, `f368d8f`) — Prod-Bootstrap `scripts/bootstrap-admin.ts` (legt Erst-Superadmin im `platformAdmin`-Store + Mandant/Mandanten-Admin idempotent an, ersetzt in Prod den Demo-Seed; per `BOOTSTRAP_*`-Env im `migrate`-Job der `docker-compose.coolify.yml`); `.env.prod.example`; **Fonts selbst gehostet** (`next/font/local`, committete woff2 in `src/app/fonts` → reproduzierbarer Offline-Build, DSGVO); Runbook **`docs/DEPLOY-PROD-CONTABO.md`** (VPS/Coolify/Gitea, TLS `app.certvia.de`, Bootstrap, Backups, Go-Live-Checkliste).
|
||||
|
||||
7. **Branding-Umstellung auf Certvia** — **in `dev` integriert (Gate grün)**: getrennte Token-Ebenen `--brand-*` (Logo/Print/Export) vs. `--ui-*` (Produktpalette, inhaltlich unverändert) mit `src/lib/brand.ts` als JS-Pendant; Certvia-Logo als Inline-SVG-Komponente (`<CertviaLogo>`), Favicon-/PWA-Icons + `site.webmanifest`, Metadaten/OG/i18n/TOTP-Issuer, gebrandete Auth-Seiten sowie **neue 404-/500-Seiten**, Druck-/Dokument-CD (`@media print` + `src/lib/document-brand.ts`) als Andockpunkt für den offenen DOCX/PDF-Export, brandfähige E-Mail-Basis (`src/lib/email-brand.ts`), Mandanten-Branding-Default (`resolveTenantBranding`). **GEFIM bleibt Dachmarke** („Ein Produkt von GEFIM"). Reines Branding, keine Funktionsänderung — Ausnahme: der Route-Gate-Matcher in `src/proxy.ts` musste `.webmanifest` freigeben, sonst lieferte `/site.webmanifest` die Login-HTML. Details: **`docs/BRANDING-CERTVIA.md`**.
|
||||
|
||||
**In Arbeit (parallele Entwicklung, 2-Lane Dev A × Dev B):** **Onboarding-Wizard** (`docs/wizard-uebergabe/`). **Beide Lanes bis hierher in `dev` konsolidiert** (inkl. Dev-B **B4**, per Fast-Forward integriert)**:**
|
||||
- **Dev A:** A1-1 — Wizard-Shell: Modul `onboarding`, Step-Registry (`registerStep`, Keys 1–9, `guard` kann Schritte ausblenden), resumierbarer Fortschritt (`OnboardingProgress`). **F2** — generalisiertes `ObjectReviewStatus` (5 Zustände inkl. `zurueckgewiesen`) als wiederverwendbares Review-Enum; RBAC-Recht `validate_objects` + klonbare Rolle `external_validator`; Wizard-State-Machine mit Rechte-Trennung: Bearbeiter (`onboarding:use`) advance/rework/reset, Validator (`validate_objects`) validieren/zurückweisen (mit Begründung). „Weiter"-Gate: nur `validiert` zählt. Migration `object_review_status`. **A1-2** — Dashboard-Kachel „Onboarding-Fortschritt" (Anteil validierter Schritte + nächster offener Schritt, verlinkt in den Wizard). **A2-1** — Assessment-Level (AL2/AL3) als **einzige** Quelle des Schutzbedarfs: `protectionFlags(level)` (`src/server/assessment-level.ts`) leitet `FLAG_HIGH_PROTECTION`/`FLAG_VERY_HIGH_PROTECTION` zentral ab (Wizard/Provisioning seeden daraus, **nicht** mehr aus dem Fragebogen); Schutzbedarf-Frage `Q-FEAT-01` + Regeln `feat01-*` entfernt. **A2-2** — Scope-Objekt `WizardScope` + Filter-Engine (`src/lib/scope-filter.ts`: `activeRequirements`/`scopeSummary`, client-safe): filtert die Anforderungen nach AL-Baseline, `FLAG_INCLUDE_SHOULD` und Prüfzielen; Grunddaten `seed/scoping/c1-scope.json` (412 Anforderungen, generiert via `scripts/build-c1-scope.ts`); Action `saveScope` (`moduleGuard('onboarding')`) am Wizard-Schritt „scoping"; Migration `wizard_scope`; Tests `scripts/test-scope-filter.ts` (grün). **A3-1** — Validierungs-Workflow generalisiert: wiederverwendbares generisches Objekt-Review (`src/server/object-review.ts`, `src/lib/object-review.ts`, `src/components/object-review.tsx`) über Objekttypen hinweg (u. a. Risiken), an Risk-/Task-Actions angebunden. **A4** — ISMS-Rollen als Wizard-Schritt 3 „roles" inkl. Funktionstrennung FT-01…06 (`src/lib/ft-rules.ts`, Tests `scripts/test-ft-rules.ts`), ISB-Bestellung (`src/lib/isb-bestellung.ts`) und Rollen-Logik (`src/server/roles.ts`). **A5-1** — Asset-Schritt (Wizard-Schritt 5) auf dem Bestandsmodul (`steps/assets/step.tsx`). **A7** — **Control-Assessment** (Wizard-Schritt 7): Reifegrad-Engine R0–R3 + Zielreifegrad (`src/lib/maturity.ts`, Tests `scripts/test-maturity.ts`), Modell `ControlAssessment` (Migration `control_assessments`, RLS, in `TENANT_MODELS`) mit Belegstatus/Reifegrad-Bestätigung/Gap-Aufgaben; SoA-Kontext (`src/server/soa-context.ts`, `actions/soa.ts`), Control-Grunddaten `seed/scoping/c5-controls.json`. **A6** — **Standard-Risikokatalog (C4)**: globaler Katalog `RiskCatalogEntry` (Migration `risk_catalog`, kein RLS) + Import/Übernahme (`prisma/import-risks.ts`, `/risks/catalog`); A6-2 Standardmaßnahme→Aufgabe und **Restrisiko-Akzeptanz** (Migration `risk_acceptance`: Felder `accepted_at/by/rationale` an `risks`, VA-09). **A8** — **Gap-Konsolidierung** (Wizard-Schritt 8): Aggregations-/Priorisierungs-Engine (`src/lib/gap-consolidation.ts`: Dedup, Priorisierung, Quick-Wins), Task-Abgleich + Kontext (`src/server/gap-context.ts`, `src/server/actions/gap.ts`), Tests `scripts/test-gap-consolidation.ts` (keine neue Migration/Modell).
|
||||
- **Dev B:** F1 (Task-Objekt um Wizard-Felder `type/owner/dueDate/priority/status/resources/origin/links` erweitert, Migration `tasks_wizard_fields`), B1 (Auto-Generierung von Aufgaben-Vorschlägen aus Triggern, C2 §8; `src/lib/task-triggers.ts`, `src/lib/tasks.ts`), F4 (Wizard-Flags in `variables.schema.json`: `FLAG_PROTOTYPE_PROTECTION`, `FLAG_ISB_EXTERNAL`, `FLAG_ISB_INTERNAL`; `_verify.py` = OK). **F3+B2** — Regel-/Mapping-Engine: deklarative DSL (`src/lib/rules/dsl.ts`), Auswerter (`engine.ts`, `evaluateCondition`) und C2-§5-Regelwerk (`feature-rules.ts`: Feature-Flags, Schutzbedarf-Ableitung, Control-Scope, Risiko-/Aufgaben-Trigger); Tests `scripts/test-rules.ts` (18 Fälle, grün). **B3** — Fragebogen als Wizard-Schritt 2 „context": Frage-Katalog A–F (`src/lib/onboarding/questions.ts`), Fakten-Ableitung (`facts.ts`, `deriveContext` über die Regel-Engine), Schritt-Komponente + `saveFacts`-Action (`onboarding-facts.ts`), Modell `WizardFact` (Migration `wizard_facts`, RLS, in `TENANT_MODELS`); echte Schritte via Side-Effect-Import `register-steps.ts` in die Registry eingeklinkt (überschreibt Platzhalter). Der Fragebogen schreibt **nur** Fakten/Flags, nie die gesperrten Zentralvariablen. **B4** (Richtlinien-Import/Upload) — **in `dev` integriert (Fast-Forward), Gate grün**: **B4-1** nicht-destruktiver Vorlagen-Import bei Aktivierung des Richtlinien-Moduls + Self-Service-Button (`/policies`, Report-Banner) und Admin-Button (`src/server/actions/policy-package.ts`, Trigger in `toggleTenantModule`); **B4-2** „Eigene Richtlinie hochladen" (`/policies/upload`, `policy-upload.ts`) mit Pflicht-Control-Zuordnung + gekapseltem Storage-Adapter-Stub (`src/server/storage/adapter.ts`, echtes Backend = Epic S1) → EIGENES-Dokument (`EIG-*`) + PolicyRequirement-Zeilen (Coverage/Nachweislage); **B4-3** neue Vorlagen `P01_Prototypenschutz` + `VA-20` (Kap. 8.x) und `D01_Datenschutz` (9.x) + 5 `mapping.json`-Anforderungen (condition-gated per Prüfziel-Flag), `_verify.py` = OK. **Keine neue Migration** (nur String-Status/Seed-Content). **B5** (Umsetzungshinweise C6) — **in `dev` integriert, Gate grün**: **B5-1** Datenmodell `ImplementationHint` (Migration `implementation_hints`; **globaler C6-Katalog**, identisch je Mandant → kein `tenantId`/RLS) + C6-Import (~397 Hinweis-Blöcke via `prisma/import-hints.ts` / `scripts/import-c6-hints.ts`); **B5-2** kontextsensitives Umsetzungshinweis-Panel (`/policies/hints`, `src/server/actions/hints.ts`), aus `/policies` verlinkt. **Prüfziele Single Source** (Follow-up zu A2): der context-Step seedet die Prüfziele aus `WizardScope` statt aus einer zweiten Quelle (Doppelquelle behoben; `feature-rules.ts`/`facts.ts`/`questions.ts`, `test-rules.ts` angepasst). **B6** — Vorlagenpaket-**Versionierung** + kontrollierte **Diff-Übernahme**: Modell `PolicyPackageState` (Migration `policy_package_state`, RLS, in `TENANT_MODELS`) hält je Mandant Paket-Version/-Stand; `stampPackageState` (in `prisma/import-policies.ts`) beim Import; Updates-Ansicht `/policies/updates` zeigt/übernimmt Änderungen kontrolliert. **B7-1** — Assessment-**Readiness-Dashboard** als Wizard-Schritt 9 „readiness" (`src/lib/readiness.ts`, Tests `scripts/test-readiness.ts`) mit Interpretationstexten (C9 §1/§2). **B7-2** — **VDA-ISA-Katalog-Export** (CSV) + **Management-Zusammenfassung** (C9 §3/§4): Export-Route `onboarding/export/route.ts`, Export-Engine `src/lib/export/vda-isa.ts` + `src/server/export-context.ts`, Zusammenfassungs-Seite `onboarding/summary`, Tests `scripts/test-vda-isa.ts`. Damit ist **B7 vollständig** (keine neue Migration). **Wizard-Schritte 4 + 6 (echte Komponenten)** — Richtlinien-Schritt „policies" (Schritt 4, Guard: nur bei aktivem Richtlinien-Modul) und Risiken-Schritt „risks" (Schritt 6, Guard: nur bei aktivem Risiko-Modul) zeigen jetzt den echten Modul-Status statt Platzhalter (`steps/policies/step.tsx`, `steps/risks/step.tsx`, `src/server/actions/onboarding-steps.ts`) — keine Doppel-Datenhaltung. Damit sind **alle Wizard-Schritte 1–9 echte Komponenten**.
|
||||
- **Offen:** **Keine offenen Feature-Branches mehr** — alle bestehenden Lanes in `dev` konsolidiert (Dev A: A1–A8; Dev B: F1/B1/F4/F3+B2/B3/B4/B5/B6/B7 + Prüfziel-Follow-up). Nächste geplante Stories siehe §6.
|
||||
|
||||
**Migrationen (31 neu, laufen beim Deploy automatisch über den Init-Container):**
|
||||
`platform_admins` · `policy_lifecycle_archived` · `user_mgmt_and_platform_settings` · `tasks` · `strip_tool_variable_articles` · `managed_registers` · `software_and_project_assets` · `onboarding_progress` · `tasks_wizard_fields` · `object_review_status` · `wizard_facts` · `wizard_scope` · `implementation_hints` · `policy_package_state` · `control_assessments` · `risk_catalog` · `risk_acceptance` · `task_description` · `control_implementations` · `login_lockout` · `mail_fundament` (SEC1) · `auth_tokens_sessions` (SEC2) · `tisax_m0_foundation` · `tisax_m1_m4_consolidated` · `tisax_rekey_onboarding_steps` · `tisax_v3_process_fields` · `tisax_v4_catalog_parent` · `tisax_v5_audit` · `tisax_v7_policy_domain` · `webauthn_credentials` (SEC3) · `platform_admin_role` (SEC4)
|
||||
|
||||
---
|
||||
|
||||
## 1a. Sicherheitspaket P1/P2 (Branch `dev-security-p1`, Stand 2026-07-30)
|
||||
|
||||
Nach einem externen Secure-Code-Review (AEGIS-SAST, 21 Findings) wurde ein Härtungspaket umgesetzt: **alle P1 (2) und P2 (5) sowie mehrere P3** sind behoben. Das Paket liegt auf **`dev-security-p1`** (von `dev` abgezweigt, Gate grün, noch **nicht** nach `dev` gemergt). Parallelisiert in drei konfliktfreien Lanes plus Vorlauf, danach additiv integriert.
|
||||
|
||||
| Finding | Priorität | Behebung | Kern-Dateien |
|
||||
|---|---|---|---|
|
||||
| **F-01** Auth.js „fail open" + Next.js-CVEs | P1 | `next-auth`→`5.0.0-beta.32` (`@auth/core` 0.41.3), `next`→`16.2.12`; Guards **positiv** statt existenzbasiert; **Fail-Secure-Startprüfung** `assertSecureEnv()` (lazy/memoisiert, build-safe) | `package.json`, `src/server/env.ts`, `auth.ts`, `platform-auth.ts` |
|
||||
| **F-02** Cross-Tenant-Leck bei `findUnique`+`select` | P1 | Tenant-Guard **fail-closed**: skalare `where`→`findFirst` mit `tenantId`-Vorfilter (verhindert statt erkennt), Compound-Unique→`tenantId`-Injektion + harter Abbruch; drei Aufrufstellen zusätzlich explizit gefiltert; Regressionstest | `src/server/db.ts`, `actions/risks.ts`, `actions/risk-catalog.ts`, `scripts/test-tenant-isolation.ts` |
|
||||
| **F-03** Stored XSS im Richtlinien-Rendering | P2 | `renderPolicyHtml` sanitisiert `marked`-Output gegen strikte Allowlist (`sanitize-html`); Variablenwerte + Upload-Titel HTML-kodiert vor `noEscape`-Handlebars | `src/lib/policy-render.ts`, `actions/policy-upload.ts` |
|
||||
| **F-05** Kein Brute-Force-Schutz Mandanten-Login | P2 | Kontosperre (5/15 min) + `denied`-Audit analog Plattform-Login; Enumeration via Dummy-Hash konstanter Laufzeit; DoS-Ausnahme letzter aktiver Admin | `auth.ts`, Migration `login_lockout` (`User.failedLogins/lockedUntil`) |
|
||||
| **F-07** Keine Security-Header/CSP | P2 | CSP + HSTS + `nosniff` + `X-Frame-Options: DENY` + Referrer-/Permissions-Policy; `unsafe-eval`/`ws:` nur im Dev | `next.config.ts` |
|
||||
| **F-08** Kritische Kontoänderung ohne Re-Auth | P2/P3 | Passwortwechsel verlangt aktuelles Passwort (+ TOTP bei aktiver MFA); MFA-Deaktivierung erfordert TOTP-Code; Ausnahme nur beim erzwungenen Erstwechsel | `actions/account.ts`, `actions/platform.ts` |
|
||||
| **F-09** 30-Tage-Sessions | P3 | `maxAge` 8 h (Mandant) / 2 h (Plattform) + `updateAge` | `auth.ts`, `platform-auth.ts` |
|
||||
| **F-12** Weitere verwundbare Abhängigkeiten | P3 | `overrides` für `postcss`/`sharp`/`valibot`; **Produktionsbaum (`--omit=dev`): 0 kritisch / 0 hoch** (vorher 2/5) | `package.json` |
|
||||
| **F-15** Upload ohne Validierung | P3 | Größenlimit vor RAM-Read, Endungs-/MIME-Allowlist, Magic-Byte-Prüfung, kanonischer MIME statt `f.type` | `actions/policy-upload.ts` |
|
||||
| **F-16** (Teil) Isolationsverletzung unsichtbar | P3 | Verletzungen als `[SECURITY]`-Log; zentrale Audit-Anbindung (`action:"denied"`) als Folge-TODO offen (Importzyklus `audit.ts`↔`db.ts`) | `src/server/db.ts` |
|
||||
| **F-19** Unvalidiertes `callbackUrl` | P4 | Allowlist (nur eigene absolute Pfade), doppelt validiert | `src/app/login/page.tsx` |
|
||||
|
||||
**Korrekturen am Bericht** (dessen Codevorschläge waren an drei Stellen falsch): `npm install next-auth@latest` hätte auf **v4** downgegradet (Major-Bruch) — korrekt ist `5.0.0-beta.32`. Der pauschale `findUnique`→`findFirst`-Umbau bricht an den Compound-Unique-Keys (`tenantId_key` etc.) → stattdessen Hybrid-Guard. Das RLS-Snippet aus F-04 funktioniert nicht (Kontext in falscher Transaktion) → F-04 bewusst herausgelöst.
|
||||
|
||||
| **F-06** JWT-Sessions ohne Widerruf | P2 | ✅ **Branch `dev-security-f06-session-auth`** (auf `dev-security-f04-rls`): `moduleGuard` prüft Kontostatus, `mustChangePassword` und effektive Rechte je Mutation **autoritativ aus der DB** statt aus dem JWT → Deaktivierung/Rechteentzug wirkt sofort (vorher bis Token-Ablauf); `requirePlatformSession` prüft Plattform-Admin-Status. Test `test-action-guard-authz.ts` (4 Nachweise), Browser-Regression ok | `src/server/action-guard.ts`, `platform-auth.ts` |
|
||||
| **F-04** RLS definiert, aber wirkungslos | P2 | ✅ **Separates Paket, Branch `dev-security-f04-rls`** (auf `dev-security-p1` aufgesetzt): env-gesteuert (`RLS_ENFORCED`). Zweite Verbindung als `isms_app` (`RLS_DATABASE_URL`, NOBYPASSRLS); `dbForTenant` setzt `app.tenant_id` transaktionslokal auf derselben Connection; Policies mit `USING`+`WITH CHECK` + `FORCE` auf allen **49** Tenant-Tabellen. Owner-Rolle (Superuser/BYPASSRLS) bleibt für Migrationen/Seed/Login und lokal unberührt → Default-Betrieb unverändert. Test `test-rls-enforcement.ts` (5 Nachweise) | `src/server/db.ts`, Migration `rls_enforce`, `docker-compose.coolify.yml`, `.env*.example`, `DEPLOY-PROD-CONTABO.md` |
|
||||
|
||||
**Gate (kombinierter Stand A+B+C):** `tsc`=0 · `lint` sauber · `build` grün · `_verify.py`=OK · `test-tenant-isolation`=OK (15 Fälle) · Browser-Smoke (Login, Dashboard, Richtlinien-Register, CSP-Header, Guard-Redirect) verifiziert. **F-04 separat:** `tsc`/`lint`/`build` grün · `test-rls-enforcement`=OK (5/5, inkl. Nachweis „Owner-Betrieb heil unter FORCE") · Owner-Pfad-Smoke verifiziert.
|
||||
|
||||
### P3/P4-Paket (Branch `dev-security-p3`, auf `dev-security-f06-session-auth`, Stand 2026-07-30)
|
||||
|
||||
Vier dateidisjunkte Lanes, additiv gemergt, kombiniertes Gate grün. **Nur die MFA-Lane migriert.**
|
||||
|
||||
| Finding | Prio | Behebung | Kern-Dateien |
|
||||
|---|---|---|---|
|
||||
| **F-10** Aufgaben-Modul ohne Rechteprüfung | P3 | Neues Recht `task:write`; `guard("task:write")` in `createTask`/`proposeTasksFromTriggers`/`claimTask`/`updateTask`; `CreateTaskInput` per Zod (Längen-/Größenlimits); `owner`/`assignee` gegen aktiven Mandanten-Nutzer geprüft | `rbac.ts`, `actions/tasks.ts` |
|
||||
| **F-13** Privilege Escalation über `role:manage` | P3 | **Pragmatische Variante** (Entscheidung): Delegation erlaubt (Admin darf fachliche/geklonte Rollen für andere anlegen), aber **Selbstzuweisung** höher privilegierter Rollen gesperrt → Selbst-Eskalation ausgeschlossen; volle Auditierung | `actions/tenant-users.ts` |
|
||||
| **F-20** Schwache Passwort-Policy bei Provisionierung | P3 | `validatePassword(…, DEFAULT_PASSWORD_POLICY)` statt `min(8)` | `actions/admin.ts` |
|
||||
| **F-16-zentral** Sicherheitsereignisse nur im Log | P3 | Importzyklus per Lazy-Import gelöst → Isolationsverletzung wird echter `denied`-Audit; Error-Boundary `withActionErrors` (generische Außenmeldung, volles internes Log) bereitgestellt | `db.ts`, neu `action-error.ts` |
|
||||
| **F-17** Recovery-Codes SHA-256, TOTP-Replay | P3 | Recovery-Codes → Argon2id, Entropie 40→80 Bit (Alt-Codes per Kompatibilitätspfad bis Neuausstellung); TOTP-Replay-Schutz via `lastTotpStep` (User+PlatformAdmin) | `mfa.ts`, `auth.ts`, `platform-auth.ts`, `account.ts`, `platform.ts`, Migration `mfa_totp_replay` |
|
||||
| **F-11** Supply Chain | P3 | `npm ci` (Base-Image → `node:22.14.0-slim`/glibc, npm 11 gepinnt), alle Images auf feste Tags/Digests, schlanke `migrate`-Stage, SBOM dokumentiert; lokaler `docker build` grün (386 MB) | `Dockerfile`, `docker-compose*.yml` |
|
||||
| **F-18** Container-Härtung | P3/P4 | Redis-Passwort, internes Netz (`internal: true`), `no-new-privileges`/`cap_drop: ALL`/Ressourcenlimits, Dev-Compose auf `127.0.0.1` gebunden | `docker-compose*.yml`, `.env*.example` |
|
||||
| **CI/Renovate** (Begleitmaßnahmen) | — | `.gitea/`+`.github/workflows/ci.yml` (tsc/lint/build + `npm audit --omit=dev --audit-level=high`-Gate), `renovate.json` (Auth-Updates manuell) | `.gitea/`, `.github/`, `renovate.json` |
|
||||
|
||||
**Gate (kombiniert):** `tsc`=0 · `lint` · `build` · `_verify.py`=OK · 7 Sicherheitstests grün (`tenant-isolation`, `rls-enforcement`, `action-guard-authz`, `tenant-users-authz`, `mfa-hardening`, `action-error`) · Browser-Smoke (Task-Anlage F-10) verifiziert.
|
||||
|
||||
> ✅ **Deployment-Schritt (F-06 × F-10) — automatisiert:** Da F-06 Rechte **DB-autoritativ** prüft, wirkt eine neue Permission (z. B. `task:write`) erst, wenn `scripts/sync-role-permissions.ts` gegen die Ziel-DB läuft (legt Permission + Rolle→Recht-Verknüpfung an; additiv, idempotent). Ein reiner Re-Login genügt NICHT. Das läuft jetzt **bei jedem Deploy automatisch im `migrate`-Init-Job** (`docker-compose.coolify.yml`, direkt nach `prisma migrate deploy`, über die Owner-`DATABASE_URL`) — deckt jede künftig neu eingeführte Permission ab. Betroffene Nutzer danach neu einloggen. Manuell nachziehen nur, falls ohne Redeploy nötig: `npx tsx scripts/sync-role-permissions.ts`.
|
||||
|
||||
**Noch offen:** **F-14** (Demo-Seed-Härtung — auf Wunsch bewusst zurückgestellt), **F-21** (Monitoring/Log-Aggregation/Tamper-Schutz Audit-Trail — eigenes Betriebspaket). Damit sind **alle P1, alle P2 und die adressierten P3** behoben. Details: AEGIS-Bericht.
|
||||
|
||||
**Aktivierung F-04 in Prod:** Rolle `isms_app` LOGIN+starkes Passwort geben, `RLS_DATABASE_URL` setzen, `RLS_ENFORCED=true` am `app`-Service; Migrations-/Owner-Rolle muss BYPASSRLS/Superuser sein. Anleitung in `docs/DEPLOY-PROD-CONTABO.md`. Lokal bewusst **aus**.
|
||||
|
||||
---
|
||||
|
||||
## 2. Für das Projektmanagement — fachlicher Status
|
||||
|
||||
### ✅ Neu fertig auf `dev`
|
||||
|
||||
| Thema | Nutzen | Status |
|
||||
|-------|--------|--------|
|
||||
| **API-seitige Modul-Durchsetzung** | Deaktiviertes Modul sperrt jetzt auch Schreibzugriffe serverseitig (nicht nur Navigation); automatischer Vollständigkeitscheck als Build-Gate | ✅ |
|
||||
| **Getrennter Superadmin-Login** | Betreiber-Zugang unter `/platform/login` mit eigenem Store, ohne Mandantenkontext; Kundenfachdaten für Superadmin gesperrt | ✅ |
|
||||
| **MFA (optional)** | TOTP für Plattform-Admins **und** Mandanten-Nutzer freiwillig; Policy-Flag „MFA-Pflicht" kann Erzwingung wiederherstellen; Recovery-Codes | ✅ |
|
||||
| **Benutzerverwaltung (Superadmin)** | Superadmin legt je Kunde Nutzer an (Initial-/Einmal-Passwort), weist Rollen zu, deaktiviert/reaktiviert, setzt Passwörter zurück | ✅ |
|
||||
| **Benutzer- & Rollenverwaltung (Kunde)** | Mandanten-Admin verwaltet **intern** Nutzer und Rollen (eigene Rollen + granulare Rechte, Standardrollen klonbar); strikt mandantengetrennt; Lockout-Schutz | ✅ |
|
||||
| **Nutzer-Onboarding ohne E-Mail** | Start mit Initialpasswort + erzwungenem Wechsel beim ersten Login; E-Mail-Einladung (Paket 4) später nahtlos ergänzbar | ✅ |
|
||||
| **Popup-Bedienung** | Anlegen/Bearbeiten von Nutzern über Popups wie bei Assets; Tabelle nur Anzeige | ✅ |
|
||||
| **Zuständigkeiten geklärt** | Superadmin steuert Kern-Einstellungen (Module, TISAX-Tiefe); Mandanten-Admin nur seinen Bereich (Stammdaten, Nutzer/Rollen) | ✅ |
|
||||
| **Richtlinien-Governance zentral** | Zentrale Variablen (Unternehmensname, Rollen, Schutzbedarf) nur in Einstellungen pflegbar; Coverage-Matrix zeigt nur Controls des aktiven Assessment-Levels (AL2 ohne „sehr hoch") | ✅ |
|
||||
| **Scoping & zentraler Schutzbedarf (A2)** | Anforderungs-Scope leitet sich zentral aus Assessment-Level (AL2/AL3), `FLAG_INCLUDE_SHOULD` und den Prüfzielen ab — nicht mehr aus dem Fragebogen; Schutzbedarf hat damit eine einzige, konsistente Quelle (AL → Flags). Scope-Filter (`scope-filter.ts`) + `c1-scope.json` (412 Anforderungen) | ✅ |
|
||||
| **Umsetzungshinweise (B5)** | Kontextsensitive C6-Umsetzungshinweise (~397 Blöcke) zu den Controls, als eigenes Panel unter `/policies/hints` und aus den Richtlinien verlinkt — praktische Hilfestellung bei der Umsetzung | ✅ |
|
||||
| **Validierungs-Workflow generalisiert (A3)** | Das Vier-Augen-/Review-Muster ist jetzt objekttyp-übergreifend nutzbar (nicht nur Aufgaben) — z. B. für Risiken | ✅ |
|
||||
| **ISMS-Rollen & Funktionstrennung (A4)** | Wizard-Schritt „Rollen": ISMS-Rollen zuweisen, Funktionstrennungs-Regeln FT-01…06 prüfen (z. B. ISB ≠ IT-Leitung), ISB-Bestellung | ✅ |
|
||||
| **Vorlagen-Versionierung & Diff (B6)** | Das Vorlagenpaket ist versioniert; Updates werden je Mandant kontrolliert per Diff-Ansicht (`/policies/updates`) übernommen statt blind überschrieben | ✅ |
|
||||
| **Assessment-Readiness & Export (B7)** | Readiness-Dashboard (Reifegrad-Interpretation, C9) **plus** VDA-ISA-Katalog-Export (CSV) und Management-Zusammenfassung — Grundlage für Reporting/Abschluss | ✅ |
|
||||
| **Wizard-Schritte Richtlinien & Risiken (B)** | Onboarding-Schritte 4 (Richtlinien) und 6 (Risiken) zeigen den echten Modul-Status statt Platzhaltern — der Wizard ist damit über alle 9 Schritte durchgängig | ✅ |
|
||||
| **Umsetzungshinweise im Control-Schritt (#10)** | Je Control-Anforderung lassen sich die Umsetzungshinweise **dokumentieren, abhaken und in eine Aufgabe überführen**; der Umsetzungsstatus je Spiegelstrich fließt in den Reifegrad ein (`ControlImplementation`) | ✅ |
|
||||
| **Aufgaben/Maßnahmen-Vereinheitlichung (7-9)** | Aufgaben und Maßnahmen im selben Bedien-Design (gemeinsamer Anlage-Dialog); Standardmaßnahmen aus dem Risikokatalog werden zu echten, verknüpften Maßnahmen; neue Rolle **`pm`** mit Voll-Sicht auf Aufgaben (`task:read_all`) | ✅ |
|
||||
| **Wizard-UX-Feinschliff (#1/#3/#6)** | Interne Identifier aus den Wizard-Texten entfernt, Assets-Schritt gibt Rückmeldung beim „Aufgaben anlegen", Aufgaben-Sichtbarkeit als Pool-Popup | ✅ |
|
||||
| **Asset-Schritt (A5)** | Wizard-Schritt 5 bindet das Bestands-/Asset-Modul ein — Assets werden im Onboarding erfasst statt separat | ✅ |
|
||||
| **Control-Assessment & Reifegrad (A7)** | Wizard-Schritt 7: Controls bewerten (Belegstatus, Reifegrad R0–R3, Zielreifegrad); offene Punkte erzeugen automatisch Gap-Aufgaben | ✅ |
|
||||
| **Standard-Risikokatalog (A6)** | Vorgefertigter Risikokatalog (C4) zum Übernehmen; Standardmaßnahmen erzeugen Aufgaben; dokumentierte **Restrisiko-Akzeptanz** (VA-09) | ✅ |
|
||||
| **Gap-Konsolidierung (A8)** | Wizard-Schritt 8 bündelt alle offenen Punkte/Gaps aus den Schritten — dedupliziert, priorisiert (Quick-Wins) und gleicht sie mit Aufgaben ab | ✅ |
|
||||
| **Freigabe-Workflow + Aufgaben** | Einreicher wählt Freigeber → Aufgabe; Freigeben/Ablehnen (mit Kommentar) im Modul „Aufgaben" (Vier-Augen); Dashboard-Kachel für offene Freigaben | ✅ |
|
||||
| **Nicht-destruktiver Re-Import** | Richtlinien-Paket-Updates erhalten Status/Freigabe/Overrides/Variablenwerte; entfernte Einträge werden deaktiviert statt gelöscht; Änderungsreport | ✅ |
|
||||
| **GAP-Report Richtlinien** | 6 neue Verfahrensanweisungen (VA-14..19), alle zuständigen VAs inline verlinkt, Rendering-Fehler behoben, verwaltete Register editierbar | ✅ |
|
||||
| **Software-Verwaltung** | Software ist ein Asset (Typ SOFTWARE) und wird im Lieferantenbereich unter „Software" gepflegt (Popups wie IT-Services): Anbieter/Lieferant, Version/Patch-Stand, Freigabestatus, Freigeber, Review. Ersetzt die frühere „Software-Whitelist" | ✅ |
|
||||
| **Projekte** | Projekte sind Assets (Typ PROJECT) im Assetinventar: bewertbar wie Assets (Kritikalität C/I/A), Risiken zuordenbar, IS-Klassifizierung, ISB-Einbindung, Projektstatus — Bedienung als Popup | ✅ |
|
||||
| **Kritische IT-Dienste** | Schreibgeschützte Auto-Sicht (`/assets?view=critical`): leitet kritische Dienste automatisch aus Verfügbarkeit und BIA ab, mit RTO/RPO aus den verknüpften Prozessen und Abhängigkeiten — keine gepflegte Doppelliste mehr | ✅ |
|
||||
| **Register-Konsolidierung** | Doppelte Register (externe IT-Dienste, Software-Whitelist, kritische Dienste, Projekte) entfernt und in die Fachmodule überführt; Richtlinien-Verweise zeigen jetzt auf die Module. REG-NET (Netzplan) auf ein Referenz-/Speicherort-Feld reduziert | ✅ |
|
||||
| **Produktmarke Certvia** | Die Anwendung heißt und erscheint durchgängig als **Certvia** — Logo und Wortmarke, Tab-/App-Icon, Seitentitel, Anmelde- und Fehlerseiten, Druckansicht. GEFIM bleibt als Dachmarke sichtbar („Ein Produkt von GEFIM"). Ohne eigenes Mandanten-Logo zeigt jeder Kunde Certvia. Reine Design-Umstellung ohne Funktionsänderung | ✅ |
|
||||
| **Wizard-Parallelisierung (Fix)** | Bearbeitung und Validierung im Onboarding-Wizard entkoppelt — Schritte können parallel bearbeitet werden, statt streng nacheinander; dazu `scripts/sync-role-permissions.ts` zum Nachziehen neuer Rechte für bestehende Mandanten | ✅ |
|
||||
|
||||
### 🟥 Bewusst zurückgestellt / offen
|
||||
|
||||
| Thema | Anmerkung |
|
||||
|-------|-----------|
|
||||
| **Paket 4 — SMTP + E-Mail-Einladungs-/Reset-Flow** | Auf Kundenwunsch später; Aktivierung läuft vorerst über Initial-/Einmal-Passwort, gekapselt für spätere Token-Aktivierung |
|
||||
| **Netzplan-Datei-Upload (REG-NET)** | Datei-Upload-/Storage-Infrastruktur existiert noch nicht; REG-NET verweist vorerst per Feld auf den extern gepflegten Netzplan. Upload als eigenes Paket (Storage-Backend + Coolify-Volume) |
|
||||
| **Tenant-weite MFA-Pflicht scharfschalten** | Flag `securityPolicy.mfaRequired` vorhanden + von „MFA deaktivieren" respektiert; Enrollment-Erzwingung beim Login noch nicht verdrahtet (analog Force-Change-Gate) |
|
||||
| **Admin Phase 2** | Impersonation, Plan/Limits, Logo-Upload, DSGVO-Export/Retention |
|
||||
| **NIS2-Modul** | nie begonnen (großes Framework, Incident-Reporting mit Fristen-Timern) |
|
||||
| **Richtlinien-Versionierung/Diff, DOCX/PDF-Export** | offen |
|
||||
| **ISB-Freigabe der neuen GAP-Texte** | fachlicher Prozessschritt (kein Code): neue/geänderte VA-/Richtlinien-Texte durch den ISB freigeben |
|
||||
| **Platzhalter-Module** | SoA & Controls, Vorfälle, Nachweise, Management-Review, KI-Chat |
|
||||
|
||||
---
|
||||
|
||||
## 3. Für neue Entwickler — technische Landkarte
|
||||
|
||||
> Setup, Stack, Konventionen und Fallstricke unverändert in **`docs/HANDOVER-DEV.md`** (§1–§9). Hier nur, was `dev` ergänzt.
|
||||
|
||||
### 3.1 Neue Datenmodelle (Prisma)
|
||||
|
||||
| Modell | Zweck | Mandantengebunden? |
|
||||
|--------|-------|--------------------|
|
||||
| `PlatformAdmin` | Getrennter Superadmin-Store (kein `tenant_id`), Argon2id, TOTP-Secret, Recovery-Codes, Lockout | nein (plattformweit) |
|
||||
| `PlatformSetting` (Singleton) | Plattform-Policy, u. a. `mfaRequired` | nein |
|
||||
| `Task` / `TaskComment` | Generisches Aufgaben-/Freigabe-Modell (erster Typ `policy_approval`), Kommentar-Historie | ja |
|
||||
| `ManagedRegister` / `RegisterRow` | Generisches editierbares Register (code, columns JSON, Cross-Links supplier/asset) | ja |
|
||||
| `SoftwareProfile` | 1:1 zu `Asset` (Typ SOFTWARE): Anbieter-Verknüpfung (`providerAssetId`→SUPPLIER), Version, Freigabestatus (`SoftwareApprovalStatus`), Freigeber, Kritikalität, Review | ja |
|
||||
| `ProjectProfile` | 1:1 zu `Asset` (Typ PROJECT): IS-Klassifizierung, ISB-Einbindung, `ProjectStatus`. Kritikalität via C/I/A am Asset, Risiken via `RiskAsset` | ja |
|
||||
| `AssetType` neu | Enum um `SOFTWARE` und `PROJECT` erweitert | — |
|
||||
| `User.*` neu | `mustChangePassword`, `mfaEnrolledAt`, `recoveryCodes` | ja |
|
||||
| `PolicyDocument.archivedAt`, `PolicyRequirement.archivedAt` | Lifecycle für nicht-destruktiven Re-Import (deaktivieren statt löschen) | ja |
|
||||
| `AuditLog.tenantId` nullable | Plattform-Ereignisse ohne Mandantenbezug (`scope=platform`) | — |
|
||||
| `WizardScope` (A2) | Scope des Onboarding-Wizards: Prüfziele, Geltungsbereich, Standorte, Ausschlüsse — Basis der Scope-Filter-Engine (`scope-filter.ts`) | ja (RLS) |
|
||||
| `ImplementationHint` (B5) | Globaler C6-Umsetzungshinweis-Katalog je Anforderung (organisatorisch/technisch/Nachweise/Ressourcen, AL-Filter) | nein (globaler Katalog, kein RLS) |
|
||||
| `PolicyPackageState` (B6) | Je Mandant: Version/Stand des importierten Vorlagenpakets — Basis für kontrollierte Diff-Übernahme von Updates | ja (RLS) |
|
||||
| `ControlAssessment` (A7) | Je Mandant/Control: Belegstatus, Reifegrad (R0–R3), Zielreifegrad — Basis für Gap-Aufgaben und SoA | ja (RLS) |
|
||||
| `RiskCatalogEntry` (A6) | Globaler Standard-Risikokatalog (C4) zum Übernehmen — Content identisch je Mandant | nein (globaler Katalog, kein RLS) |
|
||||
| `ControlImplementation` (#10) | Je Mandant/Control-Spiegelstrich: Umsetzungsstatus (dokumentiert/abgehakt), koppelt an Reifegrad und Aufgaben | ja (RLS) |
|
||||
| `Task.description` (7-9) | Beschreibungsfeld am bestehenden `Task` (Migration `task_description`) für die Aufgaben/Maßnahmen-Parität | ja |
|
||||
| `Risk.acceptedAt/By/Rationale` (A6) | Restrisiko-Akzeptanz-Felder am bestehenden `Risk` (Migration `risk_acceptance`) | ja |
|
||||
|
||||
Alle neuen tenant-gebundenen Modelle sind in **`TENANT_MODELS`** (`src/server/db.ts`) und haben **RLS-Policies** (in den jeweiligen Migrationen).
|
||||
|
||||
### 3.2 Auth-Architektur (wichtig!)
|
||||
|
||||
- **Zwei getrennte NextAuth-Instanzen:** Mandanten-Login (`src/server/auth.ts`, `/login`) und **Plattform-Login** (`src/server/platform-auth.ts`, eigener Cookie + basePath `/api/platform-auth`, `/platform/login`). Plattform-Session trägt **keinen** `tenantId`.
|
||||
- **Superadmin-Bereich** liegt unter `src/app/(platform)/…` (Layout erzwingt Plattform-Session + ggf. MFA); Mandanten-App unter `src/app/(app)/…`.
|
||||
- **MFA-Helfer** `src/server/mfa.ts` (otplib TOTP + Recovery-Codes) — von Plattform- und Nutzer-MFA gemeinsam genutzt.
|
||||
- **Force-Change:** `(app)`-Layout prüft Kontostatus/`mustChangePassword` autoritativ aus der DB → `/change-password` bzw. Abmelde-Screen bei deaktivierten Konten.
|
||||
- **Passwort-Policy:** `src/lib/password-policy.ts` (reine Validierung, client-safe) + `src/server/password.ts` (Argon2id + Generator); Quelle `TenantSettings.securityPolicy.password`.
|
||||
|
||||
### 3.3 Modul-Durchsetzung (§3.4) — Konvention für neue Actions
|
||||
|
||||
- Jede mutierende Server-Action eines **gegateten Moduls** läuft über `moduleGuard("<key>")` (`src/server/action-guard.ts`): Session → `assertModuleEnabled` → RBAC.
|
||||
- **Vollständigkeitscheck** `scripts/check-module-guards.ts` (als `prebuild` verdrahtet): jede Datei in `src/server/actions/` muss dort eingetragen sein (Modul-Key oder `EXEMPT`), sonst **failt der Build**. → Neue Action-Datei? Dort eintragen.
|
||||
- Neues Modul **`tasks`** in `src/lib/modules.ts` (für Bestands-Tenants per Default aktiv, da fehlende `TenantModule`-Zeile = aktiv).
|
||||
|
||||
### 3.4 Wo liegt was (neu)
|
||||
|
||||
- **Superadmin/Plattform:** `src/app/(platform)/admin/**`, `/platform/{login,enroll-mfa,profile}`, `src/server/actions/{admin,platform,platform-users}.ts`.
|
||||
- **Benutzer-/Rollenverwaltung (Kunde):** `src/app/(app)/settings/users/`, `src/server/actions/{tenant-users,account}.ts`, Komponenten `user-table.tsx`/`user-forms.tsx`/`role-manager.tsx`.
|
||||
- **Aufgaben/Freigabe:** `src/app/(app)/tasks/`, `src/server/actions/tasks.ts` (+ `submitForApproval` in `policies.ts`); Dashboard-Kachel in `dashboard/page.tsx`.
|
||||
- **Register:** `src/components/generic-register.tsx`, `src/server/actions/register.ts`, Definitionen in `prisma/import-managed.ts` (`GENERIC_REGISTERS` + `RETIRED_REGISTERS`-Cleanup).
|
||||
- **Software (Lieferantenbereich):** Tab in `src/app/(app)/suppliers/page.tsx` (`?tab=software`), `src/components/software-modals.tsx`, `src/server/actions/software.ts`, `SOFTWARE_INCLUDE` in `src/lib/supplier-include.ts`.
|
||||
- **Projekte (Assetinventar):** Typ-Filter/Popup in `src/app/(app)/assets/page.tsx`, `src/components/project-modals.tsx`, `src/server/actions/projects.ts`, `PROJECT_INCLUDE` in `src/lib/supplier-include.ts`.
|
||||
- **Kritische IT-Dienste:** Auto-Sicht-Zweig in `src/app/(app)/assets/page.tsx` (`?view=critical`) — abgeleitet aus Verfügbarkeit + BIA (`ProcessAsset`→`Process`→`BiaEntry`); Link-Ziel von `resolveLink("REG-CRIT-SERVICES")`.
|
||||
- **Richtlinien-Import (nicht-destruktiv):** `prisma/import-policies.ts` (Diff/Upsert, `{ dryRun }`, Änderungsreport, `archivedAt`).
|
||||
- **Richtlinien-Import/Upload (B4):** Actions `src/server/actions/policy-package.ts` (Import-Kapselung: Self-Service `importPolicyPackage` + Plattform `importPolicyPackageForTenant`) und `policy-upload.ts` (`uploadOwnPolicy`); Aktivierungs-Trigger in `toggleTenantModule` (`admin.ts`); Storage-Adapter `src/server/storage/adapter.ts` (Stub, Epic S1); UI `src/app/(app)/policies/page.tsx` (Buttons + Report-Banner) + `src/app/(app)/policies/upload/page.tsx`. Eigene Uploads liegen im Namensraum `EIG-*` (außerhalb des Paket-Namensraums → vom Re-Import unberührt).
|
||||
- **Branding (in `dev`):** Tokens in `src/app/globals.css` (`--brand-*` / `--ui-*`) mit JS-Pendant `src/lib/brand.ts`; Komponenten `src/components/brand/{certvia-logo,tenant-brand,powered-by-gefim}.tsx`; Assets `public/assets/logo/`, `public/favicon/`, `public/site.webmanifest`; Dokument-/Mail-CD `src/lib/{document-brand,email-brand}.ts`; Doku `docs/BRANDING-CERTVIA.md` (+ Design-Paket unter `docs/branding/`).
|
||||
- **Vorlagenpaket (Source of Truth):** `seed/isms-vorlagenpaket-v2/` — 28→**37 Dokumente** (VA-14..19; **P01/D01/VA-20** neu für Prototypen-/Datenschutz, B4-3), `mapping.json` (321 Anforderungen), `variables.schema.json`, Baseline, Nachweisregister, **`_verify.py`** (Rendering-/Anker-Check; nach Änderungen `python3 _verify.py` → **OK**).
|
||||
|
||||
### 3.5 Konventionen / Fallstricke (Ergänzungen)
|
||||
|
||||
- **Dev-Server & Server-Actions:** Änderungen an Server-Actions greifen im Turbopack-Dev manchmal erst nach **Neustart** des Dev-Servers.
|
||||
- **Migrations-Flow Prisma 7** wie gehabt (`migrate diff --from-config-datasource … --to-schema … --script`, dann RLS-DO-Block manuell anhängen, `migrate deploy`). Data-Migrationen (z. B. `strip_tool_variable_articles`) sind reine SQL-`UPDATE`-Migrationen.
|
||||
- **Geteilte DB bei paralleler 2-Lane-Entwicklung (Dev A × Dev B):** Beide Worktrees zeigen auf **dieselbe** lokale Postgres-DB. Dadurch enthält `migrate diff --from-config-datasource` **fremde**, vom anderen Branch angewandte Schemaänderungen (z. B. wollte A1-1 fälschlich Dev Bs `tasks`-Spalten `links/origin/priority/resources` droppen). **Regel:** beim Erzeugen einer Migration nur die **eigenen** DDL-Blöcke übernehmen und Fremd-Drops von Hand entfernen; anschließend prüfen, dass die Spalten/Objekte des anderen erhalten sind. Migrations-Reihenfolge & „nie gleichzeitig" strikt nach Contracts §6. **Merge-Nachsorge:** Wird eine Migration im anderen Branch neu erzeugt (anderer Timestamp) und die geteilte DB hat noch die alte angewandt, meldet `migrate status` „applied ≠ lokal". Fix ohne Datenverlust: stalen `_prisma_migrations`-Eintrag löschen + `prisma migrate resolve --applied <neuer_name>` (kein SQL läuft neu). So geschehen bei `tasks_wizard_fields` (`…103650` in DB → `…104412` committet).
|
||||
- **Zentrale Variablen** (Organisation/Rollen/Schutzbedarf-Flags, `src/lib/policy-variables.ts`) sind im Richtlinien-Editor gesperrt und werden serverseitig geblockt — nur in `/settings` pflegbar.
|
||||
- **Rendering (Variante B):** Tool-Variablen-Defaults ohne führenden Artikel (`TOOL_TICKET`=„Ticketsystem" etc.); der Fließtext setzt Artikel/Deklination. Bestandswerte werden per Migration migriert.
|
||||
- **Register vs. Managed-Register-Docs:** die verwalteten Register (CRYPTO/RISKMATRIX/CLASSIFICATION/HANDBUCH) sind spezifische Modelle; die verbliebenen `REG-*` (SENS-ROLES, AUDIT-PLAN, NET) nutzen das **generische** `ManagedRegister`-Modell. `importPolicies` archiviert nur den Paket-Namensraum (L00/R*/VA-*/BASELINE/NACHWEIS) — Register bleiben unberührt.
|
||||
- **Register-Konsolidierung (Block 5):** REG-EXT-SERVICES / REG-SW-WHITELIST / REG-CRIT-SERVICES / REG-PROJECTS sind **stillgelegt** (Liste `RETIRED_REGISTERS` in `import-managed.ts` löscht Dokument + `ManagedRegister` + Zeilen idempotent beim Import). Ihre `{{LINK:REG-…}}` in den Seed-Texten bleiben unverändert — nur `resolveLink` (`src/lib/policy-render.ts`) biegt sie auf die Modul-Routen um (`/suppliers?tab=services|software`, `/assets?view=critical`, `/assets?type=PROJECT`). Wer ein Register neu stilllegen will: Code aus `GENERIC_REGISTERS` entfernen, in `RETIRED_REGISTERS` eintragen, `resolveLink`-Fall ergänzen.
|
||||
- **Software/Projekte als Asset-Typen:** folgen exakt dem bestehenden Muster von SUPPLIER/IT_SERVICE (Asset + 1:1-Profil, `refNo` je Mandant, Cockpit-Popups auf `/suppliers` **und** `/assets`, backHref-gesteuert). Neue Action-Dateien (`software.ts`→`suppliers`, `projects.ts`→`assets`) sind in `scripts/check-module-guards.ts` registriert.
|
||||
|
||||
### 3.6 Demo-Logins (Passwort `Demo1234!`)
|
||||
|
||||
- Mandanten-Login `/login`: `admin@demo.example` (Mandanten-Admin + ISB), **`bea.approver@demo.example`** (ISB, zweiter Freigeber für den Vier-Augen-Workflow), `auditor@…`, `owner@…`, `user@…`.
|
||||
- Plattform-Login `/platform/login`: `admin@demo.example` (getrennte Session; MFA optional, Enrollment beim ersten Login nur wenn Policy es verlangt).
|
||||
|
||||
---
|
||||
|
||||
## 4. Commit-Übersicht (`main..dev`, neueste zuerst)
|
||||
|
||||
```
|
||||
55260a7 Merge SEC3+SEC4 (MFA pro Mandant erzwingen, WebAuthn/Passkeys, TOTP-Verschlüsselung at rest, Plattform-Admin-Verwaltung) in dev
|
||||
8a154f0 Merge TISAX v7-Fortsetzung (Fachbereich-Ableitung beim Import, Richtlinien nach Fachbereich im Onboarding, parametrisierbares Redirect-Ziel) in dev
|
||||
a0c0d14 Merge TISAX v6/v7 (ABGABE-xlsx-Export, echter MinIO/S3-Adapter, PolicyDocument.domain/Fachbereich, Audit-Permissions) in dev
|
||||
850b691 Merge TISAX v5 (Audit-Vorbereitung Phase 1: Audit-Übersicht/Wizard-Shell, Readiness/GAP-Tab, Nachweise-Tab, Control-Beschreibungen mit KI-Entwurf + ABGABE-CSV-Export) in dev
|
||||
6370cee Merge TISAX v4 (Prozesshaus-Ausbau: Löschen, Katalog-Teilprozesse parentCode, Details-Overlay; BIA-Popup vereinfacht + Träger-/Risiko-Neuanlage) in dev
|
||||
23df560 Merge TISAX v3 (Prozesshaus + geführtes BIA je Prozess, Popup-Bearbeitung Rollen/Kriterien, zusätzliche Prozess-Felder) in dev
|
||||
f1c11aa Feature: Plattform-Konsole legt Tenant-Nutzer per Einladungslink an (wie Mandanten-Admin)
|
||||
2bfc071 Merge TISAX-Integration (M0–M4 + Wizard-Neustruktur) in dev — Fundament, Strukturanalyse, Cockpit (RACI/Evidence), Audit-Wizard, TISAX-Tasks, Content-Seed; 3 Migrationen + RLS für neue Tabellen
|
||||
2fd522c Feature: Benutzer-Anlegen verschickt Einladungslink per Mail (invitation-Template, /reset-Token 7 Tage) statt Passwort-Anzeige
|
||||
4d28c86 Fix: Benutzer-/Mail-Actions graceful statt Fehlerseite + Formular-Werterhalt
|
||||
6b4c6fb Coolify: Mail-Worker-Service (SEC1) ergänzt
|
||||
c47ace0 Merge SEC1+SEC2: Mailversand/Queue (SEC1, BullMQ/ioredis/nodemailer, Worker) + Auth-Self-Service (SEC2, AuthToken, Reset/Passwortwechsel/E-Mail-Änderung, Session-Invalidierung, Rate-Limit) in dev
|
||||
3998f9f Fix: /tasks SSR-Crash — entfernte Variable `open` im Untertitel wiederhergestellt
|
||||
3932ff2 Merge 7-9/4: Aufgaben als Kanban-Board (Maßnahmen-Design) + Vorschläge/Bearbeiten korrigiert in dev
|
||||
00e7e79 Dockerfile: Fachcontent (docs/wizard-uebergabe) ins migrate-Image für Demo-Seed (C4/C6)
|
||||
fb1935e Dockerfile: Richtlinien-Vorlagenpaket (seed/) in migrate- und runner-Image
|
||||
d0dfe0b Merge Security: P1/P2/P3-Härtungspaket (F-01…F-20) in dev — Tenant-Isolation, Auth/Session, RLS scharf (F-04), moduleGuard-DB-Authz (F-06), Web-Härtung, MFA-Replay, Supply-Chain/Container (F-11/F-18)
|
||||
63b583d Merge Dev-A: A6-1 + A6-2 (Standard-Risikokatalog C4, Standardmaßnahme→Aufgabe, Restrisiko-Akzeptanz) in dev
|
||||
e6c5e51 Merge Dev: UX-Fixes (#1/#3/#6) + Aufgaben/Maßnahmen-Vereinheitlichung (7-9) + Umsetzungshinweise Control-Schritt (#10, ControlImplementation) in dev
|
||||
6b4b190 Merge Dev-B: Wizard-Schritte 4 (Richtlinien) + 6 (Risiken) — echte Komponenten statt Platzhalter in dev
|
||||
0629613 Merge Branding: Umstellung auf Certvia (Design-Tokens, Logo/Icons, Metadaten, i18n, Auth-/Systemseiten, Dokument-CD) in dev
|
||||
7f4a85c Merge Fix: Wizard-Bearbeitung von Validierung entkoppeln (Parallelisierung) + Rollen-Rechte-Sync-Skript in dev
|
||||
6b20e13 Merge Dev-B: B7-2 (VDA-ISA-Katalog-Export CSV + Management-Zusammenfassung, C9) in dev
|
||||
2cc422c Merge Dev-A: A8-1/A8-2 (Gap-Konsolidierungs-Engine) + A8 (Gap-Schritt 8: Aggregation/Priorisierung/Task-Abgleich) in dev
|
||||
76cfebc Merge Dev-A: A5-1 (Asset-Schritt) + A7-1/A7-2 (Control-Assessment + Reifegrad-Engine) in dev
|
||||
7dc5ae1 Merge Dev-B: B6 (Vorlagenpaket-Versionierung + kontrollierte Diff-Übernahme) in dev
|
||||
1238564 Merge Dev-B: B7-1 (Assessment-Readiness-Dashboard + Interpretationstexte C9) in dev
|
||||
de76856 Merge Dev-A: A4 (ISMS-Rollen Schritt 3 + Funktionstrennung FT-01…06) in dev
|
||||
012c0fa Merge Dev-B: Prüfziele als Single Source aus WizardScope (Doppelquelle behoben) in dev
|
||||
227d7a3 Merge Dev-A: A3-1 (generisches Objekt-Review / Validierungs-Workflow) in dev
|
||||
8c9f648 Merge Dev-B: B5-1 + B5-2 (Umsetzungshinweise C6, kontextsensitives Panel) in dev [+ 98d5e26 B5-1, 93e2f44 B5-2]
|
||||
d5c11df Merge Dev-A: A2-1 + A2-2 (Assessment-Level zentral, Scope-Filter) in dev [+ 69cc25a A2-1, 177df8b A2-2]
|
||||
78be114 Doku: STAND B4 · c473cad B4-3 (P01/D01/VA-20) · eb7c899 B4-2 (Upload) · 269506b B4-1 (Import) — Dev B, per FF in dev
|
||||
4e1b116 Merge Dev-B: B3 Fragebogen (Schritt 2 context) in dev [+ f818093 B3-Feature-Commit]
|
||||
872c35e Merge Dev-B: F3+B2 Regel-/Mapping-Engine in dev [+ 20afd63 B2-Feature-Commit]
|
||||
(DevOps-Integration: dev-b2-regel-engine + dev-b3-fragebogen additiv gemergt; Gate grün)
|
||||
b9d8027 Story A1-2: Dashboard-Kachel „Onboarding-Fortschritt" (Dev A)
|
||||
949d7c5 Story F2: ObjectReviewStatus + external_validator + Wizard-Validierung (Dev A)
|
||||
12c94fe Merge Dev-B-Lane in dev: F1 + B1 + F4 (Konsolidierung beider Lanes)
|
||||
0d52090 F4: Wizard-Flags in variables.schema.json (Dev B)
|
||||
ddd2dc4 B1: Auto-Generierung von Aufgaben-Vorschlägen (C2 §8) (Dev B)
|
||||
30c3638 F1: Task-Objekt um Wizard-Felder erweitern (Contracts §1) (Dev B)
|
||||
97b3b4e Story A1-1: Onboarding-Wizard-Shell (Step-Registry, State-Machine, Gate) (Dev A)
|
||||
(darüber Wizard-Kickoff-Commits: Sign-off, Dev-B-Bestätigung, Contracts, Übergabepaket)
|
||||
(sowie lokale Doku-Commits — Onboarding-Prompt + STAND-Updates)
|
||||
f368d8f Fix: Fonts selbst hosten (next/font/local) + Bootstrap an Superadmin-Store anpassen
|
||||
cc8d486 Feat: Prod-Bootstrap (Erst-Superadmin) + Contabo-Runbook
|
||||
── ab hier auf origin/dev (gepusht) ──
|
||||
9b479ab Software und Projekte als Assets + Auto-Sicht kritische Dienste
|
||||
150a1d9 Register-Konsolidierung: 4 Register in Fachmodule überführt
|
||||
0806030 Datenmodell: Asset-Typen SOFTWARE und PROJECT mit Fachprofilen
|
||||
2ec0230 Doku: Konsolidierte Übergabe des dev-Stands (PM + neue Entwickler)
|
||||
95d4479 GAP WP3.1: IMPL-Texte mit verwalteten Registern verdrahtet
|
||||
bd56a47 GAP WP3.0: Generisches, editierbares Register-Datenmodell + Editor
|
||||
b9784e5 GAP E2: ISA 3.1.3-Stub entfernt (3.1.2 deprecated)
|
||||
b7d5df4 GAP WP2.2 (Rendering Variante B) + WP4 (Feinschliff)
|
||||
36c2903 GAP WP1: Neue VAs 14–19 + Register + Baseline + Eltern-Wiring
|
||||
522508a GAP WP2.1: Inline-VA-Verweise + Verify-Fix (F17)
|
||||
742277f Doku: Benutzer-Popups, Aufgaben-Modul, Richtlinien-Governance, Demo-Approver
|
||||
1d8f563 Freigabe-Workflow + Aufgaben-Modul + Dashboard-Kachel
|
||||
73c9813 Benutzerverwaltung als Popup (Einstellungen + Admin)
|
||||
959d816 Richtlinien-Fixes: zentrale Variablen, Schutzbedarf zentral, Coverage nach Level
|
||||
d38b265 Benutzer bearbeiten (Name/E-Mail) + Kern-Einstellungen nur Superadmin
|
||||
303dcd0 Doku: Produktionshärtung + Benutzer-/Rollenverwaltung
|
||||
d0821e2 Paket B — Mandanten-Admin: Benutzer- & Rollenverwaltung
|
||||
3db820e Paket C — MFA optional (Superadmin + Tenant)
|
||||
908b098 Paket A — Plattform-Admin: Benutzerverwaltung je Mandant
|
||||
db36c79 Fundament Benutzer-/Rollenverwaltung: Schema, Passwort-Policy, Force-Change
|
||||
e07dcd9 Nicht-destruktiver Richtlinien-Re-Import (Härtung Paket 3)
|
||||
8e4040d Separater Superadmin-Store + eigener Login + MFA (Härtung Paket 2)
|
||||
8348764 API-seitige Modul-Durchsetzung (§3.4, Härtung Paket 1)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Deployment & Verifikation
|
||||
|
||||
- **Test-/Coolify-Deploy (Demo):** `dev` deployen; die 7 neuen Migrationen laufen automatisch im Init-Container (`prisma migrate deploy`), Bootstrap-Seed legt Demo-Daten + Demo-Approver an. Die letzte Migration ändert das `AssetType`-Enum und legt zwei RLS-Tabellen an — einmal komplett durchlaufen lassen, bevor die neuen Ansichten getestet werden.
|
||||
- **Prod-Deploy (ohne Demo-Seed):** Runbook **`docs/DEPLOY-PROD-CONTABO.md`**. Statt Demo-Seed läuft `scripts/bootstrap-admin.ts` (Erst-Superadmin im `platformAdmin`-Store + Mandant/Mandanten-Admin, idempotent), gesteuert per `BOOTSTRAP_*`-Env im `migrate`-Job der `docker-compose.coolify.yml`; Env-Referenz `.env.prod.example`. Fonts sind selbst gehostet (kein Google-Fonts-Fetch zur Build-Zeit → reproduzierbarer Offline-Build).
|
||||
- **Lokale Verifikation:** `npx tsc --noEmit` → `npm run lint` → `npm run build` (führt `prebuild`-Guard-Check aus); für das Vorlagenpaket `python3 seed/isms-vorlagenpaket-v2/_verify.py` (**OK** = rückstandsfrei, Mapping sauber).
|
||||
- **Sync-Status (Gitea aktuell offline):** lokaler `dev` ist **27 Commits vor `origin/dev`** (inkl. der beiden Dev-B-Integrations-Merges F3+B2 und B3). Sobald Gitea erreichbar ist: **erst `git fetch`**, prüfen ob `origin/dev` noch `9b479ab` ist (bzw. ob jemand anderes gepusht hat), dann `git push origin dev`. Bei Divergenz nicht blind force-pushen — abstimmen.
|
||||
- **Merge `dev` → `main`:** liegt beim PM/Lead (Gitea-PR: `…/msolarczek/ISMS-Tool/pulls/new/dev`).
|
||||
|
||||
---
|
||||
|
||||
## 6. Empfohlene nächste Schritte
|
||||
|
||||
1. **ISB-Freigabe** der neuen/angepassten Richtlinien- und VA-Texte (fachlich, inkl. **P01/D01/VA-20** aus B4-3).
|
||||
2. **Storage-Backend (Epic S1)** — echten Adapter hinter `src/server/storage/adapter.ts` (B4-2-Stub) einhängen (S3/MinIO/Coolify-Volume); danach Datei-Persistenz eigener Richtlinien + Netzplan-Upload REG-NET.
|
||||
3. **Wizard-Stories vollständig konsolidiert** — Dev A: A1–A8, Dev B: F1–F4, B1–B7 (inkl. B7-2 Export + Prüfziel-Follow-up). **Alle Feature-Branches in `dev`.** Als Nächstes (neue Stories/Epics): SoA-/Reifegrad-Auswertungen auf Basis von A7, Reporting-Ausbau auf Basis des VDA-ISA-Exports, echtes Storage-Backend (Epic S1).
|
||||
4. **Paket 4** — SMTP + E-Mail-Einladungs-/Aktivierungs-/Reset-Flow (Aktivierung ist bereits gekapselt).
|
||||
5. **Tenant-weite MFA-Pflicht** scharfschalten (Enrollment-Gate).
|
||||
6. **Admin Phase 2** (Impersonation, Plan/Limits) oder **NIS2-Modul** — je nach Vertriebs-/Compliance-Priorität.
|
||||
|
||||
## Hotfix: Docker-Build brach ohne PASSWORD_PEPPER ab (Deploy-Blocker)
|
||||
- **Symptom:** Coolify-Deploy „erfolgreich", aber KEINE certvia-Container. Ursache war der Image-Build selbst: `RUN npx prisma generate && npm run build` (Dockerfile:40) exit 1 → kein `up`.
|
||||
- **Root Cause:** `src/server/auth.ts` erzeugte den Konstant-Zeit-Dummy-Hash auf **Modulebene** (`const DUMMY_HASH_PROMISE = hashPassword(...)`). `hashPassword()` liest den `PASSWORD_PEPPER`, der zur Docker-**Build**-Zeit fehlt (nur `DATABASE_URL`-Platzhalter gesetzt). `next build` (Page-Data-Collection für `/api/auth/[...nextauth]`) lud das Modul → Import-Zeit-Throw (fail-secure) → Build-Abbruch. Lokal grün, weil `.env` den Pepper liefert (im Image per `.dockerignore` ausgeschlossen).
|
||||
- **Fix:** Dummy-Hash lazy + memoisiert (`dummyHash()`), Aufruf erst zur Laufzeit in `verifyIdentityPassword` — gleiches Muster wie `assertSecureEnv()`/`pepper()`. Konstant-Zeit-Verhalten (F-05) bleibt erhalten.
|
||||
- **Verifiziert:** `docker build --target builder` grün OHNE gesetzten `PASSWORD_PEPPER` (Coolify-Build-Bedingung); tsc grün.
|
||||
|
||||
## Hotfix 2: incident-inbound-worker Crash-Loop riss den Stack ab
|
||||
- **Symptom (nach Build-Fix):** migrate ✅, app ✅ `Ready`, mail-/backup-worker ✅ — aber Coolify-Status flippte auf „exited" und riss den ganzen Stack ab. Ursache: `incident-inbound-worker` ohne IMAP-Konfig `process.exit(1)` + `restart: unless-stopped` → Crash-Loop → Coolify wertet Deploy als unhealthy → `compose down` (auch der gesunden App).
|
||||
- **Fix:** `scripts/incident-inbound-worker.ts` idlet jetzt bei fehlender IMAP-Konfig (`idleUntilSignal()`), statt zu exiten. Container bleibt „running", SIGTERM beendet sauber (Exit 0). Bei nachträglicher IMAP-Konfig: Container-Neustart aktiviert den Betrieb.
|
||||
- **Verifiziert:** tsc grün; Smoke-Test ohne IMAP-Env → Prozess bleibt am Leben, loggt Idle-Hinweis, kein Crash.
|
||||
|
||||
## Merge: Objektspeicher MinIO → Garage (self-hosted)
|
||||
- feature/garage-migration → dev (`--no-ff`). Umsetzung des Konzepts `docs/KONZEPT-garage-migration.md` (4 Lanes), keine Datenmigration (nur Test-Instanzen, Neu-Deploy).
|
||||
- **Infra:** `garage`-Service ersetzt `minio` in `docker-compose.yml` + `docker-compose.coolify.yml`; `deploy/garage.toml` (Single-Node, `s3_region=us-east-1`, RPC-/Admin-Token); Volumes `garage_meta` (kritisch, ins Backup) + `garage_data`.
|
||||
- **Provisioning:** `scripts/garage-provision.ts` — idempotenter Init-Job (Layout + Bucket `isms-documents` + Key-Import aus S3_*-Env + Rechte).
|
||||
- **App-Code:** `ensureBucket()` in `adapter.ts` + `backup-store.ts` nur noch verifizierend (HeadBucket), **kein** S3-`CreateBucket` mehr (Garage kann das nicht); fehlender Bucket → sprechender Konfigfehler statt stiller Heilung. `CreateBucketCommand`-Imports entfernt.
|
||||
- **Test/Doku:** `scripts/test-garage-storage.ts` (skippt ohne `S3_ENDPOINT`, echter E2E mit gesetzten S3_*), Runbook in `docs/DEPLOY-COOLIFY.md`.
|
||||
- **Gate grün:** tsc, lint, build, Storage-Smoke-Test.
|
||||
- **Deploy-Hinweise:** Coolify-Env `S3_ENDPOINT=http://garage:3900`, `S3_REGION=us-east-1`, `GARAGE_RPC_SECRET`/`GARAGE_ADMIN_TOKEN` **literal** setzen (Interpolationsfalle); `minio`-Service erst nach Abnahme entfernen (Rollback-Netz).
|
||||
|
||||
## Hotfix Garage-Deploy: garage.toml ins Image backen (Coolify-Bind-Mount-Falle)
|
||||
- **Symptom:** `garage`-Container crasht ~2s nach Start → unhealthy → Deploy bricht ab. Log: `Error: IO error: Is a directory (os error 21)` nach „Loading configuration…".
|
||||
- **Ursache:** Coolify legt die Quelle des relativen Bind-Mounts `./deploy/garage.toml` als **Verzeichnis** an (Storage-Behandlung) → Garage bekommt `/etc/garage.toml` als Ordner.
|
||||
- **Fix:** Neue Dockerfile-Stage `garage` (`FROM dxflrs/garage:v1.2.0` + `COPY deploy/garage.toml /etc/garage.toml`); `docker-compose.coolify.yml` nutzt `build: target garage` statt `image:` + Bind-Mount. Secrets bleiben zur Laufzeit aus `GARAGE_RPC_SECRET`/`GARAGE_ADMIN_TOKEN`. Lokales `docker-compose.yml` behält den Bind-Mount (auf normalem Docker unkritisch).
|
||||
- **Verifiziert:** `docker build --target garage` + Start mit gültigem Secret → Daemon läuft, `/garage status` Exit 0.
|
||||
|
||||
## Merge: Framework-Erweiterung — ISO 27001 neben TISAX (AP1–AP5 + B1)
|
||||
- Kumulativer Merge von `feature/framework-assessment` (enthielt alle Framework-Lanes: iso27001-framework-mapping, framework-core, ap2, ap3-soa, ap4-mgmt, ap5-doccontrol, assessment) → `dev` (`--no-ff`, a747b57). 150 Dateien.
|
||||
- **AP1** Framework-Dimension (`TenantFramework`, `PolicyTemplateVersion.framework`), **AP2** Provisionierung & Framework-Flags + framework-fähiger Vorlagen-Editor, **AP3** SoA-Modul (ISO-Anwendbarkeitserklärung, 93 Annex-A-Zeilen), **AP4** Managementklauseln (9.1/9.3/10.2, CAPA + Wirksamkeitsprüfung), **AP5** Dokumentenlenkung (Prüfzyklen, Versionshistorie, Lesebestätigungen), **A1–A4/B2/B3** ISO-Inhalte, **B1** Assessment-/Readiness-Strategie-Schicht.
|
||||
- **Variante A** (Konzept D4): ein Dokumentensatz, zwei Mappings — `docs/FRAMEWORK-MAPPING-ISO27001.md`, `docs/KONZEPT-framework-iso27001.md`.
|
||||
- **Gate grün:** tsc, lint, build. Neue Tests grün: `test-framework-{core,templates,provision,assessment,dryrun}`, `test-{assessment-iso,soa,doc-control,review}`. **TISAX-Snapshot-Regression: 0 Abweichungen** (45 Controls, AL2) — TISAX-Verhalten bit-genau erhalten.
|
||||
|
||||
## Fix: Normen (Frameworks) je Mandant nachträglich umschaltbar
|
||||
- `cb2bc0b` Admin-Action + UI (`admin/[id]/page.tsx`, `actions/admin.ts`, i18n de/en): ISO/TISAX pro Mandant nachträglich aktivieren/deaktivieren. `1475193` Abnahmetest-Fix: „wiedererkannt" zählt reaktivierte Dokumente mit.
|
||||
- Neuer Test `scripts/test-framework-toggle.ts` (Aktivieren/Deaktivieren + Zustand wiederherstellen). Gate grün: tsc/lint/build, test-framework-toggle/-dryrun, TISAX-Snapshot 0 Abweichungen.
|
||||
|
||||
## BIA-Prozessübersicht: Prozesshaus-Ansicht (Standard) + Tabellen-Umschalter
|
||||
- `/processes` (`src/app/(app)/processes/page.tsx`) zeigt statt der flachen Tabelle standardmäßig ein **Prozesshaus**: Bahnen nach Kategorie (Management/Kern/Support), Hauptprozesse als aufklappbare Karten (native `<details>`), Teilprozesse eingerückt (Baumkonnektor). Je Hauptprozess **BIA-Rollup** aus den Teilprozessen: Kritikalität = Maximum, RTO/RPO/MTD = schärfster (kleinster) Wert; Farbcode + Statuspunkt nach `biaStatus`; Schnittstellen (`Process.interfaces`) als Chip. Umschalter „Prozesshaus ⇄ Tabelle“ über `?view=tabelle` (Prozesshaus = Default); Tabellen-Ansicht unverändert.
|
||||
- **Kein Datenmodell-Umbau** — nutzt vorhandene Felder (`parentId`, `category`, `biaStatus`, `BiaEntry`). KPIs: Prozesse gesamt / im Scope / BIA vollständig / hohe Kritikalität (≥3). Modals (Detail/Anlegen/Bearbeiten) unverändert. Neue i18n-Keys unter `processes` (de/en). Gate grün: tsc/lint/build. Konzept-Mockup: `docs/MOCKUP-bia-prozessuebersicht.html`.
|
||||
- **Nachtrag — jetzt umgesetzt:** strukturierte Prozess-zu-Prozess-Abhängigkeiten (siehe nächster Abschnitt); der frühere Freitext `interfaces` bleibt zusätzlich erhalten.
|
||||
|
||||
## Prozess-Abhängigkeiten (strukturiert: „benötigt" / „wird benötigt von")
|
||||
- Neues Modell **`ProcessDependency`** (`source` benötigt `target`, optionale `note`), Migration `20260907084110_add_process_dependencies` **inkl. RLS** (tenant_isolation + FORCE), Unique `(source, target)`, FK-Cascade beim Prozess-Löschen; in `TENANT_MODELS` aufgenommen. Auswahl **innerhalb des Mandanten**.
|
||||
- Server-Actions in `actions/processes.ts`: `addProcessDependency` (idempotenter Upsert, Selbstbezug ausgeschlossen, beide Prozesse müssen existieren) und `removeProcessDependency`; `deleteProcess` löst Kanten in beide Richtungen. Beide `bia:write`-gegated + Audit-Log.
|
||||
- UI: Bearbeiten-Modal neuer Abschnitt „Abhängigkeiten" (Chips + Entfernen, Auswahl-Form „benötigt: [Prozess] + Notiz", plus read-only „wird benötigt von"); Detail-Modal zeigt beide Richtungen; **Prozesshaus** zeigt „↳ benötigt: …"-Chips und „▲ N Prozesse hängen hiervon ab" (Teilprozesse kompakt inline) + Link zum Abhängigkeits-Graph. Neue i18n-Keys `deps*` (de/en). Gate grün: tsc/lint/build, Modul-Guard-Check 45 Dateien ok.
|
||||
- **Netz-/Graph-Darstellung:** `buildDependencyGraph` (`src/server/dependency-graph.ts`) um Prozess→Prozess-Kanten (`ProcessDependency`, Label „benötigt von", Flussrichtung Abhängigkeit→Nutzer) erweitert; sie erscheinen im bestehenden Graphen `/dependencies` (React Flow + dagre) und fließen in Analyse/kritischen Pfad ein. SPOF-Erkennung jetzt auch für **Prozesse** (gemeinsam benötigte Prozesse wie „IT-Betrieb", von denen mehrere kritische Prozesse abhängen). Neuer Client-Filter **„Nur Prozesse"** in `dependency-graph.tsx` (blendet Assets aus → reine Prozess-Abhängigkeitskarte). Verifiziert am `demo`-Mandanten: IT-Betrieb als SPOF (3) korrekt erkannt.
|
||||
|
||||
## Datenimport (Excel) — zurückgezogen
|
||||
- Das zuvor auf `dev` ergänzte Excel-Datenimport-Feature (geteilte Logik `src/server/import/`, UI `/settings/import`, Ops-Skript, Tabelle `ImportRef`/Migration `20260904081701_add_import_refs`, Konzept `KONZEPT-datenimport.md`) wurde **vollständig entfernt** (nie deployt, daher ohne DB-Auswirkung). Bestandsdaten werden weiterhin über die Modul-Formulare bzw. den Onboarding-Wizard erfasst.
|
||||
- `docs/HANDBUCH-KUNDENBETREUUNG.md` bleibt als produkt-/supportorientiertes Einstiegshandbuch für die Kundenbetreuung (Zugang/Rollen, Provisionierung, Framework-Wahl, Module, Onboarding, Support-Fälle, Doku-Verweise) — die Datenimport-Abschnitte wurden herausgenommen.
|
||||
|
||||
## Fix: Risikokriterien 5×5 vervollständigt (Matrix ↔ Einstellungen konsistent)
|
||||
- Bug: Risiko-Bewertung (Formular-Skala 1–5, Matrix 5×5, Score-Schwellen bis 25) war 5×5, aber die Kriterien-Daten nur 4-stufig geseedet (EW_LEVELS=4, Schadensdimensionen 1–4) → 5. Stufe ohne Definition.
|
||||
- Entscheidung (PO): **5×5** — Kriterien ergänzen (Bewertung/Matrix/Score bleiben unverändert).
|
||||
- Seed `prisma/import-managed.ts`: 5. EW-Stufe („Nahezu sicher") + 5. Stufe je Schadensdimension.
|
||||
- Editor `onboarding/steps/criteria/criteria-editor.tsx` (Settings + Wizard geteilt): Typ/Update/Neuanlage/Rendering auf 1–5; `actions.ts` zod-Schema um „5"; `settings/risk-criteria/page.tsx` + `onboarding/steps/criteria/step.tsx` editorDims um „5".
|
||||
- Backfill `scripts/backfill-risk-5x5.ts` (idempotent): ergänzt EW-Stufe 5 + Schadensstufe 5 für Bestandsmandanten. Für Test/Prod nach Redeploy je Instanz einmal ausführen (demo, gefim).
|
||||
- Gate grün (tsc/lint/build); Backfill lokal verifiziert.
|
||||
@@ -1,328 +0,0 @@
|
||||
# Übergabe: Anwendung auf zwei Frameworks umbauen (ISO 27001 neben TISAX)
|
||||
|
||||
**Stand:** 2026-08-21 · **Zielgruppe:** Entwickler:innen · **Vorarbeit:** Branch `feature/iso27001-framework-mapping`, Commit `492d315`
|
||||
|
||||
> **Ausgangslage:** Die Inhaltsseite ist fertig. `seed/isms-vorlagenpaket-v2` trägt jetzt **zwei
|
||||
> Framework-Mappings** auf **einem** Dokumentensatz — `mapping.json` (VDA ISA, 321 Anforderungen) und
|
||||
> `mapping-iso.json` (ISO/IEC 27001:2022, 120 Anforderungen). Die Anwendung kennt das zweite Mapping
|
||||
> noch nicht: `parsePackageFiles` liest `mapping.json` fest verdrahtet.
|
||||
>
|
||||
> **Auftrag:** Framework als erste Klasse im Datenmodell und in der Paketauflösung, damit ein Mandant
|
||||
> ISO, TISAX oder beides führen kann. Danach die drei ISO-Artefakte, die es im Tool noch nicht gibt:
|
||||
> SoA, Kennzahlen, Managementbewertung/Korrekturmaßnahmen.
|
||||
|
||||
Fachlicher Hintergrund und Begründung der Entscheidung: `docs/FRAMEWORK-MAPPING-ISO27001.md`.
|
||||
Gesamtarchitektur und die übrigen Lanes: `docs/KONZEPT-framework-iso27001.md`.
|
||||
|
||||
---
|
||||
|
||||
## 0. Was **nicht** angefasst werden muss
|
||||
|
||||
Die Paketinhalte sind generiert. Wer ISO-Texte oder Zuordnungen ändern will, ändert
|
||||
`_iso_crosswalk.json` bzw. `_iso_sections.json` und lässt `python3 _generate_iso.py` laufen —
|
||||
**nie direkt die Markdown-Dateien**, der Generator überschreibt sentinel-begrenzte Blöcke.
|
||||
|
||||
Danach müssen beide Prüfskripte grün sein:
|
||||
|
||||
```bash
|
||||
cd seed/isms-vorlagenpaket-v2
|
||||
python3 _generate_iso.py # idempotent, zweiter Lauf ändert nichts
|
||||
python3 _verify.py # TISAX-Sicht
|
||||
python3 _verify_iso.py # ISO-Sicht
|
||||
python3 _render_diff.py HEAD # TISAX-Regression gegen den aktuellen Stand
|
||||
```
|
||||
|
||||
Die Sichtbarkeit im Dokument steuern zwei Variablen aus `variables.schema.json`:
|
||||
`FLAG_FW_TISAX` (Default `true`) und `FLAG_FW_ISO27001` (Default `false`).
|
||||
|
||||
### Parallelbetrieb ist vorgesehen
|
||||
|
||||
Sind **beide** Flags gesetzt, rendert das Dokument beide Anforderungssichten untereinander — über
|
||||
**einem** gemeinsamen Umsetzungstext. Genau dafür ist die Bibliothek gebaut:
|
||||
|
||||
```
|
||||
3.2 Sichere Anmeldung
|
||||
*Anforderungsbezug:* VDA ISA 4.1.2 · ISO/IEC 27001 A.8.5
|
||||
|
||||
**Anforderung**
|
||||
*Anforderungen nach VDA ISA 2027:*
|
||||
- **[MUSS]** Verfahren zur Benutzerauthentifizierung nach dem Stand der Technik werden angewandt.
|
||||
- **[SOLL]** Für privilegierte Benutzerkonten werden höherwertige Verfahren genutzt …
|
||||
*Anforderungen nach ISO/IEC 27001:*
|
||||
- **[ISO A.8.5]** Sichere Authentisierungstechnologien und -verfahren sind einzusetzen.
|
||||
|
||||
**Umsetzung bei {{ORG_NAME}}**
|
||||
Die Authentifizierungsverfahren sind risikobasiert ausgewählt … Passwortvorgaben nach BL-IAM-01 …
|
||||
```
|
||||
|
||||
Der Anforderungsbezug steht in einer eigenen Zeile unter der Überschrift und nennt je nach
|
||||
Betriebsart eine oder beide Normen. Die beiden Zwischenüberschriften erscheinen **nur**, wenn
|
||||
tatsächlich beide Frameworks aktiv sind.
|
||||
Die 19 ISO-only-Abschnitte kommen bei einem Doppel-Mandanten additiv hinzu.
|
||||
|
||||
Auf der Datenseite ist der Parallelbetrieb erst nach AP1 möglich: `PolicyRequirement` trägt dann
|
||||
beide ID-Namensräume (`4.1.2-M1` und `A.5.15-1`) nebeneinander — vorausgesetzt, Falle 1.1 ist gelöst.
|
||||
|
||||
---
|
||||
|
||||
## 1. Die vier Fallen — bitte zuerst lesen
|
||||
|
||||
### 1.1 `reconcilePackage` archiviert die Anforderungen des jeweils anderen Frameworks
|
||||
|
||||
**Das ist der kritische Punkt.** `prisma/import-policies.ts:368-371` archiviert jede
|
||||
`PolicyRequirement`, deren `reqId` nicht im importierten Paket steht:
|
||||
|
||||
```ts
|
||||
for (const ex of existingReqs) {
|
||||
if (desiredReqIds.has(ex.reqId) || ex.archivedAt) continue;
|
||||
report.requirements.archived++;
|
||||
await prisma.policyRequirement.update({ where: { id: ex.id }, data: { archivedAt: now } });
|
||||
}
|
||||
```
|
||||
|
||||
Ein ISO-Import in einen Mandanten mit TISAX archiviert damit **alle 321 VDA-ISA-Anforderungen** —
|
||||
und umgekehrt. Die ID-Namensräume kollidieren zwar nicht (`4.1.2-M1` vs. `A.5.15-1`, `@@unique([tenantId, reqId])`
|
||||
bleibt heil), aber der Abgleich muss **framework-scoped** werden:
|
||||
|
||||
- `PolicyRequirement.framework Framework` ergänzen (Backfill `TISAX`),
|
||||
- den Archivierungslauf auf `where: { tenantId, framework }` einschränken.
|
||||
|
||||
Für **Dokumente** gilt das nicht: Beide Mappings lesen dieselben `richtlinien/`- und `verfahren/`-Dateien,
|
||||
`pkg.documents` ist identisch. Ebenso Variablen, Baseline-Parameter und Nachweisregister — die sind geteilt
|
||||
und dürfen genau einmal je Mandant abgeglichen werden.
|
||||
|
||||
### 1.2 Zwei Unique-Constraints brechen bei zwei Frameworks
|
||||
|
||||
| Modell | heute | muss werden |
|
||||
|---|---|---|
|
||||
| `PolicyTemplateVersion` (`prisma/schema.prisma:1639`) | `version String @unique` | `@@unique([framework, version])` — sonst kollidieren ISO 2.1 und TISAX 2.1 |
|
||||
| `PolicyPackageState` (`prisma/schema.prisma:1614`) | `tenantId String @unique` | `@@unique([tenantId, framework])` — sonst merkt sich ein Mandant nur eine Paketversion |
|
||||
|
||||
### 1.3 TISAX darf sich nicht verändern
|
||||
|
||||
Bestandsmandanten müssen bitgenau dasselbe sehen wie heute. Der Renderdiff über alle 17 Richtlinien
|
||||
(TISAX-Kontext vorher/nachher) war bei der Paketumstellung **0 Abweichungen** — dieser Wert ist die
|
||||
Messlatte. `src/lib/policy-render.ts` belegt fehlende Framework-Flags bereits vor
|
||||
(`FLAG_FW_TISAX = true`, `FLAG_FW_ISO27001 = false`), damit ein Bestandsmandant vor dem Paket-Re-Import
|
||||
keine leeren Anforderungsblöcke sieht. **Diesen Fail-Safe nicht entfernen**, auch nicht wenn die Flags
|
||||
später über `TenantFramework` gesetzt werden.
|
||||
|
||||
Nebenbei: `applyProtection` (`src/lib/policy-render.ts:54`) setzt `FLAG_HIGH_PROTECTION` bedingungslos auf `true`
|
||||
mit der Begründung „im TISAX-Modell stets aktiv". Für ISO-Mandanten ist das derzeit folgenlos (die
|
||||
ISO-Blöcke nutzen die Schutzbedarf-Flags nicht), sollte aber beim Bau der `IsoStrategy` bewusst
|
||||
entschieden werden.
|
||||
|
||||
### 1.4 Migrations- und Build-Konventionen
|
||||
|
||||
- Migrationsflow Prisma 7 wie in `docs/HANDOVER-DEV.md:100`: `migrate diff --from-config-datasource … --to-schema … --script`,
|
||||
danach den **RLS-DO-Block manuell** an die `migration.sql` anhängen, dann `migrate deploy`.
|
||||
- Jedes neue mandantengebundene Modell gehört in **`TENANT_MODELS`** (`src/server/db.ts:81`) **und**
|
||||
braucht eine RLS-Policy in seiner Migration.
|
||||
- `scripts/check-module-guards.ts` läuft als `prebuild`-Gate: **jede neue Datei** unter
|
||||
`src/server/actions/` muss dort eingetragen sein (Modul-Key oder `EXEMPT`), sonst schlägt der Build fehl.
|
||||
- Bei paralleler Lane-Entwicklung teilen sich die Worktrees dieselbe lokale Postgres-DB. Beim Erzeugen
|
||||
einer Migration nur die **eigenen** DDL-Blöcke übernehmen und Fremd-Drops von Hand entfernen.
|
||||
- `npm run lint` und `npm run build` müssen vor jedem Commit grün sein (`AGENTS.md:25`).
|
||||
|
||||
---
|
||||
|
||||
## 2. Arbeitspakete
|
||||
|
||||
### AP1 — Framework-Dimension *(Fundament, blockiert alles Weitere)*
|
||||
|
||||
**Schema**
|
||||
|
||||
```prisma
|
||||
enum Framework { ISO_27001 TISAX }
|
||||
|
||||
model TenantFramework {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
framework Framework
|
||||
isPrimary Boolean @default(false) @map("is_primary")
|
||||
config Json? // z. B. { tisaxLevel: "AL3" } bzw. { certScope, certBodyTarget }
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
@@unique([tenantId, framework])
|
||||
@@index([tenantId])
|
||||
@@map("tenant_frameworks")
|
||||
}
|
||||
```
|
||||
|
||||
Zusätzlich: `PolicyRequirement.framework`, `PolicyTemplateVersion.framework`,
|
||||
`PolicyPackageState.framework` (siehe Fallen 1.1 und 1.2). Alles additiv, Backfill der Bestandsdaten auf
|
||||
`TISAX`.
|
||||
|
||||
**Paketauflösung**
|
||||
|
||||
| Datei | Änderung |
|
||||
|---|---|
|
||||
| `prisma/import-policies.ts` | `parsePackageFiles(seedDir, mappingFile = "mapping.json")`; Requirements framework-scoped reconcilen |
|
||||
| `prisma/template-store.ts:147` | `resolvePackageForTenant(prisma, tenantId, seedDir, framework)`; `loadPublishedPackage(prisma, locale, framework)`; `getAvailableVersion` ebenso |
|
||||
| `scripts/sync-policy-templates.ts:23` | über **Frameworks × Sprachen** iterieren statt nur über Sprachen |
|
||||
|
||||
Die vier Aufrufer von `resolvePackageForTenant` bekommen den Framework-Parameter durchgereicht:
|
||||
`src/server/provision.ts:139`, `src/server/actions/policy-package.ts:28`, `src/server/actions/admin.ts`,
|
||||
`src/app/(app)/policies/updates/page.tsx:44`.
|
||||
|
||||
**Das Seed-Verzeichnis bleibt für beide Frameworks dasselbe** — die fünf `SEED_DIR`-Konstanten ändern
|
||||
sich nicht, nur der Mapping-Dateiname. Das ist der Vorteil von Variante A.
|
||||
|
||||
**DoD:** Bestandsmandanten laufen unverändert als TISAX; ein Mandant kann mit
|
||||
`frameworks: ["ISO_27001"]`, `["TISAX"]` oder beiden provisioniert werden; bei Doppel-Framework
|
||||
koexistieren 321 + 120 Anforderungen und **keine** ist fälschlich archiviert.
|
||||
|
||||
---
|
||||
|
||||
### AP2 — Provisionierung und Flags *(klein, direkt nach AP1)*
|
||||
|
||||
`ProvisionOpts` (`src/server/provision.ts:37`) um `frameworks: Framework[]` erweitern.
|
||||
`provisionTenant` schreibt die `TenantFramework`-Zeilen, importiert **je Framework** das passende
|
||||
Mapping und setzt die Sichtbarkeits-Flags als `PolicyVariable`:
|
||||
|
||||
| Mandant führt | `FLAG_FW_TISAX` | `FLAG_FW_ISO27001` |
|
||||
|---|:--:|:--:|
|
||||
| nur TISAX | `true` | `false` |
|
||||
| nur ISO | `false` | `true` |
|
||||
| beides | `true` | `true` |
|
||||
|
||||
**Achtung Reihenfolge:** `reconcilePackage` erhält nutzergepflegte Variablenwerte und überschreibt sie
|
||||
nicht. Die Flags müssen also **nach** dem Import gesetzt werden, sonst bleibt der Schema-Default stehen
|
||||
und ein ISO-Mandant sieht die VDA-ISA-Sicht.
|
||||
|
||||
`tisaxLevel` bleibt vorerst auf `TenantSettings`, wird aber als TISAX-scoped dokumentiert (Entscheidung D2).
|
||||
Die AL-Flags dürfen bei einem reinen ISO-Mandanten nicht gesetzt werden.
|
||||
|
||||
**DoD:** Ein frisch provisionierter ISO-Mandant öffnet `/policies` und sieht in jedem Dokument die
|
||||
ISO-Anforderungssicht plus die 19 ISO-only-Abschnitte; keine „ISA"-Klammern in den Überschriften.
|
||||
|
||||
---
|
||||
|
||||
### AP3 — SoA-Modul *(das fehlende ISO-Kernartefakt)*
|
||||
|
||||
Heute ist der Modul-Key `soa` (`src/lib/modules.ts:19`) mit `href: "/soa"` registriert, **die Route
|
||||
existiert aber nicht** — die Logik liegt als Wizard-Schritt 7 in `src/server/actions/soa.ts` und ist ein
|
||||
VDA-ISA-Reifegrad-Assessment (0–3), nicht die ISO-Anwendbarkeitserklärung.
|
||||
|
||||
```prisma
|
||||
model SoaEntry {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
framework Framework
|
||||
control String // "A.5.15"
|
||||
applicable Boolean @default(true)
|
||||
justification String // Begründung Einbeziehung ODER Ausschluss
|
||||
source String? // Risiko-ID / gesetzliche / vertragliche Anforderung
|
||||
implementationStatus String @default("geplant") // umgesetzt | teilweise | geplant
|
||||
ownerId String? @map("owner_id")
|
||||
policyCode String? @map("policy_code")
|
||||
evidenceId String? @map("evidence_id")
|
||||
@@unique([tenantId, framework, control])
|
||||
@@index([tenantId])
|
||||
@@map("soa_entries")
|
||||
}
|
||||
```
|
||||
|
||||
Die vier Felder `applicable`, `justification`, `implementationStatus` und die Ausschlussbegründung sind
|
||||
**normative Pflichtangaben** (ISO/IEC 27001:2022, 6.1.3 d) — ohne sie ist die SoA im Zertifizierungsaudit
|
||||
angreifbar.
|
||||
|
||||
Vorbefüllung aus `mapping-iso.json`: 93 Controls; das Feld `condition` (z. B. `FLAG_DEV_INHOUSE`) steuert
|
||||
die Default-Anwendbarkeit. Als fachliche Vorlage für Aufbau und Spalten dient
|
||||
`seed/isms-vorlagenpaket-v2/Statement-of-Applicability-ISO.md`.
|
||||
|
||||
**DoD:** Ein ISO-Mandant kann die SoA vollständig pflegen und als PDF/XLSX exportieren; ein Control ohne
|
||||
Begründung wird als unvollständig markiert.
|
||||
|
||||
---
|
||||
|
||||
### AP4 — Managementklauseln: Kennzahlen, Bewertung, Korrekturmaßnahmen
|
||||
|
||||
Drei Modelle fehlen; alle drei sind ISO-Pflichtthemen und heute nicht abbildbar:
|
||||
|
||||
| Klausel | Modell | Inhalt |
|
||||
|---|---|---|
|
||||
| 9.1 | `Kpi` / `KpiValue` | Kennzahl, Datenquelle, Zielwert, Turnus, Verantwortlicher, Messwerte je Periode |
|
||||
| 9.3 | `ManagementReview` | Datum, Eingaben nach 9.3.2, Ergebnisse nach 9.3.3, Beschlüsse mit Verantwortlichem und Termin |
|
||||
| 10.2 | `Nonconformity` + `CorrectiveAction` | Herkunft, Sofortkorrektur, Ursachenanalyse, Maßnahme, Wirksamkeitsbewertung |
|
||||
|
||||
Vorhandene Bausteine, auf denen das aufsetzen kann: `Task.recurrence` (RRULE), `Task.remindAt`,
|
||||
`Task.effectiveUntil` (Wirksamkeitsintervall, gekoppelt an `Evidence.validUntil`), `TaskParticipant` (RACI)
|
||||
und `AuditLog`. Die Datenquellen für die Kennzahlen liegen bereits im Tool: Aufgabenfristen und
|
||||
Überfälligkeit, Incident-SLA und Meldefristen (`src/lib/incident-deadlines.ts`), Reifegrade je Control,
|
||||
Maßnahmenstatus.
|
||||
|
||||
Fachlicher Inhalt der Abschnitte steht in R03 der Bibliothek (`ISO-MS-MESSUNG`, `ISO-MS-MGMTREVIEW`,
|
||||
`ISO-MS-CAPA`) — die Modelle sollten die dort beschriebenen Felder tragen.
|
||||
|
||||
**DoD:** Kennzahlenblatt mit Zielwerten pflegbar und über zwei Perioden auswertbar; Management-Review
|
||||
entlang der 9.3.2-Agenda protokollierbar; ein Maßnahmenfall inklusive dokumentierter Wirksamkeitsprüfung
|
||||
abschließbar.
|
||||
|
||||
---
|
||||
|
||||
### AP5 — Dokumentenlenkung *(klein, hohe Auditwirkung)*
|
||||
|
||||
- `PolicyDocument.reviewCycle` und `nextReviewAt` — heute führt nur `ManagedRegister` einen
|
||||
`reviewCycle`; A.5.1 verlangt die Überprüfung „in geplanten Abständen". Behelfsweise über
|
||||
`Task.recurrence` möglich, sauberer am Dokument.
|
||||
- `PolicyAcknowledgement { tenantId, policyDocumentId, version, userId, acknowledgedAt }` — die
|
||||
Lesebestätigung ist in `SPEC.md` §4.6 vorgesehen und fehlt. Sie ist zugleich der einfachste Nachweis
|
||||
für Klausel 7.3 und Control A.6.3.
|
||||
- Änderungshistorie je Dokumentversion — im Entwicklungsstand als offen geführt. Kann aus `AuditLog`
|
||||
(Vorher/Nachher) abgeleitet oder als eigene Tabelle geführt werden.
|
||||
|
||||
**DoD:** Übersicht „Prüfung fällig" im Tool; Auswertung der Lesebestätigungen je Richtlinienversion;
|
||||
Historie eines Dokuments über mindestens zwei Versionen sichtbar.
|
||||
|
||||
---
|
||||
|
||||
## 3. Reihenfolge und Aufwand
|
||||
|
||||
```
|
||||
AP1 Framework-Dimension ██████ 4–6 PT ← blockiert alles
|
||||
├─ AP2 Provisionierung ██ 1–2 PT
|
||||
├─ AP3 SoA-Modul ██████ 5–8 PT
|
||||
├─ AP4 Managementkl. ██████ 5–8 PT
|
||||
└─ AP5 Dok.-Lenkung ███ 2–3 PT
|
||||
```
|
||||
|
||||
AP3, AP4 und AP5 sind nach AP1 parallelisierbar. Die Schätzung entspricht den Lanes 1, 4 und 5 aus
|
||||
`KONZEPT-framework-iso27001.md`; der inhaltliche Teil von Lane 2 (ISO-Mapping und -Texte) ist erledigt und
|
||||
entfällt.
|
||||
|
||||
**Feature-Flag:** ISO bleibt laut Entscheidung D7 hinter einem Plattform-Schalter, bis AP3 abgenommen ist.
|
||||
|
||||
---
|
||||
|
||||
## 4. Abnahme
|
||||
|
||||
| Prüfung | Erwartung |
|
||||
|---|---|
|
||||
| `python3 _verify.py` und `_verify_iso.py` | beide `OK` |
|
||||
| `python3 _render_diff.py <rev>` (TISAX-Sicht) | 0 Abweichungen — Skript liegt im Paket bei. **Vergleichsstand ist der Kopf dieses Branches, nicht `a9649b3`**: der Anforderungsbezug ist dort bewusst aus der Überschrift in eine eigene Zeile gewandert (14 von 17 Richtlinien betroffen, ausschließlich diese Zeile — der Anforderungs- und Umsetzungstext ist unverändert). |
|
||||
| `python3 _render_diff.py <rev> --framework BEIDE` | Parallelbetrieb prüfbar |
|
||||
| `npx tsx scripts/test-framework-dryrun.ts` | alle Prüfungen bestanden — Trockenlauf ohne Schreibzugriff über Paketebene und alle Mandanten der lokalen DB |
|
||||
| Bestandsmandant (TISAX) nach Deploy | Readiness und Exporte identisch zum Snapshot vor dem Umbau |
|
||||
| Import ISO in Mandant mit TISAX | 120 neue Anforderungen, **0 archivierte** ISA-Anforderungen |
|
||||
| Import ISO, Umsetzungstexte | 120 von 120 gefüllt (0 leer) |
|
||||
| Dokumente bei Doppel-Framework | 39 Dokumente, **nicht** doppelt |
|
||||
| `npm run lint`, `npx tsc --noEmit`, `npm run build` | grün |
|
||||
|
||||
Der Importer lässt sich ohne Datenbank gegen beide Mappings prüfen — `parsePackageFiles` ist reine
|
||||
Dateiarbeit und liefert `documents`, `requirements`, `variables`, `baseline`, `evidence` als
|
||||
`ParsedPackage`. Ein Trockenlauf des Mandanten-Imports geht über `reconcilePackage(..., { dryRun: true })`;
|
||||
er erzeugt den Änderungsreport ohne Schreibzugriff und eignet sich als Freigabebedingung.
|
||||
|
||||
---
|
||||
|
||||
## 5. Offene Punkte auf der Paketseite (nicht Entwicklung)
|
||||
|
||||
Diese Punkte gehören dem ISB bzw. der Redaktion, nicht dem Entwicklungsteam — hier nur zur Abgrenzung:
|
||||
|
||||
- Nachweisregister um Zeilen für Kennzahlenblatt, Management-Review-Protokoll und Maßnahmenregister ergänzen.
|
||||
- VA-15 trennen (internes Audit vs. Managementbewertung) und ein Verfahren für Korrekturmaßnahmen
|
||||
ergänzen — **Nummer ab VA-21**, VA-20 ist belegt.
|
||||
- `REVIEW_CYCLE` wird an 33 Bestandsstellen für fünf verschiedene Zyklen verwendet; die getrennten
|
||||
Variablen (`POLICY_REVIEW_CYCLE`, `MGMT_REVIEW_CYCLE`, `RISK_REVIEW_CYCLE`) greifen bisher nur in den
|
||||
neuen ISO-Abschnitten.
|
||||
- ISB-Freigabe der 19 neuen Abschnittstexte und Review des Crosswalks.
|
||||
@@ -1,323 +0,0 @@
|
||||
# GAP-Report Runde 2 (strenger Re-Sweep): Richtlinien & Verfahrensanweisungen — ISMS-Vorlagenpaket v2
|
||||
|
||||
| Angabe | Wert |
|
||||
|--------|------|
|
||||
| Prüfgegenstand | `seed/isms-vorlagenpaket-v2/` (Source of Truth; **nicht** der Spiegel unter `.next/standalone/…`) |
|
||||
| Standard | VDA ISA 2027 (Information Security) / ISO 27001:2022 / NIS2-Kontext |
|
||||
| Umfang | 15 Richtlinien (L00, R01–R14), 13 Verfahrensanweisungen (VA-01–VA-13), Baseline, Nachweisregister, `mapping.json` (316 Anforderungen) |
|
||||
| Prüfraster (streng) | **WAS · WIE · WO eindeutig dokumentiert · WER · NACHWEIS** — je Anforderung. „erfüllt" nur, wenn ALLE fünf Dimensionen konkret beantwortet sind **und** operative Prozesse auf eine VA bzw. zentral gepflegte Werte auf Register/Baseline verweisen. Sobald eine Dimension fehlt/vage/doppeldeutig ist → mindestens „teilweise". |
|
||||
| Runde | **2 (Korrektur der zu milden Runde 1)** |
|
||||
| Erstellt | 2026-07-22 |
|
||||
| Status | Review-Report (read-only) — es wurde **nichts** am Vorlagenpaket geändert; nur diese Report-Datei wurde neu erzeugt. |
|
||||
|
||||
> Hinweis: Reiner Prüfbericht. Keine Datei des Vorlagenpakets, kein Code, keine DB, kein Seed wurde geändert; kein Commit, kein Push. Alle Textvorschläge sind einpflegefertig, aber **nicht** eingepflegt.
|
||||
|
||||
---
|
||||
|
||||
## 1. Management-Summary
|
||||
|
||||
Das Vorlagenpaket hat weiterhin einen **überdurchschnittlichen Reifegrad** (zentrale Baseline mit BL-IDs, zentrales Nachweisregister, 316 REQ-Anker ↔ 316 Mapping-IDs ohne Waisen, `-elev`-Blöcke für alle HOCH/SEHR-HOCH-Controls). Runde 1 hat diesen Reifegrad jedoch **zu wohlwollend** in Verdikte übersetzt: Sie hat Anforderungen als „erfüllt" gewertet, deren Umsetzungstext den strengen Rubric (eindeutiger Nachweisort, Inline-VA-Verweis, verwaltetes Register) nicht besteht. Runde 2 legt den skeptischen Maßstab konsequent an.
|
||||
|
||||
**Was gegenüber Runde 1 strenger/korrigiert wurde:**
|
||||
|
||||
- **8 Controls von „erfüllt" auf „teilweise" herabgestuft** (Details in §2): **1.2.3, 2.1.2, 3.1.1, 5.2.6, 5.2.8, 5.3.4-KI, 6.1.3, 7.1.2**. Die neue Control-Verteilung ist **14 erfüllt / 30 teilweise / 2 GAP** (Runde 1: 22 / 22 / 2).
|
||||
- **Doppeldeutige Verortung** („im {{TOOL_TICKET}} **bzw.** ISMS-Tool") wird konsequent als **fehlender eindeutiger Nachweisort (G2)** gewertet — betrifft u. a. 1.2.3 und 1.6.1.
|
||||
- **„Liste/Freigabeliste im ISMS-Tool"** ohne Register-ID, Pflichtattribute und Review-Turnus wird als **fehlendes verwaltetes Register (G4/G8)** gewertet — auch dort, wo Runde 1 „erfüllt" vergeben hatte (1.3.3, 1.3.4, 5.3.4, 5.3.4-KI, 6.1.3, 5.2.8, 5.2.7, 5.1.2).
|
||||
- **Inline-VA-Verweis** wird control-genau geprüft: Von **23 Controls mit zuständiger VA** verweisen nur **8** im Umsetzungstext auf ihre VA; **15** nennen das Verfahren nur generisch bzw. im Anhang → G3.
|
||||
|
||||
**Die drei in Runde 1 bestätigten Misses — in Runde 2 sauber aufgearbeitet:**
|
||||
|
||||
1. **ISA 1.2.3 / R01 §3.3 (Informationssicherheit in Projekten):** In Runde 1 fälschlich „erfüllt". Tatsächlich deckt **keine VA** 1.2.3 ab (kein `FULFILLS 1.2.3` in den VA-Headern, kein Eintrag in `mapping.json → verfahren`). Der Umsetzungstext verortet doppeldeutig („die Einstufung wird im {{TOOL_TICKET}} **bzw. ISMS-Tool** dokumentiert"), und weder der genannte „dokumentierte Kriterienkatalog" noch ein **Projektregister/Projektverzeichnis** sind als verwaltetes Artefakt referenziert. → **Neu bewertet: teilweise**; Befund **G4** (neue VA „Informationssicherheit in Projekten") **+ G2/G8** (eindeutiger Nachweisort, Kriterienkatalog- und Projektregister). Textvorschläge in §8 (A-N1).
|
||||
2. **Rendering-/Konsistenzbug `{{TOOL_TICKET}}` u. ä.:** Der Default von `{{TOOL_TICKET}}` ist **„das Ticketsystem"**; das Muster „im {{TOOL_TICKET}}" rendert daher zu **„im das Ticketsystem"** (Doppelartikel). Analog `{{TOOL_NAME}}` = „das ISMS-Tool" und `{{TOOL_IAM}}` = „das zentrale Verzeichnis …". Systemischer **G6**-Befund mit **11 konkreten Fundstellen** (§6), inkl. eines zusätzlichen Kasus-Fehlers bei `in {{TOOL_IAM}}` (R08:153).
|
||||
3. **Software-Whitelist als verwaltetes Register mit Lieferantenbezug UND Asset-Kopplung:** Empfehlung **REG-SW-WHITELIST** mit Spalten u. a. Software, Version/Patch-Stand, **Quelle/Lieferant/Dienstleister**, Freigabestatus, Verantwortlich, Review — **doppelt cross-verlinkt** an **R13/VA-10 (Lieferantensteuerung)** (zugelassene Software hat einen steuerbaren Lieferanten) und an **R02/VA-08 (Asset & Klassifizierung)** (zugelassene Software ist als Asset geführt). Analog **REG-EXT-SERVICES** für externe/Cloud-/KI-Dienste (§5, §8 A-N3).
|
||||
|
||||
**Reifegrad-Einschätzung Runde 2:** Inhaltlich bleibt die Abdeckung auf Ebene der 312 konsolidierten ISA-Zeilen hoch; die Herabstufungen betreffen überwiegend **Nachweisführung und Verortung** (Inline-Verweis, verwaltetes Register, eindeutiger Ort), nicht fehlenden Sachinhalt. Zwei echte Inhalts-GAPs bleiben (**2.1.1**, **3.1.3**). Mit der Roadmap in §7 erreicht das Paket ein durchgängig audittaugliches Niveau.
|
||||
|
||||
---
|
||||
|
||||
## 2. Bewertungs-Übersicht
|
||||
|
||||
### 2.1 Verteilung Control-Ebene (46 Controls)
|
||||
|
||||
| Verdikt | Runde 1 | **Runde 2** | Controls (Runde 2) |
|
||||
|---------|:------:|:-----------:|--------------------|
|
||||
| **erfüllt** | 22 | **14** | 1.1.1; 1.2.1; 1.2.2; 3.1.4; 4.1.2; 5.1.1; 5.2.2; 5.2.3; 5.2.4; 5.2.5; 5.2.9; 5.3.3; 6.1.1; 7.1.1 |
|
||||
| **teilweise** | 22 | **30** | 1.2.3; 1.3.1; 1.3.2; 1.3.3; 1.3.4; 1.4.1; 1.5.1; 1.5.2; 1.6.1; 1.6.2; 1.6.3; 2.1.2; 2.1.3; 2.1.4; 3.1.1; 4.1.1; 4.1.3; 4.2.1; 5.1.2; 5.2.1; 5.2.6; 5.2.7; 5.2.8; 5.3.1; 5.3.2; 5.3.4; 5.3.4-KI; 6.1.2; 6.1.3; 7.1.2 |
|
||||
| **GAP** | 2 | **2** | 2.1.1; 3.1.3 |
|
||||
|
||||
> Die 46 Controls = 45 Controls in `mapping.json` **+** der „Phantom"-Control **3.1.3** (IMPL-Stub in R07 ohne `REQ`-Anker und ohne `mapping.json`-Eintrag; siehe GAP G-B2).
|
||||
|
||||
### 2.2 Gegenüber Runde 1 KORRIGIERTE Einstufungen (alle: erfüllt → teilweise/GAP)
|
||||
|
||||
| Control | Richtlinie | Runde 1 | **Runde 2** | Grund der Verschärfung | GAP-Typ |
|
||||
|---------|-----------|---------|-------------|------------------------|---------|
|
||||
| **1.2.3** | R01 | erfüllt | **teilweise** | Keine VA deckt 1.2.3 ab; Verortung doppeldeutig („{{TOOL_TICKET}} bzw. ISMS-Tool"); Kriterienkatalog & Projektregister nicht als verwaltete Artefakte referenziert | G2, G4, G8, G6 |
|
||||
| **2.1.2** | R05 | erfüllt | **teilweise** | „Ein Verfahren zum Umgang mit Verstößen ist beschrieben" — Verfahren nicht verortet/verlinkt (kein VA-/Dok-Verweis) | G1, G2 |
|
||||
| **3.1.1** | R07 | erfüllt | **teilweise** | Zutrittsvergabe/-entzug (S1) und Besuchermanagement (S2) nur als „berücksichtigt" pauschaliert; kein Verfahren/VA verortet | G1, G3 |
|
||||
| **5.2.6** | R10 | erfüllt | **teilweise** | VA-06 erfüllt laut `FULFILLS` 5.2.6-M1, wird im IMPL 5.2.6 aber **nicht** inline referenziert | G3 |
|
||||
| **5.2.8** | R04 | erfüllt | **teilweise** | Kritische IT-Dienste nur „identifiziert"; kein verwaltetes Register (RTO/RPO nur im `-elev`-Block, keine BIA-Register-ID) | G8 |
|
||||
| **5.3.4-KI** | R12 | erfüllt | **teilweise** | „Freigabeliste im ISMS-Tool" ist informelles Register ohne Register-ID/Attribute/Turnus (REG-EXT-SERVICES) | G8, G4 |
|
||||
| **6.1.3** | R13 | erfüllt | **teilweise** | VA-10 erfüllt laut `FULFILLS` 6.1.3-M1, IMPL 6.1.3 verweist nicht inline; „Liste der IT-Dienste" (elev) informell | G3, G8 |
|
||||
| **7.1.2** | R14 | erfüllt | **teilweise** | Kein referenzierter Prozess für Betroffenenrechte/Löschfristen-Review (nur BL-DEL-01 statisch); keine Datenschutz-Pflege-VA | G4 |
|
||||
|
||||
### 2.3 Anforderungsebene (316 Einzelanforderungen) — Schwerpunkte
|
||||
|
||||
- **Inline-VA-Verweis:** 23 Controls haben eine zuständige VA; **8** verweisen inline (5.1.1, 5.2.4, 5.2.5*, 5.2.8, 5.2.9, 5.3.4, 5.3.4-KI, 6.1.1), **15** nicht (G3). *5.2.5 verweist auf VA-06, nicht auf das ebenfalls zuständige VA-04.
|
||||
- **Register/Baseline-Bezug fehlt (G8/G4)** bei allen „Liste im Tool"-Formulierungen: 1.2.3 (Kriterienkatalog/Projektregister), 1.3.3 & 5.3.4/5.3.4-KI (externe/Cloud/KI-Dienste), 1.3.4 (Software-Whitelist), 1.5.1 (Auditplan), 2.1.1 (sensible Rollen), 5.1.2 & 5.2.7 (Netz/Netzdienste), 5.2.8 & 6.1.3 (kritische IT-Dienste).
|
||||
- **Leere Anforderung / Mapping-Bruch:** 3.1.3 (leerer `REQ`-Block, IMPL-Stub ohne Mapping); ISA **3.1.2** fehlt in R07 und `mapping.json` vollständig.
|
||||
- **Strukturhinweis:** Control **1.1.1** (L00) hat **keinen gebündelten IMPL-Block**; `impl_anchor == req_anchor` — die „Umsetzung" ist die Leitlinien-Prosa selbst. Inhaltlich vertretbar (Leitlinie), aber vom übrigen `IMPL <control>`-Muster abweichend (siehe auch F-Tooling).
|
||||
|
||||
---
|
||||
|
||||
## 3. Vollständige Verlinkungs-/Coverage-Matrix — ALLE 46 Controls
|
||||
|
||||
Spalten: **Inline im Umsetzungstext verlinkt?** = verweist der `IMPL <control>`-Block per `{{LINK:VA-xx}}`/„siehe … Verfahren" auf die zuständige VA (ja) oder steht die VA nur generisch/im Anhang (nein); „n.a." = keine VA zuständig.
|
||||
|
||||
| # | Control | Anf.-Stufe(n) | Zuständige VA (FULFILLS) | Inline verlinkt? | Register/Baseline-Bezug | Status | Bemerkung |
|
||||
|--:|---------|---------------|--------------------------|:---------------:|--------------------------|--------|-----------|
|
||||
| 1 | 1.1.1 | M×5 / S×4 | n.a. | n.a. | Nachweisregister; ISMS-Tool | erfüllt | Leitlinie; kein IMPL-Block (`impl_anchor=req_anchor`) |
|
||||
| 2 | 1.2.1 | M×6 | n.a. | n.a. | ISMS-Tool; Managementbewertung | erfüllt | Governance vollständig verortet |
|
||||
| 3 | 1.2.2 | M×4 / S×2 / H×1 | n.a. | n.a. | Rollenmatrix; ISMS-Tool | erfüllt | Funktionstrennung im `-elev` |
|
||||
| 4 | 1.2.3 | M×1 / S×3 / H×1 | **keine** | **n.a. (VA fehlt)** | **kein Kriterienkatalog-/Projektregister; keine BL** | **teilweise** | **KORRIGIERT** v. erfüllt; G2/G4/G8/G6 (Miss #1) |
|
||||
| 5 | 1.3.1 | M×2 / S×1 | VA-08 | **nein** | Asset-Inventar (ISMS-Tool) | teilweise | G3 |
|
||||
| 6 | 1.3.2 | M×3 / S×1 | VA-08 | **nein** | Klassifizierungsschema | teilweise | G3 |
|
||||
| 7 | 1.3.3 | M×2 / S×4 | n.a. | n.a. | „Freigabeliste im ISMS-Tool" (informell) | teilweise | G8/G4 → REG-EXT-SERVICES |
|
||||
| 8 | 1.3.4 | M×2 / S×5 / V×1 | n.a. | n.a. | „Whitelist im ISMS-Tool" (informell) | teilweise | G8/G4 → REG-SW-WHITELIST (Miss #3) |
|
||||
| 9 | 1.4.1 | M×4 / S×4 | VA-09 | **nein** | Risikoregister (ISMS-Tool) | teilweise | G3 |
|
||||
| 10 | 1.5.1 | M×5 / S×1 | n.a. | n.a. | „Auditplan" (informell); keine BL-Frequenz | teilweise | G4/G2/G8 → VA-15, REG-AUDIT-PLAN |
|
||||
| 11 | 1.5.2 | M×2 / S×1 | n.a. | n.a. | unabhängige Prüfung; kein Turnus/BL | teilweise | G2/G8 |
|
||||
| 12 | 1.6.1 | M×3 / S×6 / V×1 | VA-01 | **nein** | Meldeweg; „{{TOOL_TICKET}} **bzw.** ISMS-Tool" | teilweise | G3/G2/G6 (doppeldeutig) |
|
||||
| 13 | 1.6.2 | M×3 / S×3 / H×5 / V×1 | VA-01 | **nein** | {{TOOL_TICKET}} | teilweise | G3/G6 |
|
||||
| 14 | 1.6.3 | M×3 / S×6 / H×5 / V×1 | VA-02 | **nein** | Krisenplan; keine BL-Übungsfrequenz | teilweise | G3/G8 |
|
||||
| 15 | 2.1.1 | M×3 / S×2 | **keine** | **n.a. (VA fehlt)** | **kein Register sensibler Rollen** | **GAP** | G1/G2/G4/G5 → VA-14, REG-SENS-ROLES |
|
||||
| 16 | 2.1.2 | M×2 / S×3 | n.a. | n.a. | Personalakte; Verstoß-„Verfahren" unverortet | **teilweise** | **KORRIGIERT** v. erfüllt; G1/G2 |
|
||||
| 17 | 2.1.3 | M×1 / S×6 | VA-12 | **nein** | BL-HR-01; {{TOOL_NAME}} | teilweise | G3/G6 |
|
||||
| 18 | 2.1.4 | M×1 / S×2 / H×1 | n.a. | n.a. | „eine Regelung" — nicht verortet | teilweise | G2/G1 |
|
||||
| 19 | 3.1.1 | M×3 / S×5 / H×1 | n.a. | n.a. | BL-PHY-01/02; Besucher/Zutritt generisch | **teilweise** | **KORRIGIERT** v. erfüllt; G1/G3 → VA-17 |
|
||||
| 20 | 3.1.3 | — (leer) | n.a. | n.a. | IMPL-Stub ohne REQ/Mapping | **GAP** | G6/G1; ISA 3.1.2 fehlt zudem ganz |
|
||||
| 21 | 3.1.4 | M×1 / S×1 / H×1 | n.a. | n.a. | TECH_MDM; BL-EP-02 | erfüllt | Baseline-verankert |
|
||||
| 22 | 4.1.1 | M×1 / S×1 / H×1 | VA-03 | **nein** | BL-IAM-07; TOOL_IAM | teilweise | G3 |
|
||||
| 23 | 4.1.2 | M×2 / S×3 / H×1 / V×1 | n.a. | n.a. | BL-IAM-01/02; TECH_MFA | erfüllt | Baseline-verankert |
|
||||
| 24 | 4.1.3 | M×7 / S×10 | VA-03 | **nein** | TOOL_IAM | teilweise | G3 |
|
||||
| 25 | 4.2.1 | M×2 / S×5 / H×1 / V×2 | VA-03 | **nein** | BL-IAM-05; RECERT_FREQ | teilweise | G3 |
|
||||
| 26 | 5.1.1 | M×1 / S×1 / H×1 | VA-07 | **ja** | BL-CRY-02/05 | erfüllt | Vorbildliche Referenzkette |
|
||||
| 27 | 5.1.2 | M×3 / S×3 / H×1 / V×1 | VA-07 | **nein** | BL-CRY-01/04; Netzdienste informell | teilweise | G3/G8 → REG-NET |
|
||||
| 28 | 5.2.1 | M×1 / S×4 / H×1 | VA-04 | **nein** | BL-OPS-09; {{TOOL_TICKET}} | teilweise | G3/G6 |
|
||||
| 29 | 5.2.2 | M×2 / S×1 | n.a. | n.a. | Trennung Dev/Test/Prod | erfüllt | Konkret |
|
||||
| 30 | 5.2.3 | M×2 / S×8 | n.a. | n.a. | BL-OPS-03; TECH_MALWARE | erfüllt | Baseline-verankert |
|
||||
| 31 | 5.2.4 | M×5 / S×3 / H×2 / V×1 | VA-13 | **ja** | BL-OPS-04; LOG_RETENTION | erfüllt | Referenzkette vollständig |
|
||||
| 32 | 5.2.5 | M×3 / S×3 | VA-04, VA-06 | **teils** | BL-OPS-01/02; PATCH_SLA_CRIT | erfüllt | VA-06 inline; VA-04 nicht inline |
|
||||
| 33 | 5.2.6 | M×5 / S×3 / H×1 / V×1 | VA-06 | **nein** | BL-OPS-07/08; PENTEST_FREQ | **teilweise** | **KORRIGIERT** v. erfüllt; G3 |
|
||||
| 34 | 5.2.7 | M×2 / S×2 / H×1 | n.a. | n.a. | BL-NET-01/02; „Netzplan" informell | teilweise | G8/G2 → REG-NET |
|
||||
| 35 | 5.2.8 | M×2 / S×3 / H×7 / V×3 | VA-02 | **ja** | kein REG-CRIT-SERVICES; RTO/RPO nur elev | **teilweise** | **KORRIGIERT** v. erfüllt; G8 |
|
||||
| 36 | 5.2.9 | M×2 / S×1 / H×2 / V×3 | VA-05 | **ja** | BL-OPS-05; BACKUP_SCHEME/RETENTION | erfüllt | Referenzkette vollständig |
|
||||
| 37 | 5.3.1 | M×4 / S×5 / V×1 | n.a. | n.a. | {{TOOL_TICKET}}; keine Secure-Dev-VA | teilweise | G4/G1/G6 → VA-16 |
|
||||
| 38 | 5.3.2 | M×1 / S×3 / H×1 | n.a. | n.a. | „über ein Verfahren" (generisch) | teilweise | G1/G4 → VA-16 |
|
||||
| 39 | 5.3.3 | S×1 | n.a. | n.a. | BL-DEL-01; Löschprotokoll | erfüllt | Konkret |
|
||||
| 40 | 5.3.4 | M×1 / S×1 | VA-11 | **ja** | „Freigabeliste im ISMS-Tool" (informell) | teilweise | G8 → REG-EXT-SERVICES |
|
||||
| 41 | 5.3.4-KI | M×3 / S×1 | VA-11 | **ja** | „Freigabeliste im ISMS-Tool" (informell) | **teilweise** | **KORRIGIERT** v. erfüllt; G8/G4 |
|
||||
| 42 | 6.1.1 | M×3 / S×2 / H×3 / V×2 | VA-10 | **ja** | BL-SUP-01; Lieferantenverzeichnis | erfüllt | Referenzkette vollständig |
|
||||
| 43 | 6.1.2 | M×4 / S×5 | VA-10 | **nein** | NDAs „im ISMS-Tool" (informell) | teilweise | G3 |
|
||||
| 44 | 6.1.3 | M×5 / S×2 / H×5 | VA-10 | **nein** | „Liste der IT-Dienste" (elev, informell) | **teilweise** | **KORRIGIERT** v. erfüllt; G3/G8 |
|
||||
| 45 | 7.1.1 | M×2 / S×1 | n.a. | n.a. | Compliance-/Rechtsregister (ISMS-Tool) | erfüllt | Register vorhanden |
|
||||
| 46 | 7.1.2 | M×3 | n.a. | n.a. | VVT (ISMS-Tool); BL-DEL-01 | **teilweise** | **KORRIGIERT** v. erfüllt; G4 (Betroffenenrechte/Löschfristen-Prozess) → VA-18 |
|
||||
|
||||
---
|
||||
|
||||
## 4. GAP-Tabelle
|
||||
|
||||
Legende Schwere: **hoch** = unmittelbar auditrelevant / Inhaltslücke · **mittel** = schwächt Nachweisführung / Konsistenz · **niedrig** = Feinschliff.
|
||||
GAP-Typen: G1 zu generisch · G2 kein/eindeutiger Nachweisort fehlt · G3 fehlende Inline-Verlinkung · G4 fehlende VA/Register · G5 Verantwortlicher unklar · G6 Widerspruch/Redundanz/veraltet/Rendering · G7 Schutzbedarf nicht adressiert · G8 Baseline-/Register-Referenz fehlt.
|
||||
|
||||
| # | Richtlinie | Control | Anf. (M/S/H/V) | Umsetzung heute (Kurz) | GAP-Typ | Schwere | Empfehlung | Konkreter Textvorschlag | Ziel-Referenz |
|
||||
|---|-----------|---------|----------------|------------------------|---------|---------|------------|--------------------------|---------------|
|
||||
| **N1** | R01 | **1.2.3** | M/S/H | „Klassifizierung anhand Kriterienkatalog; Einstufung im {{TOOL_TICKET}} **bzw. ISMS-Tool**; Maßnahmen als Aufgaben" — keine VA, doppeldeutiger Ort, Kriterienkatalog/Projektregister nicht referenziert | **G4, G2, G8, G6** | **hoch** | Neue VA „Informationssicherheit in Projekten"; Kriterienkatalog + Projektregister als verwaltete Artefakte; eindeutigen Ort setzen; Rendering fixen | siehe A-N1 | Neue **VA-19**, **REG-PROJECTS**, Kriterienkatalog (BL-PROJ-01) |
|
||||
| G-B1 | R05 | 2.1.1 | M×3 / S×2 | „Sensible Tätigkeiten sind bestimmt; Eignung im rechtlich zulässigen Rahmen geprüft" — ohne Register, ohne Einstellungs-/Verifizierungs-VA, WER unklar | G1, G2, G4, G5 | **hoch** | Register sensibler Tätigkeitsbereiche + VA-14 (Eignungs-/Verifizierungsprozess) | siehe A-G-B1 | Neue **VA-14**, **REG-SENS-ROLES** |
|
||||
| G-B2 | R07 | 3.1.3 | — (leer) | **Anforderungsblock leer**; IMPL-Stub ohne `REQ`/Mapping; **ISA 3.1.2 fehlt ganz** | G6, G1 | **hoch** | Scope 3.1.2/3.1.3 klären; REQ-Anker + Mapping ergänzen **oder** Stub entfernen | siehe A-G-B2 | `mapping.json`, R07 |
|
||||
| N2 | R05 | 2.1.2 | M/S | „Ein Verfahren zum Umgang mit Verstößen ist beschrieben" — Verfahren nicht verortet/verlinkt | G1, G2 | mittel | Verstoß-/Disziplinarverfahren benennen & verorten (Dok/VA-14) | „… ein dokumentiertes Verfahren zum Umgang mit Verstößen **(siehe {{LINK:VA-14}})** ist etabliert; Nachweis in der Personalakte." | {{LINK:VA-14}} / Personalakte |
|
||||
| N3 | R07 | 3.1.1 | M/S/H | Besuchermanagement, Zutrittsvergabe/-entzug (S1/S2) nur als „berücksichtigt" pauschaliert | G1, G3 | mittel | Zutritts-/Besuchermanagement-Verfahren verorten | „… Zutrittsrechte werden über {{TOOL_TICKET}} vergeben/entzogen **(Ablauf siehe {{LINK:VA-17}})**; Besuchermanagement (Registrierung/Begleitung) ist geregelt (BL-PHY-…)." | Neue **VA-17** |
|
||||
| N4 | R10 | 5.2.6 | M/S/H/V | Härtung/technische Prüfungen; VA-06 erfüllt 5.2.6-M1, aber **nicht inline** referenziert | G3 | mittel | VA-06 im IMPL 5.2.6 inline referenzieren | „… risikoorientiert geprüft **(siehe {{LINK:VA-06}})**; Ergebnisse werden gespeichert, der Leitung berichtet …" | {{LINK:VA-06}} |
|
||||
| N5 | R04 | 5.2.8 | M/S/H/V | Kritische IT-Dienste „identifiziert"; RTO/RPO nur im `-elev`-Block; kein Register | G8 | mittel | Register kritischer IT-Dienste inkl. BIA/RTO/RPO referenzieren | „Kritische IT-Dienste sind mit Geschäftsauswirkung im **Register kritischer IT-Dienste ({{LINK:REG-CRIT-SERVICES}})** (inkl. RTO/RPO, Wiederanlaufreihenfolge) erfasst … (siehe {{LINK:VA-02}})." | **REG-CRIT-SERVICES** |
|
||||
| N6 | R12 | 5.3.4-KI | M/S | „Freigabeliste im ISMS-Tool" ohne Register-ID/Attribute/Turnus | G8, G4 | mittel | KI-/externe Dienste als verwaltetes Register mit Lieferant+Asset-Kopplung | siehe A-N6 | **REG-EXT-SERVICES**, {{LINK:VA-11}} |
|
||||
| N7 | R13 | 6.1.3 | M/S/H | VA-10 erfüllt 6.1.3-M1, IMPL nicht inline; „Liste IT-Dienste/Dienstleister" (elev) informell | G3, G8 | mittel | VA-10 inline; Dienste-/Dienstleister-Register formalisieren | „… Verantwortlichkeiten … definiert **(siehe {{LINK:VA-10}})**; betroffene IT-Dienste und Dienstleister im **{{LINK:REG-EXT-SERVICES}}** geführt." | {{LINK:VA-10}}, **REG-EXT-SERVICES** |
|
||||
| N8 | R14 | 7.1.2 | M | VVT im Tool; kein referenzierter Prozess für Betroffenenrechte/Löschfristen-Review | G4 | mittel | Datenschutz-/Compliance-Pflege-VA referenzieren | siehe A-N8 | Neue **VA-18** |
|
||||
| N9 | R09 | 5.1.2 | M/S/H/V | VA-07 erfüllt 5.1.2-M1/S1, IMPL 5.1.2 verweist nicht inline; Netzdienste nur „identifiziert" | G3, G8 | mittel | VA-07 inline; Netzdienste-Register | „Genutzte Netzdienste sind im **{{LINK:REG-NET}}** identifiziert/dokumentiert; Krypto-/Schlüsselverwaltung **(siehe {{LINK:VA-07}})**." | {{LINK:VA-07}}, **REG-NET** |
|
||||
| F3 | R02 | 1.3.1, 1.3.2 | M/S | IMPL ohne Inline-Verweis auf VA-08 | G3 | mittel | VA-08 im Umsetzungstext inline referenzieren | „… als Katalog gepflegt **(siehe {{LINK:VA-08}})**; Zu-/Abgänge über {{TOOL_TICKET}}." | {{LINK:VA-08}} |
|
||||
| F4 | R03 | 1.4.1 | M/S | „Das dokumentierte Risikomanagement-Verfahren …" ohne Inline-Link auf VA-09 | G3 | mittel | VA-09 inline referenzieren | „Das dokumentierte Risikomanagement-Verfahren **(siehe {{LINK:VA-09}})** …" | {{LINK:VA-09}} |
|
||||
| F5 | R04 | 1.6.1, 1.6.2 | M/S/H/V | „nach einem definierten Incident-Verfahren im {{TOOL_TICKET}}" ohne Inline-Link auf VA-01 | G3 | mittel | VA-01 inline referenzieren | „… nach einem definierten Incident-Verfahren **(siehe {{LINK:VA-01}})** … behandelt und dokumentiert." | {{LINK:VA-01}} |
|
||||
| F6 | R04 | 1.6.3 | M/S/H/V | Krisenmanagement generisch; VA-02 nur im Anhang | G3, G8 | mittel | VA-02 inline; Übungsfrequenz in Baseline | „Ein Krisenmanagement … ist etabliert **(Auslösung/Wiederanlauf siehe {{LINK:VA-02}})** (Übungen BL-IR-01)." | {{LINK:VA-02}}, **BL-IR-01** |
|
||||
| F7 | R05 | 2.1.3 | M/S | Awareness stark (BL-HR-01); VA-12 nur im Anhang | G3 | mittel | VA-12 inline referenzieren | „… mindestens {{REVIEW_CYCLE}} … geschult **(Ablauf siehe {{LINK:VA-12}})**." | {{LINK:VA-12}} |
|
||||
| F8 | R08 | 4.1.1, 4.1.3, 4.2.1 | M/S/H/V | JML/Rezertifizierung stark, aber VA-03 nur im Anhang | G3 | mittel | VA-03 inline referenzieren | „Benutzerkonten werden über einen definierten Lebenszyklus (Joiner/Mover/Leaver) **(siehe {{LINK:VA-03}})** … verwaltet." | {{LINK:VA-03}} |
|
||||
| F9 | R10 | 5.2.1 | M/S/H | „formales Change-Verfahren … im {{TOOL_TICKET}} (BL-OPS-09)" ohne Inline-Link auf VA-04 | G3 | mittel | VA-04 inline referenzieren | „Änderungen durchlaufen ein formales Change-Verfahren **(siehe {{LINK:VA-04}})** …" | {{LINK:VA-04}} |
|
||||
| F10 | R02 | 1.3.4 | M/S/V | „Liste zugelassener Software (Whitelist) … im ISMS-Tool" ohne Register-ID, Lieferant/Freigabestatus | G8, G4 | mittel | REG-SW-WHITELIST mit Lieferant- UND Asset-Kopplung | siehe A-N3 (Miss #3) | **REG-SW-WHITELIST** |
|
||||
| F11 | R02 / R12 | 1.3.3 / 5.3.4 | M/S | „Freigabeliste im ISMS-Tool" für externe/Cloud-/KI-Dienste — generisch | G8, G4 | mittel | Gemeinsames REG-EXT-SERVICES mit Schutzbedarf/Exit/Lieferant | siehe A-N6 | **REG-EXT-SERVICES**, {{LINK:VA-11}} |
|
||||
| F12 | R03 | 1.5.1, 1.5.2 | M/S | Audits „nach einem Auditplan"; kein Audit-Verfahren, keine Verortung/Frequenz | G2, G4, G8 | mittel | Audit-Verfahren (VA-15) + Audit-Programm-Register + Baseline-Frequenz | siehe A-F12 | Neue **VA-15**, **REG-AUDIT-PLAN**, **BL-GOV-01** |
|
||||
| F13 | R11 | 5.3.1, 5.3.2 | M/S/H/V | Security-by-Design/Abnahme, aber keine VA; 5.3.2 „über ein Verfahren umgesetzt" | G4, G1 | mittel | VA-16 (Sichere Beschaffung/Entwicklung & Abnahme) inline | siehe A-F13 | Neue **VA-16** |
|
||||
| F14 | R09 / R10 | 5.1.2 / 5.2.7 | M/S/H | „Netzplan/Segmentierungskonzept wird gepflegt", „Netzdienste identifiziert" — ohne Register-ID | G2, G8 | niedrig | Verwaltetes Netz-/Netzdienste-Register mit Turnus | „… ein aktueller Netzplan/Segmentierungskonzept wird im **{{LINK:REG-NET}}** gepflegt (Review {{REVIEW_CYCLE}})." | **REG-NET** |
|
||||
| F16 | R06 | 2.1.4 | M/S/H | „Mobiles Arbeiten ist in einer Regelung festgelegt" — welche, wo? | G2, G1 | niedrig | Regelung konkret benennen/verorten | „Mobiles Arbeiten ist in der **Regelung mobiles Arbeiten (im ISMS-Tool ({{TOOL_NAME}}) hinterlegt)** festgelegt …" | {{TOOL_NAME}} |
|
||||
| F17 | — (Tooling) | — | — | `mapping.json` ohne `implementation`-Feld (0/316); Integrationsleitfaden §5/§8 setzt es voraus (Assessment-Export) | G6 | mittel | Feld `implementation` ergänzen **oder** Leitfaden korrigieren (`impl_anchor`-Auflösung dokumentieren) | siehe A-F17 | `mapping.json` / `00_Integrationsleitfaden_Wizard.md` |
|
||||
| F18 | Alle (elev) | div. | H/V | `-elev`-Blöcke mischen HOCH- und SEHR-HOCH-Sätze unter **einem** `FLAG_ELEVATED_PROTECTION`; bei nur HOCH erscheint „Bei sehr hohem Schutzbedarf …" | G6, G7 | niedrig | SEHR-HOCH-Sätze in `{{#if FLAG_VERY_HIGH_PROTECTION}}` auslagern | siehe A-F18 | R04/R08/R10 u. a. `-elev`-Blöcke |
|
||||
| F19 | R13 | 6.1.2 | M/S | NDA-Prozess stark; VA-10 deckt 6.1.2-M1/S1, IMPL nicht inline | G3 | niedrig | VA-10 auch bei NDA inline referenzieren | „… gültige NDAs auf Basis geprüfter Standardvorlagen **(Ablauf siehe {{LINK:VA-10}})** …" | {{LINK:VA-10}} |
|
||||
| F21 | VA-10 | 6.1.x | — | RACI-Schritttexte in der Tabelle abgeschnitten („… (Schutzb", „…(Selbstauskunft/Nac") | G6 | niedrig | Spaltentext vervollständigen | RACI-Schrittbezeichnungen ausschreiben | VA-10 |
|
||||
| **R-1..R-11** | R01/R04/R05/R08/R10/R11 | div. | — | **Rendering-Doppelartikel** „im {{TOOL_TICKET/TOOL_NAME/TOOL_IAM}}" → „im **das** …" | G6 | mittel | Präposition anpassen (siehe §6) | „… dokumentiert **im Ticketsystem ({{TOOL_TICKET}})** …" bzw. „… **im {{TOOL_TICKET}}**" → „… **in {{TOOL_TICKET}}**"-Muster entschärfen | §6 |
|
||||
|
||||
---
|
||||
|
||||
## 5. Empfohlene neue VAs / Register
|
||||
|
||||
### 5.1 Neue Verfahrensanweisungen
|
||||
|
||||
| ID | Titel | Zweck | Betroffene Controls | Priorität |
|
||||
|----|-------|-------|---------------------|-----------|
|
||||
| **VA-19** *(NEU, Miss #1)* | **Informationssicherheit in Projekten** | Projektklassifizierung nach dokumentiertem Kriterienkatalog; Risikobewertung in früher Phase & bei Änderungen; Maßnahmenableitung/-verfolgung; Pflege des Projektregisters; ISB-Einbindung bei erhöhtem Schutzbedarf | 1.2.3 (M1, S1–S3, H1) | **hoch** |
|
||||
| **VA-14** | Personalsicherheit – Eignungsprüfung & sensible Tätigkeiten | Definition sensibler Bereiche; Einstellungs-/Verifizierungsprozess (Identität, Referenzen, Führungszeugnis im rechtlich zulässigen Rahmen); Umgang mit Verstößen gegen IS-/Vertraulichkeitspflichten | 2.1.1 (M1–M3, S1–S2), 2.1.2 | **hoch** |
|
||||
| **VA-15** | Interne Audits & Complianceprüfungen | Auditprogramm, -planung, Durchführung, Berichterstattung, Maßnahmenverfolgung; unabhängige Überprüfung | 1.5.1 (M1–M5, S1), 1.5.2 (M1–M2, S1) | mittel |
|
||||
| **VA-16** | Sichere Beschaffung, Entwicklung & Abnahme | Sicherheitsanforderungen in Design/Beschaffung/Änderung; Abnahmetests; (bei Eigenentwicklung) Secure-Coding/SAST/Dependency-Scan; Testdaten-Handling | 5.3.1 (M1–M4, S1–S5, V1), 5.3.2 | mittel |
|
||||
| **VA-17** *(optional)* | Zutritts- & Besuchermanagement (physisch) | Vergabe/Entzug Zutrittsrechte, Besucherregistrierung/-begleitung, Umgang mit Betriebsmitteln | 3.1.1 (S1–S5), 3.1.3 | niedrig |
|
||||
| **VA-18** *(optional)* | Datenschutz- & Compliance-Pflege | Rechtsregister-Review, Löschfristen/Löschkonzept, Betroffenenrechte, VVT-Pflege | 7.1.1, 7.1.2 | niedrig |
|
||||
|
||||
### 5.2 Neue / zu formalisierende Register
|
||||
|
||||
| Register-ID | Inhalt / Pflichtattribute | Cross-Link | Ersetzt heutige Formulierung in | Priorität |
|
||||
|-------------|---------------------------|-----------|----------------------------------|-----------|
|
||||
| **REG-SW-WHITELIST** *(Miss #3)* | Software, Version/Patch-Stand, **Quelle/Lieferant/Dienstleister**, Freigabestatus, Freigeber/Verantwortlich, Review-Datum | **R13/VA-10** (Lieferant steuerbar) **+ R02/VA-08** (als Asset geführt) | R02 1.3.4 („Liste zugelassener Software") | mittel |
|
||||
| **REG-EXT-SERVICES** *(Miss #3 analog)* | Externe/Cloud/KI-Dienste: Schutzbedarf, Datenlokation (EU), Verschlüsselung, Exit-Strategie, **Quelle/Lieferant**, Freigabestatus, Freigeber | **R13/VA-10 + R02/VA-08** | R02 1.3.3; R12 5.3.4 / 5.3.4-KI; R13 6.1.3 | mittel |
|
||||
| **REG-SENS-ROLES** | Sensible Tätigkeitsbereiche/Rollen, geforderte Eignungsnachweise, Prüftiefe | R05/VA-14 | R05 2.1.1 | **hoch** |
|
||||
| **REG-PROJECTS** *(NEU, Miss #1)* | Projekte, IS-Klassifizierung, Risikobewertung, abgeleitete Maßnahmen/Status, ISB-Einbindung | R01/VA-19 | R01 1.2.3 | **hoch** |
|
||||
| **REG-CRIT-SERVICES** | Kritische IT-Dienste, BIA-Einstufung, RTO/RPO, Abhängigkeiten, Wiederanlaufreihenfolge | R04/VA-02 | R04 5.2.8; R13 6.1.3 | mittel |
|
||||
| **REG-NET** | Netzplan/Segmentierung, Netzdienste, Zonen, Review-Turnus | R09/R10, VA-07 | R09 5.1.2; R10 5.2.7 | niedrig |
|
||||
| **REG-AUDIT-PLAN** | Auditprogramm: Zeitplan, Umfang, geprüfte Controls, Prüfer, Ergebnisse | R03/VA-15 | R03 1.5.1 (S1) | mittel |
|
||||
|
||||
> Mehrere „Register" existieren heute implizit als Datensätze im ISMS-Tool. Empfehlung: als **benannte, verwaltete Register mit Register-ID** führen und über `{{LINK:REG-…}}` konsistent referenzieren (analog zur Baseline-/VA-Mechanik). Dazu Link-Auflösungstabelle (Integrationsleitfaden §6) und ggf. `variables.schema.json` um die neuen Ziele erweitern.
|
||||
|
||||
### 5.3 Ergänzung Baseline
|
||||
|
||||
| BL-ID | Parameter | Vorschlag |
|
||||
|-------|-----------|-----------|
|
||||
| **BL-GOV-01** | Audit-/Prüfzyklus | Interne Prüfung {{REVIEW_CYCLE}}; unabhängige Prüfung/Assessment mind. alle 3 Jahre bzw. nach grundlegenden Änderungen |
|
||||
| **BL-IR-01** | Krisen-/Notfallübungen | Tabletop {{REVIEW_CYCLE}} (HOCH); Vollübung mit Entscheidungsträgern (SEHR HOCH) |
|
||||
| **BL-PROJ-01** | Projekt-Klassifizierungskriterien | Dokumentierter Kriterienkatalog zur IS-Klassifizierung von Projekten (Auslöser/Schwellen für ISB-Einbindung) |
|
||||
|
||||
---
|
||||
|
||||
## 6. Konsistenz-/Rendering-Befunde (G6)
|
||||
|
||||
**Ursache:** Mehrere Variablen-Defaults beginnen bereits mit einem Artikel: `{{TOOL_TICKET}}`=„das Ticketsystem", `{{TOOL_NAME}}`=„das ISMS-Tool", `{{TOOL_IAM}}`=„das zentrale Verzeichnis (Entra ID / Active Directory)", `{{TECH_MDM}}`=„das eingesetzte MDM", `{{TECH_MFA}}`=„die eingesetzte MFA-Lösung" usw. Steht davor eine kontrahierte Präposition („im", „in"), entsteht beim Rendern ein **Doppelartikel** („im **das** Ticketsystem") bzw. ein Kasus-Fehler.
|
||||
|
||||
**Konkrete Fundstellen (Datei : Zeile — Control):**
|
||||
|
||||
| # | Fundstelle | Muster (rendert zu) | Control |
|
||||
|---|-----------|----------------------|---------|
|
||||
| R-1 | R01_ISMS-Organisation-und-Rollen.md:110 | „im {{TOOL_TICKET}}" → „im **das** Ticketsystem" (**2×** in der Zeile) | 1.2.3 |
|
||||
| R-2 | R04_Incident-…:69 | „im {{TOOL_TICKET}} **bzw. ISMS-Tool**" (Doppelartikel **+** doppeldeutiger Ort G2) | 1.6.1 |
|
||||
| R-3 | R04_Incident-…:126 | „im {{TOOL_TICKET}}" → „im **das** Ticketsystem" | 1.6.2 |
|
||||
| R-4 | R05_Personalsicherheit-…:111 | „im {{TOOL_NAME}}" → „im **das** ISMS-Tool" | 2.1.3 |
|
||||
| R-5 | R08_Identitaets-…:45 | „im {{TOOL_TICKET}}" → „im **das** Ticketsystem" | 4.1.1 |
|
||||
| R-6 | R08_Identitaets-…:153 | „**in** {{TOOL_IAM}}" → „in **das** zentrale Verzeichnis …" (Doppelartikel **+** Kasus: müsste „im zentralen Verzeichnis") | 4.1.3 |
|
||||
| R-7 | R08_Identitaets-…:199 | „im {{TOOL_TICKET}}" → „im **das** Ticketsystem" | 4.2.1 |
|
||||
| R-8 | R10_Betriebssicherheit.md:57 | „im {{TOOL_TICKET}}" → „im **das** Ticketsystem" | 5.2.1 |
|
||||
| R-9 | R10_Betriebssicherheit.md:203 | „im {{TOOL_TICKET}}" → „im **das** Ticketsystem" | 5.2.5 |
|
||||
| R-10 | R11_Sichere-Systembeschaffung-…:67 | „im {{TOOL_TICKET}}" → „im **das** Ticketsystem" | 5.3.1 |
|
||||
| R-11 | R01_…:110 (2. Vorkommen) | „als Aufgaben im {{TOOL_TICKET}} nachgehalten" → „im **das** …" | 1.2.3 |
|
||||
|
||||
> **Zusätzlich doppeldeutig verortet (G2, „… bzw. ISMS-Tool"):** R01:110 („im {{TOOL_TICKET}} **bzw. ISMS-Tool**") und R04:69 („Formular im {{TOOL_TICKET}} **bzw. ISMS-Tool**"). Diese Stellen brechen den Grundsatz „ein Nachweisort je Sachverhalt" und sind Auslöser der Herabstufung von 1.2.3 (und Mitgrund bei 1.6.1).
|
||||
>
|
||||
> **Grammatikalisch unkritisch** (kein Fix nötig) sind Vorkommen ohne kontrahierte Präposition, z. B. „über {{TOOL_IAM}}", „und {{TOOL_TICKET}}", „{{TOOL_TICKET}}-Aufträge" — hier passt der eingebettete Artikel bzw. es entsteht keine Doppelung.
|
||||
|
||||
**Empfohlener Fix (zwei Varianten):**
|
||||
- **Variante A (Text):** Präpositionsmuster „im {{VAR}}" → „**in {{VAR}}**" bzw. Artikel explizit ausschreiben: „**im Ticketsystem ({{TOOL_TICKET}})**". Bei R08:153 zusätzlich Kasus/Präposition „**im** {{TOOL_IAM}}" verwenden.
|
||||
- **Variante B (Daten):** Variablen-Defaults ohne führenden Artikel definieren (`{{TOOL_TICKET}}`=„Ticketsystem") und Artikel im Fließtext setzen. **Achtung:** wirkt global auf alle Fundstellen; nur konsistent umsetzen.
|
||||
|
||||
---
|
||||
|
||||
## 7. Priorisierte Roadmap
|
||||
|
||||
**Priorität 1 — Inhalts-GAPs & Fehleinstufungen mit hoher Auditrelevanz:**
|
||||
1. **N1 / VA-19 / REG-PROJECTS** — R01 1.2.3 Informationssicherheit in Projekten: VA anlegen, Kriterienkatalog (BL-PROJ-01) + Projektregister formalisieren, eindeutigen Ort setzen, Rendering fixen. *(Miss #1)*
|
||||
2. **G-B1 / VA-14 / REG-SENS-ROLES** — R05 2.1.1 Personalsicherheit konkretisieren.
|
||||
3. **G-B2** — R07 3.1.3 leeren Anforderungsblock beheben; ISA-Scope 3.1.2/3.1.3 klären; Mapping ergänzen oder Stub entfernen.
|
||||
|
||||
**Priorität 2 — Nachweiskette & Konsistenz (geringer Aufwand, hoher Nutzen):**
|
||||
4. **F3–F9, F19, N4, N7, N9** — Inline-Verlinkung der Verfahren in den 15 Umsetzungstexten vereinheitlichen (VA-01/02/03/04/06/07/08/09/10/12).
|
||||
5. **§6 / R-1..R-11** — Rendering-Doppelartikel `{{TOOL_TICKET}}` u. ä. beheben; doppeldeutige Orte („bzw. ISMS-Tool") auflösen. *(Miss #2)*
|
||||
6. **F17** — `mapping.json` ↔ Integrationsleitfaden abgleichen (`implementation`-Feld ergänzen oder Leitfaden korrigieren).
|
||||
|
||||
**Priorität 3 — Register formalisieren (Reifegrad):**
|
||||
7. **F10/F11/N5/N6/N7 / REG-SW-WHITELIST, REG-EXT-SERVICES, REG-CRIT-SERVICES, REG-NET** — verwaltete Register mit Pflichtattributen + `{{LINK:REG-…}}`; **REG-SW-WHITELIST/REG-EXT-SERVICES mit Lieferant- UND Asset-Kopplung**. *(Miss #3)*
|
||||
8. **F12 / VA-15 / REG-AUDIT-PLAN / BL-GOV-01** und **F13 / VA-16** — Audit- und Secure-Development-Verfahren.
|
||||
|
||||
**Priorität 4 — Feinschliff:**
|
||||
9. **N2, N3, N8, F14, F16, F18, F21** — Verstoß-Verfahren verorten; VA-17/VA-18 (optional); Netz-/mobile-Regelung verorten; SEHR-HOCH-`{{#if}}`-Trennung; VA-10 RACI-Text.
|
||||
|
||||
---
|
||||
|
||||
## 8. Anhang: Einfügefertige Textvorschläge
|
||||
|
||||
Alle Vorschläge im bestehenden Stil (Variablen `{{…}}`, Baseline-/VA-/Register-Verweise), **nicht** eingepflegt.
|
||||
|
||||
### A-N1 — R01 §3.3 (ISA 1.2.3), IMPL 1.2.3 (Ersatztext, Miss #1)
|
||||
|
||||
> Projekte werden zu Beginn anhand des **dokumentierten Kriterienkatalogs (BL-PROJ-01)** hinsichtlich Informationssicherheitsbedarf klassifiziert; Einstufung, Risikobewertung und abgeleitete Maßnahmen werden im **Projektregister ({{LINK:REG-PROJECTS}})** geführt. In einer frühen Projektphase und bei Änderungen erfolgt eine Risikobewertung nach dem **Verfahren Informationssicherheit in Projekten ({{LINK:VA-19}})**; Maßnahmen werden als Aufgaben **in {{TOOL_TICKET}}** nachgehalten und vor Projektabschluss geprüft. Verantwortlich ist die Projektleitung; bei erhöhtem Schutzbedarf wird {{ROLE_ISB}} eingebunden.
|
||||
|
||||
*Ergänzung Abschnitt 8 „Verwandte Dokumente" von R01:* `- Zugehörige Verfahren: {{LINK:VA-19}}; Register: {{LINK:REG-PROJECTS}}`
|
||||
|
||||
*Hinweis:* Damit entfällt die doppeldeutige Verortung („{{TOOL_TICKET}} bzw. ISMS-Tool"), der Kriterienkatalog wird als Baseline-Artefakt (BL-PROJ-01) geführt, und die fehlende VA/das fehlende Register werden geschlossen.
|
||||
|
||||
### A-G-B1 — R05 3.1 (ISA 2.1.1), IMPL 2.1.1 (Ersatztext)
|
||||
|
||||
> Sensible Arbeitsbereiche und Tätigkeiten sind im **Register sensibler Tätigkeiten ({{LINK:REG-SENS-ROLES}})** bestimmt und mit der geforderten Prüftiefe hinterlegt; Anforderungen an Positionen sind in Stellenbeschreibungen dokumentiert und werden erfüllt. Identitätsverifizierung sowie die persönliche und – bei sensiblen Rollen – erweiterte Eignungsprüfung (Gespräch, Referenzen, Führungszeugnis im rechtlich zulässigen Rahmen) erfolgen nach dem **Eignungs- und Verifizierungsverfahren ({{LINK:VA-14}})**; Verantwortlich: {{ROLE_HR_LEAD}}; Nachweis in der Personalakte.
|
||||
|
||||
### A-G-B2 — R07 3.2 (ISA 3.1.3) Anforderungsblock (heute leer)
|
||||
|
||||
**(a) Falls 3.1.3 im ISA-Scope ist** — Anforderungstext + Anker ergänzen und `mapping.json`-Einträge nachziehen:
|
||||
> `<!-- REQ 3.1.3-M1 -->`
|
||||
> - **[MUSS]** Der Umgang mit unterstützenden Betriebsmitteln (z. B. Verkabelung, Strom-/Klimaversorgung, Serverräume) ist bestimmt; Schutz gegen Ausfall, Wartung und Überwachung sind geregelt.
|
||||
|
||||
**(b) Falls 3.1.3 nicht im Scope ist** — Abschnitt 3.2 samt IMPL-Stub entfernen, damit kein Umsetzungstext ohne zugehörige Anforderung/Mapping verbleibt.
|
||||
|
||||
In beiden Fällen: Klären, ob **ISA 3.1.2** bewusst ausgelassen ist (fehlt in R07 und `mapping.json`) und dokumentieren.
|
||||
|
||||
### A-N3 — R02 3.4 (ISA 1.3.4), IMPL 1.3.4 (REG-SW-WHITELIST, Miss #3)
|
||||
|
||||
> Software (inkl. Spezial-/Wartungssoftware) wird vor Einsatz freigegeben. Zugelassene Software wird im **Register Software-Whitelist ({{LINK:REG-SW-WHITELIST}})** mit Version/Patch-Stand, **Quelle/Lieferant**, Freigabestatus und Freigeber geführt; jeder Eintrag ist mit dem verantwortlichen **Lieferanten ({{LINK:VA-10}} / {{LINK:R13}})** und – als verwaltetes Asset – mit dem **Asset-Inventar ({{LINK:VA-08}} / {{LINK:R02}})** verknüpft. Beschaffung/Freigabe läuft über {{TOOL_TICKET}}; Repositorys sind gegen Manipulation geschützt; Verantwortlich: {{ROLE_IT_LEAD}}; Review {{REVIEW_CYCLE}}.
|
||||
|
||||
### A-N6 — R12 3.1 (ISA 5.3.4 / 5.3.4-KI), IMPL (REG-EXT-SERVICES)
|
||||
|
||||
> … Cloud-/KI-Dienste werden vor Nutzung bewertet (Schutzbedarf, Datenlokation/EU, Verschlüsselung, Exit) und von {{ROLE_ISB}} freigegeben; Freigaben werden im **Register externe IT-/Cloud-/KI-Dienste ({{LINK:REG-EXT-SERVICES}})** mit Schutzbedarf, Datenlokation, **Quelle/Lieferant**, Freigabestatus und Freigeber geführt und mit **Lieferantensteuerung ({{LINK:VA-10}})** sowie **Asset-Inventar ({{LINK:VA-08}})** verknüpft (Ablauf siehe {{LINK:VA-11}}); die ausschließliche Nutzung freigegebener Dienste wird {{REVIEW_CYCLE}} geprüft.
|
||||
|
||||
### A-N8 — R14 (ISA 7.1.2), IMPL 7.1.2 (Datenschutz-Pflege-VA)
|
||||
|
||||
> … das Verzeichnis der Verarbeitungstätigkeiten wird im ISMS-Tool ({{TOOL_NAME}}) geführt, TOM und Löschkonzepte (BL-DEL-01) sind geregelt; Rechtsregister-Review, Löschfristen und Betroffenenrechte werden nach dem **Datenschutz-/Compliance-Pflegeverfahren ({{LINK:VA-18}})** bearbeitet; Verantwortlich: {{ROLE_DPO}}.
|
||||
|
||||
### A-F12 — R03 3.2 (ISA 1.5.1), IMPL 1.5.1 (VA-/Register-Verweis)
|
||||
|
||||
> Die Einhaltung von Richtlinien, Verfahren und technischen Anforderungen wird organisationsweit nach dem **Audit-Programm ({{LINK:REG-AUDIT-PLAN}})** und dem **Audit-/Complianceprüfungs-Verfahren ({{LINK:VA-15}})** durch interne Audits und Kontrollen regelmäßig überprüft (Turnus BL-GOV-01); Ergebnisse werden aufgezeichnet und aufbewahrt, Abweichungen als Maßnahmen im {{TOOL_NAME}} nachverfolgt; Verantwortlich: {{ROLE_ISB}}.
|
||||
|
||||
### A-F13 — R11 3.1 (ISA 5.3.1), IMPL 5.3.1 (VA-Verweis)
|
||||
|
||||
> Informationssicherheitsanforderungen sind fester Bestandteil von Design, Beschaffung, Erweiterung und Änderung von IT-Diensten (Security by Design); Anforderungsspezifikation, Prüfung und Abnahmetests unter Sicherheitsaspekten erfolgen nach dem **Verfahren Sichere Beschaffung/Entwicklung & Abnahme ({{LINK:VA-16}})**; Produktivsetzung erst nach Prüfung **in {{TOOL_TICKET}}**. Produktivdaten in Tests werden vermieden/anonymisiert, Testsysteme angemessen geschützt.{{#if FLAG_DEV_INHOUSE}} Für die Eigenentwicklung gelten Secure-Coding-Vorgaben mit Code-Reviews und automatisierten Sicherheitstests (SAST/Dependency-Scan) gemäß {{LINK:VA-16}}.{{/if}}
|
||||
|
||||
### A-F17 — `mapping.json` / Integrationsleitfaden
|
||||
|
||||
**Variante 1 (Daten an Leitfaden angleichen):** je Anforderung ein Feld `implementation` mit dem gebündelten Umsetzungstext (bzw. eindeutiger Kennung des Control-IMPL-Blocks) aufnehmen, damit der Assessment-Export (§8, „Implementation description") direkt aus `mapping.json` speisbar ist.
|
||||
|
||||
**Variante 2 (Leitfaden an Daten angleichen, geringerer Aufwand):** In §5/§8 dokumentieren, dass `implementation` **nicht** in `mapping.json` liegt, sondern zur Laufzeit über `impl_anchor` (control-gebündelter Anker `IMPL <control>`) aus der jeweiligen `.md` aufgelöst wird. **Zusätzlich klären:** Für Control **1.1.1** ist `impl_anchor == req_anchor` (kein `IMPL 1.1.1`-Block; Leitlinien-Prosa) — diese Sonderauflösung im Leitfaden explizit ausweisen.
|
||||
|
||||
### A-F18 — Trennung SEHR-HOCH in `-elev`-Blöcken (Muster)
|
||||
|
||||
Statt eines gemeinsamen `{{#if FLAG_ELEVATED_PROTECTION}}`-Blocks, der HOCH- und SEHR-HOCH-Sätze mischt:
|
||||
|
||||
> `{{#if FLAG_HIGH_PROTECTION}}` … HOCH-Umsetzungssätze … `{{/if}}`
|
||||
> `{{#if FLAG_VERY_HIGH_PROTECTION}}` … „Bei sehr hohem Schutzbedarf …" … `{{/if}}`
|
||||
|
||||
So erscheint der SEHR-HOCH-Umsetzungstext nur, wenn auch die zugehörigen `[SEHR HOCH]`-Anforderungen im Set sind (betrifft u. a. IMPL 1.2.2-elev, 1.6.2-elev, 1.6.3-elev, 4.1.2-elev, 4.2.1-elev, 5.1.2-elev, 5.2.4-elev, 5.2.6-elev, 5.2.9-elev, 6.1.1-elev).
|
||||
|
||||
---
|
||||
|
||||
## 9. Positiv-Befunde (zur Absicherung, kein Handlungsbedarf)
|
||||
|
||||
- **Baseline-Disziplin:** konkrete Werte durchgängig in `Technische-Sicherheits-Baseline.md` zentralisiert (31 BL-IDs); Umsetzungstexte referenzieren korrekt (z. B. R08 4.1.2 → BL-IAM-01/02, R10 5.2.9 → BL-OPS-05).
|
||||
- **Vorbildliche Referenzketten:** 5.1.1, 5.2.4, 5.2.8, 5.2.9, 6.1.1 verbinden IMPL ↔ VA ↔ Baseline eindeutig — Zielbild für die übrigen Controls.
|
||||
- **Mapping-Integrität:** 316 REQ-Anker ↔ 316 Mapping-IDs, keine Waisen (verifiziert); VA-`FULFILLS`-Header stimmen mit `mapping.json → verfahren` überein.
|
||||
- **Schutzbedarf:** `-elev`-Abdeckung für alle Controls mit HOCH/SEHR-HOCH-Anforderungen vorhanden (Trennungs-Feinschliff siehe F18).
|
||||
- **KI-/GenAI-Ergänzung (R12 3.2)** inhaltlich stark und aktuell (Datenklassen je Dienst, kein Training auf Eingaben, Human-in-the-Loop, EU AI Act) — die Herabstufung von 5.3.4-KI betrifft ausschließlich die Register-Formalisierung, nicht den Sachinhalt.
|
||||
Generated
+6
-2054
File diff suppressed because it is too large
Load Diff
+4
-14
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "isms-tool",
|
||||
"name": "craftvia",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -9,35 +9,27 @@
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint",
|
||||
"test": "tsx scripts/run-tests.ts",
|
||||
"gate": "prisma generate && tsc --noEmit && npm run lint && npm run build && npm run test",
|
||||
"worker:mail": "tsx scripts/mail-worker.ts",
|
||||
"worker:backup": "tsx scripts/backup-worker.ts",
|
||||
"worker:incident-inbound": "tsx scripts/incident-inbound-worker.ts",
|
||||
"seed:content": "tsx prisma/seed-content.ts"
|
||||
"brand:icons": "tsx scripts/generate-brand-icons.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.115.0",
|
||||
"@aws-sdk/client-s3": "^3.1103.0",
|
||||
"@base-ui/react": "^1.6.0",
|
||||
"@dagrejs/dagre": "^3.0.0",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@node-rs/argon2": "^2.0.2",
|
||||
"@prisma/adapter-pg": "^7.8.0",
|
||||
"@prisma/client": "^7.8.0",
|
||||
"@simplewebauthn/browser": "^9.0.1",
|
||||
"@simplewebauthn/server": "^9.0.3",
|
||||
"@xyflow/react": "^12.11.1",
|
||||
"bullmq": "^6.0.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"dotenv": "^17.4.2",
|
||||
"exceljs": "^4.4.0",
|
||||
"handlebars": "^4.7.9",
|
||||
"html-to-image": "^1.11.13",
|
||||
"imapflow": "^1.7.1",
|
||||
"ioredis": "^5.11.1",
|
||||
"lucide-react": "^1.23.0",
|
||||
"mailparser": "^3.9.15",
|
||||
"marked": "^18.0.5",
|
||||
"next": "16.2.12",
|
||||
"next-auth": "5.0.0-beta.32",
|
||||
"next-intl": "^4.13.1",
|
||||
@@ -46,7 +38,6 @@
|
||||
"qrcode": "^1.5.4",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4",
|
||||
"sanitize-html": "^2.17.6",
|
||||
"shadcn": "^4.12.0",
|
||||
"tailwind-merge": "^3.6.0",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
@@ -59,7 +50,6 @@
|
||||
"@types/qrcode": "^1.5.6",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@types/sanitize-html": "^2.16.1",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "16.2.12",
|
||||
"prisma": "7.8.0",
|
||||
|
||||
@@ -8,16 +8,16 @@
|
||||
# - Vorher an der Registry angemeldet: docker login "$REGISTRY_HOST"
|
||||
#
|
||||
# Aufruf (im Repo-Root, auf dem gewünschten Commit ausgecheckt):
|
||||
# REGISTRY=git.certvia.de/msolarczek TAG=$(git rev-parse --short HEAD) ./scripts/build-and-push-images.sh
|
||||
# REGISTRY=registry.example.com/craftvia TAG=$(git rev-parse --short HEAD) ./scripts/build-and-push-images.sh
|
||||
#
|
||||
# Env-Variablen:
|
||||
# REGISTRY Image-Präfix (Default: git.certvia.de/msolarczek)
|
||||
# REGISTRY Image-Präfix (Default: registry.example.com/craftvia)
|
||||
# TAG Image-Tag (Default: kurzer Git-SHA des aktuellen HEAD)
|
||||
# PLATFORM Zielplattform (Default: linux/amd64 — passend zum Prod-Host)
|
||||
# ALSO_MAIN wenn "true": zusätzlich das bewegliche Tag :main setzen/pushen
|
||||
set -euo pipefail
|
||||
|
||||
REGISTRY="${REGISTRY:-git.certvia.de/msolarczek}"
|
||||
REGISTRY="${REGISTRY:-registry.example.com/craftvia}"
|
||||
TAG="${TAG:-$(git rev-parse --short HEAD)}"
|
||||
PLATFORM="${PLATFORM:-linux/amd64}"
|
||||
ALSO_MAIN="${ALSO_MAIN:-false}"
|
||||
@@ -43,13 +43,13 @@ build_one() {
|
||||
|
||||
# migrate + runner teilen sich die teuren Stages deps/builder (npm ci + next build).
|
||||
# Sequentiell auf demselben Host -> zweiter Build nutzt den Layer-Cache des ersten.
|
||||
build_one runner certvia-app
|
||||
build_one migrate certvia-migrate
|
||||
build_one garage certvia-garage
|
||||
build_one runner craftvia-app
|
||||
build_one migrate craftvia-migrate
|
||||
build_one garage craftvia-garage
|
||||
|
||||
echo
|
||||
echo ">> Push ..."
|
||||
for name in certvia-app certvia-migrate certvia-garage; do
|
||||
for name in craftvia-app craftvia-migrate craftvia-garage; do
|
||||
docker push "$REGISTRY/$name:$TAG"
|
||||
[ "$ALSO_MAIN" = "true" ] && docker push "$REGISTRY/$name:main" || true
|
||||
done
|
||||
|
||||
@@ -10,7 +10,7 @@ import "dotenv/config";
|
||||
* betriebsbereiten Zustand her:
|
||||
* 1. Layout: dem Node einmalig Zone + Kapazität zuweisen und anwenden (ohne Layout
|
||||
* lehnt Garage jeden Schreibzugriff mit „no capacity" ab).
|
||||
* 2. Bucket `S3_BUCKET` (Default isms-documents) anlegen.
|
||||
* 2. Bucket `S3_BUCKET` (Default craftvia-documents) anlegen.
|
||||
* 3. Access-Key deterministisch IMPORTIEREN — aus S3_ACCESS_KEY/S3_SECRET_KEY der
|
||||
* Coolify-Env, damit App-Env und Garage denselben Schlüssel teilen (kein
|
||||
* Nachpflegen erzeugter Keys).
|
||||
@@ -58,7 +58,7 @@ function readCfg(): Cfg | null {
|
||||
}
|
||||
const accessKeyId = process.env.S3_ACCESS_KEY?.trim();
|
||||
const secretKey = process.env.S3_SECRET_KEY?.trim();
|
||||
const bucket = process.env.S3_BUCKET?.trim() || "isms-documents";
|
||||
const bucket = process.env.S3_BUCKET?.trim() || "craftvia-documents";
|
||||
if (!accessKeyId || !secretKey) {
|
||||
throw new Error(
|
||||
"GARAGE_ADMIN_TOKEN ist gesetzt, aber S3_ACCESS_KEY/S3_SECRET_KEY fehlen. " +
|
||||
@@ -210,7 +210,7 @@ async function ensureKey(cfg: Cfg): Promise<void> {
|
||||
const imported = await admin(cfg, "POST", "/v1/key/import", {
|
||||
accessKeyId: cfg.accessKeyId,
|
||||
secretAccessKey: cfg.secretKey,
|
||||
name: "isms-app",
|
||||
name: "craftvia-app",
|
||||
});
|
||||
if (imported.status === 200) {
|
||||
log(`Access-Key ${cfg.accessKeyId} importiert.`);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Test-Runner: führt alle `scripts/test-*.ts` nacheinander via tsx aus und liefert eine
|
||||
* Zusammenfassung + Exit-Code (≠ 0, sobald ein Test scheitert).
|
||||
*
|
||||
* Voraussetzungen: lokale Infra (Postgres/Redis/Garage) läuft, `.env` gesetzt, Datenbank
|
||||
* migriert und geseedet (`npx prisma migrate deploy && npx prisma db seed`).
|
||||
*
|
||||
* Lauf: npm run test (alle)
|
||||
* npm run test -- mail tenant (nur Tests, deren Name einen der Filter enthält)
|
||||
*/
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { readdirSync } from "node:fs";
|
||||
import { join, dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const SCRIPTS_DIR = dirname(fileURLToPath(import.meta.url));
|
||||
const filters = process.argv.slice(2);
|
||||
|
||||
const tests = readdirSync(SCRIPTS_DIR)
|
||||
.filter((f) => /^test-.+\.ts$/.test(f))
|
||||
.filter((f) => filters.length === 0 || filters.some((flt) => f.includes(flt)))
|
||||
.sort();
|
||||
|
||||
if (tests.length === 0) {
|
||||
console.error("Keine Tests gefunden.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const results: { name: string; ok: boolean; ms: number }[] = [];
|
||||
for (const file of tests) {
|
||||
const started = Date.now();
|
||||
console.log(`\n━━━ ${file} ━━━`);
|
||||
const run = spawnSync(process.execPath, ["--import", "tsx", join(SCRIPTS_DIR, file)], {
|
||||
stdio: "inherit",
|
||||
env: process.env,
|
||||
});
|
||||
results.push({ name: file, ok: run.status === 0, ms: Date.now() - started });
|
||||
}
|
||||
|
||||
const failed = results.filter((r) => !r.ok);
|
||||
console.log("\n══════════ Test-Zusammenfassung ══════════");
|
||||
for (const r of results) console.log(`${r.ok ? "✓" : "✗"} ${r.name.padEnd(36)} ${(r.ms / 1000).toFixed(1)}s`);
|
||||
console.log(`\n${results.length - failed.length}/${results.length} Testskripte grün${failed.length ? ` — ${failed.length} fehlgeschlagen` : ""}.`);
|
||||
process.exit(failed.length ? 1 : 0);
|
||||
Reference in New Issue
Block a user