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
| Regra | Triggers |
|---|---|
Eventos são append-only: UPDATE e DELETE recusados | task_run_events_append_only, platform_task_run_events_append_only |
| Runs nunca são apagadas | task_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 mudam | task_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éuserousystem. Uma run deuserprecisa de uma linha emtask_run_user_actors(usuário e membership do mesmo tenant) na mesma transação: a constraint triggertask_runs_user_actor_presentéDEFERRABLE INITIALLY DEFERREDe verifica no commit.platform_task_runs.actor_kindésystemouscheduler;scheduleranda junto comtrigger = 'schedule'(CHECK). Uma run deschedulerprecisa de uma origem emplatform_task_run_schedule_origins, verificada no commit porplatform_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_kindnão aceita esse valor, e o dispatcher recusa em vez de gravar como sistema.
Outras garantias por linha
statusemqueued,running,retrying,succeeded,failed,skipped, efinished_atpreenchido se e somente se o status é final (CHECK).nameno formato^[a-z][a-z0-9._-]{1,63}$,progressentre 0 e 100,outcomeedetailsão objetos JSON de até 2048 bytes.task_runstem FK paratenants; 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
UPDATEeDELETEdessas 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.