-- ========================================================= -- Migration 028: Legal Documents Extension -- User Consents, Consent Audit Log, Cookie Categories -- ========================================================= -- compliance_user_consents: End-User Consent-Records CREATE TABLE IF NOT EXISTS compliance_user_consents ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, user_id TEXT NOT NULL, document_id UUID NOT NULL REFERENCES compliance_legal_documents(id) ON DELETE CASCADE, document_version_id UUID REFERENCES compliance_legal_document_versions(id) ON DELETE SET NULL, document_type TEXT NOT NULL, consented BOOLEAN NOT NULL DEFAULT TRUE, ip_address TEXT, user_agent TEXT, consented_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), withdrawn_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_user_consents_tenant ON compliance_user_consents(tenant_id); CREATE INDEX IF NOT EXISTS idx_user_consents_user ON compliance_user_consents(user_id); CREATE INDEX IF NOT EXISTS idx_user_consents_doc ON compliance_user_consents(document_id); CREATE INDEX IF NOT EXISTS idx_user_consents_type ON compliance_user_consents(document_type); -- compliance_consent_audit_log: Immutable Audit-Trail CREATE TABLE IF NOT EXISTS compliance_consent_audit_log ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, action TEXT NOT NULL, -- consent_given|consent_withdrawn|consent_checked|document_published entity_type TEXT NOT NULL, -- user_consent|legal_document|cookie_category entity_id UUID, user_id TEXT, details JSONB DEFAULT '{}', ip_address TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_consent_audit_tenant ON compliance_consent_audit_log(tenant_id); CREATE INDEX IF NOT EXISTS idx_consent_audit_action ON compliance_consent_audit_log(action); CREATE INDEX IF NOT EXISTS idx_consent_audit_entity ON compliance_consent_audit_log(entity_type, entity_id); CREATE INDEX IF NOT EXISTS idx_consent_audit_created ON compliance_consent_audit_log(created_at); -- compliance_cookie_categories: Cookie-Kategorien fuer Banner CREATE TABLE IF NOT EXISTS compliance_cookie_categories ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, name_de TEXT NOT NULL, name_en TEXT, description_de TEXT, description_en TEXT, is_required BOOLEAN NOT NULL DEFAULT FALSE, sort_order INTEGER NOT NULL DEFAULT 0, is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_cookie_cats_tenant ON compliance_cookie_categories(tenant_id); -- Default Cookie-Kategorien INSERT INTO compliance_cookie_categories (tenant_id, name_de, name_en, description_de, description_en, is_required, sort_order) VALUES ('9282a473-5c95-4b3a-bf78-0ecc0ec71d3e'::UUID, 'Notwendig', 'Necessary', 'Technisch notwendige Cookies fuer den Betrieb der Website.', 'Technically necessary cookies for website operation.', TRUE, 0), ('9282a473-5c95-4b3a-bf78-0ecc0ec71d3e'::UUID, 'Funktional', 'Functional', 'Cookies fuer erweiterte Funktionalitaet und Personalisierung.', 'Cookies for enhanced functionality and personalization.', FALSE, 10), ('9282a473-5c95-4b3a-bf78-0ecc0ec71d3e'::UUID, 'Analyse', 'Analytics', 'Cookies zur Analyse der Websitenutzung.', 'Cookies for analyzing website usage.', FALSE, 20), ('9282a473-5c95-4b3a-bf78-0ecc0ec71d3e'::UUID, 'Marketing', 'Marketing', 'Cookies fuer personalisierte Werbung.', 'Cookies for personalized advertising.', FALSE, 30) ON CONFLICT DO NOTHING;