Files
eden/docs/architecture.md
Matheus (Handix) 44510bd019 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>
2026-09-03 08:01:14 -03:00

103 lines
8.4 KiB
Markdown

# EDEN — Arquitetura (Fase 0)
## 1. Estilo arquitetural
**Modular monolith** em monorepo TypeScript (pnpm workspaces + Turborepo), conforme Master Prompt §4. Um único processo de API (`apps/api`) organizado por bounded contexts internos, com fronteiras de módulo explícitas e comunicação interna via eventos de domínio (outbox) — nunca chamada direta cross-módulo que quebre a fronteira. Ver ADR-0001.
Motivo de não usar microserviços desde o início: custo operacional de dezenas de serviços não se paga no estágio atual; o modular monolith permite extrair um bounded context para serviço próprio no futuro (ex.: billing/fiscal, que já são os candidatos naturais por volume/isolamento) sem reescrever o domínio.
## 2. Bounded contexts
| Contexto | Núcleo de dados | Depende de | Agente responsável |
|---|---|---|---|
| **Identity & Access** | users, roles, permissions, sessions, resellers (vínculo) | — (fundacional) | `eden-security` |
| **Organization** | legal entities, companies, branches, warehouses, cost centers | Identity | `eden-architect` |
| **Commercial (CRM)** | leads, opportunities, quotes, pricing tiers, approval workflow | Identity, Organization | `eden-commercial` |
| **Customer 360** | client accounts (PF/PJ), reseller accounts, partners/QSA | Commercial | `eden-commercial` |
| **Contracts** | contracts, versions, amendments, renewals, status history | Customer 360, Commercial | `eden-commercial` |
| **Documents & E-signature** | templates, versions, generations, envelopes, signers, audit hash-chain | Contracts, Organization | `eden-frontend` (editor) + domínio próprio |
| **Inventory & Assets** | warehouses, stock ledger, serialized assets, RMA | Contracts (instalação) | `eden-inventory` |
| **Finance (AR/AP)** | receivables, boletos, dunning, payables, reconciliation | Contracts, Billing | `eden-finance` |
| **Billing** | billing accounts, cycles, subscriptions, invoices, billing runs | Contracts, Inventory (consumo) | `eden-finance` |
| **Fiscal** | catálogos fiscais, fiscal profiles, documentos fiscais emitidos | Billing | `eden-fiscal` |
| **Telecom (SaperX)** | circuitos, DIDs, consumo/CDR, conciliação | Customer 360, Billing | `eden-telecom` |
| **Support (Service Desk)** | tickets, SLA, OS | Customer 360, Contracts, Inventory | `eden-support` |
| **HR/Timeclock** | devices, employees, AFD, apuração, banco de horas | Organization (isolado do resto) | `eden-hr-timeclock` |
| **Integrations/Events** | outbox, webhooks, API clients, delivery log | transversal | `eden-api-integrations` |
Regra de dependência: setas só "para trás" na tabela acima (uma linha não depende de uma que a segue) — evita ciclo entre módulos. HR/Timeclock é deliberadamente isolado (só depende de Organization) — pode ser paralelizado/adiado sem travar o núcleo comercial, replicando a recomendação do próprio `eden.md`.
## 3. Estrutura do monorepo
Conforme Master Prompt §4.2:
```text
apps/
api/ # API principal (modular monolith)
worker/ # jobs assíncronos (BullMQ)
core-web/ # EDEN Core (ERP interno)
reseller-web/ # EDEN Parceiros
subscriber-web/ # EDEN Assinante
packages/
database/ # schema, migrations, query layer
contracts/ # DTOs/schemas/event contracts compartilhados
ui/ # Design System (derivado do tema DreamsERP)
auth/ # SDK de auth client-side comum às 3 apps
observability/
config/
testing/
integrations/ # adapters Focus NFe, SaperX, Control iD, S3, SMTP
domain-shared/
infra/
docker/
migrations/
docs/
.claude/
```
## 4. Topologia de deployment / containers
**Decisão explícita solicitada pelo operador**: Postgres roda em container próprio, separado dos containers de aplicação; cada uma das três aplicações web roda em seu próprio container, cada uma em porta distinta. Detalhamento completo em `docs/adr/0002-container-topology.md`. Resumo:
```text
┌─────────────────────────────────────────────────────────────┐
│ docker compose (rede interna "eden_net") │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐ │
│ │ eden-postgres │ │ eden-redis │ │ eden-api │ │
│ │ :5432 (int) │ │ :6379 (int) │ │ :8080 → host │ │
│ └───────┬───────┘ └───────┬───────┘ └────────┬────────┘ │
│ │ │ │ │
│ └─────────────┬─────┴─────────────────────┘ │
│ │ (api é o único que fala com o banco) │
│ ┌───────────────┐ ┌──▼────────────┐ ┌─────────────────┐ │
│ │ eden-worker │ │ eden-core │ │ eden-parceiros │ │
│ │ (sem porta) │ │ :3001→host │ │ :3002→host │ │
│ └───────────────┘ └───────────────┘ └─────────────────┘ │
│ ┌────────────────┐ │
│ │ eden-assinante │ │
│ │ :3003→host │ │
│ └────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
Princípios:
1. **Nenhuma aplicação web fala direto com o Postgres** — todas as 3 (core/parceiros/assinante) consomem exclusivamente a API (`eden-api`), que é a única com credencial de banco. Isso preserva o requisito do Master Prompt de "nascer preparado para ser consumido por essas três aplicações" sem triplicar a superfície de acesso a dados.
2. **Postgres nunca expõe porta ao host em produção** — só rede interna do compose; em dev, opcionalmente mapeada para uma porta alta não-padrão para acesso de ferramenta local (ex. `55432:5432`), nunca `5432:5432` direto.
3. **Cada app web em porta própria e distinta**, definida em `.env` (`EDEN_CORE_PORT`, `EDEN_PARCEIROS_PORT`, `EDEN_ASSINANTE_PORT`, `EDEN_API_PORT`) — nenhuma hardcoded no compose, para permitir múltiplos ambientes na mesma máquina (dev/staging) sem colisão.
4. **Build multi-stage por app** (`infra/docker/Dockerfile.api`, `Dockerfile.web` parametrizado por app via build-arg) — imagens enxutas, sem devDependencies em produção.
5. **Healthcheck obrigatório em todo container** (Postgres via `pg_isready`, API via `/health/ready`, apps web via HTTP 200 na raiz) — `depends_on: condition: service_healthy`, não apenas ordem de start.
6. **Volumes nomeados** para dados do Postgres (`eden_pgdata`) — nunca bind mount direto de dado de produção para o filesystem do host sem estratégia de backup (backup lógico via `pg_dump` streaming para S3, Master Prompt §6.15, roda **de dentro** do container/worker, não do host).
7. Redis (cache/fila BullMQ) entra como container próprio (`eden-redis`) só quando o primeiro job assíncrono real precisar dele — não subir vazio "por precaução" (Master Prompt §4.1: "somente quando houver benefício real").
## 5. Identidade compartilhada entre as 3 apps
Uma única API de autenticação/autorização (dentro de `eden-api`) emite sessão para as 3 aplicações. Uma identidade pode ter acesso a `core`/`reseller`/`subscriber` de forma explícita (tabela de vínculo, não inferida pelo nome do papel) — ver ADR-0012 e Master Prompt §5.1.
## 6. Próximos documentos
- `docs/security/threat-model.md`
- `docs/adr/*` (decisões referenciadas acima)
- `docs/implementation-plan.md` (backlog por fase)
- `docs/data-model/*` (ERD por domínio — produzido ao entrar em cada Fase)