# 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)