Beim ersten Deploy-Versuch auf dem Testsystem schlug die neue app_user_role_check-Constraint fehl, weil echte Bestandszeilen noch alte Rollenwerte (admin, creator) trugen — die Migration ging naiv davon aus, dass es keine bestehenden Nutzer mit alten Rollen gäbe. Fix: alte Constraint zuerst droppen (sie kennt neue Werte wie "betreiber" noch nicht und hätte die Datenmigration selbst blockiert), dann bestehende Zeilen umschreiben (admin -> betreiber, da das die alte Plattform-Betreiber-Rolle war, nicht der neue mandantenbezogene admin; creator/agentur/marke/kanzlei -> mitarbeiter), erst danach die neue Constraint scharf schalten. Lokal gegen eine Datenbank mit manuell eingefügten Alt-Rollen-Zeilen verifiziert (0001-0007 anwenden, Testdaten einfügen, 0008 anwenden, Rollen prüfen).
118 lines
5.7 KiB
SQL
118 lines
5.7 KiB
SQL
-- Produktwechsel: Deklarix war eine Kennzeichnungsprüfung für
|
|
-- Werbe-Content (UWG/MStV), wird jetzt eine KI-Antragsprüfung
|
|
-- (Fragebogen -> Datenklasse/KI-VO-Einstufung -> Werkzeug-Katalog ->
|
|
-- Entscheidung). Alles, was ausschließlich für das alte Werberecht-
|
|
-- Produkt existierte, wird entfernt. account/app_user/session/
|
|
-- audit_log bleiben — Mandantentrennung, Login und
|
|
-- Protokollierungsprinzip sind produktunabhängig.
|
|
|
|
DROP TABLE IF EXISTS platform_connection;
|
|
DROP TABLE IF EXISTS asset;
|
|
DROP TABLE IF EXISTS participant;
|
|
DROP TABLE IF EXISTS evidence_package;
|
|
DROP TABLE IF EXISTS finding;
|
|
DROP TABLE IF EXISTS extraction;
|
|
DROP TABLE IF EXISTS submission;
|
|
|
|
-- "verified"/Kanzlei-Verzeichnis gab es nur für die alte Berufsrecht-
|
|
-- Sonderrolle "kanzlei".
|
|
ALTER TABLE account DROP COLUMN IF EXISTS verified;
|
|
|
|
-- Fünf Rollen (Ebenen 2-5 der Frontend-Spezifikation):
|
|
-- mitarbeiter Ebene 2 — stellt Anträge, sieht nur eigene
|
|
-- verantwortlicher Ebene 3 — KI-Verantwortlicher, volles Entscheidungsrecht
|
|
-- pruefer Ebene 3 — identische Sicht wie verantwortlicher, aber
|
|
-- ohne Entscheidungsrecht (reine Prüfsicht)
|
|
-- admin Ebene 4 — Mandanten-Verwaltung (Nutzer, Abteilungen,
|
|
-- Anmeldeverfahren, eigene Werkzeug-Freigaben) — bezogen
|
|
-- auf GENAU EINEN Mandanten, nicht plattformweit
|
|
-- betreiber Ebene 5 — Netcell-IT-Personal, plattformweit
|
|
-- (Werkzeugkatalog, Regelwerk, Mandantenverwaltung);
|
|
-- entspricht der alten "admin"-Rolle vor dieser Migration
|
|
--
|
|
-- Die alte CHECK-Constraint muss zuerst weg, sonst lehnt sie die
|
|
-- Datenmigration unten (die neue Rollenwerte wie "betreiber" schreibt)
|
|
-- sofort ab — die alte Constraint kennt diese Werte ja noch nicht.
|
|
ALTER TABLE app_user DROP CONSTRAINT app_user_role_check;
|
|
|
|
-- Bestehende Zeilen auf gültige neue Werte umstellen, bevor die neue
|
|
-- Constraint das erzwingt — sonst schlägt sie auf jeder Installation
|
|
-- mit echten Nutzern fehl. Die alte Rolle "admin" war der Plattform-
|
|
-- Betreiber (Netcell-IT) — wird zu "betreiber", nicht zum neuen,
|
|
-- mandantenbezogenen "admin". Alle anderen alten Rollen (creator/agentur/
|
|
-- marke/kanzlei) waren gewöhnliche Mandanten-Logins ohne Sonderrechte —
|
|
-- werden zu "mitarbeiter", der schlankesten neuen Rolle.
|
|
UPDATE app_user SET role = 'betreiber' WHERE role = 'admin';
|
|
UPDATE app_user SET role = 'mitarbeiter' WHERE role IN ('creator', 'agentur', 'marke', 'kanzlei');
|
|
|
|
ALTER TABLE app_user ADD CONSTRAINT app_user_role_check
|
|
CHECK (role IN ('mitarbeiter', 'verantwortlicher', 'pruefer', 'admin', 'betreiber'));
|
|
|
|
-- Stammdaten: Abteilungen zur Auswahl im Fragebogen (Feld A.abteilung).
|
|
CREATE TABLE abteilung (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
account_id UUID NOT NULL REFERENCES account (id),
|
|
name TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE (account_id, name)
|
|
);
|
|
|
|
-- Werkzeugkatalog: der eigentliche Wert des Produkts. account_id NULL
|
|
-- markiert einen zentral gepflegten, für alle Mandanten identischen
|
|
-- Katalogeintrag; ein gesetzter account_id ist eine mandantenspezifische
|
|
-- Ergänzung (siehe Spezifikation "jeder Mandant kann zusätzlich eigene
|
|
-- Einträge ... führen"). letzte_pruefung und quelle sind Pflicht — jede
|
|
-- Zusicherung im Katalog muss belegbar sein, siehe CLAUDE.md.
|
|
CREATE TABLE werkzeug (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
account_id UUID REFERENCES account (id),
|
|
name TEXT NOT NULL,
|
|
anbieter TEXT NOT NULL,
|
|
verarbeitungsort TEXT NOT NULL CHECK (verarbeitungsort IN ('EU', 'USA', 'gemischt', 'on-prem')),
|
|
avv_verfuegbar BOOLEAN NOT NULL DEFAULT false,
|
|
avv_url TEXT NOT NULL DEFAULT '',
|
|
training_opt_out BOOLEAN NOT NULL DEFAULT false,
|
|
training_standard BOOLEAN NOT NULL DEFAULT false,
|
|
aufbewahrung_tage INTEGER NOT NULL DEFAULT 0,
|
|
zertifizierungen TEXT[] NOT NULL DEFAULT '{}',
|
|
geeignete_zwecke TEXT[] NOT NULL DEFAULT '{}',
|
|
einschraenkungen TEXT[] NOT NULL DEFAULT '{}',
|
|
letzte_pruefung TIMESTAMPTZ NOT NULL,
|
|
quelle TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
-- Ein Mandant kann einen (auch zentralen) Katalogeintrag für sich
|
|
-- sperren, ohne den zentralen Katalog selbst zu verändern.
|
|
CREATE TABLE werkzeug_sperre (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
account_id UUID NOT NULL REFERENCES account (id),
|
|
werkzeug_id UUID NOT NULL REFERENCES werkzeug (id),
|
|
grund TEXT NOT NULL,
|
|
gesperrt_am TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE (account_id, werkzeug_id)
|
|
);
|
|
|
|
-- Antrag: das Vorhaben aus Fragebogen-Abschnitt A, plus die vollständigen
|
|
-- Antworten aus B/C/D als JSON (adaptiver Fragebogen — welche Folgefragen
|
|
-- beantwortet wurden, hängt von vorherigen Antworten ab, ein starres
|
|
-- Spaltenschema würde das nicht abbilden). status ist eine normale
|
|
-- Zustandsänderung (wie submission es früher war), kein Beweis-Eintrag.
|
|
CREATE TABLE antrag (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
account_id UUID NOT NULL REFERENCES account (id),
|
|
ersteller_user_id UUID NOT NULL REFERENCES app_user (id),
|
|
abteilung_id UUID REFERENCES abteilung (id),
|
|
titel TEXT NOT NULL,
|
|
beschreibung TEXT NOT NULL DEFAULT '',
|
|
ergebnis TEXT NOT NULL DEFAULT '',
|
|
haeufigkeit TEXT NOT NULL DEFAULT 'einmalig'
|
|
CHECK (haeufigkeit IN ('einmalig', 'gelegentlich', 'taeglich', 'automatisiert')),
|
|
antworten JSONB NOT NULL DEFAULT '{}',
|
|
status TEXT NOT NULL DEFAULT 'entwurf'
|
|
CHECK (status IN ('entwurf', 'eingereicht', 'entschieden')),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|