Monalisa
Garantias do banco

Auditoria das execuções

A trilha de tasks e eventos é permanente, append-only e com ator explícito, imposta por triggers.

Cada execução em segundo plano (uma task, um assinante de evento ou um agendamento) tem uma linha em task_runs (de tenant) ou platform_task_runs (sem tenant) e uma trilha de eventos em task_run_events ou platform_task_run_events. Essas tabelas são auditoria permanente: nenhuma rotina de limpeza as toca, e o banco recusa reescrevê-las.

O que os triggers impõem

RegraTriggers
Eventos são append-only: UPDATE e DELETE recusadostask_run_events_append_only, platform_task_run_events_append_only
Runs nunca são apagadastask_runs_never_deleted, platform_task_runs_never_deleted
Ator e origem não mudam nem somem (UPDATE e DELETE recusados)task_run_user_actors_never_deleted, platform_task_run_schedule_origins_never_deleted
TRUNCATE recusado nas seis tabelas (triggers de linha não disparam em TRUNCATE)*_no_truncate, em nível de statement
Identidade da run congelada: só status, attempts, progress, outcome, started_at, finished_at e updated_at mudamtask_runs_identity_fixed, platform_task_runs_identity_fixed

Todos usam a mesma função de recusa, cuja mensagem diz o que era esperado: audit trail is append-only — expected INSERT only on <tabela>.

Ator explícito

Toda run diz quem a causou, e o banco confere:

  • task_runs.actor_kind é user ou system. Uma run de user precisa de uma linha em task_run_user_actors (usuário e membership do mesmo tenant) na mesma transação: a constraint trigger task_runs_user_actor_present é DEFERRABLE INITIALLY DEFERRED e verifica no commit.
  • platform_task_runs.actor_kind é system ou scheduler; scheduler anda junto com trigger = 'schedule' (CHECK). Uma run de scheduler precisa de uma origem em platform_task_run_schedule_origins, verificada no commit por platform_task_runs_origin_present. A origem é única por (agendamento, horário previsto), então o mesmo disparo não gera duas runs.
  • Runs de operador de plataforma ainda não existem: o CHECK de actor_kind não aceita esse valor, e o dispatcher recusa em vez de gravar como sistema.

Outras garantias por linha

  • status em queued, running, retrying, succeeded, failed, skipped, e finished_at preenchido se e somente se o status é final (CHECK).
  • name no formato ^[a-z][a-z0-9._-]{1,63}$, progress entre 0 e 100, outcome e detail são objetos JSON de até 2048 bytes.
  • task_runs tem FK para tenants; os eventos apontam para a run pelo par (run_id, tenant_id), então ficam no mesmo tenant da run.

As colunas e constraints completas estão em Execuções e auditoria.

O que fica fora do banco

  • Retirar UPDATE e DELETE dessas tabelas por permissão de papel (REVOKE) ainda não foi feito; vem com os papéis de banco da política de RLS. Hoje a proteção são os triggers.
  • O redrive de mensagens da dead-letter queue (trigger = 'redrive') está previsto no schema, mas a ferramenta de operação ainda não existe.

Nesta página