Bootstrap EDEN: Fase 0 (arquitetura) e Fase 1 (monorepo + infra)

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>
This commit is contained in:
2026-09-03 08:01:14 -03:00
commit 44510bd019
149 changed files with 13006 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
# 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`.