Files
craftvia/prisma/migrations/20260817130000_incidents/migration.sql
T
msolarczekandClaude Opus 5 c8e6f30a27
CI / build-and-check (push) Canceled after 0s
CI / audit (push) Canceled after 0s
CI / sbom (push) Canceled after 0s
Basis: Certvia dev@a48c5fb als Fundament für Craftvia
Unveränderter Stand von certvia/dev (a48c5fb) plus Craftvia-Spezifikation
und Brandbook unter docs/craftvia/. ISMS-Module werden im Folgecommit entfernt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 11:05:39 +02:00

247 lines
9.0 KiB
SQL

-- CreateEnum
CREATE TYPE "IncidentCategory" AS ENUM ('malware', 'phishing', 'unauthorized_access', 'data_loss', 'outage', 'physical', 'misconfiguration', 'supplier', 'prototype_customer_data', 'other');
-- CreateEnum
CREATE TYPE "IncidentStatus" AS ENUM ('neu', 'triage', 'in_bearbeitung', 'eingedaemmt', 'behoben', 'abgeschlossen', 'wiedereroeffnet');
-- AlterTable
ALTER TABLE "tenant_settings" ADD COLUMN "nis2_category" TEXT NOT NULL DEFAULT 'keine';
-- CreateTable
CREATE TABLE "incidents" (
"id" TEXT NOT NULL,
"tenant_id" TEXT NOT NULL,
"ref_no" TEXT NOT NULL,
"title" TEXT NOT NULL,
"description" TEXT,
"source" TEXT NOT NULL DEFAULT 'manual',
"reporter_name" TEXT,
"reporter_contact" TEXT,
"occurred_at" TIMESTAMP(3),
"detected_at" TIMESTAMP(3),
"reported_at" TIMESTAMP(3),
"category" "IncidentCategory" NOT NULL DEFAULT 'other',
"impact_c" INTEGER NOT NULL DEFAULT 0,
"impact_i" INTEGER NOT NULL DEFAULT 0,
"impact_a" INTEGER NOT NULL DEFAULT 0,
"urgency" INTEGER NOT NULL DEFAULT 2,
"affected_data_categories" TEXT[] DEFAULT ARRAY[]::TEXT[],
"personal_data" BOOLEAN NOT NULL DEFAULT false,
"prototype_data" BOOLEAN NOT NULL DEFAULT false,
"severity" TEXT NOT NULL DEFAULT 'mittel',
"priority" TEXT NOT NULL DEFAULT 'mittel',
"owner_id" TEXT,
"assignee_id" TEXT,
"status" "IncidentStatus" NOT NULL DEFAULT 'neu',
"restricted" BOOLEAN NOT NULL DEFAULT false,
"nis2_relevant" BOOLEAN NOT NULL DEFAULT false,
"dsgvo_relevant" BOOLEAN NOT NULL DEFAULT false,
"report_status" TEXT NOT NULL DEFAULT 'none',
"erstmeldung_due_at" TIMESTAMP(3),
"folgemeldung_due_at" TIMESTAMP(3),
"abschluss_due_at" TIMESTAMP(3),
"dsgvo_due_at" TIMESTAMP(3),
"root_cause" TEXT,
"resolution" TEXT,
"closing_note" TEXT,
"lessons_learned" TEXT,
"created_by" TEXT,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL,
CONSTRAINT "incidents_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "incident_comments" (
"id" TEXT NOT NULL,
"tenant_id" TEXT NOT NULL,
"incident_id" TEXT NOT NULL,
"author_id" TEXT,
"body" TEXT NOT NULL,
"internal" BOOLEAN NOT NULL DEFAULT false,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL,
CONSTRAINT "incident_comments_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "incident_assets" (
"id" TEXT NOT NULL,
"tenant_id" TEXT NOT NULL,
"incident_id" TEXT NOT NULL,
"asset_id" TEXT NOT NULL,
CONSTRAINT "incident_assets_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "incident_processes" (
"id" TEXT NOT NULL,
"tenant_id" TEXT NOT NULL,
"incident_id" TEXT NOT NULL,
"process_id" TEXT NOT NULL,
CONSTRAINT "incident_processes_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "incident_risks" (
"id" TEXT NOT NULL,
"tenant_id" TEXT NOT NULL,
"incident_id" TEXT NOT NULL,
"risk_id" TEXT NOT NULL,
CONSTRAINT "incident_risks_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "incident_controls" (
"id" TEXT NOT NULL,
"tenant_id" TEXT NOT NULL,
"incident_id" TEXT NOT NULL,
"control_ref" TEXT NOT NULL,
CONSTRAINT "incident_controls_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "incident_measures" (
"id" TEXT NOT NULL,
"tenant_id" TEXT NOT NULL,
"incident_id" TEXT NOT NULL,
"measure_id" TEXT NOT NULL,
CONSTRAINT "incident_measures_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "incident_attachments" (
"id" TEXT NOT NULL,
"tenant_id" TEXT NOT NULL,
"incident_id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"storage_key" TEXT,
"size" INTEGER,
"mime" TEXT,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "incident_attachments_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "incidents_tenant_id_idx" ON "incidents"("tenant_id");
-- CreateIndex
CREATE INDEX "incidents_tenant_id_status_idx" ON "incidents"("tenant_id", "status");
-- CreateIndex
CREATE INDEX "incidents_tenant_id_severity_idx" ON "incidents"("tenant_id", "severity");
-- CreateIndex
CREATE UNIQUE INDEX "incidents_tenant_id_ref_no_key" ON "incidents"("tenant_id", "ref_no");
-- CreateIndex
CREATE INDEX "incident_comments_tenant_id_incident_id_idx" ON "incident_comments"("tenant_id", "incident_id");
-- CreateIndex
CREATE INDEX "incident_assets_tenant_id_idx" ON "incident_assets"("tenant_id");
-- CreateIndex
CREATE UNIQUE INDEX "incident_assets_incident_id_asset_id_key" ON "incident_assets"("incident_id", "asset_id");
-- CreateIndex
CREATE INDEX "incident_processes_tenant_id_idx" ON "incident_processes"("tenant_id");
-- CreateIndex
CREATE UNIQUE INDEX "incident_processes_incident_id_process_id_key" ON "incident_processes"("incident_id", "process_id");
-- CreateIndex
CREATE INDEX "incident_risks_tenant_id_idx" ON "incident_risks"("tenant_id");
-- CreateIndex
CREATE UNIQUE INDEX "incident_risks_incident_id_risk_id_key" ON "incident_risks"("incident_id", "risk_id");
-- CreateIndex
CREATE INDEX "incident_controls_tenant_id_idx" ON "incident_controls"("tenant_id");
-- CreateIndex
CREATE UNIQUE INDEX "incident_controls_incident_id_control_ref_key" ON "incident_controls"("incident_id", "control_ref");
-- CreateIndex
CREATE INDEX "incident_measures_tenant_id_idx" ON "incident_measures"("tenant_id");
-- CreateIndex
CREATE UNIQUE INDEX "incident_measures_incident_id_measure_id_key" ON "incident_measures"("incident_id", "measure_id");
-- CreateIndex
CREATE INDEX "incident_attachments_tenant_id_incident_id_idx" ON "incident_attachments"("tenant_id", "incident_id");
-- AddForeignKey
ALTER TABLE "incidents" ADD CONSTRAINT "incidents_owner_id_fkey" FOREIGN KEY ("owner_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incidents" ADD CONSTRAINT "incidents_assignee_id_fkey" FOREIGN KEY ("assignee_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incident_comments" ADD CONSTRAINT "incident_comments_incident_id_fkey" FOREIGN KEY ("incident_id") REFERENCES "incidents"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incident_assets" ADD CONSTRAINT "incident_assets_incident_id_fkey" FOREIGN KEY ("incident_id") REFERENCES "incidents"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incident_assets" ADD CONSTRAINT "incident_assets_asset_id_fkey" FOREIGN KEY ("asset_id") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incident_processes" ADD CONSTRAINT "incident_processes_incident_id_fkey" FOREIGN KEY ("incident_id") REFERENCES "incidents"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incident_processes" ADD CONSTRAINT "incident_processes_process_id_fkey" FOREIGN KEY ("process_id") REFERENCES "processes"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incident_risks" ADD CONSTRAINT "incident_risks_incident_id_fkey" FOREIGN KEY ("incident_id") REFERENCES "incidents"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incident_risks" ADD CONSTRAINT "incident_risks_risk_id_fkey" FOREIGN KEY ("risk_id") REFERENCES "risks"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incident_controls" ADD CONSTRAINT "incident_controls_incident_id_fkey" FOREIGN KEY ("incident_id") REFERENCES "incidents"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incident_measures" ADD CONSTRAINT "incident_measures_incident_id_fkey" FOREIGN KEY ("incident_id") REFERENCES "incidents"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incident_measures" ADD CONSTRAINT "incident_measures_measure_id_fkey" FOREIGN KEY ("measure_id") REFERENCES "measures"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "incident_attachments" ADD CONSTRAINT "incident_attachments_incident_id_fkey" FOREIGN KEY ("incident_id") REFERENCES "incidents"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- Row Level Security (zweite Verteidigungslinie, analog übrige Mandanten-Tabellen;
-- FORCE + WITH CHECK für den scharfen isms_app-Pfad, F-04). Lokal (Owner-Rolle ohne
-- FORCE) bleibt der Betrieb unverändert.
DO $$
DECLARE t text;
BEGIN
FOREACH t IN ARRAY ARRAY[
'incidents',
'incident_comments',
'incident_assets',
'incident_processes',
'incident_risks',
'incident_controls',
'incident_measures',
'incident_attachments'
] LOOP
EXECUTE format('ALTER TABLE %I ENABLE ROW LEVEL SECURITY', t);
EXECUTE format('DROP POLICY IF EXISTS tenant_isolation ON %I', t);
EXECUTE format(
'CREATE POLICY tenant_isolation ON %I USING (tenant_id = current_setting(''app.tenant_id'', true)) WITH CHECK (tenant_id = current_setting(''app.tenant_id'', true))',
t
);
EXECUTE format('ALTER TABLE %I FORCE ROW LEVEL SECURITY', t);
END LOOP;
END $$;