A auditoria: quanto cada app se desvia
Veja quanto cada um dos seis apps adere ao padrão da casa, de 0 a 100. O placar vai de 96 a 43: uma dispersão de 53 pontos.
Score alto não significa app bom: significa app parecido com o padrão. O mypanel tem 43 e mesmo assim é o único com verificação hermética em container descartável. A fonte desta página é a AUDITORIA-ALINHAMENTO.md, na raiz do repositório.
O placar geral#
A tabela completa, do mais alinhado ao menos alinhado:
agent-package — 96render — 80motor — 67load-balance — 63conta-central — 61mypanel — 43A média de cada app vem de cinco dimensões, como estão na auditoria:
| App | Arquitetura | Organização | Soluções | Ferramental | Documentação | Média |
|---|---|---|---|---|---|---|
agent-package | 100 | 94 | 99 | 93 | 97 | 96 |
render | 86 | 88 | 90 | 85 | 50 | 80 |
motor | 66 | 68 | 72 | 58 | 70 | 67 |
load-balance | 77 | 60 | 76 | 56 | 46 | 63 |
conta-central | 81 | 62 | 70 | 70 | 20 | 61 |
mypanel | 33 | 48 | 44 | 33 | 55 | 43 |
A diferença de 2 pontos entre o load-balance (63) e o conta-central (61) é quase toda documentação: 46 contra 20. Nas outras dimensões, o conta-central fica à frente em arquitetura, organização e ferramental, e o load-balance em soluções. Não leia 2 pontos como hierarquia.
Radar mede se você passou do limite daquela via. Não diz se você é bom motorista. O score mede aderência ao padrão, não qualidade.
Antes de modelar um datamart, você roda o profiling: nulos, tipos errados, duplicadas. A auditoria fez isso com o código.
Use o score para priorizar convergência. Nunca para dizer que um app é melhor que outro.
O padrão de casa em duas camadas#
O padrão existe, mas tem duas forças diferentes. Na medição da auditoria, a divisão era esta:
| Camada | O que converge | Quem segue |
|---|---|---|
| Núcleo | Fastify 5, TypeScript strict, pino, zod, shutdown gracioso, migração no boot, Vitest, zero CI | 5 ou 6 de 6 |
| Frente avançada | RFC 9457, ESLint com fronteiras, lint ratchet, coverage-floor, knip, gitleaks, ADRs | só o agent-package e o render |
A casa converge no esqueleto e diverge no rigor. O esqueleto todo mundo tem; as travas automáticas, só o agent-package e o render.
Alguns pontos nem chegaram a virar padrão: o envelope de erro (três formatos entre seis backends), a geração de cliente de API (só 1 de 6) e o casing dos arquivos do backend (4 em kebab-case, 2 em camelCase). Cada projeto resolveu do seu jeito.
As 12 divergências#
A auditoria lista 12 divergências, da mais cara à mais barata de conviver: 4 críticas, 5 altas e 3 médias. A última coluna leva à tarefa que fecha cada uma:
| # | Divergência | Quem afeta | Severidade | Tarefa |
|---|---|---|---|---|
| 1 | Contrato de API copiado à mão em 5 de 6 | todos menos o agent-package | crítica | TB-02, TB-11 |
| 2 | Fronteira rota → serviço → ORM violada em 33 arquivos de rota | conta-central, load-balance, motor, mypanel | crítica | TB-01 (feita) |
| 3 | Backend sem ESLint em 3 de 6 | load-balance, motor, mypanel | crítica | TB-01 (feita) |
| 4 | Documentação ausente, com links mortos ou gate quebrado em 4 de 6 | conta-central, load-balance, render, motor | crítica | TB-03 |
| 5 | Três formatos de envelope de erro convivendo | conta-central, load-balance, motor, mypanel | alta | TB-08 |
| 6 | process.env lido fora de um módulo único em 4 de 6 | conta-central, load-balance, motor, mypanel | alta | TB-07 |
| 7 | Sem piso de cobertura nem detecção de código morto em 4 de 6 | conta-central, load-balance, motor, mypanel | alta | TB-09 |
| 8 | Varredura de segredo e atualização de dependência em 1 de 6 | todos menos o agent-package | alta | TB-04 |
| 9 | Container sem HEALTHCHECK, sem USER ou sem digest em 3 de 6 | load-balance, mypanel, motor | alta | TB-05 |
| 10 | @nomad/ui com 3 pins divergentes e ausente no mypanel | conta-central, load-balance, mypanel | média | TB-06 |
| 11 | Três topologias de repositório convivendo | motor e mypanel fora do padrão; a decisão vale para os 6 | média | TB-10 |
| 12 | features/ ausente em 2 de 6 e kit de UI local fazendo sombra ao @nomad/ui | render, mypanel, conta-central | média | TB-12 |
O fio que liga quase todas é regra escrita sem ferramenta fiscalizando. A fronteira rota → serviço → ORM existia como texto, e sem gate 33 arquivos de rota a violaram: 8 no conta-central, 11 no load-balance, 7 no motor e 7 no mypanel.
Cada garçom copia o cardápio à mão. A cozinha muda um prato e metade dos cardápios fica errada. Contrato manual apodrece igual.
Receita, faturamento e valor em três tabelas: nenhum dashboard fecha sem tratar cada nome à mão. Três envelopes de erro custam o mesmo.
Placa de 60 sem radar não segura ninguém. Regra sem gate automático não segura nenhum projeto.
O que mudou desde a medição#
A auditoria mediu o disco em 2026-10-25, antes do primeiro commit do monorepo. Desde então, 5 pontos mudaram:
| Onde | O que mudou | Tarefa |
|---|---|---|
| Divergência 3 · ESLint no backend | Fechada. Os 3 backends sem lint ganharam ESLint flat e Prettier. | TB-01 (feita) |
| Divergência 2 · fronteira rota → ORM | Medida, ainda não fechada. A regra roda como aviso nos 3 backends novos e lista cada rota que importa o ORM; zerar a lista e promover a regra a erro é o passo seguinte. | TB-01 (feita) |
| Divergência 8 · varredura de segredo | Piorou. O .pre-commit-config.yaml e o .gitleaks.toml que a auditoria contou no agent-package não entraram no monorepo: hoje são 0 de 6. Sem a trava, dois tokens chegaram ao histórico pelo .mcp.json. | TB-04, TB-29 |
| Divergência 4 · documentação | O AGENTS.md do agent-package, com a tabela de gates que a auditoria citava, também não entrou no monorepo, e o backend/README.md dele aponta para o arquivo que falta. | TB-03 |
| Logger do load-balance | O lint novo achou um eval('require') que nunca funcionou em ESM. Trocado por createRequire. | TB-30 (feita) |
O caso do motor em 30 segundos#
O motor trocou as pastas be/ e fe/ por backend/ e frontend/, e cada referência ao nome antigo quebrou junto: os scripts da raiz, os 3 contexts do compose, um import de teste, os testes que liam paths, o gerador do catálogo e o WorkingDirectory do systemd.
O conserto (TB-13) atualizou tudo isso menos o systemd, e um guard novo trava a volta do erro: o teste de Dockerfiles reprova se o backend copiar o frontend (TB-15). Falta rodar o npm run gates com instalação limpa (TB-16) e corrigir o WorkingDirectory dos dois units, no repo e na VPS (TB-17).
A lição cabe numa frase: renomear é fácil; o trabalho é atualizar tudo que apontava para o nome antigo. É igual a renomear coluna no data warehouse sem avisar: o ETL quebra, o dashboard zera e o teste acusa.
Próximos passos#
Você mediu a casa e sabe de onde vem cada divergência. A seguir, veja o trabalho que fecha cada uma.
Explore além: