Stack tecnológica
| Camada | Tecnologia | Versão |
|---|---|---|
| Framework | NestJS | 11.x |
| Linguagem | TypeScript | 5.9 |
| Banco de dados | PostgreSQL | 15 |
| ORM | TypeORM | 0.3 |
| Filas | BullMQ + Redis | 5.x |
| Autenticação | Passport + JWT | — |
| Validação | class-validator + class-transformer | — |
| Rate limiting | @nestjs/throttler | 6.x |
| Multi-tenancy | nestjs-cls (Continuation-Local Storage) | 6.x |
| Resend + React Email | — | |
| Documentação API | Swagger (OpenAPI) | — |
Estrutura de pastas
Multi-tenancy
O sistema é estritamente multi-tenant. Cada empresa (tenant) enxerga apenas os seus próprios dados. A isolamento funciona em três camadas:Três componentes da tenancy
| Componente | Arquivo | Responsabilidade |
|---|---|---|
| TenancyMiddleware | common/tenancy/tenancy.middleware.ts | Roda em toda requisição. Decodifica o JWT e injeta tenantId e userId no CLS. |
| TenantAwareService | common/tenancy/tenant-aware.service.ts | Classe base. Services que herdam dela ganham this.currentTenantId. |
| TenantSubscriber | common/tenancy/tenant.subscriber.ts | TypeORM subscriber global. Injeta tenantId automaticamente em INSERT. |
TenantBaseEntity
Toda entity de domínio herda deTenantBaseEntity, que já traz as colunas id, tenantId, createdAt e updatedAt:
CQRS — Command / Query
Módulos complexos (comocatalog) separam leitura e escrita em services distintos:
| Tipo | Exemplo | Responsabilidade |
|---|---|---|
| CommandService | ProductCommandService | Criação, atualização, exclusão. Gerencia transações. |
| QueryService | ProductQueryService | Listagem, filtros, paginação. Otimizado para leitura. |
| ValidationService | ProductValidationService | Regras de negócio chamadas pelo CommandService antes de gravar. |
Regras de performance (QueryService)
- Sem joins pesados em listagem — agregados como BOM, componentes e estoque só são carregados em endpoints de detalhe (
findOne). - Paginação obrigatória — todo endpoint de lista deve paginar.
- Índices compostos — sempre criar
@Indexem combinaçõestenantId + campo_de_filtro.
Padrão de transação (CommandService)
Sempre passe o
manager recebido no callback para métodos auxiliares. Isso garante que tudo roda dentro da mesma transação.Autenticação
| Conceito | Implementação |
|---|---|
| Login | POST /auth/login — LocalStrategy valida credenciais, retorna JWT |
| Access token | JWT com { sub, tenantId, role }, expira em minutos |
| Refresh token | Armazenado como cookie HttpOnly, gerenciado no Redis |
| Refresh | POST /auth/refresh — lê cookie, valida no Redis, gera novo access |
| Logout | POST /auth/logout — apaga refresh token do Redis |
Guards
- JwtAuthGuard — protege todas as rotas autenticadas.
- ThrottlerGuard — rate limit global: 200 req/min por IP.
Filas e processamento assíncrono
Jobs assíncronos usam BullMQ com Redis como broker:Configuração global
| Parâmetro | Valor | Descrição |
|---|---|---|
attempts | 3 | Tentativas antes de marcar como falha |
backoff.type | exponential | Atraso cresce a cada retry |
backoff.delay | 5 000 ms | Delay base |
removeOnComplete | true | Jobs completos são apagados do Redis |
removeOnFail.age | 24h | Jobs falhos são mantidos por 24h |
Padrão Outbox
O módulocommon/outbox/ implementa o padrão Transactional Outbox: eventos são gravados no banco dentro da mesma transação da operação de domínio e depois processados pelo worker. Isso garante consistência mesmo que o Redis esteja temporariamente indisponível.
Integrações com marketplaces
A camada de integrações segue o padrão Adapter:Fluxo de conexão OAuth
- Frontend redireciona o usuário para a URL de autorização do marketplace.
- Marketplace redireciona de volta para
POST /integrations/oauth/callback. - Backend troca o
codepor tokens de acesso. - Tokens são criptografados com
TOKEN_ENCRYPTION_KEYe salvos no banco. - Um
@Cronjob renova tokens automaticamente antes de expirarem.
Serviço de tokens
O módulointegrations/tokens/ gerencia o armazenamento seguro dos tokens OAuth:
- Criptografia AES usando a variável
TOKEN_ENCRYPTION_KEY. - Cada par de tokens (access + refresh) é associado ao
tenantId+ marketplace. - Renovação automática via scheduler.
Módulos do sistema
| Módulo | Diretório | Descrição |
|---|---|---|
| Auth | auth/ | Login, refresh, logout, password reset, strategies |
| Catalog | catalog/ | PIM completo: produtos, estoque, kits, custos, NCM |
| Integrations | integrations/ | Conectores OAuth (Mercado Livre, Shopee), adapters |
| Listings | listings/ | Gerenciamento de anúncios publicados nos marketplaces |
| Orders | orders/ | Pedidos de venda sincronizados dos marketplaces |
| Users | users/ | CRUD de usuários, perfis e permissões (RBAC) |
| Tenants | tenants/ | Gestão de contas SaaS |
| Companies | companies/ | Dados cadastrais da empresa |
| Brands | brands/ | Cadastro de marcas |
| Suppliers | suppliers/ | Cadastro de fornecedores |
| Warehouses | warehouses/ | Depósitos e locais de estoque multi-warehouse |
| Processing | processing/ | Lógica de processamento batch |
| Workers | workers/ | Consumers BullMQ (processamento assíncrono) |
Módulo Catalog em detalhe
O catálogo é o módulo mais extenso. Seus services cobrem:| Service | Responsabilidade |
|---|---|
ProductCommandService | CRUD de produtos, bulk create/update |
ProductQueryService | Listagem com filtros, busca, paginação |
ProductValidationService | Regras de negócio (SKU único, campos obrigatórios) |
InventoryService | Saldo de estoque por warehouse |
InventoryEntryService | Entradas e ajustes de estoque |
InventoryDashboardService | Dashboard analytics de estoque |
StockMovementService | Histórico de movimentações |
StockTransferService | Transferências entre depósitos |
KitService | Kits e produtos compostos (BOM) |
ProductComponentsService | Componentes de cada kit |
CostService | Cálculo de custos (CMC, custo médio) |
ProductCostService | Custo de produção e markup |
NcmService | Classificação fiscal NCM/CEST |
NfeParserService | Parser de XML de NF-e para importação |
ProductCacheService | Cache Redis de dados de produto |
ProductInheritanceService | Herança de atributos para variações |
Padrões de código
Entities
DTOs
Error handling
Testes
| Tipo | Localização | Comando | Foco |
|---|---|---|---|
| Unitários | src/**/*.spec.ts | npm run test | Lógica de negócio nos services |
| E2E | test/ | npm run test:e2e | Fluxos completos da API |
| Carga | load-tests/ | npm run test:load | Performance sob carga (k6) |
Checklist para novos desenvolvedores
Entenda a multi-tenancy
Leia
common/tenancy/ — middleware, subscriber e TenantAwareService. Toda query deve filtrar por tenantId.Crie a Entity
Em
src/seu-modulo/entities/. Herde de TenantBaseEntity. Use snake_case para colunas e crie índices.Crie o Service
Para módulos simples, um único service. Para módulos complexos, separe em Command e Query.
Registre no Module
Adicione controllers e providers no module do domínio. Importe no
AppModule se for um módulo novo.