Fundament: ISMS-Module entfernt; Craftvia-Rollen, Module, Navigation, i18n-Split

- ISMS-Routen, Actions, Server-/Lib-Code, Komponenten, Prisma-Modelle, Seeds,
  Importer, Skripte und ISMS-Tests entfernt (Fundament bleibt: Auth, Identity,
  MFA/WebAuthn, RBAC, Audit, Mail, Storage, Backup/DSGVO, Plattform-Admin)
- Schema auf Fundament-Modelle reduziert; TenantSettings generisch (+phone/email)
- TENANT_MODELS (db.ts, backup/topology.ts) und PII-Felder ausgedünnt
- RBAC: Rollen tenant-admin/backoffice/team-lead/technician + Craftvia-Permissions
- Modul-Katalog (customers, sites, teams, work_orders, imports, field, reports,
  emergency, documents, notifications, lotse) + Navigation aus src/lib/nav.ts
- Modul-Routen mit requireModule-Layout und Platzhalterseite
- Message-Katalog je Namespace (messages/<locale>/<namespace>.json), fs-Loader
- check-module-guards: Modul-Key aus src/server/actions/<moduleKey>/
- Provisionierung, Admin-Konsole, Einstellungen, Files-Route, Mail entkoppelt
- Seed minimal (demo/demo2, Nutzer je Rolle); Fundament-Tests auf Role/
  NotificationPreference-Fixtures umgestellt

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 11:35:44 +02:00
co-authored by Claude Opus 5
parent c8e6f30a27
commit 8491c7f173
443 changed files with 1325 additions and 87773 deletions
+19 -14
View File
@@ -5,28 +5,26 @@ import createNextIntlPlugin from "next-intl/plugin";
// zum Dev-Server. Diese Lockerungen gelten NUR in der Entwicklung, nie im Build.
const isDev = process.env.NODE_ENV !== "production";
// Content-Security-Policy (F-07) — zweite Verteidigungslinie hinter dem
// HTML-Sanitizing (F-03).
// Content-Security-Policy (F-07).
//
// Hinweis Skripte: 'unsafe-inline' ist ein bewusster Zwischenstand. Next.js
// liefert seinen Hydration-Bootstrap als Inline-Skript aus; eine Nonce-basierte
// CSP (Nonce in proxy.ts erzeugen und an <script>/Next durchreichen) ist ein
// eigenes Folgepaket. Bis dahin bleibt 'unsafe-inline' für Skripte bestehen.
// Hinweis Skripte: 'unsafe-inline' ist ein bewusster Zwischenstand. Next.js liefert
// seinen Hydration-Bootstrap als Inline-Skript aus; eine Nonce-basierte CSP (Nonce in
// proxy.ts erzeugen und durchreichen) ist ein eigenes Folgepaket.
const csp = [
"default-src 'self'",
// Skripte: 'unsafe-inline' als Zwischenstand (s.o.); 'unsafe-eval' nur im Dev
// (Turbopack/HMR wertet zur Laufzeit aus, im Produktionsbuild nicht nötig).
`script-src 'self' 'unsafe-inline'${isDev ? " 'unsafe-eval'" : ""}`,
// Next.js sowie @xyflow/react und Tailwind v4 setzen Inline-Styles.
// Next.js und Tailwind v4 setzen Inline-Styles.
"style-src 'self' 'unsafe-inline'",
// data: für den MFA-QR-Code (qrcode → data:-URI); blob: für Graph-Bildexport
// (html-to-image) und ähnliche clientseitig erzeugte Bilder.
// data: für den MFA-QR-Code; blob: für clientseitige Foto-Vorschauen (Einsatz-Fotos).
"img-src 'self' data: blob:",
// blob: für lokale Wiedergabe von Sprachnotizen vor dem Upload.
"media-src 'self' blob:",
"font-src 'self' data:",
// Im Dev zusätzlich der HMR-WebSocket des Dev-Servers.
`connect-src 'self'${isDev ? " ws: wss:" : ""}`,
// html-to-image kann Worker aus Blobs erzeugen.
"worker-src 'self' blob:",
// PWA: Service Worker nur vom eigenen Ursprung.
"worker-src 'self'",
"manifest-src 'self'",
"frame-ancestors 'none'",
"form-action 'self'",
"base-uri 'self'",
@@ -40,12 +38,19 @@ const securityHeaders = [
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "X-Frame-Options", value: "DENY" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
{ key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=(), payment=()" },
// Einsatz-App: Kamera (Fotos), Mikrofon (Sprachnotizen), Standort (Einsatzstart) —
// nur für den eigenen Ursprung. Zahlungs-API bleibt aus.
{ key: "Permissions-Policy", value: "camera=(self), microphone=(self), geolocation=(self), payment=()" },
];
const nextConfig: NextConfig = {
// Standalone-Output für den Docker-Multi-Stage-Build (siehe Dockerfile)
output: "standalone",
// i18n-Kataloge werden zur Laufzeit per fs geladen (src/i18n/request.ts) — für den
// standalone-Output explizit mitkopieren.
outputFileTracingIncludes: {
"/*": ["./messages/**/*.json"],
},
async headers() {
return [
{