Projekt-Fundament: Spec, Docker-Stack, Prisma-Basis, Tenant-Guard
- docs/SPEC.md (v1.2: Assets & BIA als ein Modul, Risiko-Detailansicht mit Maßnahmen/betroffenen Assets, Risiko-Verknüpfungen in allen Detailansichten) + UI-Mockup als Referenz - Docker-Compose: app, worker, postgres (pgvector), redis, minio, mailhog - Prisma 7: Fundament-Schema (Tenant, User, RBAC, AuditLog), prisma.config.ts, pg-Treiberadapter - Tenant-Guard (src/server/db.ts): erzwungene Mandanten-Isolation für alle tenant-gebundenen Modelle - AGENTS.md/README mit Projektregeln (Isolation, RBAC, Audit-Log, i18n, Lizenz) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# --- Datenbank ---
|
||||
POSTGRES_USER=isms
|
||||
POSTGRES_PASSWORD=isms
|
||||
POSTGRES_DB=isms
|
||||
DATABASE_URL=postgresql://isms:isms@localhost:5432/isms?schema=public
|
||||
|
||||
# --- Redis (BullMQ) ---
|
||||
REDIS_URL=redis://localhost:6379
|
||||
|
||||
# --- Objektspeicher (MinIO / S3-kompatibel) ---
|
||||
S3_ENDPOINT=http://localhost:9000
|
||||
S3_ACCESS_KEY=isms
|
||||
S3_SECRET_KEY=isms-secret
|
||||
S3_BUCKET=isms-documents
|
||||
|
||||
# --- Auth ---
|
||||
AUTH_SECRET=change-me-generate-with-openssl-rand-base64-32
|
||||
AUTH_URL=http://localhost:3000
|
||||
|
||||
# --- KI-Provider (anthropic | openai) ---
|
||||
AI_PROVIDER=anthropic
|
||||
AI_API_KEY=
|
||||
|
||||
# --- E-Mail (Dev: Mailhog) ---
|
||||
SMTP_HOST=localhost
|
||||
SMTP_PORT=1025
|
||||
SMTP_USER=
|
||||
SMTP_PASSWORD=
|
||||
SMTP_FROM=isms@example.com
|
||||
@@ -32,6 +32,7 @@ yarn-error.log*
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
.env*
|
||||
!.env.example
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
@@ -3,3 +3,32 @@
|
||||
|
||||
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
|
||||
<!-- END:nextjs-agent-rules -->
|
||||
|
||||
# ISMS-Tool — Projektregeln
|
||||
|
||||
Multi-Tenant-SaaS für Informationssicherheits-Managementsysteme (ISO/IEC 27001:2022, TISAX/VDA-ISA 6.0).
|
||||
|
||||
**Maßgebliche Spezifikation: [docs/SPEC.md](docs/SPEC.md)** — Architektur, Datenmodell, Module, Rollen, Akzeptanzkriterien. UI-Referenz: [docs/ISMS-Prototyp-GEFIM.html](docs/ISMS-Prototyp-GEFIM.html) (Orientierung für Navigation/Layout; fachlich gilt die Spec, die über das Mockup hinausgeht).
|
||||
|
||||
## Eiserne Regeln
|
||||
|
||||
1. **Mandanten-Isolation:** Kein DB-Zugriff an Prisma vorbei, kein Query ohne Tenant-Kontext. Fachliche Tabellen tragen `tenant_id`; Zugriff nur über den Tenant-Guard (`src/server/db.ts`), zusätzlich Postgres RLS.
|
||||
2. **RBAC serverseitig:** Jede Mutation/Query prüft Permissions am Server (`asset:read`, `risk:write`, …). UI-Ausblenden ist nur Komfort, nie Sicherheit.
|
||||
3. **Audit-Log:** Jede schreibende Aktion erzeugt einen `AuditLog`-Eintrag (before/after).
|
||||
4. **i18n:** Keine hartkodierten UI-Texte — alle Strings über den Message-Katalog (`de` default, `en` vorbereitet).
|
||||
5. **Lizenz:** Keine ISO-Normtexte oder VDA-ISA-Kataloginhalte einchecken — nur Control-Referenzen/Titel; VDA-ISA-Inhalte kommen per Kunden-Import (`ISA6-EN.xlsx`).
|
||||
|
||||
## Stack & Konventionen
|
||||
|
||||
- Next.js (App Router) + TypeScript, Tailwind CSS 4, shadcn/ui, dnd-kit, Recharts.
|
||||
- Prisma + PostgreSQL 16 (pgvector), BullMQ + Redis (Worker), MinIO (S3), Auth.js (Credentials, Argon2id).
|
||||
- Tests: Vitest (Unit), Playwright (E2E). `npm run lint` und `npm run build` müssen vor jedem Commit grün sein.
|
||||
- Sprache: UI und Fachbegriffe Deutsch; Code (Bezeichner, Kommentare) Englisch.
|
||||
|
||||
## Entwicklung
|
||||
|
||||
```bash
|
||||
docker compose up -d postgres redis minio # Infrastruktur
|
||||
npx prisma migrate dev # Migrationen
|
||||
npm run dev # App auf :3000
|
||||
```
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
# ISMS-Tool — Next.js App (Multi-Stage-Build)
|
||||
FROM node:22-alpine AS deps
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
COPY prisma ./prisma
|
||||
RUN npm ci
|
||||
|
||||
FROM node:22-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
RUN npx prisma generate && npm run build
|
||||
|
||||
FROM node:22-alpine AS runner
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
RUN addgroup -S app && adduser -S app -G app
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
COPY --from=builder /app/.next/static ./.next/static
|
||||
COPY --from=builder /app/public ./public
|
||||
USER app
|
||||
EXPOSE 3000
|
||||
CMD ["node", "server.js"]
|
||||
@@ -1,36 +1,42 @@
|
||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
||||
# ISMS-Tool
|
||||
|
||||
## Getting Started
|
||||
Multi-Tenant-SaaS zum Betrieb eines Informationssicherheits-Managementsystems (ISMS), ausgerichtet auf **ISO/IEC 27001:2022** und **TISAX / VDA-ISA 6.0**.
|
||||
|
||||
First, run the development server:
|
||||
📄 Vollständige Spezifikation: [docs/SPEC.md](docs/SPEC.md) · UI-Mockup: [docs/ISMS-Prototyp-GEFIM.html](docs/ISMS-Prototyp-GEFIM.html)
|
||||
|
||||
## Module
|
||||
|
||||
- **Assets & BIA** — Asset-Inventar und Business Impact Analyse als gemeinsames Modul (Schutzbedarf, RTO/RPO/MTD, primäre/sekundäre Assets, zugeordnete Risiken)
|
||||
- **Risikoanalyse** — 5×5-Heatmap mit Drag-and-Drop, Detailansicht mit Maßnahmen, betroffenen Assets und Rest-Risiko
|
||||
- **SoA & Control-Kataloge** — ISO 27001:2022 Annex A (93 Controls), VDA-ISA-6.0-Struktur mit Reifegraden
|
||||
- **Maßnahmen** — Kanban, wiederkehrende Aufgaben, Fristen und Eskalation
|
||||
- **Vorfälle, Audits, Lieferanten, Nachweise, Richtlinien (KI-Assistent), RAG-Chat, Dashboards, Management-Review**
|
||||
|
||||
## Tech-Stack
|
||||
|
||||
Next.js (App Router, TypeScript) · Prisma + PostgreSQL 16 (pgvector) · BullMQ + Redis · MinIO (S3) · Auth.js · Tailwind CSS + shadcn/ui · Docker Compose
|
||||
|
||||
## Quickstart (Entwicklung)
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
cp .env.example .env # Werte anpassen
|
||||
docker compose up -d postgres redis minio # Infrastruktur starten
|
||||
npm install
|
||||
npx prisma migrate dev # Datenbank migrieren
|
||||
npm run dev # http://localhost:3000
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
Produktions-Stack (App + Worker + Infrastruktur):
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||
## Projektstruktur
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||
```
|
||||
docs/ Spezifikation (SPEC.md) und UI-Mockup
|
||||
prisma/ Datenbankschema, Migrationen, Seeds
|
||||
src/app/ Next.js App Router (UI + API)
|
||||
src/server/ Server-Logik (Tenant-Guard, RBAC, Services)
|
||||
```
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
ports:
|
||||
- "3000:3000"
|
||||
env_file: .env
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
minio:
|
||||
condition: service_started
|
||||
restart: unless-stopped
|
||||
|
||||
worker:
|
||||
build: .
|
||||
command: ["npm", "run", "worker"]
|
||||
env_file: .env
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
restart: unless-stopped
|
||||
|
||||
postgres:
|
||||
image: pgvector/pgvector:pg16
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-isms}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-isms}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-isms}
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-isms}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
volumes:
|
||||
- redisdata:/data
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
||||
minio:
|
||||
image: minio/minio:latest
|
||||
command: server /data --console-address ":9001"
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-isms}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-isms-secret}
|
||||
volumes:
|
||||
- miniodata:/data
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
|
||||
mailhog:
|
||||
image: mailhog/mailhog:latest
|
||||
profiles: ["dev"]
|
||||
ports:
|
||||
- "1025:1025"
|
||||
- "8025:8025"
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
redisdata:
|
||||
miniodata:
|
||||
File diff suppressed because one or more lines are too long
+310
@@ -0,0 +1,310 @@
|
||||
# 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
|
||||
+2
-1
@@ -1,7 +1,8 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
/* config options here */
|
||||
// Standalone-Output für den Docker-Multi-Stage-Build (siehe Dockerfile)
|
||||
output: "standalone",
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
Generated
+1748
-17
File diff suppressed because it is too large
Load Diff
+7
-1
@@ -9,9 +9,13 @@
|
||||
"lint": "eslint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/adapter-pg": "^7.8.0",
|
||||
"@prisma/client": "^7.8.0",
|
||||
"dotenv": "^17.4.2",
|
||||
"next": "16.2.10",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4"
|
||||
"react-dom": "19.2.4",
|
||||
"zod": "^4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4",
|
||||
@@ -20,7 +24,9 @@
|
||||
"@types/react-dom": "^19",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "16.2.10",
|
||||
"prisma": "^7.8.0",
|
||||
"tailwindcss": "^4",
|
||||
"tsx": "^4.22.4",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import "dotenv/config";
|
||||
import { defineConfig, env } from "prisma/config";
|
||||
|
||||
export default defineConfig({
|
||||
schema: "prisma/schema.prisma",
|
||||
datasource: {
|
||||
url: env("DATABASE_URL"),
|
||||
},
|
||||
migrations: {
|
||||
path: "prisma/migrations",
|
||||
seed: "tsx prisma/seed.ts",
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,129 @@
|
||||
// ISMS-Tool — Prisma-Schema
|
||||
// Fundament (Iteration 1): Mandanten, Nutzer, RBAC, Audit-Log.
|
||||
// Fachliche Entitäten (Assets, BIA, Risiken, …) folgen je Iteration — siehe docs/SPEC.md §5.
|
||||
//
|
||||
// Multi-Tenant-Regel: Jede fachliche Tabelle trägt tenantId. Zugriff nur über den
|
||||
// zentralen Tenant-Guard (src/server/db.ts); zusätzlich Postgres RLS (prisma/rls.sql).
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
previewFeatures = ["postgresqlExtensions"]
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
extensions = [pgvector(map: "vector")]
|
||||
}
|
||||
|
||||
enum TenantStatus {
|
||||
ACTIVE
|
||||
SUSPENDED
|
||||
}
|
||||
|
||||
enum UserStatus {
|
||||
ACTIVE
|
||||
INVITED
|
||||
LOCKED
|
||||
DEACTIVATED
|
||||
}
|
||||
|
||||
model Tenant {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
slug String @unique
|
||||
status TenantStatus @default(ACTIVE)
|
||||
config Json @default("{}")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
users User[]
|
||||
roles Role[]
|
||||
auditLogs AuditLog[]
|
||||
|
||||
@@map("tenants")
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
email String
|
||||
passwordHash String @map("password_hash")
|
||||
name String
|
||||
status UserStatus @default(ACTIVE)
|
||||
mfaSecret String? @map("mfa_secret")
|
||||
// Plattform-Admin ist mandantenübergreifend (Betreiberrolle)
|
||||
isPlatformAdmin Boolean @default(false) @map("is_platform_admin")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
userRoles UserRole[]
|
||||
|
||||
@@unique([tenantId, email])
|
||||
@@index([tenantId])
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model Role {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
key String // z. B. tenant-admin, isb, auditor, owner, user
|
||||
name String
|
||||
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
userRoles UserRole[]
|
||||
rolePermissions RolePermission[]
|
||||
|
||||
@@unique([tenantId, key])
|
||||
@@index([tenantId])
|
||||
@@map("roles")
|
||||
}
|
||||
|
||||
model Permission {
|
||||
id String @id @default(cuid())
|
||||
key String @unique // z. B. asset:read, risk:write, incident:manage
|
||||
|
||||
rolePermissions RolePermission[]
|
||||
|
||||
@@map("permissions")
|
||||
}
|
||||
|
||||
model UserRole {
|
||||
userId String @map("user_id")
|
||||
roleId String @map("role_id")
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([userId, roleId])
|
||||
@@map("user_roles")
|
||||
}
|
||||
|
||||
model RolePermission {
|
||||
roleId String @map("role_id")
|
||||
permissionId String @map("permission_id")
|
||||
|
||||
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
||||
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([roleId, permissionId])
|
||||
@@map("role_permissions")
|
||||
}
|
||||
|
||||
model AuditLog {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
actorId String? @map("actor_id")
|
||||
action String // create | update | delete | login | export | …
|
||||
entity String // z. B. asset, risk, user
|
||||
entityId String? @map("entity_id")
|
||||
before Json?
|
||||
after Json?
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
|
||||
@@index([tenantId, entity, entityId])
|
||||
@@index([tenantId, createdAt])
|
||||
@@map("audit_logs")
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import { PrismaPg } from "@prisma/adapter-pg";
|
||||
|
||||
/**
|
||||
* Central database access for the ISMS tool.
|
||||
*
|
||||
* Multi-tenant rule (see docs/SPEC.md §2): no query on tenant-scoped models
|
||||
* without a tenant context. Application code MUST use `dbForTenant(tenantId)`
|
||||
* for all tenant-scoped models — the raw client is only for global data
|
||||
* (permissions, control catalogs) and platform administration.
|
||||
*
|
||||
* Postgres Row Level Security is added on top as a second line of defense
|
||||
* (prisma/rls.sql, applied via migration).
|
||||
*/
|
||||
|
||||
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };
|
||||
|
||||
export const prisma =
|
||||
globalForPrisma.prisma ??
|
||||
new PrismaClient({
|
||||
adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL }),
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
|
||||
|
||||
/** Models that carry a tenantId column and must never be queried without one. */
|
||||
const TENANT_MODELS = new Set<string>(["User", "Role", "AuditLog"]);
|
||||
|
||||
/**
|
||||
* Returns a Prisma client that transparently enforces the tenant scope:
|
||||
* reads are filtered by tenantId, creates get the tenantId injected.
|
||||
*/
|
||||
export function dbForTenant(tenantId: string) {
|
||||
if (!tenantId) throw new Error("dbForTenant: tenantId is required");
|
||||
|
||||
return prisma.$extends({
|
||||
query: {
|
||||
$allModels: {
|
||||
async $allOperations({ model, operation, args, query }) {
|
||||
if (!TENANT_MODELS.has(model)) return query(args);
|
||||
|
||||
const a = args as Record<string, unknown>;
|
||||
|
||||
if (
|
||||
operation === "findMany" ||
|
||||
operation === "findFirst" ||
|
||||
operation === "count" ||
|
||||
operation === "aggregate" ||
|
||||
operation === "updateMany" ||
|
||||
operation === "deleteMany"
|
||||
) {
|
||||
a.where = { AND: [{ tenantId }, (a.where as object) ?? {}] };
|
||||
} else if (operation === "create") {
|
||||
a.data = { ...(a.data as object), tenantId };
|
||||
} else if (operation === "createMany") {
|
||||
const data = a.data as Record<string, unknown>[];
|
||||
a.data = data.map((d) => ({ ...d, tenantId }));
|
||||
} else if (operation === "findUnique" || operation === "findUniqueOrThrow") {
|
||||
// Unique lookups cannot be widened with AND — verify ownership on the result.
|
||||
const result = await query(args);
|
||||
if (
|
||||
result &&
|
||||
typeof result === "object" &&
|
||||
"tenantId" in result &&
|
||||
(result as { tenantId: string }).tenantId !== tenantId
|
||||
) {
|
||||
throw new Error(
|
||||
`Tenant isolation violation: ${model} belongs to another tenant`
|
||||
);
|
||||
}
|
||||
return result;
|
||||
} else if (
|
||||
operation === "update" ||
|
||||
operation === "delete" ||
|
||||
operation === "upsert"
|
||||
) {
|
||||
// Mutations on unique keys: verify ownership BEFORE mutating.
|
||||
const delegate = (
|
||||
prisma as unknown as Record<
|
||||
string,
|
||||
{ findUnique: (a: unknown) => Promise<{ tenantId?: string } | null> }
|
||||
>
|
||||
)[model.charAt(0).toLowerCase() + model.slice(1)];
|
||||
const existing = await delegate.findUnique({ where: a.where });
|
||||
if (existing && existing.tenantId !== tenantId) {
|
||||
throw new Error(
|
||||
`Tenant isolation violation: ${model} belongs to another tenant`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return query(args);
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export type TenantDb = ReturnType<typeof dbForTenant>;
|
||||
Reference in New Issue
Block a user