- docker-compose.coolify(.prebuilt).yml: Service craftvia-worker (Target worker, Chromium, shm_size 1gb, gleiche Härtung), Craftvia-Variablen für app und worker. - Dockerfile: worker-Stage mit HOME=/home/app (Chromium-Profil für non-root); lokaler docker build der Targets runner und worker erfolgreich, PDF-Erzeugung im Image geprüft. - .env.example/.env.prod.example/.env.coolify.example: alle Craftvia-Variablen inkl. RLS, KI-Provider, PDF_CHROMIUM_PATH, OFFLINE_MAX_DAYS, API_RATE_LIMIT_*, AI_GENERATION_RETENTION_DAYS, AI_MONTHLY_TOKEN_LIMIT. - CI (.github, .gitea): Job gate mit Postgres (pgvector) und Redis als Service: migrate deploy, seed, Passwort für craftvia_app, tsc, lint, build, npm run test. - docs/craftvia/DEPLOY.md (aus den Certvia-Deploy-Docs abgeleitet): Architektur, Domains, Secrets, Worker, Migrationen, RLS-Aktivierung, Backup/Restore, KI, Rate Limits, Aufbewahrung, Smoke, Update/Rollback. build-and-push-images.sh baut craftvia-worker. - Certvia-/ISMS-Dokumente aus docs/ nach docs/_certvia-archiv/ (mit README); Verweise in README.md und Skript-Kommentaren angepasst. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8.3 KiB
Umsetzungspaket — Sicherheit & Administration (1 Entwickler)
Claude-Code-Prompt. Basis-Branch
dev; je Story ein Feature-Branchdev/sec<n>-…(PR-Zieldev). Grundlage:Sicherheit-und-Administration-Konzept.md+ Ist-StandSTAND-dev-branch.md. Entscheidungen (fix): Mail via SMTP · 1 Entwickler (sequenziell) · 2FA bleibt optional, aber pro Tenant im Adminportal als Pflicht einstellbar · Passkeys dabei · DSGVO-Funktionen dabei.
Vorhandenes wiederverwenden (nicht neu bauen)
- MFA-Kern (TOTP + Recovery-Codes) für Plattform- und Mandanten-Nutzer:
src/server/mfa.ts; Policy-FlagsecurityPolicy.mfaRequiredexistiert. - Passwort:
src/lib/password-policy.ts(Validierung) +src/server/password.ts(Argon2id + Generator); Force-Change-Gate im(app)-Layout. - Auth: zwei NextAuth-Instanzen — Mandant
src/server/auth.ts(/login), Plattformsrc/server/platform-auth.ts(/platform/login).PlatformAdmin-Store getrennt. - Queue: BullMQ + Redis im Stack. Audit-Log mit
tenantIdnullable (scope=platform). Task/TaskComment für Ticket-/Freigabe-Ereignisse. - Modul-Guard: neue Server-Actions in
scripts/check-module-guards.tseintragen; tenant-Modelle inTENANT_MODELS+RLS.
Betriebs-/DNS-Voraussetzungen (kein Code, aber Vorbedingung)
Dedizierte Absenderdomain (no-reply@certvia.de) mit SPF, DKIM, DMARC; TLS/HSTS; SMTP-Zugangsdaten + alle Secrets aus Env/Secret-Store (nicht im Repo).
Reihenfolge (sequenziell, 1 Entwickler)
SEC1 → SEC2 → SEC3 → SEC4 → SEC5 → SEC6. Einzelne P0-Härtungen (Rate-Limit an Login/Reset/MFA, Token-Hashing) landen inline in SEC2/SEC3; die globalen Härtungen bündelt SEC5.
SEC1 — SMTP-Mail-Fundament (dev/sec1-mail-smtp) [L]
Ziel: zuverlässiger, gebrandeter, asynchroner Mail-Versand als Fundament für Reset/Einladung/Benachrichtigung.
- Mail-Service
src/server/mail/**mit SMTP-Transport (nodemailer, TLS) hinter einem InterfacesendMail(template, to, vars, locale)— Provider später austauschbar. - Queue/Worker über BullMQ/Redis: asynchron, Retry mit Backoff, Dead-Letter, Rate-Limit; Fehler/Bounce ins Log.
- Templates (Certvia-gebrandet, de/en, HTML + Text-Alternative): Einladung, Passwort-Reset, „Passwort geändert", E-Mail-Änderung bestätigen, „MFA geändert", Ticket-/Freigabe-/Fristen-Benachrichtigung.
- Benachrichtigungsregeln: je Nutzer/Ereignis opt-in/opt-out + Sprache; strikt mandantengetrennt. Trigger aus Task-Ereignissen (Zuweisung, Freigabe-Anfrage, Entscheidung, Fälligkeit).
- Admin-Testversand (eine Aktion „Test-Mail senden") zur Zustellprüfung.
- AK: Mail wird asynchron mit Retry versendet; Templates gebrandet + zweisprachig; Bounces/Fehler geloggt; Ticket-Benachrichtigung wird bei Task-Zuweisung/Freigabe ausgelöst; keine Secrets im Repo.
SEC2 — Passwort-Self-Service & Sessions (dev/sec2-auth-selfservice) [M–L] · Abh. SEC1
- Passwort-Reset: „Passwort vergessen" → Single-Use-Token, kurzlebig (30–60 Min), serverseitig gehasht gespeichert, an E-Mail gebunden. Enumeration-Schutz (immer gleiche Antwort), Rate-Limit je IP/Konto. Nach Reset: alle Sessions invalidieren + Bestätigungs-Mail + Audit; deaktivierte/gesperrte Konten erhalten keinen Reset.
- Passwort selbst ändern: Profilseite mit Alt-Passwort-Bestätigung, Policy-Prüfung, danach andere Sessions abmelden (aktuelle behalten), Bestätigungs-Mail + Audit.
- E-Mail-Änderung: Double-Opt-in an neue Adresse + Benachrichtigung an alte; Audit.
- Session-Invalidierung als wiederverwendbarer Baustein (bei Reset/Änderung/Deaktivierung/MFA-Änderung).
- AK: Reset-Token single-use/gehasht/rate-limited/enumeration-safe; Self-Change funktioniert; E-Mail-Änderung verifiziert; Sessions werden korrekt invalidiert; alle Ereignisse im Audit.
SEC3 — MFA pro Tenant erzwingen + Passkeys (dev/sec3-mfa-passkeys) [L] · Abh. SEC1
- Optional bleibt Default. Im Adminportal kann pro Mandant
securityPolicy.mfaRequiredgesetzt werden (Superadmin) → Enrollment-Gate: Nutzer dieses Mandanten werden beim nächsten Login zur MFA-Einrichtung gezwungen (analog Force-Change-Gate im(app)-Layout). Ebenso erzwingbar für alle Plattform-Admins. - Passkeys/WebAuthn als zusätzlicher 2. Faktor (
@simplewebauthn/server+ Browser-API): Registrierung + Login; Nutzer kann TOTP oder Passkey verwenden; Credentials verwaltbar (anlegen/entfernen). - Step-up-Re-Auth für sensible Aktionen: MFA deaktivieren, Plattform-Admin anlegen, Datenexport, Mandant löschen.
- TOTP-Secret at rest verschlüsselt (falls noch Klartext) + Rate-Limit auf Code-Eingabe; Recovery-Codes-Flow (Anzeige/Regenerierung, Verbrauch protokolliert) abrunden.
- AK: Admin setzt
mfaRequiredje Tenant → betroffene Nutzer müssen beim Login enrollen; Passkey-Registrierung + -Login funktionieren; Step-up greift bei sensiblen Aktionen; TOTP-Secret verschlüsselt; MFA global weiterhin optional, wenn Policy es nicht verlangt.
SEC4 — Plattform-Admin-Verwaltung (dev/sec4-platform-admins) [M] · Abh. SEC1, SEC3
- Verwaltungs-UI im Adminportal (
src/app/(platform)/admin/**, Actionsplatform*.ts): weiterePlatformAdminanlegen (Einladung via SEC1 oder Initial-Passwort), Rollen (z. B. „Voll-Admin" vs. „Support/Read-only"), sperren/reaktivieren, Passwort-Reset, MFA-Pflicht für Plattform-Admins. - Selbst-Aussperr-Schutz auf Plattform-Ebene (letzter Voll-Admin nicht entfernbar/deaktivierbar); kritische Aktionen mit Step-up (SEC3).
- Vollständiges Plattform-Audit (
scope=platform) jeder Aktion. - AK: ein zweiter Voll-Admin ist anlegbar und kann verwalten; Rollen greifen (Read-only kann nichts ändern); Last-Admin-Schutz aktiv; jede Aktion protokolliert.
SEC5 — Härtung P0 (quer) (dev/sec5-hardening) [M]
- HTTP-Security-Header (zentrale Middleware): CSP, HSTS,
X-Frame-Options/frame-ancestors,X-Content-Type-Options,Referrer-Policy,Permissions-Policy. - Rate-Limiting/Brute-Force global an Login/Reset/MFA/Admin-Aktionen (IP und kontobezogen), ergänzt den bestehenden Konto-Lockout.
- Security-Audit erweitern: Logins (Erfolg/Fehlschlag), Rechte-/Rollenänderungen, MFA-Änderungen, Exporte, Admin-Aktionen; append-only/manipulationssicher; Aufbewahrung definiert.
- Passwort-Breach-Check (HaveIBeenPwned k-Anonymity) beim Setzen/Ändern zusätzlich zur Policy.
- Token-/Secret-Hygiene: alle Tokens single-use + gehasht (Konsistenz zu SEC2/SEC3); Secret-Scanning in CI.
- AK: Header messbar gesetzt (z. B. securityheaders-Check); Rate-Limits greifen; Audit-Ereignisse vorhanden; bekannte kompromittierte Passwörter werden abgelehnt.
SEC6 — DSGVO-Funktionen (dev/sec6-dsgvo) [L] · Abh. SEC1, SEC3 (Step-up)
- Mandanten-Datenexport (vollständig, maschinenlesbar, z. B. JSON/ZIP), Admin-getriggert, asynchron via Queue, Download-Link mit Ablauf.
- Löschung/Retention: Mandanten-Löschung (Soft→Hard mit Karenz), Aufbewahrungsfristen/Löschkonzept, RLS-bewusste Kaskaden; Audit; Step-up-Bestätigung.
- Betroffenenrechte: Export/Löschung nutzerbezogener Daten, soweit anwendbar.
- Doku-Bausteine (Inhalt, kein Code): AVV/DPA + TOMs — als offener fachlicher Punkt markieren.
- AK: vollständiger Tenant-Export erzeugbar; Löschung respektiert Retention + Audit + Step-up; DSGVO-Aktionen protokolliert.
Definition of Done (jede Story)
npx tsc --noEmit → npm run lint → npm run build (Guard-Check) grün · neue Actions in check-module-guards.ts · neue tenant-Modelle in TENANT_MODELS+RLS+Migration (RLS-DO-Block) · Security-Verifikation (Header/Rate-Limit/Token) · Browser-Test der Flows · Demo-Umgebung lauffähig · Secrets nur aus Env.
Hot Files (koordiniert, da 1 Entwickler → nur Reihenfolge beachten)
prisma/schema.prisma + Migrationsreihenfolge · zentrale Middleware (Header/Rate-Limit) · (app)- und (platform)-Layouts (Enrollment-/Force-Gates) · src/server/auth.ts / platform-auth.ts / mfa.ts · scripts/check-module-guards.ts.
Offene fachliche Punkte
- DNS: SPF/DKIM/DMARC vor Produktivversand aktiv.
- AVV/DPA-Texte + TOMs (Datenschutz/ISB).
- Aufbewahrungsfristen je Datenart festlegen (Grundlage für SEC6-Retention).