Backend do Desafio 1 do Hackathon Construtech 2026 (PBQP-H / NBR 15575).
Fecha o ciclo: câmera detecta → engenheiro tria → nasce a Não Conformidade → ação corretiva → verificação por outro engenheiro → painel de conformidade, com evidência hasheada e norma no meio.
NestJS 12 · TypeScript 6 · ESM puro · TypeORM 1 · PostgreSQL 18
Requer apenas Docker.
docker compose up -d --buildIsso sobe o Postgres, espera ficar saudável, roda as migrations num container efêmero e só então sobe a API.
docker compose --profile seed run --rm seedPopula os dados da demo. A API fica em http://localhost:3000 e o Swagger em http://localhost:3000/docs.
| Comando | O que faz |
|---|---|
npm run docker:up |
build + sobe tudo |
npm run docker:seed |
popula os dados da demo |
npm run docker:logs |
acompanha o log da API |
npm run docker:down |
derruba (mantém o volume do banco) |
npm run docker:reset |
derruba apagando o volume e sobe do zero |
Usuários do seed (senha única perceptra123):
| Papel | |
|---|---|
gestora@perceptra.dev |
GESTOR |
ana@perceptra.dev |
ENGENHEIRO — executou a ação da NC resolvida |
bruno@perceptra.dev |
ENGENHEIRO — verificou a ação da Ana |
Ana e Bruno são pessoas diferentes de propósito: é essa separação que a demonstração da segregação de função usa.
O .env já aponta para o Postgres do container em localhost:5432, então dá para rodar a API na máquina com hot-reload e o banco no Docker:
docker compose up -d postgresnpm run start:devnpm test149 testes, sem precisar de banco nenhum: as invariantes do schema rodam contra as migrations reais num PostgreSQL 18 em processo (PGlite). Funciona em qualquer máquina e no CI.
npm run test:e2e132 testes que sobem a aplicação inteira contra o Postgres do container: ciclo da qualidade, ingestão de dispositivo, relatórios, painel e cadastros. Usa o banco qualidade_obra_test, nunca o de desenvolvimento — a suíte trunca tabelas. Crie-o uma vez:
docker compose exec postgres psql -U perceptra -d postgres -c "CREATE DATABASE qualidade_obra_test OWNER perceptra;"docker compose run --rm -e DATABASE_URL="postgresql://perceptra:perceptra@postgres:5432/qualidade_obra_test" migracaoTrês coisas que, se ignoradas, destroem trabalho silenciosamente:
- Nunca
synchronize: trueno TypeORM. Ele apaga CHECK, trigger e índice parcial sem avisar — e é neles que moram as invariantes do MER (segregação de função, imutabilidade da evidência, prazo por severidade). - Nunca adicione plugin esbuild/swc ao Vitest. O pipeline atual (Oxc) emite
emitDecoratorMetadatacorretamente; o esbuild não. Trocar quebra toda a injeção de dependência de uma vez, em todos os testes. - Nunca use glob de entities (
entities: ['dist/**/*.entity.js']). Sob ESM no Windows o caminho viraD:\...e o loader do Node rejeita, lendoD:como protocolo. UseautoLoadEntities: truee a lista explícita emsrc/database/entidades.ts.
Outras convenções que o código assume:
- Todo import relativo termina em
.js, mesmo apontando para um.ts(exigência domoduleResolution: nodenext). Arquivos gerados pornest gvêm sem — rodenpm run typecheckdepois. - Sem barrel files (
index.ts) emsrc/. Sob ESM um barril transforma ciclo de tipo, inofensivo, em ciclo de runtime com TDZ. - Portas de injeção (
ArmazenamentoPort) sãoabstract class, nuncainterface: interface some no emit e o Nest não resolve o provider. - Nenhum arquivo de
src/lêprocess.envdireto, exceto os factories deregisterAse odata-source.ts(que roda fora do Nest).
Rodam contra o build, não contra .ts — o typeorm-ts-node-esm depende de um ts-node que não conhece TypeScript 6 nem os loader hooks do Node 24.
npm run db:migrateAs migrations são escritas à mão. migration:generate não produz CHECK, trigger, índice parcial nem FK com política de delete — que é justamente o que carrega as regras de negócio aqui.
src/
├─ config/ validação de env no boot (falha subindo, não na 1ª request)
├─ database/ DataSource, migrations, seed, mapeador de erro do Postgres
├─ shared/ contrato de erro, pipes, interceptors, middlewares
├─ armazenamento/ porta de storage (S3/R2 e disco local)
├─ auth/ JWT + guards de papel
├─ identidade/ usuario
├─ obras/ obra + local
├─ catalogo-ia/ modelo_ia + camera
├─ ingestao/ deteccao (lote) + triagem
├─ normas/ requisito_norma
├─ qualidade/ NÚCLEO — NC, ação corretiva, verificação, domínio puro
├─ evidencias/ upload, SHA-256 em streaming, cadeia de custódia
├─ relatorios/ relatório PBQP-H
├─ painel/ indicadores (read model)
└─ health/ liveness e readiness
O domínio em src/qualidade/dominio/ é puro: sem Nest, sem TypeORM, sem I/O. A máquina de estados da NC e a segregação de função são funções testáveis em milissegundos.