-- 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.
