# Padrões e Diretrizes de Engenharia

**Versão:** 5.6
**Atualizado em:** 2026-06-12
**Status:** Documento normativo **e contexto operacional**. Desvios exigem ADR aprovado.

---

## 0. Como Ler

- **MUST / Obrigatório** — regra. Desvio bloqueia merge ou exige ADR.
- **SHOULD / Recomendado** — padrão. Desvio precisa de justificativa no PR.
- **MAY / Opcional** — sugestão.
- **VETADO / Proibido** — não existe "atalho". Não se faz, não se cogita, não se "resolve depois". Burlar é incidente, não decisão técnica.

Quando este documento conflitar com a realidade do problema, **registre um ADR** explicando o desvio. Padrão sem exceção vira dogma; dogma vira dívida. **Mas itens marcados VETADO não têm ADR de exceção** — são pisos de segurança e integridade, não preferências.

Versões concretas de stacks ficam no **Anexo A**, atualizado independentemente deste corpo.

---

## 0.1. Aplicação Universal — Este Arquivo é Contexto Máximo

**MUST**

- Este documento é **anexado a TODO prompt / sessão / tarefa** de engenharia (humana ou assistida por IA). É **contexto pinado**, não referência opcional. Se a tarefa toca código, infra, dados, deploy ou design de sistema, este arquivo está em contexto. Sem exceção.
- Nenhuma resposta, PR, geração de código ou decisão arquitetural é válida se ignorar este documento. "Não estava no contexto" não é desculpa — **garantir o anexo é responsabilidade de quem abre a tarefa**, e a ausência dele é, por si só, motivo para parar e recarregar o contexto antes de produzir qualquer coisa.
- Em caso de conflito entre uma instrução pontual ("faz rápido", "ignora o teste", "depois a gente arruma") e este documento, **este documento vence**. Pressa não revoga regra.
- Assistentes de IA operam sob as mesmas regras dos humanos (§34) **e** sob as proibições explícitas da §37. Velocidade de geração nunca justifica violar um piso.

> Um padrão que não está no contexto na hora da decisão é um padrão que não existe. Por isso ele é pinado, não linkado.

---

## 1. Filosofia

Prioridades, em ordem de desempate:

1. Clareza > esperteza
2. Simplicidade > abstração antecipada
3. Manutenibilidade > velocidade pontual
4. Observabilidade > debugging manual
5. Segurança por padrão > segurança como camada final
6. Evolução incremental > big-bang
7. **Registro do que foi decidido > memória de quem decidiu** (ver §28)

**Princípios:** Clean Code, SOLID, KISS, DRY (com bom senso — duplicação acidental ≠ duplicação semântica).

**Regra suprema:** se algo aumenta acoplamento, reduz observabilidade, cria dependência desnecessária, **vaza segredo, mistura contexto, ou pula registro** ou adiciona complexidade sem benefício claro, **provavelmente está errado**.

---

## 2. Estrutura de Repositórios

**MUST**
- Um repositório = uma aplicação ou um bounded context.
- Comunicação entre serviços via HTTP, gRPC, eventos ou mensageria — nunca via banco compartilhado.
- Cada serviço é dono do seu schema.

**VETADO**
- **Aplicação monolítica que acopla múltiplos bounded contexts num só deploy/processo.** Não se cogita "começar monolito e quebrar depois" sem ADR explícito de plano e prazo de quebra. Misturar domínios de negócio "pra entregar rápido" é dívida disfarçada de produtividade.
- **Monólito distribuído** — o pior dos dois mundos: serviços separados fisicamente, mas acoplados por banco compartilhado, shared lib de domínio (§7) ou chamadas síncronas em cascata sem fronteira. Tão proibido quanto o monólito clássico.
- **Big ball of mud** — código sem fronteira de contexto, onde tudo importa tudo.

**SHOULD**
- Evitar mais de um domínio de negócio no mesmo repositório.
- Leitura cross-service por réplica read-only só com ADR e contrato documentado.

**MAY**
- *Modular monolith* (módulos com fronteira de contexto rígida, schema separado, comunicação por interface interna) **somente com ADR** que justifique estágio do produto e contenha o plano de extração. É exceção registrada, não default. Nunca usar como atalho para colar domínios.

> Não existe "MVP monolítico que vira microserviço depois" sem o ADR que prova que o depois tem data. Sem isso, "depois" é "nunca", e "nunca" é um big ball of mud em produção.

---

## 3. Linguagens

**Backend — apenas Go e Rust.**

| Cenário | Stack |
|---|---|
| Serviços backend, APIs, glue code, concorrência, padrão da casa | **Go** |
| Performance crítica, segurança de memória | **Rust** |

**Frontend — Node é 100% permitido (e só frontend).** Frontend baseado em Node é a stack da casa porque hoje é o melhor do mercado: **Next.js** é a stack principal, mas **Astro e outros frameworks consolidados** são permitidos. O server-side do próprio front (route handlers, server actions, BFF) faz parte do frontend e é governado pelo §13.4 e §38 (segredo só server-side, etc.). Isso vale **apenas** para frontend — **não** reabre Node como linguagem de serviço backend (ver o MUST abaixo e §3.1: backend novo em Node é proibido; o ganho marginal de tooling/npm não compensa o histórico de incidentes de segurança).

**MUST**
- Versão exata em uso fica no Anexo A.
- Não misturar linguagens dentro do **mesmo bounded context** sem ADR.
- **Backend novo só em Go ou Rust.** Nenhum serviço backend novo em Node.

**SHOULD**
- Default é **Go**; **Rust** quando performance crítica ou segurança de memória justificam. Em empate técnico, Go vence (padrão do time).
- Frameworks são bem-vindos; abstrações mágicas não. Critério: consigo entender o stack trace?

### 3.1 Node legado (backend) — migração para Go/Rust

Node como linguagem de **serviço backend** está em saída. Tudo que existe em Node backend será migrado para Go ou Rust, guiado por esforço (não big-bang) e medido **por funcionalidade do módulo**, não por linha.

**Modelo da métrica.** Um módulo tem N funcionalidades (ex.: 10 — cálculo, ABAC, CRUD, etc.). O quanto uma mudança "pesa" é a fração de funcionalidades que ela altera ou cria sobre o total do módulo. Ex.: módulo com 10 funcionalidades — refatorar 2 = 20%; refatorar 3 (ou criar ~4 novas) ≈ 30%.

**MUST**
- **Não mexer no que está feito em Node, a menos que solicitado.** Node backend funcionando fica como está até ser tocado.
- **Gatilho de extração (~30%):** quando uma mudança atingir ~30% das funcionalidades do módulo (alteradas + novas), **não cresça o Node** — extraia essa(s) funcionalidade(s) para um **módulo Go/Rust à parte** e incorpore o comportamento Node nessa nova base.
- **Extração incremental:** conforme se mexe no módulo Node ao longo do tempo, vai-se extraindo aos poucos para Go/Rust.
- **Virada dos 50%:** quando ~50% do módulo já estiver extraído/inutilizado (substituído pela versão Go/Rust), **migra-se os 50% restantes de uma vez** — encerra o módulo Node.
- **Ajuste pontual não porta.** Mudança pequena/localizada (abaixo do gatilho) é feita no próprio Node, sem portabilidade.
- Toda migração registra ADR (§27) e segue o DDD híbrido/coexistência (§4.X, §36): flag de coexistência, sem big-bang.

> Os percentuais (~30% pra extrair, ~50% pra finalizar) são os limiares da casa; ajuste por ADR se um módulo específico exigir. A regra é: parou de ser ajuste pontual, vira extração; passou da metade, termina.

### 3.2 PHP — proibido

**VETADO** — PHP não é linguagem da casa, em nenhuma camada.

- Nenhum código novo em PHP.
- Projeto existente em PHP é **migrado sumariamente** para Go/Rust (backend) — prioridade de migração, com ADR e plano. Não é "quando der"; é dívida ativa a ser zerada.

---

## 4. Arquitetura

**MUST — todos os projetos**
- Separação explícita de camadas: `domain`, `application`, `infrastructure`, `interface`.
- Inversão de dependência: domínio não conhece infra.
- Domínio não importa frameworks nem ORM.

**SHOULD — projetos com regra de negócio relevante**
- DDD tático (agregados, value objects, eventos de domínio).
- Arquitetura hexagonal (ports & adapters).

**MAY — CRUDs simples**
- Manter as 4 camadas, dispensar táticas DDD pesadas.

### Dependências permitidas

```
interface       → application
application     → domain
infrastructure  → domain, application
```

### Dependências proibidas

```
domain          → qualquer outra camada
domain          → frameworks, ORM, libs de IO
application     → interface
```

### Anti-Corruption Layer

**MUST** em integrações com sistemas externos: adapter dedicado em `infrastructure/external/` que traduz o modelo externo para o modelo de domínio. **Nunca** expor DTOs externos diretamente no domínio.

### 4.X DDD híbrido durante transição

Projetos legados onde código já existe sem separação de camadas **podem** adotar DDD progressivamente em vez de big-bang. Regras:

**MUST**
- Toda nova feature/refactor em código tocado segue o layout completo (`domain/`, `application/`, `infrastructure/`, `interface/`) — não introduzir mais código "flat".
- Ao mover/quebrar arquivo legado, organize já em folders DDD mesmo que internamente alguma classe ainda misture responsabilidades (ex.: service em `application/` ainda chamando SQL direto). Estrutura primeiro, inversão depois.
- Cada PR que toca arquivo híbrido **deve** mover ao menos um pedaço pra direção certa (ex.: extrair entidade pra `domain/`, mover query pra `infrastructure/repositories/`).
- ADR registrando o débito e o plano de remoção: `<project>/docs/adr/<n>-ddd-migration-<contexto>.md`.

**SHOULD**
- Manter teste de cobertura por camada (§22) durante a transição — domain começa com 0%, sobe a cada PR.
- Linter ou guard test que **rejeita imports proibidos** logo que possível (mesmo que com whitelist de exceções legadas):
  - `domain/` não importa `@nestjs/*`, `pg`, `axios`, `infrastructure/*`, `application/*`, `interface/*`.
  - `application/` não importa `interface/*`.

**MAY**
- Marcar arquivos híbridos com comment `// @ddd-hybrid` pra busca fácil e cleanup priorizado.

---

## 5. Estrutura de Pastas

### Node.js

```
src/
├── domain/           # entities, value-objects, services, events, repositories (interfaces)
├── application/      # use-cases, dto, commands, queries
├── infrastructure/   # persistence, messaging, external, observability
├── interface/        # http, grpc, cli
├── shared/
└── config/
tests/
```

### Go

```
cmd/<app-name>/
internal/
├── domain/
├── application/
├── infrastructure/
├── interface/
├── shared/
└── config/
tests/
```

### Rust

```
src/
├── domain/
├── application/
├── infrastructure/
├── interface/
├── shared/
└── config/
tests/
```

---

## 6. Complexidade e Tamanho

**MUST — arquivos pequenos, micro-funções**
- **Arquivo alvo: ≤ 300 linhas.** Acima disso, o arquivo **deve ser quebrado** — extraia responsabilidades em módulos menores e a lógica em **micro-funções** com nome que explica a intenção. Não existe "arquivo de 800 linhas porque é coeso": coesão real cabe em arquivos pequenos colaborando.
- **Funções pequenas e de responsabilidade única.** Ideal ≤ 50 linhas; função grande vira micro-funções compostas. Use case: uma responsabilidade.
- Exceções (não disparam quebra): testes, migrations, código gerado, schemas/fixtures.

**MUST — toda função documentada**
- **TODA função/método tem comentário** no formato de doc da linguagem (JSDoc, GoDoc, rustdoc). O comentário declara, no mínimo:
  - **O quê** — o que a função faz, em uma linha.
  - **Onde é usada / prevista** — quem chama, em que fluxo/camada ela foi pensada pra servir (ex.: "usado pelo use-case `CreateOrder`", "handler HTTP de `/v1/checkout`"). Isto dá contexto explícito de propósito e evita função órfã.
  - Parâmetros, retorno e efeitos colaterais relevantes.
- Esse comentário é a **fonte do índice de microfunções** (§39) — escreva pensando que ele será extraído e indexado, não como enfeite.

Convenção mínima (adapte à linguagem):

```
/**
 * O quê: valida o payload de checkout e cria o pedido.
 * Onde:  use-case CreateOrder; chamado pelo handler POST /v1/checkout.
 * Efeitos: persiste em orders, publica catalog.order.created via outbox.
 */
```

**Bloqueio rígido em CI**
- Arquivo de produção > 300 linhas sem quebra (exceto as exceções acima) → bloqueia.
- Função de produção sem doc-comment → bloqueia.
- Complexidade ciclomática > 15 em função de produção.
- Aninhamento > 4 níveis.

> Linha de código é proxy ruim para complexidade — complexidade ciclomática é a métrica honesta. Mas arquivo gigante e função sem contexto são dívidas óbvias: quebre e documente antes do merge.

---

## 7. Dependências Internas e Shared Libraries

**MUST**
- Shared libraries são **mínimas** e com escopo claramente delimitado.
- Permitido como shared: observabilidade, autenticação/auth, primitives de infraestrutura, SDKs internos, logging, configuração.

**MUST NOT**
- Criar `commons` / `core-lib` / `platform-utils` genéricos.
- Compartilhar **lógica de domínio** entre bounded contexts.
- Compartilhar entidades de domínio. Cada contexto modela o seu.

> O caminho mais rápido pra um monólito distribuído é uma shared lib chamada `commons`.

**SHOULD**
- Shared libs versionadas com SemVer próprio.
- Breaking changes em shared lib exigem ADR.

---

## 8. CQRS e Padrões de Aplicação

- **Commands**: alteram estado, retornam id ou void.
- **Queries**: nunca alteram estado, otimizadas para leitura, podem usar projeções.
- CQRS **não exige** event sourcing.

---

## 9. Eventos e Mensageria

**MUST — produção e consumo**
- Eventos são imutáveis e versionados (`v1`, `v2`).
- Consumidores idempotentes (deduplicação por id de evento).
- Suporte a replay.

**MUST — compatibilidade evolutiva**
- Novos campos são **opcionais**, com default seguro.
- Nunca remover ou renomear campo sem **nova versão** do evento.
- Consumidores **ignoram campos desconhecidos** (forward compatible).
- Coexistência de versões durante janela de migração documentada.

**MUST — entrega**
- **Transactional Outbox** para publicação de eventos. Dual-write (banco + broker no mesmo fluxo) é **VETADO** (ver §37).
- DLQ (dead letter queue) configurada para todo consumidor.
- **Retry infinito proibido.** Política de retry explícita com limite e backoff.

**MUST — backpressure**
- Consumidores com limites explícitos de concorrência e prefetch.
- Throttling em produtores quando broker sinaliza pressão.

**Convenção de nome:** `<dominio>.<entidade>.<evento>` no passado.
Exemplos: `catalog.product.created`, `billing.invoice.paid`.

**Brokers**

| Cenário | Stack |
|---|---|
| Eventos leves, baixa latência, pub/sub simples | **NATS** |
| Alto throughput, retenção, replay, streaming | **Kafka** |
| Workflows com routing complexo (caso a caso) | RabbitMQ |

> NATS e Kafka são padrão. RabbitMQ exige justificativa pelo custo operacional.

---

## 10. Banco de Dados

| Caso | Stack |
|---|---|
| Relacional | PostgreSQL |
| Cache | Redis |
| Busca textual | OpenSearch |
| Analytics / eventos | ClickHouse |

**MUST**
- Migrations versionadas, **reversíveis** (com `down`), automatizadas no deploy.
- Schema próprio por serviço.
- Sem joins cross-service no banco.
- **Timestamps em UTC, sempre.** Conversão de timezone apenas na borda (UI/API response).
- **IDs:** UUIDv7 ou ULID por padrão. IDs sequenciais apenas com justificativa (ex: ordenação natural exigida pelo domínio).
- **Toda query com input externo é parametrizada.** Concatenação de string em SQL é **VETADA** (§37).

**SHOULD — alta escala**
- Separação leitura/escrita (réplicas) quando volume justificar.
- Revisão periódica de índices.
- Análise de query plan em endpoints críticos.
- Particionamento para tabelas com crescimento previsível alto.

**Ferramentas sugeridas:** `golang-migrate`, `node-pg-migrate`, `sqlx-cli`, `flyway`.

---

## 11. Cache

**MUST**
- TTL **sempre explícito**. Sem TTL infinito sem ADR.
- Mitigação de cache stampede (single-flight, lock, jitter).
- Fallback seguro em cache miss — degradação graciosa, nunca falha total.
- Invalidação documentada por chave.
- Resposta autenticada **sempre** tem a chave de cache segmentada por usuário e tenant (§37).

**MUST NOT**
- Cache como source of truth.
- Cache de dados pessoais sensíveis sem criptografia.

---

## 12. APIs

**MUST**
- **OpenAPI 3.1** em `/docs/openapi.yaml` — fonte da verdade.
- Versionamento na URL: `/v1`, `/v2`.
- Validação de payload na borda.
- Erro padrão (compatível com RFC 7807):

```json
{
  "error": {
    "code": "PRODUCT_NOT_FOUND",
    "message": "Product not found",
    "trace_id": "01HXYZ...",
    "details": []
  }
}
```

- Operações de escrita aceitam `Idempotency-Key` **e o implementam de fato** (aceitar o header e ignorar é VETADO — §37).
- Quebra de contrato exige nova versão + janela de deprecação ≥ 90 dias com headers `Deprecation` e `Sunset`.
- Timestamps em **ISO-8601 com timezone explícito** (preferencialmente `Z`).

**MUST — paginação**
- **Cursor pagination** é o padrão.
- Offset apenas em listas pequenas (< 10k itens) e estáticas.
- Resposta inclui `next_cursor` e `has_more`.

**MUST — rate limiting**
- Rate limiting **distribuído** (Redis, gateway, ou serviço dedicado).
- Chave por usuário, API key e tenant.
- Resposta 429 com header `Retry-After`.

**SHOULD**
- Contratos consumer-driven (Pact) entre serviços.
- gRPC para alta performance interna; HTTP/JSON para externa.

---

## 13. Segurança

**MUST — pipeline (fail on high/critical)**
- Dependabot ou Renovate
- SAST (Semgrep / CodeQL)
- SCA (dependências + licenças)
- Container scan (Trivy / Grype)
- Secret scan (Gitleaks)
- Commit signing (GPG / SSH / Sigstore)
- SBOM no build (CycloneDX ou SPDX)

**MUST — runtime**
- Containers não-root, read-only filesystem.
- Distroless ou chainguard quando viável.
- Multi-stage build.
- Healthcheck na imagem.

**MUST — segredos**
- Nunca em código, nunca em env file commitado.
- Storage: Vault, AWS/GCP Secret Manager, sealed-secrets.
- Rotação documentada.

**Licenças permitidas:** MIT, Apache 2.0, BSD, MPL 2.0, ISC.
**Bloqueadas sem ADR:** GPL/AGPL, SSPL, proprietárias.

### 13.4 Segredos no Cliente / Frontend / NextJS

**VETADO — sem exceção, sem ADR**

- **Qualquer segredo no bundle que vai pro browser.** API key privada, secret de JWT, senha de banco, service-role key (Supabase/Firebase admin), token de provedor de pagamento, chave de terceiro — **nada** disso entra em código que o cliente baixa. O navegador não guarda segredo. Ponto.
- Prefixar segredo com `NEXT_PUBLIC_` (ou equivalente `VITE_`, `REACT_APP_`, `PUBLIC_`). Esse prefixo **expõe a variável publicamente por definição** — usar só para valor que pode estar num outdoor.
- Chamar API de terceiro com chave secreta **direto do browser**. Toda chamada que usa segredo passa por um **BFF / route handler / server action** server-side (§38).
- Guardar token de sessão em `localStorage`/`sessionStorage`. Sessão vai em **cookie `HttpOnly` + `Secure` + `SameSite`** (§38, §22.3 hardening).
- Confiar em validação de auth/role feita no client (`if (user.isAdmin)` no React) como controle de acesso. Isso é UX, não segurança — a decisão é **sempre server-side** (§15, §37).

> "Coloca a senha no NextJS pra funcionar" não é uma solução, é um vazamento agendado. Se o cliente pode ver, o atacante já viu.

---

## 14. Autenticação e Autorização

- OAuth2 / OIDC.
- JWT assinado (RS256 ou EdDSA; **nunca HS256** em fluxo público).
- Validação **completa** do JWT em toda request: assinatura, `exp`, `nbf`, `aud`, `iss` e `alg` contra allowlist. Decodar o payload e confiar é VETADO (§37).
- Refresh token rotativo com detecção de reuso.
- RBAC com permissões granulares; ABAC quando necessário.
- Hash de senha: **bcrypt cost ≥ 12** ou **argon2id**. MD5/SHA1/sem-salt/plaintext são VETADOS (§37).
- Tokens, ids de sessão e códigos de reset gerados por **CSPRNG** (`crypto/rand`, `crypto.randomBytes`) — nunca `Math.random()` (§37).

---

## 15. Multi-tenancy

**MUST — quando aplicável (SaaS, plataformas)**
- Isolamento de tenant explícito em todas as camadas.
- `tenant_id` propagado em contexto, logs e traces.
- Autorização validada **server-side** em toda operação. **Nunca** confiar em `tenant_id` (ou role, ou user_id) enviado pelo cliente sem verificação contra o token. Derivar sempre do token, server-side.
- Queries com `tenant_id` no `WHERE`, sempre. Considerar Row Level Security no Postgres.

**SHOULD**
- Testes de cross-tenant leak em CI.
- Métricas e logs particionáveis por tenant.

---

## 16. Observabilidade

**Stack obrigatória:** Grafana, Alloy, Loki, Tempo, Prometheus, OpenTelemetry.

### 16.1 Logs

- JSON estruturado.
- `trace_id`, `correlation_id`, `tenant_id` (se aplicável) em toda request.
- Níveis: DEBUG, INFO, WARN, ERROR.
- **Proibido logar:** senhas, tokens, JWT, PII (CPF, email, telefone), dados financeiros, payloads de pagamento. Mascaramento obrigatório.
- **VETADO** logar request/response inteiros, headers ou body cru "pra debugar" (§37). Logue campos específicos, mascarados.

### 16.2 Métricas

- **RED por endpoint/handler:** Rate, Errors, Duration (histograma p50/p95/p99).
- **USE para infra:** Utilization, Saturation, Errors.

### 16.3 Tracing

- Toda chamada externa, fila, banco e fluxo crítico instrumentados.
- Propagação **W3C Trace Context**.

### 16.4 SLOs

- Cada serviço define SLI/SLO em `/docs/slo.md`.
- Error budget consumido → freeze de features até recuperação.

### 16.5 Business Observability

**SHOULD**
- Métricas de negócio expostas (pedidos/min, conversão, churn, etc).
- Dashboards de negócio separados dos técnicos.
- KPIs principais instrumentados desde o dia 1.

### 16.6 Auditoria

**MUST**
- Operações sensíveis (mudança de permissão, transações financeiras, alteração de configuração, ações administrativas) registradas em **trilha de auditoria imutável**.
- Campos mínimos: `actor_id`, `tenant_id`, `action`, `resource`, `timestamp`, `ip`, `user_agent`, `result`.
- Retenção mínima conforme regulação aplicável.
- Storage append-only (não usar a mesma tabela de domínio).

---

## 17. Healthchecks

Endpoints obrigatórios:
- `/health` — liveness (processo está vivo)
- `/ready` — readiness (dependências OK, pronto pra tráfego)
- `/metrics` — Prometheus

---

## 18. Resiliência

**MUST em chamadas externas:**
- Timeout explícito (nunca infinito).
- Retry com backoff exponencial + jitter, idempotência garantida.
- Circuit breaker.
- Rate limiting na borda.
- Bulkhead em integrações críticas.

---

## 19. Jobs e Workers

**MUST**
- Jobs **idempotentes** (pode executar 2x sem corromper).
- Timeout obrigatório por job.
- Política de retry explícita com limite.
- Progress/state persistido para jobs longos ou críticos.
- DLQ para jobs que falharem após max retries.

**SHOULD**
- Jobs longos divisíveis em chunks com checkpoint.
- Cancelamento gracioso (respeitar context/signal).

---

## 20. Configuração

- Via environment variables (12-factor).
- Validação tipada no startup — falha rápido.
- Sem hardcode.
- Defaults seguros (fail closed).

---

## 21. Infraestrutura e Deploy

**MUST**
- Kubernetes + Helm.
- IaC: Terraform ou OpenTofu.
- CI/CD: GitHub Actions.
- Ambientes isolados: `dev`, `staging`, `production`.
- Promoção entre ambientes por **artefato imutável** (mesma imagem).

### 21.1 Estratégia de Deploy

| Estratégia | Quando usar |
|---|---|
| Rolling update | Default para serviços comuns |
| Blue/green | Serviços críticos, rollback instantâneo necessário |
| Canary | Mudanças de alto impacto, rollouts graduais |

**MUST**
- Rollback automatizado quando healthcheck falhar pós-deploy.
- Healthcheck gating: tráfego só vai pra pod ready.
- Janela de validação antes de declarar deploy bem-sucedido.

### 21.2 Preview Environments

**SHOULD**
- PRs em serviços principais geram ambiente efêmero automaticamente.
- Destruído ao merge ou após X dias de inatividade.

---

## 22. Testes

**Obrigatório**
- Testes em **dois eixos**: por código (unit/integration, dentro de cada serviço) e por sistema vivo (smoke/security/pentest/authz/hardening/chaos/simulated, no repo `<project>_ops`).
- Caminhos críticos (auth, pagamento, autorização, billing, eventos de domínio, multi-tenancy) têm testes explícitos cobrindo sucesso, falha e edge cases — independentemente da cobertura agregada.

**Cobertura mínima (por código)**

| Camada | Mínimo |
|---|---|
| `domain` | 80% |
| `application` | 70% |
| `infrastructure` | 40% |
| Global | 60% |

> Editar o threshold ou pular teste pra "passar o CI" é VETADO (§37). O número é contrato.

**Mutation testing (SHOULD)** no domínio em serviços críticos: Stryker (JS/TS), `go-mutesting`, `cargo-mutants`.

---

### 22.1 Test Kit do `<project>_ops`

Toda a malha de testes "do sistema vivo" mora num repo dedicado (`<project>_ops`), invocada por um CLI único.

**Estrutura padrão**

```
<project>_ops/
├── bin/
│   └── <project>-test          # CLI: run modes, agrega saída
├── tests/
│   ├── lib.sh                  # helpers compartilhados (cores, assertions, http_call)
│   ├── README.md               # tabela de modos × scripts × duração
│   ├── smoke/                  # health, rotas-chave, shape de respostas
│   ├── integration/            # login real + CRUD ponta-a-ponta
│   ├── security/               # auth bypass, headers, rate-limit
│   ├── pentest/                # OWASP + extensão
│   ├── authz/                  # RBAC + multi-tenancy isolation
│   ├── hardening/              # TLS, cookies, CORS, exposed paths
│   ├── chaos/                  # fuzz, property-based, kill, db-disconnect
│   ├── simulated/              # matriz exaustiva: rotas × personas × injections
│   ├── seeds/                  # SQL de setup (personas de teste, superadmin)
│   ├── unit/                   # delega `go test` / `npm test` por serviço
│   └── workspace-code.sh       # smell-scan no monorepo (arquivos > N linhas, etc.)
├── Makefile
└── README.md
```

**CLI padrão**

```bash
<project> test                  # default: smoke
<project> test smoke
<project> test integration
<project> test security
<project> test pentest
<project> test authz
<project> test hardening
<project> test chaos
<project> test simulated
<project> test unit
<project> test all              # tudo exceto chaos+unit
<project> test full             # all + chaos + unit
<project> test seed-superadmin  # setup inicial (uma vez)
```

**MUST**
- Cada script é executável standalone: `bash tests/smoke/auth-endpoints.sh` deve rodar e sair `0/1`.
- Cada script declara `TEST_NAME` e usa helpers de `lib.sh` (`test_pass`, `test_fail`, `test_skip`, `test_section`, `test_summary`, `http_call`, `assert_http_in`).
- Banner ENORME em vermelho quando há falha — feedback visual impossível de ignorar em CI.
- Skip sem erro quando dependência opcional falta (ex.: openssl ausente em hardening/tls).

---

### 22.2 Saída estruturada (machine-readable)

Toda execução escreve em `/<project>/logs/test-<YYYY-MM-DD>-<HHMMSS-pid>/`:

| Arquivo | Conteúdo |
|---|---|
| `summary.txt` | PASS/FAIL por script, legível |
| `summary.json` | **fonte única pra dashboards/CI** — schema fixo abaixo |
| `run-totals.txt` | 7 linhas: mode, started, finished, duration, scripts, pass, fail, exit |
| `<mode>-<name>.log` | output completo de cada script |
| `cookies.txt` | sessão dos personas (só em `integration`) |
| `coverage-summary.{txt,json}` | cobertura por serviço (só em `unit`) |

**Schema `summary.json`**

```json
{
  "started_at": "2026-05-11T11:35:50Z",
  "finished_at": "2026-05-11T11:35:57Z",
  "duration_seconds": 7,
  "mode": "smoke",
  "log_dir": "/<project>/logs/test-2026-05-11-083550-448694",
  "scripts": [
    {"category": "smoke", "name": "auth-endpoints", "status": "pass"},
    {"category": "smoke", "name": "services-health", "status": "fail"}
  ],
  "totals": {"pass": 23, "fail": 1, "scripts": 24, "exit_code": 1}
}
```

**MUST**
- Exit code 0 se tudo passou; 1 se qualquer caso falhou.
- `summary.json` é contrato — não quebre os campos `mode`, `totals`, `scripts[]`.
- Logs zipados e enviados pra storage de longo prazo após cada CI run (90 dias mínimo).

---

### 22.3 Categorias de teste (por modo)

#### `smoke` — saúde do sistema, < 2min

Cobre: health/metrics de cada serviço, rotas-chave do dispatcher, frontends, observability stack, endpoints por domínio (auth, catalog, billing, etc.), DB connectivity, microservices-status, shape de health/metrics, response-time p95, CORS preflight, OpenAPI availability, log scan pra PII vazada.

Falha = bloqueio de deploy. Roda **antes e depois** de cada `update` em todo ambiente.

**MUST — anti "verde mentiroso" (smoke que passa com bug dentro)**

Um smoke que só confere status `200` é teatro: a rota responde, o conteúdo está quebrado, e o deploy passa. Para impedir isso:

- **Assertar conteúdo, não só status.** Toda rota-chave valida o **shape do body** (campos esperados via `jq -e`), não apenas o código HTTP. `200` com body vazio, `{}`, `null`, `[]` onde deveria haver dado, ou HTML de erro com status 200 = **FALHA**.
- **Assertion negativa obrigatória.** Cada rota crítica também testa que o que **não** deveria estar lá não está: sem stack trace, sem `error`/`exception` no body de sucesso, sem `"undefined"`/`"null"`/`"NaN"` serializado, sem placeholder de template não renderizado (`{{`, `${`, `%s`).
- **Self-test do próprio smoke (meta-teste).** O suite tem um caso que **força uma falha conhecida** (ex.: bater numa rota fake `/_smoke_canary_should_404` esperando 404, e numa asserção que deve falhar de propósito num modo `--self-check`) pra provar que o runner **consegue reportar FAIL**. Se o "self-check" passa quando deveria falhar, o smoke está cego → CI quebra. Nenhum teste pode ser estruturalmente incapaz de falhar.
- **Cobertura de rota verificada.** O smoke compara as rotas que testou contra o inventário do OpenAPI/dispatcher. **Rota em produção sem caso de smoke = FALHA**, não silêncio. (Liga com §35 e com `simulated`.)
- **Sem `|| true`, sem swallow.** Proibido `curl ... || true`, `set +e` sem `set -e` de volta, ou condição que transforma erro em pass. Falha de rede/timeout numa dependência obrigatória é FAIL, não skip (skip só pra dependência **opcional** declarada).
- **Latência e dado fresco.** Healthcheck que devolve `200` cacheado/estático não conta — `/ready` valida dependência **de verdade** (ping no DB, no broker), e o smoke afere `response-time p95` contra o SLO (§30). Resposta lenta demais = FALHA.
- **Fail loud.** Banner vermelho ENORME (§22.1) e o `summary.json` com `totals.fail > 0` travando o deploy. Verde só quando **todas** as asserções de conteúdo passaram.

> Smoke que nunca falha não é smoke saudável — é smoke quebrado. Se você não viu o teste falhar de propósito, você não sabe se ele funciona.

#### `integration` — fluxos end-to-end com credenciais reais, < 3min

Cobre: login do superadmin com cookie real, CRUD course/user/subscription via API admin, upload de imagem, reset de senha completo. Usa seed `tests/seeds/test-superadmin.sql` pra garantir user existente.

**Requer pré-seed**: rodar `<project> test seed-superadmin` na primeira vez no ambiente.

#### `security` — controles de segurança "óbvios", < 1min

Cobre: auth bypass tentando rotas admin sem cookie, headers de segurança (CSP, X-Content-Type, HSTS), rate limit no login (50 paralelas → expect 429), formato de password hash (bcrypt cost ≥ 12 / argon2id), `npm audit --audit-level=high`, JWT algorithm validation (RS256 only).

#### `pentest` — OWASP Top 10 + extensão, < 3min

Scripts cobrem (cada um isolado):
- `sql-injection.sh` — payloads SQLi clássicos em query/body. Esperado: 400/422 ou 401/403/404. **NUNCA 500** e nunca 200 com data revelando "OR 1=1".
- `xss.sh` — `<script>`, `<img onerror>`, `javascript:` em campos refletidos. Resposta não pode incluir payload sem escape.
- `idor.sh` / `user-bola.sh` — IDs de outro tenant/user nos paths.
- `ssrf.sh` — URLs apontando pra `127.0.0.1`, `169.254.169.254`, `file://`, redirect chains.
- `jwt-tampering.sh` / `jwt-claim-tampering.sh` / `jwt-algorithm.sh` — alg=none, alg=HS256-com-RS256-pubkey, exp futuro, sub trocado.
- `path-traversal.sh` — `../`, `..%2f`, null bytes.
- `mass-assignment.sh` — POST com campos extras (`is_admin`, `tenant_id`, `created_at`) que deveriam ser ignorados.
- `open-redirect.sh` — `?next=https://evil.com`.
- `host-header.sh` — Host header arbitrário pra envenenar links em emails.
- `csrf.sh` — POST sem origin/referer válido.
- `http-method-tampering.sh` — TRACE, OPTIONS, métodos não suportados.
- `request-smuggling.sh` — `Transfer-Encoding: chunked` + `Content-Length` conflitantes.
- `cache-poisoning.sh` — headers exóticos que envenenam CDN.
- `cookie-bomb.sh` — flood de cookies grandes → expect 4xx limpo, não 500.
- `session-fixation.sh` — session ID atribuído pré-login persiste pós-login.
- `timing-attack.sh` — diff de latência entre user existente vs inexistente no login (alvo: < 30% variance).
- `prototype-pollution.sh` — `__proto__`, `constructor.prototype` no body JSON.
- `redos.sh` — strings catastróficas pra regex (`aaaaaa...aaa!`).
- `billion-laughs.sh` — JSON/XML bomb (nested arrays profundos).
- `clickjacking.sh` — `X-Frame-Options` / CSP `frame-ancestors`.
- `refresh-token-reuse.sh` — usar mesmo refresh duas vezes → 2ª deve revogar família.
- `parameter-pollution.sh` — `?id=1&id=2`.
- `excessive-data-exposure.sh` — endpoint público vaza email/cpf/telefone.
- `header-spoof.sh` — `X-Forwarded-For`, `X-Real-IP`, `X-Original-User` injetados.
- `oversized-payload.sh` — body de 10MB+ → 413, não 500.

**Validação de tipo e sanitização de entrada** — campo só aceita o que deveria, e o que não deveria vira **422/400 limpo, nunca 500 e nunca persistido cru**:
- `type-confusion.sh` — manda o tipo errado em cada campo: string/varchar onde o schema espera `int`/`uuid`/`bool`/`enum`/`date`; número onde espera string; array onde espera objeto; objeto aninhado onde espera escalar. Esperado: `422` com erro de validação. **Aceitar `"123"` como int por coerção silenciosa, ou estourar 500, é FALHA.**
- `boundary-values.sh` — limites numéricos: negativo onde só positivo, `0`, `MAX_INT+1`, `-1`, float onde espera int, `NaN`, `Infinity`, notação científica (`1e999`).
- `charset-fuzz.sh` — caracteres estrangeiros e estranhos em **todo** campo de texto: unicode astral (emoji 𝕏, `𝓪`), CJK (中文), árabe/hebraico (RTL), combinação de diacríticos, zero-width (`\u200b`), homoglyphs, `\u0000` null byte, control chars (`\x01`-`\x1f`), BOM. Esperado: aceitar normalizado (NFC) **ou** rejeitar com 422 — **nunca** quebrar encoding, corromper o dado, ou refletir sem escape.
- `format-validation.sh` — campos com formato declarado (email, cpf, telefone, url, uuid, cep) recebem lixo que casa o "shape" mas é inválido (`a@b`, cpf com dígito verificador errado, `uuid` de 35 chars). Validação semântica, não só regex frouxa.
- `length-overflow.sh` — string acima do `maxLength` do schema, campo obrigatório vazio/ausente, whitespace-only. Esperado: 422, e o limite **vem do schema**, não de um `varchar(255)` implícito que estoura no banco.
- `injection-in-every-field.sh` — roda o conjunto SQLi + XSS + path-traversal + command-injection + template-injection (`${7*7}`, `{{7*7}}`) contra **cada** parâmetro de **cada** rota mutável, não só os "óbvios". Tudo que entra é tratado como hostil até prova de sanitização.

> Regra do pentest de entrada: **todo campo é um campo de ataque.** Se o schema diz `int`, prove que `int` é tudo que entra. Se diz texto, prove que sai escapado e normalizado. Coerção silenciosa e `500` são as duas faces do mesmo bug.

#### `authz` — autorização e isolamento, < 1min

- `cross-tenant-idor.sh` — tenant A não vê dados de tenant B (cobre §15: tenant_id sempre no WHERE).
- `rbac-negative.sh` — viewer não consegue write, editor não consegue admin.
- `privilege-escalation.sh` — tenant_admin não consegue virar platform superadmin.
- `permission-boundary.sh` — combinações de roles + recursos → matriz de allow/deny.
- `tenant-isolation.sh` — cookie/JWT de tenant A injetado em rota de tenant B → 403.

#### `hardening` — endurecimento da superfície de ataque, < 1min

- `tls-config.sh` — TLS 1.2/1.3 ok, 1.0/SSLv3 rejeitados, cert válido, HSTS no header, nome bate.
- `headers-full.sh` — CSP, COOP, CORP, Referrer-Policy, Permissions-Policy, X-Content-Type-Options.
- `cookies.sh` / `cookie-attributes.sh` — HttpOnly + Secure + SameSite=Lax|Strict em todos os cookies de sessão.
- `cors.sh` — origens permitidas explícitas, sem `*` em rotas autenticadas.
- `exposed-paths.sh` — `.git/HEAD`, `.env`, `/debug`, `/actuator`, `phpinfo.php` retornam 404 (não 200).
- `default-creds.sh` — login com `admin/admin`, `root/root`, `test/test` falha sempre.

#### `chaos` — comportamento sob stress / falha, < 5min

- `input-fuzz.sh` — strings longas (10MB), null bytes, unicode astral, JSON malformado.
- `property-based.sh` — idempotência (`POST` com `Idempotency-Key` igual 2x → mesmo resultado), p95 < SLO, JWKS sempre formado corretamente, enums com valores fora do range.
- `service-kill.sh` — `systemctl stop <service>`, mede recuperação (gated por `EDUCE_CHAOS_ALLOW=1` — perigoso).
- `db-disconnect.sh` — derruba conexão DB momentaneamente, valida que pool recupera.
- `concurrent-load.sh` — 50 GETs concorrentes em rotas públicas, mede taxa de sucesso e p50/p95/p99, hang > 10s = falha.

#### `simulated` — matriz exaustiva, ~5min

Engine Python (`tests/simulated/run.py`) que cruza **rotas × personas × injections**:

- **Personas (mínimo 3)** declaradas em `personas.json`:
  - `superadmin` (platform role)
  - `tenant_admin` (escopo de 1 tenant de teste)
  - `normal_user` (sem roles)
  Cada persona declara `expected_access` por categoria de rota (`public`, `auth`, `authenticated`, `admin`, `internal`, `import`).

- **Injections (mínimo 10)** em `injections.json`:
  - SQLi (`' OR 1=1 --`, `'; DROP TABLE users CASCADE; --`)
  - XSS (`<script>alert(1)</script>`)
  - Path traversal (`../../etc/passwd`, `..%2f..%2fetc%2fpasswd`)
  - Null byte, unicode RTL override, long string
  - Mass-assignment keys (`is_admin`, `tenant_id`, `created_at`, `password_hash`)

- **Rota catalog** — JSON gerado a partir do OpenAPI ou inventário de rotas do dispatcher (no Educe: `educe_api_go/docs/legacy_inventory.json`).

**MUST — cobertura total de rotas (garantia de acessibilidade)**
- O engine **enumera 100% das rotas** do catalog e prova, por persona, que cada uma responde como esperado (acessível pra quem deve, `403`/`401` pra quem não deve). **Rota no catalog sem resultado no `raw.jsonl` = FALHA** — não existe rota "não testada".
- **Reconciliação obrigatória:** rota servida em runtime mas ausente do catalog (rota fantasma) **e** rota no catalog que não responde (rota morta / `404` inesperado) **ambas** quebram o run. O número de rotas testadas tem que bater com o inventário.
- Toda rota é exercida com persona autorizada **e** não autorizada — acessibilidade e isolamento no mesmo passe.
- Saída lista explicitamente, no `report.md`, a **matriz rota × persona × esperado × obtido**, com as linhas `REVIEW` destacadas pra olho humano.

**Outputs**:
- `raw.jsonl` — uma linha por request, toda evidência.
- `report.md` — relatório humano com seções **AUTO** (passou claro) e **REVIEW** (status inesperado, precisa olho humano).
- `summary.json` — totais por categoria.

**Setup**: `bash tests/simulated/setup.sh` cria as 3 personas no DB com hash bcrypt.

Vars de ambiente úteis (`EDUCE_TEST_*` no Educe — generalizar com `<PROJECT>_TEST_*`):
- `<P>_TEST_API_BASE` (default `http://127.0.0.1:13000`)
- `<P>_TEST_LOG_DIR` (default `/<project>/logs`)
- `<P>_SIM_TENANT_ID`
- `<P>_SIM_MAX_ROUTES` (debug: limita)
- `<P>_SIM_SKIP_MUTATIONS=1` (só GET)

#### `unit` — testes por código, 5-15min — **agressivos, não decorativos**

CLI delega para o test runner nativo de cada serviço:
- Go: `go test -cover -race ./...`
- Node/Nest: `npm test` ou `vitest run`
- Next.js: `vitest run` ou `jest`

Gera `coverage-summary.json` agregando cobertura por serviço.

**MUST — teste unitário que realmente caça bug (não só cobre linha)**
- **`-race` sempre** (Go), detector de concorrência ligado. Teste flaky por corrida = bug, não "re-roda".
- **Caminho de erro é obrigatório, não opcional.** Para cada função, testar o sucesso **e** as falhas: input inválido, dependência que retorna erro, timeout, nil/null, slice/array vazio, divisão por zero, overflow. Cobertura de 80% só de happy-path é cobertura mentirosa.
- **Tabela de casos hostis por validador/parser:** tipo errado, fora do range, string gigante, vazia, unicode/RTL/null byte, número como string e vice-versa — espelhando o `type-confusion`/`charset-fuzz` do pentest, só que na fronteira da função. Bug de sanitização tem que morrer no unit, antes do pentest achar.
- **Property-based testing (SHOULD → MUST em domínio crítico):** `fast-check` (TS), `gopter`/`rapid` (Go), `proptest` (Rust). Idempotência, round-trip (encode→decode), invariantes de agregado. Encontra o edge case que você não imaginou.
- **Mutation testing no domínio crítico** (§22, Stryker/`go-mutesting`/`cargo-mutants`): se o teste não pega a mutação, o teste é decorativo. **Mutation score mínimo definido por serviço crítico**, não só line coverage.
- **Boundary obrigatório:** `0`, `-1`, `1`, `MAX`, `MAX+1`, vazio, um, muitos. O bug mora na borda.
- **Proibido teste que não pode falhar:** assert ausente, `expect(true)`, mock que devolve o próprio input esperado. Revisão de PR rejeita teste tautológico.

> Cobertura mede o que o teste **executa**, não o que ele **verifica**. Mutation testing mede o que ele verifica. Por isso line coverage é piso, não meta.

---

### 22.4 Padrão de script (`tests/<mode>/<name>.sh`)

Skeleton obrigatório:

```bash
#!/usr/bin/env bash
# <Categoria> · <Nome curto>
# Descrição clara do que cobre e o esperado.
# Esperado: status X em caso Y. Falha = significado Z.

set -uo pipefail
_DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# shellcheck source=../lib.sh
source "$_DIR/lib.sh"

test_section "<Categoria> · <Nome>"

API="$(api_base)"

# Caso 1
assert_http_in "<descrição do caso>" "200|401" GET "$API/v1/<rota>"

# Caso 2 — body shape
http_call GET "$API/v1/<rota>"
if [[ "$HTTP_CODE" == "200" ]]; then
  if echo "$HTTP_BODY" | jq -e '.data | length > 0' >/dev/null 2>&1; then
    test_pass "<rota> retorna dados"
  else
    test_fail "<rota> sem 'data'" "$HTTP_BODY"
  fi
fi

test_summary "<categoria>/<nome>"
exit $TEST_EXIT_CODE
```

**MUST**
- Banner do `test_section` na primeira linha do output.
- Cada caso assertado vira uma linha `✓` ou `✗` ou `○ skip`.
- `test_summary` no fim agrega contadores pra o runner.
- Falhas incluem `HTTP_BODY` truncado nos primeiros 2000 chars (sem PII).

---

### 22.5 Seeds e personas de teste

**MUST**
- Personas declaradas em `tests/seeds/test-*.sql` ou `tests/<mode>/*.json` — versionadas, reproduzíveis.
- Senhas test-only **explicitamente flagadas** (ex.: prefixo `SimTest!`) e **rejeitadas em produção** por validador de senha fraca.
- Setup idempotente: `INSERT ... ON CONFLICT DO UPDATE` — re-rodar não duplica.
- Cleanup automático no fim de cada run? **Não** — deixa lixo pra inspeção. Limpe via comando explícito (`<project> test clean-seeds`).

**Personas mínimas pra cobrir RBAC + multi-tenancy**:

1. `superadmin` — platform role, vê tudo.
2. `tenant_admin_A` — escopo do tenant A.
3. `tenant_admin_B` — escopo do tenant B (pra testar isolamento).
4. `normal_user` — sem role, só dados próprios.
5. (Opcional) `viewer`, `editor`, `support` — combinações de roles dentro de A.

---

### 22.6 Integração com CI

**MUST**
- PR check: `<project> test smoke + security + authz + hardening` (rápido — ~3min total).
- Pré-deploy: `<project> test all` (full minus chaos+unit — ~6min).
- Nightly: `<project> test full` (inclui chaos + unit).
- Bloqueio de merge: fail no `summary.json` (`.totals.fail > 0`) trava merge.

**Dashboards**
- `summary.json` é parseado por job de métricas pra empurrar `tests_pass_total`, `tests_fail_total`, `tests_duration_seconds_bucket` pra Prometheus.
- Falha em smoke pós-deploy dispara rollback automático.

---

### 22.7 Pentest leve via ferramentas externas (complementar)

**SHOULD** — em CI noturno, não a cada PR:
- **OWASP ZAP baseline** (`zap-baseline.py -t https://api.example.com`) — passive scan.
- **Nuclei** (`nuclei -u https://api.example.com -t cves,exposures,misconfiguration`).
- **trivy fs** ou **grype** sobre o repo + imagens Docker pra CVE em deps + base images.
- **Semgrep** ruleset `p/owasp-top-ten` pra SAST.

Resultados em PR comment ou dashboard, **não bloqueiam merge** por default (alto ruído) — mas qualquer **Critical** sem ADR de aceite trava.

---

### 22.8 Diretrizes de Pentest (princípios, não só scripts)

Os scripts da §22.3 são a implementação; estes são os princípios que regem **como** se faz pentest interno e **o que conta como passar**.

**Postura**
- **Assume-breach / hostil por padrão.** Todo input vindo de fora (body, query, header, cookie, path, arquivo, webhook) é tratado como hostil até prova de validação. Não existe "campo interno confiável" exposto numa rota.
- **Cobrir a rota toda, não a amostra.** Pentest roda contra o inventário completo de rotas (mesmo catalog do `simulated`). Rota nova sem caso de pentest correspondente bloqueia (liga com §35).
- **Caixa-cinza.** O time tem o OpenAPI, o schema e as roles — testa sabendo o que **deveria** acontecer, não no escuro. Pentest sem mapa vira teatro de "tentei o `' OR 1=1` e deu 403, tá seguro".

**Critério de resultado — o que é PASS / FAIL**
- **Nunca `500` por input malicioso.** Erro do servidor (5xx) diante de payload hostil é FALHA — significa que o input chegou fundo demais sem validação. O esperado é `400`/`422` (input inválido) ou `401`/`403`/`404` (sem acesso).
- **Nunca eco sem escape.** XSS/template injection refletido no body/header sem encode = FALHA, mesmo com status 200.
- **Nunca coerção silenciosa.** `varchar` aceito como `int`, string vazia virando `0`, `"true"` virando bool = FALHA (liga com `type-confusion.sh`). O tipo do schema é contrato.
- **Nunca vazamento entre tenants/usuários.** Qualquer `200` com dado de outro escopo = FALHA crítica, para o deploy na hora (§15).
- **Nunca diferença observável que ajude o atacante.** Mensagem de erro distinta pra "user existe" vs "senha errada", timing > 30% de variância, stack trace no response = FALHA.
- **Idempotência sob ataque.** Replay, duplicação, race no mesmo recurso não corrompe estado.

**Severidade e gate**
- Classificar todo achado: `Critical` / `High` / `Medium` / `Low` / `Info`.
- **`Critical` e `High` bloqueiam merge/deploy.** Sem exceção silenciosa — ou conserta, ou ADR de aceite de risco **com prazo de remediação e dono** (e mesmo assim `Critical` de auth/tenant/injeção **não aceita ADR** — é piso da §37).
- `Medium`/`Low` viram issue rastreável com prazo; acumular não é opção.

**Higiene**
- **Pentest roda só contra `dev`/`staging`** (ou alvo autorizado). Scripts destrutivos (`service-kill`, `db-disconnect`) gated por env var explícita (§22.3 chaos). Nunca contra produção sem autorização formal e janela.
- **Evidência sempre.** Todo achado tem request/response reproduzível no `raw.jsonl` — "achei uma falha" sem repro não conta.
- **Falso-positivo é bug do teste.** Pentest que grita sem motivo treina o time a ignorar — calibra ou remove. Mas **na dúvida, FAIL** (vai pra `REVIEW`, olho humano decide), nunca silencia por padrão.

**Escopo mínimo coberto** (mapeia OWASP Top 10 + API Top 10): injeção (SQL/NoSQL/command/template), XSS, validação de tipo e sanitização (§22.3), authz/IDOR/BOLA, broken auth (JWT, sessão, refresh), SSRF, mass assignment, exposição excessiva de dados, misconfig (headers, CORS, paths expostos), rate limiting, e abuso de recurso (payload gigante, ReDoS, billion-laughs).

> Pentest não "tenta hackear pra ver se acha algo". Ele **prova, rota por rota, campo por campo, que o sistema rejeita o que deve rejeitar.** Achado é evidência; ausência de achado só vale se a cobertura for total.

---

### 22.9 Fluxo de execução de Q.A. (plan-first, aprovação obrigatória)

A malha de Q.A. inclui passos potencialmente destrutivos (chaos `service-kill`/`db-disconnect`, pentest, mutações). Por isso **nenhuma submissão de Q.A. roda às cegas**: toda submissão de um formulário/pedido de Q.A. passa por planejamento, aprovação humana e execução controlada.

**MUST — antes de executar qualquer coisa**

1. **Planejar tudo primeiro.** Ao receber a submissão, o agente **não executa nada ainda**. Levanta o escopo completo: quais modos vão rodar (smoke/integration/security/pentest/authz/hardening/chaos/simulated/unit), ambiente alvo, rotas e personas afetadas, ordem de execução, dependências entre passos, o que é **destrutivo/gated**, e os riscos.
2. **Gerar um MD de passo a passo detalhado** em `<project>_archive/qa/<YYYY-MM-DD-HH-MM-SS>-<contexto>.md` (liga com §28 — é archive obrigatório). Cada passo declara: objetivo, comando exato, ambiente, resultado esperado, critério de pass/fail, e flag de **destrutivo** quando aplicável. O plano referencia o `summary.json` (§22.2) que será produzido.
3. **Pedir aprovação explícita do usuário.** Sem aprovação registrada, **nada roda**. O agente apresenta o plano e aguarda o "ok". Aprovação parcial (subconjunto de passos) é válida e vira o escopo efetivo.

**MUST — após aprovado**

4. **Oferecer a modalidade de execução.** O agente pergunta como rodar:
   - **Faseado e assistido** — executa por fase, **pausa entre fases** para revisão/confirmação, mostra resultado parcial e só segue com o "continuar". Default recomendado para staging sensível e para qualquer plano com passo destrutivo.
   - **De uma vez (autônomo)** — executa o plano inteiro sem parar.
5. **No modo "de uma vez":**
   - **Multiagentes para produção da execução** — paralelizar categorias independentes (ex.: `security`, `authz`, `hardening`, `pentest`, `simulated` em workers separados), respeitando dependências declaradas no plano e os limites de concorrência (§9 backpressure).
   - **Cron/watchdog de continuidade ininterrupta** — um agendador supervisiona a execução e a **retoma de checkpoint até concluir**, sem exigir intervenção manual se um worker cair. A "conclusão" é condição de parada explícita: todos os passos aprovados terminaram, **ou** uma falha bloqueante escalou para o humano. Checkpoints são **idempotentes** (§19) e a retomada não reexecuta passo já concluído.

**MUST — segurança do fluxo (herda do resto do §22)**

- Passo destrutivo (`service-kill`, `db-disconnect`, drop, mutação em massa) **só roda se constava no plano aprovado** e com o gate de ambiente ligado (ex.: `<PROJECT>_CHAOS_ALLOW=1` — §22.3). Aprovação do plano não dispensa o gate.
- Modo autônomo "de uma vez" roda por default só em `dev`/`staging`. Produção exige confirmação adicional explícita no momento da execução (alinha com §22.8 — alvo autorizado).
- **Sem retry infinito** no watchdog: a continuidade tem limite de tentativas por passo, backoff, e escala para humano ao estourar (§9, §18). "Ininterrupto até finalizar" é retomar até concluir, **não** repetir pra sempre.

**VETADO**

- Pular o plano ou a aprovação "pra ir mais rápido" — é macaquice na linha da §37 (atalho que troca segurança por velocidade). Q.A. sem plano aprovado registrado **não roda**.

> O plano aprovado é o contrato da execução. Multiagente e cron aceleram o *como*, nunca dispensam o *o quê foi autorizado*.

---

## 23. Makefile Padrão

```bash
make dev              # ambiente local
make test             # unit + integration
make test-unit
make test-integration
make lint
make fmt
make build
make run
make docker
make migrate
make docs             # gera/valida openapi
make security-scan    # sast + sca local
make smoketest
make pentest-light
make ci               # tudo que o CI roda
make clean
```

---

## 24. Qualidade e Git

**Commits:** Conventional Commits.
**Versionamento:** SemVer.

**Branches — trunk-based como padrão**

```
main      → produção (protegida, linear history)

feature/<ticket>-<slug>
fix/<ticket>-<slug>
hotfix/<ticket>-<slug>
```

GitFlow (`develop`) é opcional e exige justificativa — só vale a pena em times com release cadenciado pesado.

**Pull Requests**
- Tamanho alvo: ≤ 400 linhas alteradas.
- ≥ 1 reviewer (≥ 2 para `domain`, schema, segurança).
- **CODEOWNERS obrigatório.**
- CI verde obrigatório.
- Squash merge na `main`.
- **Merge direto na `main` é VETADO.** Force push em branch protegida idem (§37).

---

## 25. Ownership

**MUST**
- Cada serviço tem **owner explícito** (squad ou pessoa).
- `CODEOWNERS` configurado.
- Documentação de **oncall** definida.
- Contato de escalação documentado no README.

---

## 26. Runbooks e Incidentes

### 26.1 Runbooks

**MUST**
- Serviços críticos têm runbook em `/docs/runbook.md`.
- Conteúdo mínimo: como diagnosticar falhas comuns, dashboards relevantes, comandos úteis, como fazer rollback, contatos.
- Incidentes recorrentes atualizam o runbook.

### 26.2 Incidentes

**MUST**
- Postmortem **blameless** para todo incidente Sev1/Sev2.
- RCA (root cause analysis) documentado.
- Ações preventivas rastreáveis (issue/task) com prazo.
- Repositório central de postmortems acessível ao time.

---

## 27. ADR — Architecture Decision Records

Toda decisão arquitetural relevante vira ADR.

```
/docs/adr/
  0001-use-postgresql.md
  0002-adopt-hexagonal-architecture.md
```

Formato MADR. Status: `proposed`, `accepted`, `deprecated`, `superseded by NNNN`.

**Quando criar:** escolha de banco/broker/linguagem, padrão arquitetural, mudança de contrato público, qualquer desvio deste documento (exceto itens VETADO, que não admitem exceção).

---

## 28. Archive de Conversas e Tarefas — INEGOCIÁVEL

> **Esta seção não tem modo "pula pra ir mais rápido".** O archive é parte da entrega, não um extra. Tarefa sem archive = tarefa não feita (§35). Gerar os `.md` é tão obrigatório quanto compilar.

**Princípio:** todo trabalho que produz código, decisão ou mudança de estado **gera registro em Markdown, TODA vez, sem exceção**. Não existe "depois eu documento". O `.md` nasce junto com o trabalho e é commitado junto.

### 28.1 Chat Archive

**MUST — gerar SEMPRE** para conversas/sessões que produzem:
- Decisão arquitetural ou de segurança
- Mudança de contrato público
- Escolha de tecnologia
- Resolução de incidente
- **Qualquer geração de código não trivial** (inclui código assistido por IA — §34)

**SHOULD** para tasks de implementação significativas.
**MAY** para o resto (troca trivial, dúvida pontual).

```
<project>_archive/chat/
  <YYYY-MM-DD-HH-MM-SS>-<contexto>.md
```

Conteúdo mínimo (todos os campos preenchidos, nunca placeholder vazio):
- Pergunta/objetivo original
- Entendimento do problema
- Resposta/decisão tomada
- Alternativas consideradas
- Riscos e trade-offs
- Próximos passos

### 28.2 Task Archive

**MUST — gerar SEMPRE** para toda task de implementação significativa.

```
<project>_archive/task/
  <task-name>.md
```

Conteúdo: contexto, objetivo, checklist, decisões, blockers, progresso. **Atualizar ao fim de cada sessão** — não acumular pra depois.

### 28.3 Garantias de processo

**MUST**
- O archive é **verificável**: PR sem o `.md` correspondente (quando a regra acima exige) **não passa no review** (item de checklist de §35).
- Gerar o archive é passo do fluxo, não tarefa separada que pode ser cortada por falta de tempo. **Falta de tempo não revoga a §28.**
- Assistente de IA que produz código nesta base **gera o `.md` do archive na mesma entrega** — pular isso é violação direta (§37, item 28).

> Registro indiscriminado de toda interação produz ruído. Registro seletivo do que importa produz contexto histórico útil. **Mas "seletivo" é sobre o quê registrar, nunca sobre se registrar quando a regra manda.**

---

## 29. Templates

```
/templates
├── README.md
├── ADR.md
├── TASK.md
├── PR_TEMPLATE.md
├── ISSUE_TEMPLATE.md
├── RUNBOOK.md
├── INDEX_GLOBAL.md       # índice global da aplicação (§39)
├── INDEX_FUNCTIONS.md    # índice de microfunções (§39)
└── OPENAPI_TEMPLATE.yaml
```

README mínimo: o que é, como rodar, como testar, como deployar, dependências, observabilidade, oncall, runbook.

---

## 30. Performance — Metas Padrão

| Métrica | Alvo |
|---|---|
| API p95 | < 300 ms |
| API p99 | < 1 s |
| Startup | < 10 s |
| Imagem Docker | < 200 MB (Go/Rust), < 400 MB (Node) |

Metas específicas sobrescrevem, registradas no `/docs/slo.md`.

---

## 31. Feature Flags

Obrigatório para features críticas, migrações e rollouts graduais.
Capacidades: rollout por % de tráfego, segmentação por tenant/usuário, kill switch, expiração de flag.
Sugestões: Unleash, OpenFeature, GrowthBook.

---

## 32. LGPD e Dados Pessoais

**MUST**
- Classificação de dados: público, interno, confidencial, pessoal, pessoal sensível.
- PII nunca em logs (ver §16.1).
- Política de retenção documentada por tipo de dado.
- Processo para exercício de direitos (acesso, correção, eliminação, portabilidade).
- Criptografia em trânsito (TLS 1.2+) e em repouso para dados pessoais.
- DPIA para tratamentos de alto risco.
- PII **nunca** em query string / URL (acaba em log, histórico, referer) — §37.

---

## 33. FinOps — Gestão de Custos

**SHOULD**
- Monitoramento de custo por serviço/squad/tenant.
- Budgets configurados com alertas de threshold.
- Revisão periódica de overprovisioning (CPU/memória/réplicas).
- Tags de billing consistentes em IaC.
- Custo por request rastreado em serviços de alto volume.

---

## 34. Uso de IA Assistida

**MUST**
- Código gerado por IA passa pelo mesmo PR review humano que qualquer outro.
- Autor humano é responsável: assina o commit, entende o código, mantém.
- Saídas de IA não substituem ADR.
- **IA opera sob a §37 (anti-padrões vetados) integralmente.** Gerar código que viola um item VETADO é defeito, não estilo — rejeita no review.
- **IA gera o archive (§28) junto com o código**, na mesma entrega.

**MUST NOT / VETADO**
- Colar trecho gerado sem ler.
- Aceitar dependências sugeridas sem verificar nome (typosquatting é real — §37).
- Submeter código que não passa em `make ci`.
- Aceitar "solução rápida" da IA que burla um piso de segurança da §37.

**SHOULD**
- Prompt e contexto relevantes registrados no chat archive quando a decisão for não trivial.
- Verificar licença de snippets longos sugeridos.

### 34.1 Handoff de contexto em sessões longas

Sessões longas de agente degradam quando o contexto enche: o modelo "esquece" decisões e a compactação automática resume de forma lossy. Para não perder estado, o handoff é **proativo e arquivado**, não reativo.

**MUST**
- Definir um **limite de handoff** (tokens) abaixo do teto da janela — cedo o suficiente pra sobrar espaço pra escrever o resumo. Sugestão: ~25% da janela (ex.: 250k numa janela de 1M).
- Ao cruzar o limite, **antes de qualquer compactação**, gerar dois artefatos em `<project>_archive/context/`:
  - `<YYYY-MM-DD-HH-MM-SS>-context.md` — estado do projeto, decisões tomadas, arquivos tocados, onde parou.
  - `<YYYY-MM-DD-HH-MM-SS>-checklist.md` — **feito vs. em aberto**.
- Só então compactar/limpar o contexto. O handoff é archive obrigatório (§28) — armazenar **sempre** em `<project>_archive`.
- **Rede de segurança determinística:** um backup do estado é capturado automaticamente antes de toda compactação (manual ou automática), independente de o agente ter lembrado de gerar os MDs acima.

**SHOULD**
- O limite é configurável por ambiente/projeto (ex.: env var), não hardcoded.
- O resumo de contexto preserva o que **você** escolhe (foco na tarefa corrente), não o que a compactação automática adivinha.

> Compactação automática é rede, não plano. Em sessão longa, o handoff arquivado vem antes do teto — quem controla o que sobrevive é você, não o resumo lossy.

---

## 35. Definition of Done

Uma task está pronta quando, cumulativamente:

- [ ] Testes passam (unit + integration), cobertura nos mínimos
- [ ] Caminhos críticos com testes explícitos
- [ ] **Teste emulado por IA (`simulated`, §22.3) executado — 100% das rotas do inventário acessíveis pra quem deve e bloqueadas pra quem não deve; rota fantasma/morta = bloqueio**
- [ ] **Pentest de entrada limpo: sem `500`, sem coerção de tipo, sem eco não-escapado, sem vazamento cross-tenant (§22.3, §22.8)**
- [ ] Lint, fmt, security scan limpos
- [ ] **Nenhum item da §37 (anti-padrões vetados) presente no diff**
- [ ] **Arquivos ≤ 300 linhas (ou quebrados em micro-funções) e toda função com doc-comment de contexto — o quê + onde é usada (§6)**
- [ ] **Índice de funcionalidades atualizado no mesmo PR — global e microfunções (§39)**
- [ ] Observabilidade implementada (logs, métricas, traces, audit se aplicável)
- [ ] OpenAPI atualizada (se for API)
- [ ] Migration testada com rollback (se houver schema change)
- [ ] Documentação atualizada (README, ADR, runbook se aplicável)
- [ ] Smoke tests executados em staging **(com asserção de conteúdo e self-check anti verde-mentiroso — §22.3)**
- [ ] CI verde, code review aprovado
- [ ] **Archive de chat/task gerado e commitado (§28) — gate rígido, não opcional**
- [ ] Feature flag configurada (se aplicável)
- [ ] CODEOWNERS aplicável revisou

> Os itens em negrito são **bloqueantes absolutos**: archive (§28), ausência de macaquice (§37), teste emulado por IA com rota 100% acessível (§22.3), e pentest de entrada limpo (§22.8). Faltando qualquer um, a task **não está pronta** — independente de todo o resto estar verde. Smoke verde não basta: tem que ser smoke que **prova** conteúdo, não só status.

---

## 36. Evolução

- Refactors incrementais. Big-bang rewrite exige ADR e plano de rollback.
- Toda migração de runtime/framework tem flag de coexistência.
- DDD e hexagonal podem ser adotados progressivamente — comece pelas bordas e pelos domínios mais complexos.

---

## 37. Anti-Padrões Vetados — "Macaquices" que Terminam Rápido e Quebram em Produção

> Atalhos que parecem entregar mais rápido e na real entregam vulnerabilidade, vazamento ou dívida. **Todos VETADOS** — não admitem ADR de exceção, são pisos. Aparecem em diff humano ou de IA → o PR para. Cada item traz o **veto** e o **caminho certo**.

### Segredos e exposição

1. **Segredo no bundle do cliente.** API key privada, secret de JWT, senha de banco, service-role key, token de pagamento no código que vai pro browser, ou em `NEXT_PUBLIC_*` / `VITE_*` / `REACT_APP_*`.
   → Segredo **só server-side** (BFF, route handler, secret manager). O navegador não guarda segredo (§13.4, §38).

2. **PII / token / senha em query string ou URL.** Acaba em log de acesso, histórico do browser, header `Referer`.
   → Vai em body ou header apropriado, nunca na URL (§32, §16.1).

3. **`.env` com segredo real commitado**, ou segredo hardcoded "temporário" no código.
   → Secret manager + `.env.example` sem valores. Gitleaks no pipeline (§13).

### Injeção e execução

4. **SQL por concatenação de string** com input externo.
   → Prepared statements / query parametrizada, sempre (§10).

5. **`eval`, `Function()`, `exec`, template string em `child_process`/`os/exec`/shell** com qualquer parte vinda de input.
   → Nunca. Args separados, allowlist de comandos, bibliotecas que não invocam shell.

6. **Desabilitar verificação TLS** (`rejectUnauthorized: false`, `InsecureSkipVerify: true`, `verify=False`) pra "funcionar logo".
   → Cert válido. mTLS interno. Se o cert está errado, conserta o cert.

### Auth e autorização

7. **Auth/authz só no client** (`if (user.isAdmin)` no React decide acesso).
   → Toda decisão de acesso é **server-side** (§15). Front é UX, não controle.

8. **Confiar em `tenant_id` / `role` / `user_id` vindos do body ou header do cliente** sem validar contra o token.
   → Derivar sempre do token verificado, server-side (§15).

9. **JWT decodado sem validar** assinatura, `exp`, `aud`, `iss`, e `alg` contra allowlist (aceitar `alg: none` ou HS256 com pubkey RS256).
   → Validação completa em toda request (§14).

10. **Hash de senha fraco** — MD5, SHA1, sem salt, ou plaintext.
    → bcrypt cost ≥ 12 ou argon2id (§14).

11. **`Math.random()` (ou rand não-cripto) pra token, id de sessão, código de reset, nonce.**
    → CSPRNG: `crypto.randomBytes`, `crypto/rand` (§14).

### CORS, headers e superfície

12. **`Access-Control-Allow-Origin: *` em rota autenticada** (pior ainda com `allow-credentials`).
    → Allowlist explícita de origens (§22.3 hardening).

13. **Endpoint de debug/admin/management sem auth, ou bind em `0.0.0.0`** expondo porta interna.
    → Bind restrito, auth obrigatória, `/debug` e `/actuator` retornam 404 externamente (§22.3).

14. **Mass assignment** — dar bind do body inteiro direto na entidade, deixando passar `is_admin`, `tenant_id`, `created_at`, `password_hash`.
    → Allowlist explícita de campos aceitos por endpoint.

### Erros, tipos e qualidade

15. **Catch que engole erro** — `catch {}`, `except: pass`, `_ = err`, `.catch(() => {})`.
    → Tratar, logar com contexto e `trace_id`, propagar ou degradar de forma consciente.

16. **`// @ts-ignore`, `any`, `interface{}`, `unwrap()`/`panic`/`!` pra calar o compilador/linter.**
    → Tipar de verdade, tratar o caso de erro. Inline-ignore de regra **de segurança** (`nolint`, `eslint-disable security/*`, `# nosec`) é VETADO sem ADR.

17. **Logar request/response inteiro, headers ou body cru "pra debugar".**
    → Logar campos específicos, mascarados. Nunca PII/token/senha (§16.1).

### Testes e cobertura

18. **Pular/comentar teste pra passar o CI** — `.skip`, `t.Skip`, `xit`, `@Ignore`, comentar o `assert`.
    → Conserta o código, não silencia o teste.

19. **Baixar o threshold de cobertura ou editar o gate** pra o número fechar.
    → Cobertura é contrato (§22). Sobe escrevendo teste, não mexendo na régua.

20. **Mockar o próprio sistema sob teste** retornando sucesso fixo, dando "verde" falso.
    → Testar comportamento real; mock só nas bordas externas.

### Dados e migrations

21. **Migration sem `down`, ou destrutiva sem backup** (`DROP`/`ALTER` que perde dado).
    → Reversível, testada com rollback antes do merge (§10).

22. **Cache de resposta autenticada sem chave por usuário/tenant** — um user recebe dado do outro.
    → Chave de cache sempre segmentada por usuário e tenant (§11, §15).

### Operação e entrega

23. **Container root, `chmod 777`, `--privileged`, filesystem RW** "pra funcionar".
    → Não-root, read-only, least-privilege (§13).

24. **Dependência nova sem verificar** nome (typosquatting), manutenção, licença, e sem pin de versão (`latest`, range frouxo).
    → Pin exato, checar nome/manutenção/licença, SCA no pipeline (§13, §34).

25. **Retry infinito / sem backoff/jitter** — DoS no próprio sistema ou no terceiro.
    → Limite explícito + backoff exponencial + jitter (§9, §18).

26. **`Idempotency-Key` aceito mas ignorado** (header existe, lógica não).
    → Implementar de fato a deduplicação (§12).

27. **Dual-write** — gravar no banco e publicar no broker no mesmo fluxo, sem outbox.
    → Transactional Outbox (§9, Anexo B).

28. **Pular o archive/MD "pra ir mais rápido"** (§28).
    → Archive é parte da entrega. Sempre gerado. Tarefa sem archive não está pronta (§35).

29. **Merge direto na `main` / force push em branch protegida / pular o PR e o review.**
    → Trunk-based com PR, CI verde, CODEOWNERS (§24).

30. **Desligar rate limit, validação de payload, ou security scan "temporariamente".**
    → "Temporário" vira permanente. Não se desliga piso de segurança (§12, §13).

31. **Criar serviço backend novo em Node, ou qualquer código novo em PHP.**
    → Backend novo só em Go/Rust; Next.js segue valendo pro frontend. PHP é proibido e migra (§3). Node backend legado segue a regra dos 30% (§3.1).

> Regra de bolso: se a justificativa começa com "só pra funcionar", "depois eu arrumo", ou "é mais rápido assim" e o resultado mexe em segredo, auth, dado, ou registro — **provavelmente é uma macaquice desta lista. Para e faz certo.**

---

## 38. Frontend / NextJS / SPA — Regras Específicas

**MUST**
- **Fronteira clara client/server.** Tudo que toca segredo, banco, ou terceiro com credencial roda **server-side** (route handler, server action, BFF, server component que não serializa segredo pra props).
- Sessão em **cookie `HttpOnly` + `Secure` + `SameSite=Lax|Strict`**. Token de auth **nunca** em `localStorage`/`sessionStorage` (XSS lê tudo lá).
- Variáveis públicas (`NEXT_PUBLIC_*` etc.) contêm **apenas** dado não-sensível (URL de API pública, id de analytics público). Tratar esse prefixo como "vai pro outdoor".
- Validação de input no client é **UX**; a validação que importa é a do servidor (§12). Autorização idem é server-side (§15).
- CSP, `X-Content-Type-Options`, `Referrer-Policy`, `Permissions-Policy` e `frame-ancestors` configurados (§22.3 hardening).
- Chamada a API de terceiro com chave secreta passa por proxy server-side. O browser nunca segura a chave.

**VETADO**
- Service-role key / admin SDK (Supabase, Firebase, etc.) no código do client.
- `dangerouslySetInnerHTML` com conteúdo não sanitizado (XSS).
- Confiar em `redirect`/`next` param sem allowlist (open redirect — §22.3).

> "Bota a senha no NextJS" não existe como solução. Existe como CVE. O front pede ao servidor; o servidor guarda o segredo.

---

## 39. Índice de Funcionalidades (fonte da verdade viva)

O código diz **como** está agora; o índice diz **o que existe, onde mora e como se faz cada coisa** — e é tratado como **fonte da verdade do projeto**, consultado antes de criar algo (pra não duplicar) e atualizado a cada mudança. Índice que apodrece é pior que não ter; por isso ele é gerável/validável e tem gate na DoD.

**MUST — existência e localização**
- Todo projeto mantém o índice versionado em `<project>_archive/index/` (ou `/docs/index/`), em **dois níveis**:
  - **Índice global da aplicação** (`INDEX_GLOBAL.md`) — o mapa macro: repos/serviços/bounded contexts e como se comunicam; a relação de **pastas top-level** de cada repo e a responsabilidade de cada uma; **o que cada coisa faz** e o ponto de entrada de **como se faz** (link pro fluxo/use-case/runbook). É o "mapa do território".
  - **Índice de microfunções** (`INDEX_FUNCTIONS.md`, por serviço) — o catálogo fino: cada função/módulo relevante → **o quê**, **onde é usada/prevista**, dependências e efeitos colaterais. Gerado a partir dos doc-comments obrigatórios (§6).

**MUST — atualização e gate**
- Todo PR que **adiciona, remove ou move** funcionalidade atualiza o índice no mesmo PR. Índice desatualizado **trava o merge** (item da DoD, §35).
- O índice é **fonte da verdade**: ao planejar uma feature, consulte-o primeiro pra não reimplementar o que já existe (anti-duplicação — liga com DRY semântico, §1).
- Formato **machine-friendly** (markdown com tabelas, ou JSON/YAML que renderiza) pra permitir geração e validação automáticas — não prosa solta.

**SHOULD — geração assistida**
- O índice de microfunções é **gerado por script** que varre os doc-comments padronizados (§6) e monta a tabela `função → o quê → onde → arquivo:linha`. CI compara o índice commitado com o gerado; divergência aponta índice ou comentário desatualizado.
- Cada entrada linka pro arquivo/linha de origem.
- Índice global revisado em cada mudança arquitetural (junto com o ADR, §27).

**Conteúdo mínimo**

`INDEX_GLOBAL.md`: lista de repos/serviços com 1 linha de propósito cada; por repo, árvore de pastas top-level com responsabilidade; mapa de comunicação (quem chama quem, quais eventos/contratos); links pra OpenAPI, SLO, runbook.

`INDEX_FUNCTIONS.md`: tabela por módulo — `função | o quê | onde é usada | efeitos | arquivo:linha`.

> O índice responde "isso já existe? onde? como faço X?" sem precisar reler o código. Se a resposta exige caçar no código, o índice falhou — ou está desatualizado, e isso é bug.

---

## Anexo A — Versões Correntes

> Atualizado independentemente do documento principal. Revisão trimestral.

| Stack | Versão alvo (2026-05) |
|---|---|
| Node.js | 24 LTS (frontend: Next.js, Astro, etc. / legado backend em migração — §3) |
| Go | 1.25 |
| Rust | 1.85 |
| PostgreSQL | 16+ |
| Redis | 7+ |
| Kubernetes | 1.30+ |
| OpenAPI | 3.1 |
| OpenTelemetry | 1.x (estável) |

Mudanças de versão major exigem ADR.

---

## Anexo B — Glossário Mínimo

- **Bounded Context** — fronteira explícita dentro da qual um modelo de domínio é consistente.
- **Monólito distribuído** — serviços fisicamente separados mas acoplados por banco compartilhado, shared lib de domínio ou cadeia síncrona sem fronteira. O pior dos dois mundos. Proibido (§2).
- **BFF (Backend for Frontend)** — camada server-side que serve um frontend específico e mantém os segredos fora do browser (§38).
- **Outbox Pattern** — gravar evento em tabela no mesmo commit do dado de negócio; publicador assíncrono lê a tabela e publica no broker. Garante consistência sem dual-write.
- **DLQ** — dead letter queue, fila de mensagens que falharam após retries.
- **Anti-Corruption Layer** — adapter que isola seu domínio do modelo externo.
- **SLO** — service level objective, alvo mensurável de qualidade (ex: 99.9% das requests < 300ms em 30 dias).
- **Error Budget** — quanto você pode falhar dentro do SLO antes de freezar features.
- **Blameless Postmortem** — análise de incidente focada em sistema/processo, não em culpa individual.
- **CSPRNG** — gerador pseudoaleatório criptograficamente seguro. Obrigatório para tokens, ids de sessão e segredos (§14).
- **Macaquice** — atalho que parece entregar mais rápido e entrega vulnerabilidade ou dívida. Catalogadas e vetadas na §37.
