Fase 0 — descoberta e arquitetura:
- Inventário do projeto, glossário de domínio, arquitetura com bounded
contexts e topologia de containers, threat model inicial.
- 12 ADRs cobrindo modular monolith, topologia de containers (Postgres
isolado + eden-core/parceiros/assinante em containers e portas
distintos), auth/sessões, modelo de permissões, criptografia/segredos,
contrato first-class, stock ledger, separação billing/finance/fiscal,
outbox transacional, adapters SaperX e Focus NFe, e identidade
compartilhada entre as 3 apps.
- 14 subagentes e 7 skills especializados por domínio em .claude/.
- Hooks de segurança (PreToolUse/PostToolUse/Stop) testados via pipe.
Fase 1 — plataforma (em andamento):
- Monorepo pnpm workspaces + Turborepo: apps/{api,worker,core-web,
reseller-web,subscriber-web} + 9 packages compartilhados.
- apps/api: NestJS mínimo com /health/live e /health/ready (checando
Postgres real via @eden/database).
- 3 frontends Vite + React + TypeScript + Tailwind, com o favicon
oficial do EDEN.
- packages/database: migration baseline (node-pg-migrate) criando
roles/role_permissions/applications/users/user_applications/sessions/
audit_log — audit log append-only com hash-chain, testado ao vivo
(UPDATE/DELETE bloqueados pelo trigger).
- compose.yaml implementando a topologia da ADR-0002, validada de ponta
a ponta: os 6 containers sobem e ficam saudáveis com um único
`docker compose up`.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1.7 KiB
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.