O PR #983 tirou a `vps-fresh-onboarding.spec.ts` da `FORA_DO_CI` e a pôs
para rodar na `SPECS_PARTE_4` do `e2e.yml` (matrix `parte: [1, 2, 3, 4]`;
o agregador obrigatório `e2e` tem `needs: [e2e-alcance, e2e-parte]`).
Medido em origin/main @ af6730f0f: a `FORA_DO_CI` lista só
`inbox-tempo-real` e `cadastro-sem-confirmacao-de-email`.
Com isso, venceram as afirmações de que a jornada de instalação fresca
segue sem gate e de que `e2e` verde não a prova:
- CLAUDE.md (item `e2e` dos checks obrigatórios): a frase vira histórico
datado e a pergunta passa a ser respondida pelo comando python que o
próprio item já traz, amarrado ao `e2e-cobertura-completa.test.ts`.
- AGENTS.md (Limitações conhecidas): o item carrega o comando que mede a
`FORA_DO_CI` e o histórico em uma frase. Também a linha "`e2e` roda
três partes", que venceu no mesmo PR, vira comando.
- docs/current-state.md §4.1 e docs/harness-audit.md: são retratos
datados, então ganham nota de atualização em vez de reescrita.
A ressalva que continua verdadeira fica escrita em todos: PR que não
alcança o `e2e` (scripts/pr-alcanca-o-e2e.sh) pula as partes, e ali o
verde não prova tela nenhuma.
Só documentação: não muda comportamento para quem opera VPS, então não
leva fragmento em .changes/.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
13 KiB
type, project, status, last_updated, generated_by, confidence, audited_against
| type | project | status | last_updated | generated_by | confidence | audited_against |
|---|---|---|---|---|---|---|
| harness-audit | DeskcommCRM | draft | 2026-07-29 | auditoria documental (Claude Code) — verificação de arquivos, CI e configs | alta (todos os itens verificados por leitura direta de arquivo/config; nenhum comando executado) | origin/main @ 789dfa6 (v1.0.0, 2026-07-29) |
Auditoria do harness — DeskcommCRM
⚠️ ESTE DOCUMENTO É UM RETRATO, NÃO O ESTADO DE HOJE
Ele descreve
origin/mainno commit789dfa6(v1.0.0, 2026-07-29). Os números, contagens e vereditos abaixo conferem contra aquele commit — não contra o que está namainagora. Entre um e outro há 1.014 commits e 71 migrations (medido em 2026-08-14).Nada aqui é mantido. É deliberado, e é a alternativa honesta: um retrato datado nunca mente, enquanto um documento atualizado uma vez volta a mentir na semana seguinte — e sem aviso, porque a atualização recente faz o leitor confiar mais.
Antes de agir sobre qualquer linha, remeça. Uma auditoria de 2026-08-14 encontrou 20 afirmações desatualizadas só neste arquivo — várias dizendo que falta algo que já foi feito. Os comandos de medição de cada uma estão em
audits/2026-08-14-afirmacoes-de-estado.md.Precisa do estado de agora? Meça na fonte. Para o que este documento mais cita:
gh api repos/melgarafael/DeskcommCRM/branches/main/protection \ --jq '.required_status_checks.contexts' # os checks obrigatórios pnpm typecheck && pnpm lint && pnpm lint:channels && pnpm test:unit && pnpm test:shell
"Harness" = a infraestrutura que permite a um humano ou agente instalar, entender, alterar e verificar o projeto com segurança. Um harness fraco não impede o trabalho; ele torna o trabalho não-verificável, e é aí que a regressão entra sem ninguém ver.
Nada aqui foi executado — a auditoria é read-only por instrução. Todos os itens foram verificados por leitura de arquivo, config e workflow.
Nível de maturidade: H4 — Preparado para agentes
| Nível | Veredito | Evidência |
|---|---|---|
| H0 — Não documentado | superado | 119 docs em docs/, README de 302 linhas em 3 idiomas, PRDs, specs, CHANGELOG.md |
| H1 — Documentado | ✅ | README.md, ARCHITECTURE.md, VISION.md, CLAUDE.md, CONTRIBUTING.md, SECURITY.md, CHANGELOG.md (Keep a Changelog + SemVer) |
| H2 — Reproduzível | ✅ | Quickstart no README, docs/SETUP.md, .nvmrc (22), packageManager fixo, pnpm-lock.yaml, docker-compose.yml, install.sh do kit self-host, baseline.sql |
| H3 — Verificável | ✅ | lint + typecheck + test:unit + build; CI roda os 3 primeiros em PR |
| H4 — Preparado para agentes | ✅ | CLAUDE.md doutrinal forte; AGENTS.md criado nesta auditoria; documentação técnica extensa; e o CI roda o gate de isolamento RLS (job invariants → pnpm test:db) |
| H5 — Automação avançada | ⚠️ parcial | CI confiável e ambiente isolado ✅ (Postgres efêmero pg15, worktrees, gov-loop com maker≠checker e hash-check). Falta: 1 das 46 specs E2E fora do CI (45 rodam via e2e.yml, obrigatório desde 2026-08-08; a de fora é vps-fresh-onboarding, que é justamente a P0), format:check fora do CI, e o comando único local (gov:verify) não cobre test:db/test:e2e. (Números recontados em 2026-08-14 @ 741c4ec8; a redação anterior — "4 das 32, não-obrigatório" — apodreceu.) (Nota de 2026-09-19: a vps-fresh-onboarding deixou de estar fora — desde o PR #983 roda na SPECS_PARTE_4. O que fica fora hoje: ver a nota logo abaixo de "O que separa de H5".) |
Por que H4 e não H5: a instrução da auditoria é explícita — não atribuir nível só
porque os arquivos existem, avaliar se o processo está implementado. Aqui está: o gate de
isolamento multi-tenant roda em CI como check nomeado, em job paralelo, aplicando
baseline.sql em modo install e update contra um Postgres descartável. Isso é o
processo funcionando, não a intenção.
O que separa de H5 é estreito: 16 dos 19 E2E não rodam em CI (e2e.yml cobre smoke, auth e error-pages desde 2026-07-30) — de fora seguem
vps-fresh-onboarding.spec.ts, que protege a primeira impressão que a doutrina classifica
como o caminho mais crítico do produto. E pnpm gov:verify, o comando único que um agente
naturalmente usa como critério de pronto, não inclui test:db nem test:e2e: o CI
pega o que ele deixa passar, mas só depois do push.
Nota de 2026-09-19 (PR #983): a
vps-fresh-onboarding.spec.tscitada acima como fora do CI passou a rodar naSPECS_PARTE_4doe2e.yml. Em PR que alcança oe2e(regra emscripts/pr-alcanca-o-e2e.sh), o verde agora cobre a jornada de instalação fresca; em PR que pula as partes, continua não provando tela nenhuma. O parágrafo acima é retrato de antes e fica como está. O que fica fora hoje não se lê deste documento — meça:git show origin/main:.github/workflows/e2e.yml | \ python3 -c "import sys,re; y=sys.stdin.read(); print(sorted({s for _,c in re.findall(r'(FORA_DO_CI):\s*>-\n((?:[ ]{8,}.*\n)+)',y) for s in re.findall(r'[a-z0-9-]+\.spec\.ts',c)}))"
O que puxa este projeto para cima e é incomum num CRM open-source: doutrina escrita e
específica (CLAUDE.md), Definition of Done de 13 itens, 56 arquivos de invariantes de
banco, gate de install+update do baseline.sql num Postgres descartável rodando em CI,
doutrina de QA visual com ambiente fresco estilo VPS, e uma máquina de governança de
agentes (loop/) com maker≠checker e hash-check.
Os 20 itens
Legenda: ✅ existente e funcional · ⚠️ existente mas incompleto · ❌ não identificado · 💡 recomendado
| # | Item | Status | Evidência / lacuna |
|---|---|---|---|
| 1 | README útil | ✅ | 302 linhas: o que é, quickstart de 5 min, stack, estrutura, testes, roadmap, suporte. Traduzido (EN/ES). Mais CHANGELOG.md com aviso de "⚠️ Requer atenção" por versão, voltado a quem roda VPS |
| 2 | Instruções de instalação | ✅ | README §Quickstart + docs/SETUP.md + docs/deploy-selfhost/ + docs/deploy-hostgator/ + install.sh |
| 3 | Versão de runtime definida | ✅ | .nvmrc = 22, engines.node >=22, packageManager: pnpm@9.15.9, e o CI usa setup-node@v7 com Node 22 — alinhados |
| 4 | Lockfile | ✅ | pnpm-lock.yaml, e ambos os jobs do CI usam --frozen-lockfile |
| 5 | .env.example |
⚠️ | Existe (+ .env.hostgator.example), mas 6 vars de lib/env.ts continuam ausentes, entre elas 3 secrets: IMPERSONATE_COOKIE_SECRET, INTERNAL_CRON_SECRET, LGPD_SIGNING_KEY (+ LGPD_DPO_EMAIL, LGPD_EXPORT_EXPIRES_HOURS, NUVEMSHOP_ENABLED) |
| 6 | Comando de desenvolvimento | ✅ | pnpm dev. Nota: docs/testing/ documenta que E2E fresco exige build + start, não dev |
| 7 | Comando de build | ✅ | pnpm build; exercitado no workflow perf.yml |
| 8 | Comando de lint | ✅ | pnpm lint (eslint), roda no CI |
| 9 | Comando de formatação | ✅ | pnpm format / format:check (Prettier). ⚠️ format:check não está no CI |
| 10 | Checagem de tipos | ✅ | pnpm typecheck (tsc --noEmit, TS 6 estrito), roda no CI |
| 11 | Testes unitários | ✅ | 221 arquivos *.test.ts(x); pnpm test:unit no CI |
| 12 | Testes de integração | ✅ | 56 arquivos de invariantes em tests/invariants/ + tests/api/. Excluídos do test:unit de propósito (vitest.config.ts:12) e rodados pelo job invariants do CI via pnpm test:db |
| 13 | Testes E2E | ⚠️ | 20 specs Playwright. 10 rodam no CI (e2e.yml, ainda não-obrigatório), incluindo o P0 vps-webhook-outbound-ssrf; o P0 vps-fresh-onboarding continua fora (issue #63) (Nota de 2026-09-19: desde o PR #983 ela roda na SPECS_PARTE_4 — ver a nota logo abaixo de "O que separa de H5".) |
| 14 | Comando único de verificação | ⚠️ | pnpm gov:verify = typecheck && lint && test:unit. Omite test:db e test:e2e — verde localmente não significa verificado. O CI cobre test:db, mas só depois do push |
| 15 | CI executando verificações | ✅ | ci.yml tem 2 jobs: verify (typecheck + lint + test:unit) e invariants (pnpm test:db — isolamento RLS + invariantes de governança, em job paralelo com timeout de 20min). Falta E2E e format:check. perf.yml faz build + bundle size; publish-image.yml publica no GHCR |
| 16 | Proteção contra secrets | ⚠️ | .gitignore cobre .env* (exceção só para os .example) e o Sentry tem beforeSend que higieniza PII. Sem gitleaks/trufflehog no CI, sem pre-commit hook |
| 17 | Documentação arquitetural | ✅ | ARCHITECTURE.md (1 página) + docs/specs/ (16 docs com schema e payloads) + docs/architecture/agent-turn + graphify-out/ |
| 18 | Regras para agentes de IA | ✅ | CLAUDE.md doutrinal (convenções não-negociáveis, anti-patterns, doutrinas de migration/QA/branch), .claude/agents/ com frota especializada, loop/ com maker≠checker. AGENTS.md criado nesta auditoria — antes, agentes não-Claude entravam sem contexto |
| 19 | Critérios de conclusão de tarefa | ✅ | Definition of Done de 13 itens em CLAUDE.md; docs/doctrine/sistema-vivo.md com o Living System Checklist; template de PR com o checklist |
| 20 | Ambiente reproduzível | ✅ | docker-compose.yml (dev), .prod.yml, Dockerfile + Dockerfile.worker, baseline.sql auto-curativo cobrindo até a migration 0092, scripts/test-db.sh com Postgres efêmero pg15 rodando em CI. ⚠️ A receita de ambiente fresco tem armadilhas que só existem em doc (node_modules real e não symlink, fora de /tmp) — reproduzível, mas com conhecimento tácito |
Plano de correção, por relação custo × benefício
Ordenado por retorno. Nada aqui foi aplicado — a auditoria não altera CI, package.json
nem código.
✅ JÁ FEITO — pnpm test:db no CI
Era o achado principal da primeira passada desta auditoria, e estava desatualizado:
origin/main já traz o job invariants no ci.yml rodando pnpm test:db em paralelo ao
verify, com timeout de 20min e comentário explicando a escolha do job separado. Fica
registrado como corrigido, não como pendência.
1. Adicionar os E2E ao CI (ou a um workflow nightly) 🔴 · custo: ~30 linhas
Maior buraco restante. vps-fresh-onboarding.spec.ts protege a primeira impressão, que a
doutrina classifica como o caminho mais crítico do produto, e
vps-webhook-outbound-ssrf.spec.ts é a única prova automatizada do guard de SSRF. Rodar
em PR pode ser lento; um workflow nightly + trigger manual já elimina a regressão silenciosa.
Nota de 2026-09-19: as duas specs que este item cita entraram no CI obrigatório, em PR — não num nightly: a
vps-webhook-outbound-ssrf.spec.tsentrou antes (item 13 da tabela acima), e avps-fresh-onboarding.spec.tsentrou no PR #983, naSPECS_PARTE_4. O que ainda fica fora: ver a nota logo abaixo de "O que separa de H5".
2. Renomear/reforçar o comando único 🟠 · custo: 2 linhas
Duas opções: (a) gov:verify passa a incluir test:db (exige Docker em toda máquina de
dev), ou (b) mantém gov:verify como o loop rápido e cria verify:full =
gov:verify && test:db, com AGENTS.md e o DoD apontando para verify:full como
critério de merge. Recomendo (b) — preserva o loop rápido e torna a diferença explícita.
3. Completar .env.example 🟠 · custo: 6 linhas
As 6 vars ausentes, com comentário sobre quais são obrigatórias. Os 3 secrets são o caso grave: quem instala não sabe que precisa gerá-los.
4. Adicionar scan de secret no CI 🟡 · custo: ~10 linhas
gitleaks como step. Projeto open-source com screenshots de evidência sendo commitados
tem risco real de vazamento acidental.
5. format:check no CI 🟡 · custo: 2 linhas
O script existe e não é exercitado.
Não pôde ser confirmado
- Se
typecheck/lint/test:unitpassam hoje — onode_modulesdeste checkout está incompleto (70 pacotes, semtypescript) e a auditoria não instala dependências. Todo status "✅" nos itens 8, 10, 11 e 12 refere-se à existência e configuração do comando e do job de CI, não a uma execução verde observada. - Taxa de sucesso histórica do CI — não consultamos a API do GitHub Actions. Sabemos que o
job
invariantsexiste; não sabemos se está passando. - Cobertura de teste em % — configurada no Vitest (
provider: v8), nunca coletada aqui. - Se as branch protection rules do GitHub exigem os dois checks verdes para merge — é config de repositório remoto, invisível no checkout. Isso decide se o gate de RLS é bloqueante ou apenas informativo, e é a pergunta mais importante em aberto sobre o harness.
Nota de método
A primeira passada desta auditoria rodou contra um checkout local 556 commits atrás da
origin/main, e por isso reportou "gate de RLS fora do CI" como achado principal — quando
já estava corrigido em produção. Os números e vereditos acima foram todos recontados contra
origin/main @ 789dfa6. Registrado aqui porque a doutrina de higiene de branches
(CLAUDE.md) existe exatamente para evitar isso: git fetch antes de auditar, não depois.