Arquitetura — CentralCRM_back
Backend central do CentralCRM: API REST versionada, autenticação JWT, diretório multi-tenant de empresas, dados operacionais, presença em tempo real (Socket.IO) e gestão de white labels.
1. Visão geral
O CentralCRM_back é uma aplicação NestJS 11 que expõe:
| Superfície | Prefixo / path | Função |
|---|---|---|
| REST | /api + versionamento URI (/v1/...) | CRUD de empresas, auth, operacional, presença (REST), white labels |
| OpenAPI | /api/docs | Swagger UI (Bearer + x-tenant-id) |
| WebSocket | namespace /presence | Presença de utilizadores do CRM cliente em tempo real |
| Health | GET /api, GET /api/health | Metadados e liveness (rotas públicas) |
flowchart TB
subgraph clients [Clientes]
CF[CentralCRM_front<br/>painel admin]
DCF[default_crm-front<br/>CRM do cliente]
end
subgraph central [CentralCRM_back]
API[REST /api/v1]
WS[Socket.IO /presence]
AUTH[JwtAuthGuard global]
end
subgraph data [Persistência]
PG1[(PostgreSQL principal<br/>cronospay / companies)]
PG2[(PostgreSQL auth<br/>G_DB_POSTGRESS / public."user")]
RD[(Redis — cache branding)]
MEM[(Map em memória<br/>sessões WebSocket)]
end
CF --> API
CF --> WS
DCF --> WS
API --> AUTH
WS --> AUTH
AUTH --> PG1
AUTH --> PG2
API --> PG1
API --> RD
WS --> PG1
WS --> MEM
Ecossistema
| Repositório | Papel |
|---|---|
| CentralCRM_back (este) | API central, diretório de empresas, presença, operacional agregado |
| CentralCRM_front | Painel admin; consome REST + WebSocket como observador admin |
| default-crm | Backend do CRM do cliente; emite JWT (sessionHash) com tenantId |
| default_crm-front | Abre socket de presença após login usando centralPresenca |
Fluxo de presença e integração JWT: ENTENDIMENTO.md.
2. Stack e dependências principais
| Camada | Tecnologia |
|---|---|
| Runtime | Node.js 20 (Alpine no Docker) |
| Framework | NestJS 11, Express |
| ORM | TypeORM 0.3 (synchronize: false) |
| BD | PostgreSQL (pg) |
| Auth | Passport JWT, @nestjs/jwt, bcrypt |
| Validação | class-validator, class-transformer |
| Tempo real | @nestjs/websockets, Socket.IO 4 |
| Cache | Redis (ioredis) — branding, não presença |
| Nodemailer (SMTP) | |
| Docs | @nestjs/swagger |
3. Estrutura do repositório
CentralCRM_back/
├── src/
│ ├── main.ts # Bootstrap: CORS, pipes, Swagger, IoAdapter
│ ├── app.module.ts # Módulos raiz + 2 conexões TypeORM
│ ├── bootstrap-env.ts # Carrega .ENV / .env antes do Nest
│ ├── config/ # database, jwt, defaults embutidos
│ ├── common/ # filters, decorators (@Public, tenant)
│ ├── controllers/ # app + health (version neutral)
│ └── modules/
│ ├── auth/ # JWT strategy + JwtAuthGuard global
│ ├── auth-login/ # login, registo, public."user" (BD G_DB_POSTGRESS)
│ ├── company/ # empresas, diretório, utilizadores
│ ├── company-operational/# TPV, ECs, comissões, propostas
│ ├── presence/ # REST + PresenceGateway
│ ├── white-label/
│ ├── portal-subdomain/
│ ├── external-apis/
│ ├── password-reset/
│ └── health/
├── docs/ # Documentação (este ficheiro, guias API, SQL)
├── Dockerfile # Multi-stage: build + produção
├── compose.yaml # Serviço backend + healthcheck
└── test/ # e2e Jest
4. Módulos funcionais
Cada feature Nest vive em src/modules/<nome>/. O padrão de bounded context (quando aplicável) repete camadas dentro de uma subpasta homónima — ver src/modules/company/README.md.
| Módulo | Responsabilidade | Controllers (path base /api/v1) |
|---|---|---|
| AuthModule | Estratégia JWT, guard global | — |
| AuthLoginModule | Login/registo em public."user"; permissões; lista CRM admin | auth, crm-admin/users |
| CompanyModule | Tenant, company, diretório (branding, moradas, documentos), users por empresa | companies, company/directory, company |
| CompanyOperationalModule | Métricas por empresa (estabelecimentos, dashboard, comissões, …) | company/directory/:companyId/operational |
| PresenceModule | Sessões online (memória) + contagens REST | presence |
| WhiteLabelModule | White labels paginados por tenant | white-labels/:tenantId |
| PasswordResetModule | Reset, first-access, templates de e-mail | auth/password-reset, auth/first-access, email-templates |
| PortalSubdomainModule | URL do portal, TLS check, ícone de tenant | portal/..., /api/tenants/... |
| ExternalApisModule | Proxies OpenCNPJ / BrasilAPI | external-apis/... |
| HealthModule | Health check | (via HealthController em /api/health) |
Lista HTTP completa: apis/catalogo-completo.md. ADRs: adr/index.md.
Rotas públicas (sem Bearer)
Marcadas com @Public() — o JwtAuthGuard ignora autenticação:
GET /api— metadados da APIGET /api/healthPOST /api/v1/auth/loginPOST /api/v1/auth/registerPOST/GETpassword-reset (request,token,confirm)GET/POSTfirst-access (token,confirm)GET /api/v1/portal/subdomain-urlGET /api/v1/portal/internal/check-host
Todas as restantes exigem Authorization: Bearer <JWT>.
5. Camadas por bounded context
Padrão usado em company (e replicável noutros recursos):
modules/company/
├── company.module.ts # Wiring Nest (imports, providers, controllers)
└── company/
├── domain/ # Portas, enums, modelos de domínio
├── application/ # Serviços / casos de uso
├── infrastructure/ # Adaptadores TypeORM (repositórios)
├── entities/ # Entidades TypeORM
└── presentation/ # Controllers v1, DTOs, mappers
Fluxo de um pedido HTTP típico:
CompaniesV1Controllervalida DTO (ValidationPipeglobal).- Resolve
tenantId(JWT, body ou headerx-tenant-id). CompanyServiceaplica regras (ex.: conflito CNPJ → HTTP 409).TypeOrmCompanyRepositorypersiste na BD principal.
6. Bases de dados (dual connection)
O AppModule regista duas conexões TypeORM independentes:
| Conexão | Variáveis | Uso |
|---|---|---|
| default | POSTGRES_* ou DATABASE_* ou libpq (PG*) | company, tenants, operacional, user (presença), white labels |
USER_PROFILES_CONNECTION | AUTH_DATABASE_* → BD G_DB_POSTGRESS | public."user" + tabelas relacionais (login, registo, CRM admin) |
Resolução centralizada em src/config/config_db.ts e database.config.ts.
synchronize: false— schema gerido por SQL/migrações (docs/sql/).- Opcional:
DATABASE_SEARCH_PATHpara schema PostgreSQL (ex.:cronospay,public). - SSL:
DATABASE_SSL/AUTH_DATABASE_SSL.
Sem variáveis de BD no Docker, o bootstrap pode aplicar defaults embutidos (database-embedded-defaults.ts) ou falhar com mensagem explícita — ver ENV_CONTAINER.md.
7. Autenticação e contexto de tenant
JWT
- Segredo:
JWT_SECRET(ouJWT_SECRET_FILE). - Extração: header
Authorization: Bearer. - Claims lidos em
JwtStrategy.validate:sub(obrigatório),tenantId/tid,role/role_code.
Tipos de token
| Origem | Claims | Uso típico |
|---|---|---|
POST /api/v1/auth/login | sub | APIs sem tenant; patch de permissões |
| Emissor externo / script / default-crm | sub + tenantId (+ opcional role) | Diretório, operacional, presença |
| Admin CentralCRM | sub + role: admin (sem tenantId) | Listagens globais; socket em admin:observer |
Header alternativo
x-tenant-id (UUID) quando o JWT não traz tenantId — usado por decorators como TenantIdFromJwt.
Autorização por papel
USER_ROLE_ADMIN: pode listar empresas/presença globalmente; white labels de qualquer tenant.- Utilizadores normais: operações restritas ao
tenantIddo token ou header.
8. Versionamento e contratos HTTP
- Prefixo global:
api(main.ts). - Versionamento URI:
VersioningType.URI→ rotas em/api/v1/.... - Erros:
HttpExceptionFilter→ JSON{ statusCode, timestamp, path, message }. - Body:
whitelist+forbidNonWhitelisted(campos extra → 400).
Swagger: GET /api/docs (UI), GET /api/docs-json, GET /api/docs-yaml.
9. Presença em tempo real
REST (PresenceV1Controller)
| Método | Rota | Descrição |
|---|---|---|
| GET | /presence/active-users | Sessões ativas no tenant |
| GET | /presence/active-users-global | Todas as sessões (só admin) |
| GET | /presence/online-count/main-companies | Contagem — empresas mãe |
| GET | /presence/online-count/sub-companies | Contagem — sub-empresas |
| GET | /presence/online-count/aggregated-by-parent | Rede mãe + filhas |
WebSocket (PresenceGateway)
- Namespace:
/presence - Path Socket.IO:
/socket.io(padrão) - Auth:
auth.tokenno handshake (mesmo JWT do CRM) - Estado:
UserPresenceService—Mapem memória (não persistido) - Salas:
tenant:<tenantId>,admin:observer(admins não contam como online)
Eventos emitidos (ex.): presence:sync, presence:join, presence:leave, presence:error.
Alinhamento JWT: o default-crm deve assinar com o mesmo JWT_SECRET (ou chave em JWT_EXTERNAL_SECRETS no consumidor). Detalhes em ENTENDIMENTO.md.
10. Módulo operacional
Base path:
/api/v1/company/directory/{companyId}/operational/...
Agrega dados das tabelas estabelecimentos, estabelecimento_config_financeira, transacoes_locais, propostas, etc., sempre resolvendo tenant + pertença da company ao utilizador.
Endpoints principais: estabelecimentos, dashboard, top-estabelecimentos, comissoes/resumo, alugueis/resumo, propostas.
11. Deploy e runtime
flowchart LR
DEV[Desenvolvimento<br/>npm run start:dev]
BUILD[npm run build]
IMG[Dockerfile multi-stage]
COMPOSE[docker compose]
PROD[node dist/main.js :3000]
DEV --> BUILD
BUILD --> IMG
IMG --> COMPOSE
COMPOSE --> PROD
| Artefacto | Notas |
|---|---|
| Dockerfile | Stage builder (npm ci + nest build); stage production com user nestjs |
| compose.yaml | env_file: .ENV, volume read-only, healthcheck em /api/health |
| PORT | Default 3000 |
| CORS | CORS_ORIGIN (lista separada por vírgula); sem valor, espelha origem (dev) |
Checklist pós-deploy:
GET /api→name: "CentralCRM API"GET /api/health→status: okJWT_SECRETdefinido- BDs acessíveis a partir do container (não
localhostse Postgres é remoto)
12. Diagrama de módulos Nest
flowchart TB
AM[AppModule]
AM --> CM[ConfigModule]
AM --> T1[TypeORM default]
AM --> T2[TypeORM USER_PROFILES]
AM --> Auth[AuthModule]
AM --> AL[AuthLoginModule]
AM --> Co[CompanyModule]
AM --> CO[CompanyOperationalModule]
AM --> Pr[PresenceModule]
AM --> WL[WhiteLabelModule]
AM --> PRS[PasswordResetModule]
AM --> PT[PortalSubdomainModule]
AM --> EX[ExternalApisModule]
AM --> RD[RedisModule]
AM --> HM[HealthModule]
AM --> Guard[JwtAuthGuard APP_GUARD]
Auth --> Guard
AL --> T2
Co --> T1
CO --> T1
Pr --> T1
WL --> T1
13. Documentação relacionada
| Documento | Conteúdo |
|---|---|
README.md | Cartão de visita (raiz) |
docs/index.md | Home MkDocs |
catalogo-completo.md | Todos os endpoints |
GUIA_FRONTEND_APIS.md | Contratos REST, erros, Bearer |
ENV_CONTAINER.md | Docker / Swarm, variáveis, JWT |
ENTENDIMENTO.md | Presença end-to-end e troubleshooting |
FRONTEND_LOGIN.md | Login |
FRONTEND_REGISTER_BASE.md | Registo |
FRONTEND_POST_COMPANY.md | Criação de empresa |
sql/ | Scripts de schema PostgreSQL |
DOCKER_DB_DEBUG.md | Diagnóstico de ligação BD no container |
14. Decisões de desenho (resumo)
Detalhe em ADRs.