TeamVis Self-Host-Bundle v0.31.0
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
-- GoBD-konformes Audit-Log: jede MA-Änderung wird mit Hash-Chain
|
||||
-- gespeichert, manipulationssicher, nur INSERT erlaubt.
|
||||
-- ====================================================================
|
||||
-- Format: jede Zeile enthält content_hash = SHA256 über (prev_hash +
|
||||
-- entity + entity_id + actor + timestamp + diff_json). Wenn ein
|
||||
-- Eintrag nachträglich geändert wird, bricht die Kette und das ist
|
||||
-- erkennbar.
|
||||
--
|
||||
-- entity: "employee" | "position" | "org_unit" | …
|
||||
-- entity_id: UUID des betroffenen Records
|
||||
-- action: "create" | "update" | "delete" | "activate" | "deactivate"
|
||||
-- actor: E-Mail des Admin-Users (oder "system" für Bulk/Cron)
|
||||
-- diff: JSON mit { field: { before, after } } — nur geänderte
|
||||
-- Felder
|
||||
--
|
||||
-- Aufbewahrung: 10 Jahre laut GoBD; aktuell keine harte Retention,
|
||||
-- App-Doku verweist auf manuelle Archivierung via CSV-Export.
|
||||
|
||||
create table if not exists public.change_log (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
occurred_at timestamptz not null default now(),
|
||||
entity text not null,
|
||||
entity_id uuid not null,
|
||||
action text not null,
|
||||
actor text not null,
|
||||
diff jsonb not null default '{}'::jsonb,
|
||||
prev_hash text, -- hash des vorherigen eintrags (kette)
|
||||
content_hash text not null -- sha256 dieses eintrags
|
||||
);
|
||||
|
||||
create index if not exists change_log_entity_idx
|
||||
on public.change_log (entity, entity_id, occurred_at desc);
|
||||
create index if not exists change_log_occurred_at_idx
|
||||
on public.change_log (occurred_at desc);
|
||||
|
||||
-- Schreibschutz auf Updates/Deletes — service-role-only, aber
|
||||
-- explizit als Trigger gegen Versehen.
|
||||
create or replace function public.protect_change_log()
|
||||
returns trigger language plpgsql as $$
|
||||
begin
|
||||
raise exception 'change_log ist immutable — keine Updates oder Deletes erlaubt';
|
||||
end;
|
||||
$$;
|
||||
|
||||
drop trigger if exists trg_protect_change_log_update on public.change_log;
|
||||
create trigger trg_protect_change_log_update
|
||||
before update on public.change_log
|
||||
for each row execute function public.protect_change_log();
|
||||
|
||||
drop trigger if exists trg_protect_change_log_delete on public.change_log;
|
||||
create trigger trg_protect_change_log_delete
|
||||
before delete on public.change_log
|
||||
for each row execute function public.protect_change_log();
|
||||
|
||||
alter table public.change_log enable row level security;
|
||||
-- Service-Role-only — anon hat gar keinen Zugriff.
|
||||
Reference in New Issue
Block a user