- Nx 22.7 monorepo (pnpm 11.1, TypeScript 5.9, Node 24) - apps/api: NestJS 11 (CJS conforme CODING-RULES.md PGD-DB-004) - apps/web: React 19 + Vite 8 (ESM) - libs/shared/api-interface: Zod contract base - Docker Compose dev: Postgres 18, Valkey 8, MinIO, Mailpit - WDS artifacts: - design-artifacts/A-Product-Brief/ (5 docs canônicos + 16 dialogs) - design-artifacts/B-Trigger-Map/ (hub + 4 personas + feature impact) - Stack canon: STACK.md v2.2 + CODING-RULES.md v2.0 + brand.md - AGENTS.md + README.md como entrada para devs/agentes Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
12 KiB
STACK.md — Referência de Tecnologias
Define o que usar: tecnologias, versões, estrutura do monorepo e filosofia arquitetural. Leia antes de decisões de tecnologia ou arquitetura. Para regras de como escrever o código (invariantes + pegadinhas 🔥), consulte
CODING-RULES.md. Humano novo? Este arquivo é projetado para consumo por agente de IA. Comece pordocs/QUICKSTART.md— 5 min, com TL;DR executável e as 5 decisões arquiteturais-chave.
1. O que é e por quê
Stack full-stack TypeScript para apps internas da empresa (Proxmox on-prem no BR · Docker Compose · MinIO · master-login · Vault · email/CDN via SaaS). Seis decisões que diferenciam de stacks genéricas:
- Schemas Zod são o contrato. Tipos derivam de schemas em
libs/shared/api-interface; mesmo schema valida no Nest e tipareact-hook-form. → §06 - Monorepo Nx ·
apps/+libs/<scope>/<type>-<nome>com 3 tags (scope:+type:+domain:) e ESLint boundaries. Um repo por produto, não por serviço. → §02 - App stateless · infra stateful self-host no Proxmox. Postgres, Valkey, MinIO, master-login e Vault rodam em VMs/LXC controladas pelo time — nunca em container efêmero da app. Email (Resend) e CDN (Cloudflare) permanecem SaaS por razões de deliverability / borda global. → §03, §11, ADR 0004, ADR 0005
- Multi-tenancy via BD-por-workspace. Cada workspace tem cluster PG próprio registrado no master-login; app cliente resolve
PrismaClientpor request viaget_workspace_connection+ roleapp_reader(senha nunca trafega por HTTP). Sem colunatenantIdem modelos; isolamento é físico. → §03.4, §23.4, ADR 0006 - Tudo que pode esperar vai pra fila (BullMQ). Email, webhook, processamento, agendado — handler HTTP só faz o mínimo síncrono. Job sempre carrega
workspaceIdno payload; worker recria o CLS. → §11 - LGPD by design. Isolamento físico cross-workspace (cluster PG dedicado por cliente), PII criptografada (MinIO SSE +
pgcrypto), redact agressivo em logs, Art. 18 implementado, hash em targeting de flags. Datacenter próprio elimina exposição ao CLOUD Act (US) sobre dados regulados. → §07, §09, §22
Princípios canônicos (11 itens) em docs/README.md → Princípios gerais (TL;DR). Filosofia arquitetural completa em §21.
2. Stack canônica (May 2026)
Tabela completa com colunas Versão/Arquivo em docs/README.md → Tabela canônica. One-liners por camada:
- Runtime: Node 24 LTS · pnpm 11.1 · TypeScript 5.9 → §01
- Monorepo: Nx 22.7 → §02
- Backend: NestJS 11.1 (Express 5) · Prisma 7 · PostgreSQL 18 ·
nestjs-cls·@nestjs/terminus·@nestjs/throttler+@nest-lab/throttler-storage-redis→ §03, §20 - Frontend: React 19.2 + Compiler · Vite 8 (Rolldown) · Ant Design 6.4 · TanStack Query 5.100 · TanStack Router · Zustand 5.0.13+ → §04
- API: REST + OpenAPI 3.1 + RFC 9457 Problem Details · Zod 4 (pnpm catalog) + nestjs-zod + react-hook-form (
zodResolver) → §05, §06 - Auth: Guards NestJS +
jose+ master-login (IdP OAuth2/OIDC próprio em VM Proxmox; HS256 hoje → RS256 roadmap) · argon2id centralizado no IdP → §07, ADR 0005 - Segredos: HashiCorp Vault (KV v2) self-host · Vault Agent injeta env vars no container → §08
- Observabilidade: Pino + nestjs-pino 10.3 · OpenTelemetry (Traces+Metrics GA; Logs Beta) · Grafana Cloud LGTM · Sentry → §09
- Flags: OpenFeature SDK + GrowthBook self-host → §10
- Filas: BullMQ 5.77 +
@nestjs/bullmq11 · Bull Board · Valkey em VM/LXC Proxmox → §11 - Cache:
@nestjs/cache-managerv3 + cache-manager 6 +@keyv/redis+cacheable(L1) — TTL em ms → §12 - Real-time: Socket.IO 4 +
@socket.io/redis-adapter· SSE via@Sse()nativo NestJS → §13 - Uploads: MinIO (S3-compat) presigned POST policy + AWS SDK v3 · Uppy +
@uppy/aws-s3· ClamAV em worker BullMQ · sharp 0.34 → §14 - Email: Resend (SaaS — não self-host) + React Email via BullMQ → §15
- Testes: Vitest 4.1 · Testcontainers 12 · Supertest 7.2.2 (encapsulado) · Playwright 1.60 → §16
- Qualidade: ESLint 10.4 flat · typescript-eslint 8.59 · Prettier 3.8.3 · eslint-plugin-import-x 4.16.2 · Husky 9 + lint-staged 17 · gitleaks → §17
- CI/Deploy: GitHub Actions + Nx Cloud · Trivy gate · pin actions por SHA · Docker multi-stage
node:24-alpine· Ansible/SSH para VMs Proxmox com docker-compose rolling (backend) · Cloudflare + Nginx servindo SPA estática (frontend, não containerizar) → §18
3. Quando aplicar este guia
- Greenfield: obrigatório do dia 0.
- Brownfield: adoção gradual, tópico a tópico.
- Spike/POC: livre até 2 semanas — se virar produto, refatora.
- Fora de escopo (React Native, GraphQL pesado, mobile nativo): exige RFC antes.
4. Filosofia em 5 bullets
Aprofunde em docs/21-filosofia-arquitetural.md.
- Monólito modular. Uma única aplicação deployável (
apps/api), organizada em um NestJS Module por domínio de negócio (ComprasModule,VendasModule,EstoqueModule,FinanceiroModule). - Dependências apontam para dentro (Clean Architecture). Domínio não conhece framework; módulos não importam domínio alheio direto.
- Um domínio = um Module = N libs (
domain-/feature-/data-access-). Boundaries enforçadas pelas três tags Nx (ADR 0002). - Cross-domínio via fila, read-model ou ACL. Nunca import direto entre módulos de domínios diferentes. Eventos como substantivo no passado (
OrderPlaced,PaymentFailed). - Entidade ≠ model Prisma. Type Prisma é mapeado para entidade em
data-access; mapper é o único ponto que conhecePrisma.*. Entidades com construtorprivate+ factoriescreate()/reconstitute(); mutações por métodos de negócio (cancel(),ship()). Side-effects (email, webhook, read-model) sempre após oprisma.$transaction, via BullMQ.
5. Estrutura do monorepo
apps/
api/ # NestJS HTTP — monólito modular (um Module por domínio)
api-worker/ # Workers BullMQ (mesma imagem, entrypoint diferente)
web/ # React + Vite SPA
web-e2e/ # Playwright
libs/
shared/<purpose>/ # usável por api e web
api/domain-<domínio>/ # entidades, VOs, repositórios abstratos
api/feature-<domínio>/ # use cases (um arquivo por ação) + Module
api/data-access-<domínio>/ # Prisma, BullMQ producers, mappers
api/util-<nome>/ # utilitários sem regra de negócio
web/<feature|data-access|ui|util>-<nome>/
Convenções de naming/branching/code review em §19; detalhes de tags Nx e depConstraints em §02 e §21.
6. Onde aprofundar (mapa por intenção)
| Para fazer… | Vá em |
|---|---|
| Invariantes e pegadinhas 🔥 (regras de código) | CODING-RULES.md |
| Setup zero (runtime, ESM, tooling) | §01 |
| Criar/configurar libs Nx, boundaries, tags | §02, ADR 0002 |
| Modelar backend (Module, Prisma, transação) | §03, §20 |
| Frontend (componente, query, form, router) | §04 |
| Desenhar endpoint REST (paginação, erro, versão) | §05 |
| Validar entrada (Zod, DTO, i18n pt-BR) | §06 |
| Implementar auth (login, refresh, OAuth/PKCE) | §07 |
| Gerir secrets e env vars | §08 |
| Logar, tracear, alertar | §09 |
| Criar feature flag / experimento | §10 |
| Enfileirar job, scheduler, retry, DLQ | §11 |
| Cachear (app, HTTP, CDN, stampede) | §12 |
| WebSocket / SSE | §13 |
| Upload de arquivo / imagem | §14 |
| Enviar email / notificação (web push) | §15 |
| Escrever teste (unit, integração, E2E) | §16 |
| Configurar lint / formatter / hook / gitleaks | §17 |
| CI, Docker, deploy Proxmox (Ansible/SSH), rolling | §18 |
| Dimensionar VMs Proxmox (sizing, HA, capacity) | §24 |
| Naming, branching, code review | §19 |
| Padrão Nest universal (DI, ciclo de vida, health) | §20 |
| Filosofia arquitetural (DDD, Clean, BC) | §21 |
| LGPD (bases legais, retenção, redact, Art. 18, RoPA) | §22 |
| Autorização (RBAC + ABAC, BD-por-workspace, anti-IDOR) | §23, ADR 0006 |
| Multi-tenancy (factory de PrismaClient, get_workspace_connection, saga de onboarding) | §03.4, ADR 0006 |
| SLOs default por tipo de endpoint / job / fluxo | ADR 0001 |
| ADRs (decisões fora do escopo deste guia) | docs/adr/ |
Meta-governança
- Adotar em uma app: copie
STACK.mdeCODING-RULES.mdpara a raiz do repo da app + referencie ambos emAGENTS.md. Procedimento completo (cópia, referência, sync, exceções, checklist) emdocs/README.md→ "Como usar STACK.md em uma app". - Sync: PR que altera tabela canônica / princípios em
docs/README.mddeve atualizarSTACK.mdno mesmo commit; PR que altera pegadinhas deve atualizarCODING-RULES.md— enforçado por.gitea/workflows/stack-sync-check.yml. - Mudanças de stack: ADR em
docs/adr/NNN-titulo.md(sequencial; nunca reescrito —Superseded by NNN); RFC via issue com labelrfc. Bump trimestral de versões. - Mantenedores: time de plataforma; canal
#plataforma.
Regra de ouro para o agente: ao propor tecnologia fora desta tabela, pergunte antes e cite a justificativa. Para regras de como escrever o código, consulte CODING-RULES.md.