-- ============================================================================= -- Kontrollierte Ausnahme vom Änderungsverbot des Audit-Logs. -- -- Ausgangslage: Der Trigger aus 20260902000100_rls_policies verbietet UPDATE -- und DELETE auf audit_log. Das ist richtig — nachträglich verändern soll den -- Log niemand. -- -- Es gibt aber genau einen Vorgang, der löschen können muss: der -- Aufbewahrungsjob des Workers. Nach AUDIT_AUFBEWAHRUNG_TAGE exportiert er die -- alten Einträge nach MinIO und räumt sie danach ab. Ohne diese Möglichkeit -- wächst die Tabelle unbegrenzt, und das Löschkonzept nach DSGVO ließe sich -- nicht umsetzen. -- -- Der Ausweg ist ein ausdrücklicher Schalter, den nur der Eigentümer-Zugang -- setzen kann und der nur für die laufende Transaktion gilt: -- -- BEGIN; -- SELECT set_config('app.audit_bereinigung', 'an', true); -- DELETE FROM audit_log WHERE zeitpunkt < now() - interval '10 years'; -- COMMIT; -- -- UPDATE bleibt unter allen Umständen verboten. Ein Eintrag kann verschwinden, -- nachdem er gesichert wurde — verfälscht werden kann er nie. -- ============================================================================= CREATE OR REPLACE FUNCTION audit_log_unveraenderlich() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN -- Änderungen sind ausnahmslos gesperrt. IF TG_OP = 'UPDATE' THEN RAISE EXCEPTION 'Der Audit-Log ist unveraenderlich. UPDATE ist auf audit_log nicht zulaessig.' USING ERRCODE = 'insufficient_privilege'; END IF; -- Löschen nur im ausdrücklich gekennzeichneten Aufbewahrungslauf. IF TG_OP = 'DELETE' THEN IF coalesce(current_setting('app.audit_bereinigung', true), '') = 'an' THEN RETURN OLD; END IF; RAISE EXCEPTION 'Der Audit-Log ist unveraenderlich. DELETE ist nur im Aufbewahrungslauf zulaessig ' '(SET LOCAL app.audit_bereinigung = ''an'').' USING ERRCODE = 'insufficient_privilege'; END IF; RETURN NULL; END; $$; COMMENT ON FUNCTION audit_log_unveraenderlich() IS 'Sperrt UPDATE auf audit_log dauerhaft und DELETE ausserhalb des Aufbewahrungslaufs.'; -- Die Anwendungsrolle darf den Schalter gar nicht erst setzen: sie hat kein -- DELETE-Recht auf audit_log (siehe vorherige Migration). Der Schalter wirkt -- also nur fuer den Eigentuemer-Zugang, den ausschliesslich Worker und -- Migrationen benutzen.