All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 36s
CI / test-python-backend-compliance (push) Successful in 31s
CI / test-python-document-crawler (push) Successful in 23s
CI / test-python-dsms-gateway (push) Successful in 18s
5-Phasen-Migration: Go consent-service Proxies durch native Python/FastAPI ersetzt. Phase 1 — DSR (Betroffenenrechte): 6 Tabellen, 30 Endpoints, Frontend-API umgestellt Phase 2 — E-Mail-Templates: 5 Tabellen, 20 Endpoints, neues Frontend, SDK_STEPS erweitert Phase 3 — Legal Documents Extension: User Consents, Audit Log, Cookie-Kategorien Phase 4 — Banner Consent: Device-Consents, Site-Configs, Kategorien, Vendors Phase 5 — Cleanup: DSR-Proxy aus main.py entfernt, Frontend-URLs aktualisiert 148 neue Tests (50 + 47 + 26 + 25), alle bestanden. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
178 lines
7.6 KiB
SQL
178 lines
7.6 KiB
SQL
-- Migration 026: DSR (Data Subject Requests) — Betroffenenanfragen nach DSGVO Art. 15-21
|
|
-- Ersetzt Go consent-service Proxy durch native Python/FastAPI Implementierung
|
|
|
|
-- Sequence für Request-Nummern
|
|
CREATE SEQUENCE IF NOT EXISTS compliance_dsr_request_number_seq START WITH 1;
|
|
|
|
-- Haupttabelle: DSR Requests
|
|
CREATE TABLE IF NOT EXISTS compliance_dsr_requests (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL DEFAULT '9282a473-5c95-4b3a-bf78-0ecc0ec71d3e',
|
|
request_number TEXT NOT NULL,
|
|
request_type TEXT NOT NULL DEFAULT 'access',
|
|
status TEXT NOT NULL DEFAULT 'intake',
|
|
priority TEXT NOT NULL DEFAULT 'normal',
|
|
|
|
-- Antragsteller
|
|
requester_name TEXT NOT NULL,
|
|
requester_email TEXT NOT NULL,
|
|
requester_phone TEXT,
|
|
requester_address TEXT,
|
|
requester_customer_id TEXT,
|
|
|
|
-- Anfrage-Details
|
|
source TEXT NOT NULL DEFAULT 'email',
|
|
source_details TEXT,
|
|
request_text TEXT,
|
|
notes TEXT,
|
|
internal_notes TEXT,
|
|
|
|
-- Fristen (Art. 12 Abs. 3 DSGVO)
|
|
received_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deadline_at TIMESTAMPTZ NOT NULL,
|
|
extended_deadline_at TIMESTAMPTZ,
|
|
extension_reason TEXT,
|
|
extension_approved_by TEXT,
|
|
extension_approved_at TIMESTAMPTZ,
|
|
|
|
-- Identitaetspruefung
|
|
identity_verified BOOLEAN NOT NULL DEFAULT FALSE,
|
|
verification_method TEXT,
|
|
verified_at TIMESTAMPTZ,
|
|
verified_by TEXT,
|
|
verification_notes TEXT,
|
|
verification_document_ref TEXT,
|
|
|
|
-- Zuweisung
|
|
assigned_to TEXT,
|
|
assigned_at TIMESTAMPTZ,
|
|
assigned_by TEXT,
|
|
|
|
-- Abschluss
|
|
completed_at TIMESTAMPTZ,
|
|
completion_notes TEXT,
|
|
rejection_reason TEXT,
|
|
rejection_legal_basis TEXT,
|
|
|
|
-- Typ-spezifische Daten (JSONB)
|
|
erasure_checklist JSONB DEFAULT '[]'::jsonb,
|
|
data_export JSONB DEFAULT '{}'::jsonb,
|
|
rectification_details JSONB DEFAULT '{}'::jsonb,
|
|
objection_details JSONB DEFAULT '{}'::jsonb,
|
|
affected_systems JSONB DEFAULT '[]'::jsonb,
|
|
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by TEXT DEFAULT 'system',
|
|
updated_by TEXT
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_requests_tenant ON compliance_dsr_requests(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_requests_status ON compliance_dsr_requests(status);
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_requests_type ON compliance_dsr_requests(request_type);
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_requests_priority ON compliance_dsr_requests(priority);
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_requests_assigned ON compliance_dsr_requests(assigned_to);
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_requests_deadline ON compliance_dsr_requests(deadline_at);
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_requests_received ON compliance_dsr_requests(received_at);
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_dsr_requests_number ON compliance_dsr_requests(tenant_id, request_number);
|
|
|
|
-- Status-History (Audit-Trail)
|
|
CREATE TABLE IF NOT EXISTS compliance_dsr_status_history (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL DEFAULT '9282a473-5c95-4b3a-bf78-0ecc0ec71d3e',
|
|
dsr_id UUID NOT NULL,
|
|
previous_status TEXT,
|
|
new_status TEXT NOT NULL,
|
|
changed_by TEXT,
|
|
comment TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_history_dsr ON compliance_dsr_status_history(dsr_id);
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_history_created ON compliance_dsr_status_history(created_at);
|
|
|
|
-- Kommunikation (E-Mail, Portal, intern)
|
|
CREATE TABLE IF NOT EXISTS compliance_dsr_communications (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL DEFAULT '9282a473-5c95-4b3a-bf78-0ecc0ec71d3e',
|
|
dsr_id UUID NOT NULL,
|
|
communication_type TEXT NOT NULL DEFAULT 'outgoing',
|
|
channel TEXT NOT NULL DEFAULT 'email',
|
|
subject TEXT,
|
|
content TEXT NOT NULL,
|
|
template_used TEXT,
|
|
attachments JSONB DEFAULT '[]'::jsonb,
|
|
sent_at TIMESTAMPTZ,
|
|
sent_by TEXT,
|
|
received_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by TEXT DEFAULT 'system'
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_comms_dsr ON compliance_dsr_communications(dsr_id);
|
|
|
|
-- Kommunikationsvorlagen
|
|
CREATE TABLE IF NOT EXISTS compliance_dsr_templates (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL DEFAULT '9282a473-5c95-4b3a-bf78-0ecc0ec71d3e',
|
|
name TEXT NOT NULL,
|
|
template_type TEXT NOT NULL,
|
|
request_type TEXT,
|
|
language TEXT NOT NULL DEFAULT 'de',
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_templates_tenant ON compliance_dsr_templates(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_templates_type ON compliance_dsr_templates(template_type);
|
|
|
|
-- Versionierte Template-Inhalte
|
|
CREATE TABLE IF NOT EXISTS compliance_dsr_template_versions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
template_id UUID NOT NULL,
|
|
version TEXT NOT NULL DEFAULT '1.0',
|
|
subject TEXT NOT NULL,
|
|
body_html TEXT NOT NULL,
|
|
body_text TEXT,
|
|
status TEXT NOT NULL DEFAULT 'draft',
|
|
published_at TIMESTAMPTZ,
|
|
published_by TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by TEXT DEFAULT 'system'
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_tpl_versions_template ON compliance_dsr_template_versions(template_id);
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_tpl_versions_status ON compliance_dsr_template_versions(status);
|
|
|
|
-- Art. 17(3) Ausnahmepruefungen
|
|
CREATE TABLE IF NOT EXISTS compliance_dsr_exception_checks (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL DEFAULT '9282a473-5c95-4b3a-bf78-0ecc0ec71d3e',
|
|
dsr_id UUID NOT NULL,
|
|
check_code TEXT NOT NULL,
|
|
article TEXT NOT NULL,
|
|
label TEXT NOT NULL,
|
|
description TEXT,
|
|
applies BOOLEAN,
|
|
notes TEXT,
|
|
checked_by TEXT,
|
|
checked_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_dsr_exception_dsr ON compliance_dsr_exception_checks(dsr_id);
|
|
|
|
-- Default-Templates einfuegen
|
|
INSERT INTO compliance_dsr_templates (id, name, template_type, request_type, language)
|
|
VALUES
|
|
(gen_random_uuid(), 'Eingangsbestaetigung', 'receipt', NULL, 'de'),
|
|
(gen_random_uuid(), 'Identitaetsanfrage', 'clarification', NULL, 'de'),
|
|
(gen_random_uuid(), 'Auskunft abgeschlossen', 'completion', 'access', 'de'),
|
|
(gen_random_uuid(), 'Loeschung abgeschlossen', 'completion', 'erasure', 'de'),
|
|
(gen_random_uuid(), 'Berichtigung abgeschlossen', 'completion', 'rectification', 'de'),
|
|
(gen_random_uuid(), 'Ablehnung Auskunft', 'rejection', 'access', 'de'),
|
|
(gen_random_uuid(), 'Ablehnung Loeschung', 'rejection', 'erasure', 'de'),
|
|
(gen_random_uuid(), 'Fristverlaengerung', 'extension', NULL, 'de')
|
|
ON CONFLICT DO NOTHING;
|