Skip to content

test: testes automatizados das rotas criticas - #28

Merged
janeiaraujo merged 1 commit into
mainfrom
test/rotas-criticas
Aug 3, 2026
Merged

test: testes automatizados das rotas criticas#28
janeiaraujo merged 1 commit into
mainfrom
test/rotas-criticas

Conversation

@janeiaraujo

Copy link
Copy Markdown
Owner

O problema

Só existia o smoke test, que valida "sobe e responde" — não valida comportamento. Com contribuidores externos mexendo em código que o mantenedor não escreveu, isso é risco real de regressão silenciosa.

O que entra

25 testes com node:test (built-in do Node 22, sem dependência nova), que não precisam de banco — rodam em qualquer ambiente e no CI antes do Mongo subir:

Arquivo Cobre
rbac.test.js Matriz de permissões por papel, incluindo o caso perigoso de permissão desconhecida/typo, que precisa negar e não liberar
auth-service.test.js Bloqueio por tentativas e recuperação de senha (não enumera contas, token só como hash, uso único, destrava a conta)
tenant-isolation.test.js Varredura que acusa consulta a coleção de tenant sem tenant_id no filtro

Sobre a varredura de tenant

Esse é o ponto mais interessante — e o que mais me fez trabalhar.

A primeira versão acusou 25 casos, mas a maioria era falso positivo do meu próprio extrator de argumento: filtro montado em variável (const baseMatch = { tenant_id }), filtro multi-linha, e indireção via filterKBsByAccess(). Um teste que grita à toa é pior que teste nenhum — alguém acaba desligando. Corrigi o detector e adicionei 7 testes do próprio detector, porque um detector quebrado passaria sempre e daria falsa segurança.

Sobraram 19 casos reais: consultas por _id/created_by sem tenant_id. Não vazam leitura hoje (o id costuma vir de um documento já filtrado por tenant), mas falta defesa em profundidade — um id de outra organização chegando pela URL seria aceito. Exemplo em review.routes.js:110:

await db.collection('records').updateOne({ _id: new ObjectId(recordId) }, { ... })

Não corrigi os 19 em lote, e essa foi uma decisão consciente: sem Mongo acessível daqui, eu não teria como verificar que adicionar o filtro não quebra funcionalidade legítima em Gamificação/GPS. Congelei no padrão catraca (KNOWN_GAPS): o teste passa com os conhecidos e falha em qualquer novo. Devem sair um por vez, com teste manual.

Isso rende uma boa leva de good first issue — que era justamente o que faltava no PR #22.

Um achado no caminho

O teste do reset de senha revelou um detalhe do próprio código: o token é reivindicado com updateOne condicional + checagem de modifiedCount (proteção contra corrida — duas requisições simultâneas não podem usar o mesmo link). Meu stub não modelava isso e o teste falhou, corretamente. O stub agora modela.

Test plan

  • npm test → 25 passam
  • Detector de tenant validado com 7 testes próprios (acusa e aceita os casos certos)
  • YAML do CI validado
  • Confirmar que o job de unit tests aparece verde no CI deste PR

So existia o smoke test, que valida "sobe e responde" - nao valida
comportamento. Com contribuidores externos mexendo em codigo que o
mantenedor nao escreveu, isso e risco real de regressao silenciosa.

25 testes com node:test (built-in do Node 22, sem dependencia nova),
sem precisar de banco - rodam em qualquer ambiente e no CI antes do
Mongo subir:

- rbac: matriz de permissoes. Cobre o caso perigoso de permissao
  desconhecida/typo, que precisa NEGAR e nao liberar.
- auth-service: bloqueio por tentativas (inclusive que o bloqueio
  responde 429 e nao 401, senao a UI diz "senha invalida" para uma
  conta travada) e recuperacao de senha (nao enumera contas, token so
  como hash, uso unico, destrava a conta).
- tenant-isolation: varredura estatica que acusa consulta a colecao de
  tenant sem tenant_id no filtro - o "ponto mais sensivel do projeto"
  segundo o CONTRIBUTING.

Sobre a varredura: a primeira versao acusou 25 casos, mas a maioria
era falso positivo do meu extrator de argumento (filtro em variavel,
filtro multi-linha, indireção via filterKBsByAccess). Corrigido, e com
7 testes do proprio detector - um detector quebrado passaria sempre e
daria falsa seguranca.

Sobraram 19 casos reais: consultas por _id/created_by sem tenant_id.
Nao vazam leitura hoje (o id costuma vir de documento ja filtrado), mas
falta defesa em profundidade. Congelei no padrao catraca (KNOWN_GAPS):
o teste passa com os conhecidos e falha em QUALQUER novo. Corrigir 19
em lote sem poder testar contra o Mongo seria arriscado; devem sair um
por vez, com teste manual.

O teste do reset de senha achou um detalhe do proprio codigo: o token e
reivindicado com updateOne condicional e checagem de modifiedCount
(protecao contra corrida). O stub agora modela isso.
Copilot AI review requested due to automatic review settings August 3, 2026 18:43
@janeiaraujo
janeiaraujo merged commit 06b652c into main Aug 3, 2026
4 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a first set of automated unit tests (Node 22 node:test) focused on critical backend security/behavior guarantees (RBAC, auth hardening, and multi-tenant isolation), and wires them into the backend CI pipeline so they run before Mongo-dependent steps.

Changes:

  • Adds unit tests for RBAC permission matrix and auth flows (login lockout + password reset properties).
  • Adds a static “tenant isolation” guard test that scans module queries and blocks new unscoped tenant collection access (ratchet via KNOWN_GAPS).
  • Updates backend npm test to run unit tests and updates CI + contributing docs accordingly.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
CONTRIBUTING.md Updates contributor guidance to run unit + smoke tests and documents the tenant isolation guard behavior.
backend/tests/tenant-isolation.test.js Adds static tenant query scanner + self-tests for the scanner + ratchet list for known gaps.
backend/tests/rbac.test.js Adds unit tests locking down RBAC permission expectations and default-deny behavior.
backend/tests/auth-service.test.js Adds unit tests for login lockout and password reset security properties using a Mongo stub.
backend/package.json Switches npm test to run the unit test suite via node --test.
.github/workflows/ci.yml Runs unit tests before DB setup/seed + smoke test in the backend CI job.
Suppressed comments (1)

backend/tests/auth-service.test.js:57

  • O stub de updateMany() marca TODOS os tokens como used = true e ignora o filtro/update recebidos. Isso diverge do comportamento real do Mongo (e do proprio requestPasswordReset()), podendo mascarar bugs ou quebrar testes futuros que dependam do estado dos tokens.
        updateMany: async () => { store.tokens.forEach(t => { t.used = true; }); return {}; }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return store.tokens.find(t =>
t.token_hash === q.token_hash && t.used === false && t.expires_at > new Date()) || null;
},
insertOne: async (doc) => { if (name !== 'users') store.tokens.push(doc); return { insertedId: 'x' }; },
Comment on lines +155 to +162
let match;
while ((match = pattern.exec(source)) !== null) {
const [, collection, method] = match;
const arg = extractFirstArgument(source, pattern.lastIndex);

// Filtro literal com tenant_id, ou variavel/spread de filtro que ja o carrega
const mentionsTenant = /tenant_id/.test(arg);
const usesScopedVar = [...scopedVars].some(v => new RegExp(`\\b${v}\\b`).test(arg));
@janeiaraujo
janeiaraujo deleted the test/rotas-criticas branch August 3, 2026 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants