> ## Documentation Index
> Fetch the complete documentation index at: https://docs.domsoftware.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Arquitetura do Backend

> Visão técnica completa da API NestJS: módulos, multi-tenancy, CQRS, filas e integrações com marketplaces.

## 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    |
| E-mail           | Resend + React Email                    | —      |
| Documentação API | Swagger (OpenAPI)                       | —      |

***

## Estrutura de pastas

```
src/
├── main.ts                  # Bootstrap — CORS, ValidationPipe, Swagger, porta
├── app.module.ts            # Módulo raiz — registra todos os imports
├── app.controller.ts        # Health check
│
├── auth/                    # Autenticação (Passport, JWT, estratégias)
│   ├── strategies/          #   LocalStrategy, JwtStrategy
│   ├── guards/              #   JwtAuthGuard
│   ├── session.service.ts   #   Refresh tokens (Redis)
│   └── auth.service.ts      #   Login, logout, refresh
│
├── common/                  # Infraestrutura compartilhada
│   ├── tenancy/             #   ⭐ Multi-tenancy (middleware + subscriber)
│   ├── base-entity/         #   TenantBaseEntity (herança)
│   ├── guards/              #   Filtros de exceção
│   ├── decorators/          #   @CurrentUser, etc.
│   ├── interceptors/        #   Logging, transformação
│   ├── mail/                #   Templates React Email + envio via Resend
│   ├── outbox/              #   Padrão Outbox (eventos assíncronos)
│   ├── queues/              #   Registro global de filas BullMQ
│   ├── redis/               #   RedisCustomModule (ioredis)
│   └── transformers/        #   BigInt, decimais
│
├── catalog/                 # PIM — Gestão de produtos (★ módulo mais complexo)
│   ├── entities/            #   Product, Inventory, InventoryEntry, Kit…
│   ├── services/            #   CQRS: CommandService + QueryService
│   ├── controllers/         #   Endpoints REST
│   ├── processors/          #   Jobs BullMQ do catálogo
│   ├── repositories/        #   Queries especializadas
│   ├── dto/                 #   Create, Update, Bulk DTOs
│   └── types/               #   Enums, interfaces
│
├── integrations/            # Conectores de marketplace
│   ├── adapters/            #   MeliAdapter, ShopeeAdapter
│   ├── base/                #   BaseMarketplaceGateway (contrato)
│   ├── meli/                #   Lógica específica Mercado Livre
│   ├── oauth/               #   Fluxo OAuth callback
│   ├── orchestrators/       #   Orquestração de sincronização
│   ├── tokens/              #   CRUD de tokens criptografados
│   └── services/            #   Serviço principal
│
├── listings/                # Anúncios em marketplaces
├── orders/                  # Pedidos de venda
├── tenants/                 # Contas SaaS (tenants)
├── users/                   # Usuários e RBAC
├── companies/               # Perfil de empresa do tenant
├── brands/                  # Cadastro de marcas
├── suppliers/               # Cadastro de fornecedores
├── warehouses/              # Depósitos e locais de estoque
├── processing/              # Lógica de processamento em batch
├── workers/                 # Consumers BullMQ
├── config/                  # Configuração centralizada
├── database/                # Migrations TypeORM
├── types/                   # Tipos globais
└── utils/                   # Utilitários puros
```

***

## Multi-tenancy

O sistema é **estritamente multi-tenant**. Cada empresa (tenant) enxerga apenas os seus próprios dados. A isolamento funciona em três camadas:

```
               ┌──────────────────────────────────┐
  Request ───▶ │   TenancyMiddleware              │
               │   Decodifica JWT, extrai          │
               │   tenantId e userId               │
               │   Salva no CLS (nestjs-cls)       │
               └───────────┬──────────────────────┘
                           │
               ┌───────────▼──────────────────────┐
   Service ───▶│   TenantAwareService             │
               │   this.currentTenantId            │
               │   Herança: extends TenantAware    │
               └───────────┬──────────────────────┘
                           │
               ┌───────────▼──────────────────────┐
     ORM  ───▶ │   TenantSubscriber               │
               │   beforeInsert() → injeta         │
               │   tenantId automaticamente        │
               └──────────────────────────────────┘
```

### 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`.            |

<Warning>
  **Regra crítica:** O `TenantSubscriber` só garante isolamento em **inserts**. Todas as queries (find, createQueryBuilder, etc.) **devem** filtrar por `tenantId` explicitamente no service. Nunca confie apenas no subscriber para leitura.
</Warning>

### TenantBaseEntity

Toda entity de domínio herda de `TenantBaseEntity`, que já traz as colunas `id`, `tenantId`, `createdAt` e `updatedAt`:

```typescript theme={null}
@Entity('products')
@Index('idx_product_tenant', ['tenantId'])
export class Product extends TenantBaseEntity {
  @Column({ name: 'name' })
  name: string;
  // ...
}
```

***

## CQRS — Command / Query

Módulos complexos (como `catalog`) 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)

1. **Sem joins pesados em listagem** — agregados como BOM, componentes e estoque só são carregados em endpoints de detalhe (`findOne`).
2. **Paginação obrigatória** — todo endpoint de lista deve paginar.
3. **Índices compostos** — sempre criar `@Index` em combinações `tenantId + campo_de_filtro`.

### Padrão de transação (CommandService)

```typescript theme={null}
async createProduct(dto: CreateProductDto) {
  return this.repository.manager.transaction(async (manager) => {
    // 1. Validação
    await this.validationService.validate(dto);
    // 2. Criação da entity principal
    const product = manager.create(Product, { ...dto, tenantId: this.currentTenantId });
    await manager.save(product);
    // 3. Criação de dependentes dentro da MESMA transação
    await this.createInventory(manager, product);
    return product;
  });
}
```

<Info>
  Sempre passe o `manager` recebido no callback para métodos auxiliares. Isso garante que tudo roda dentro da mesma transação.
</Info>

***

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

```
  Controller               FIla (Redis)              Worker (Processor)
  ──────────                ──────────                ──────────────────
  Ação do usuário  ───▶   enfileira job   ───▶      processa em background
                           (auto-retry 3x)           (exponential backoff)
```

### 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ódulo `common/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**:

```
                       ┌──────────────────────────────┐
                       │   BaseMarketplaceGateway     │
                       │   (contrato / interface)      │
                       └──────────┬───────────────────┘
                                  │
               ┌──────────────────┤──────────────────────┐
               │                  │                      │
       ┌───────▼───┐      ┌──────▼──────┐       ┌───────▼───────┐
       │MeliAdapter│      │ShopeeAdapter│       │ Futuro adapter│
       └───────────┘      └─────────────┘       └───────────────┘
```

### Fluxo de conexão OAuth

1. Frontend redireciona o usuário para a URL de autorização do marketplace.
2. Marketplace redireciona de volta para `POST /integrations/oauth/callback`.
3. Backend troca o `code` por tokens de acesso.
4. Tokens são **criptografados** com `TOKEN_ENCRYPTION_KEY` e salvos no banco.
5. Um `@Cron` job renova tokens automaticamente antes de expirarem.

### Serviço de tokens

O módulo `integrations/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

```typescript theme={null}
// ✅ Correto
@Entity('products')
@Index('idx_product_tenant', ['tenantId'])
@Index('idx_product_tenant_sku', ['tenantId', 'sku'])
export class Product extends TenantBaseEntity {
  @Column({ name: 'seq_id' })
  seqId: number;

  @Column({ name: 'sku', nullable: true })
  sku: string;
}
```

### DTOs

```typescript theme={null}
// Separar em Create, Update e Bulk
export class CreateProductDto {
  @IsString()
  @IsNotEmpty()
  name: string;

  @IsOptional()
  @IsString()
  sku?: string;
}

export class UpdateProductDto extends PartialType(CreateProductDto) {}
```

### Error handling

```typescript theme={null}
// ✅ Usar exceções HTTP do NestJS
throw new NotFoundException(`Produto ${id} não encontrado`);
throw new BadRequestException('SKU já existe para este tenant');

// ❌ Nunca expor erros internos do banco
// throw error;  ← NÃO FAÇA ISSO
```

***

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

<Steps>
  <Step title="Entenda a multi-tenancy">
    Leia `common/tenancy/` — middleware, subscriber e TenantAwareService. Toda query deve filtrar por `tenantId`.
  </Step>

  <Step title="Crie a Entity">
    Em `src/seu-modulo/entities/`. Herde de `TenantBaseEntity`. Use snake\_case para colunas e crie índices.
  </Step>

  <Step title="Crie os DTOs">
    Separe `CreateXDto`, `UpdateXDto` e, se necessário, `BulkCreateXDto`. Use `class-validator`.
  </Step>

  <Step title="Crie o Service">
    Para módulos simples, um único service. Para módulos complexos, separe em Command e Query.
  </Step>

  <Step title="Crie o Controller">
    Defina endpoints REST. Decore com `@ApiTags`, `@ApiResponse` para o Swagger.
  </Step>

  <Step title="Registre no Module">
    Adicione controllers e providers no module do domínio. Importe no `AppModule` se for um módulo novo.
  </Step>

  <Step title="Gere a Migration">
    `npm run migration:generate -- --name=NomeDaAlteracao` → revise → `npm run migration:run`.
  </Step>
</Steps>
