# ADR-0009: Outbox transacional para eventos de integração ## Status Aceito ## Contexto O EDEN precisa publicar eventos de domínio (`lead.created`, `contract.signed`, `invoice.overdue`, etc. — catálogo no Master Prompt §9.2) para consumo por n8n/webhooks/outros módulos, sem perder evento em caso de falha entre o commit da transação de negócio e a publicação. O legado não tem esse problema porque não publica eventos externos. ## Decisão Toda operação que precise emitir um evento relevante grava a linha do evento na mesma transação SQL da mudança de negócio, numa tabela `outbox_events` (payload normalizado, tipo do evento, status `pending/delivered/failed`, tentativas, correlation id). Um processo separado (`apps/worker`) lê a outbox e entrega (webhook assinado HMAC, ou fila interna para o próprio módulo consumidor), marcando como entregue só após confirmação — com retry/backoff e dead-letter após esgotar tentativas. Consumidores (internos ou externos via n8n) devem ser idempotentes por `event_id` — reentrega nunca duplica efeito. ## Consequências - Positivo: garante "at-least-once" delivery sem depender de o processo de aplicação sobreviver após o commit (invariante nº9 do Master Prompt §24 — webhook repetido não duplica efeito, aplicado também no sentido saída). - Positivo: replay manual de evento é trivial (reprocessar linha da outbox). - Negativo: exige limpeza/arquivamento periódico da tabela de outbox (retenção configurável) para não crescer indefinidamente. - Negativo: consumidores precisam de lógica de idempotência — custo replicado em cada integração, mitigado por uma camada compartilhada em `packages/integrations`.