← Módulo
Módulo 2 · Ciclo Comum · IN02

Baseline de Qualidade — IN02

Piso mínimo exigido em todas as entregas, do Artefato 1 ao Artefato 5. Não é rubrica de nota — é o que precisa estar presente para que a entrega seja sequer considerada.

← Voltar ao Módulo

Este documento define o piso de qualidade exigido em todas as entregas da disciplina, do Artefato 1 ao Artefato 5. Não é rubrica de nota — é o mínimo aceitável para que a entrega seja considerada válida. Entregas que não cumprirem este baseline podem ser devolvidas sem correção de mérito.

A lógica é simples: o aluno está aqui para aprender a construir software do zero, não para orquestrar ferramentas que escondem o que ele deveria estar entendendo. Cada critério abaixo existe para forçar contato direto com o problema.

Sobre uso de IA: é esperado e aceito como apoio na produção dos artefatos. Mas os critérios deste documento são baseline técnico — erros como senha em texto plano, .env commitado, stack trace vazando para o cliente ou código que o aluno não sabe explicar não são mitigados pelo uso de IA. A responsabilidade permanece integralmente do aluno, e o uso de IA eleva a expectativa de que o baseline seja atendido — não reduz.

1. Linguagem e escrita

  • Português impecável em toda a documentação: artefatos, README, commits, comentários, mensagens de erro, issues, PRs.
  • Sem erros de ortografia, concordância ou pontuação. Use revisor de texto antes de submeter.
  • Sem traduções automáticas mal revisadas (não escreva em inglês e traduza via IA — escreva em português direto).
  • Sem jargão inflado, sem "slop" de IA generativa (frases genéricas, listas infladas, conclusões vazias). Se foi escrito por IA sem revisão, reescreva.
  • Termos técnicos consagrados permanecem no original (ex.: endpoint, primary key, hash, middleware), grafados em itálico ou inline code quando fizer sentido.
  • Voz ativa, frases curtas, um parágrafo por ideia.

2. Notação e diagramas

  • Use a notação correta da ferramenta proposta. UML é UML (OMG), ER é ER (Chen ou Crow's Foot, consistente), BPMN é BPMN. Não misture.
  • Diagrama de casos de uso: atores como boneco, casos como elipse, <<include>> e <<extend>> com semântica correta (a maioria dos alunos usa invertido — não faça isso).
  • Diagrama de classes: diferencie associação, agregação (losango vazio), composição (losango cheio) e herança (triângulo vazio). Multiplicidade explícita em toda associação.
  • Diagrama de sequência: linha de vida vertical, ativação correta, mensagens síncronas vs. assíncronas diferenciadas, retornos tracejados.
  • DER: cardinalidade explícita em ambos os lados da relação, PK/FK identificados.
  • Ferramentas aceitas: draw.io, Mermaid, PlantUML, Lucidchart. Fotos de quadro/papel só se absolutamente legíveis. Nada de "diagrama a mão livre no Paint".
  • Todo diagrama tem título e legenda. Se precisa explicar o diagrama em texto corrido para ele fazer sentido, o diagrama está errado.
  • Referência obrigatória de notação para casos de uso: suporte/use-case_3.0_v1.0.pdf.

Evolução da modelagem estática e dinâmica

A partir da Sprint 3, espera-se ver evolução visível da modelagem estática e dinâmica a cada entrega — não basta repetir os diagramas da sprint anterior sem mudança.

  • Modelagem estática (diagrama de classes, DER, modelo lógico/físico, arquitetura de componentes): deve refletir novas entidades, atributos, relacionamentos, responsabilidades e refinamentos introduzidos pela iteração atual.
  • Modelagem dinâmica (diagrama de sequência, atividade, estados, fluxos de comunicação): deve representar os novos endpoints, interações cliente-servidor, regras de negócio e cenários implementados naquela sprint.
  • Cada entrega deve justificar as mudanças em relação à sprint anterior (o que foi adicionado, removido, refinado e por quê). Diagramas idênticos entre sprints indicam ausência de evolução de modelagem — o que, na prática, invalida o artefato.

3. Código

  • Código bom se lê sem auxílio. Nomes de variáveis, funções e classes devem explicar a intenção. x, data, temp, aux, handle são proibidos fora de escopo trivial (ex.: índice de loop).
  • Sem comentários descritivos do tipo // cria usuário antes de createUser(...). Se precisa desse comentário, o nome está ruim.
  • Comentários permitidos apenas em três situações:
    1. Explicar por que algo foi feito de forma não-óbvia (workaround, decisão de trade-off, restrição externa).
    2. Cabeçalho de classe ou módulo descrevendo responsabilidade e contexto (curto, 2–4 linhas).
    3. Trecho genuinamente complexo (algoritmo não trivial, regra de negócio densa) — e mesmo aí, prefira refatorar.
  • Funções curtas, responsabilidade única. Método de Service com mais de ~20 linhas é sinal de que precisa ser quebrado.
  • Sem código morto, sem console.log esquecido, sem TODO sem issue associada, sem imports não usados.
  • Logging estruturado a partir da Sprint 4: console.log/console.error no código entregue são proibidos. Usar logger configurável (pino, winston ou equivalente) com níveis (info, warn, error), formato JSON em produção e nível controlado por variável de ambiente. Debug local pode usar console, mas não pode sobreviver ao commit.
  • Indentação e formatação consistentes. Use formatador (Prettier, equivalente) configurado no projeto.
  • Sem duplicação: três linhas iguais repetidas viram função. Mas não crie abstração para uso único.
  • Tratamento de erro nas fronteiras (entrada de API, I/O, rede). Não espalhe try/catch defensivo em código interno que não pode falhar.

4. Persistência e banco de dados

  • Proibido o uso de ORM: Sequelize, Prisma, TypeORM, Mongoose, Eloquent, Hibernate, Active Record, etc. O aluno escreve SQL cru via driver nativo (pg, mysql2, better-sqlite3, sqlite3).
  • Proibido query builder: Knex, Drizzle, Kysely, MikroORM no modo query builder, ou qualquer camada que gere SQL por encadeamento de métodos. Sem exceções — nem para conexão, nem para migration, nem para queries. O acesso ao banco acontece sempre via driver nativo.
  • Migrations em SQL puro e versionado: arquivos .sql numerados (001_create_users.sql, 002_add_sessions.sql), aplicados em ordem explícita. Duas formas aceitas:
    1. Script próprio do aluno (Node.js ~40 linhas) que lê a pasta, executa via driver nativo e registra o estado em uma tabela _migrations(filename, applied_at).
    2. Ferramenta que leia .sql cru sem camada de abstração (ex.: node-pg-migrate em modo SQL, postgrator). Ferramentas cuja migration é escrita em JS/TS com DSL próprio (Knex migrations, Prisma migrate) estão fora.
  • Nada de "sync automático do schema". O estado do banco é sempre resultado de migrations aplicadas em ordem.
  • Modelo físico escrito à mão, revisado contra o DER. Constraints explícitas (NOT NULL, UNIQUE, FOREIGN KEY, CHECK).
  • Consultas principais formalizadas logicamente (Sprint 2): o aluno deve conseguir explicar a consulta em álgebra relacional ou cálculo, não só copiar-colar.
  • Senhas, tokens e dados sensíveis nunca armazenados em texto plano. Ver seção 5.
  • Sem dados de produção no repositório. Seeds usam dados fictícios. .env.example sim, .env não.

5. Autenticação, autorização e segurança

  • Construir autenticação do zero. Proibido passport, auth0, firebase-auth, next-auth, clerk, supabase-auth, bibliotecas prontas de sessão completa. O aluno precisa entender o que está fazendo.
  • Hash de senha com bcrypt (ou argon2/scrypt) — parâmetros de custo explícitos e justificados.
    Reprovação imediata

    Senha em texto plano no banco é reprovação imediata do artefato.

  • Sessão por session id persistido em tabela própria, com expiração. JWT só é aceito se o aluno souber explicar por que escolheu e souber os trade-offs (stateless, não-revogável, payload exposto) — e a justificativa deve estar documentada explicitamente na seção de decisões arquiteturais do artefato, não no README nem implícita no código.
  • Autorização por rota e por operação, baseada no perfil do usuário autenticado. Verificação no backend — nunca confiar no frontend.
  • Validação de entrada em toda rota: tipos, obrigatoriedade, tamanho, formato. Inputs inválidos retornam 400/422, não 500.
  • Nenhum campo de senha/hash/token retornado em resposta de API. Nunca. Inspecionar JSON nos testes.
  • Proteção contra SQL injection: sempre prepared statements / parameterized queries. Nunca concatenar string com input do usuário.
  • Segredos fora do código: variáveis de ambiente. .env em .gitignore. Repositório com credenciais exposta = entrega inválida.
  • CORS configurado com origens explícitas. Access-Control-Allow-Origin: * em API que autentica usuários é falha de baseline. Liste os hosts permitidos explicitamente (ambientes de dev e produção separados) e restrinja métodos/headers ao mínimo necessário.
  • Headers HTTP de segurança: X-Content-Type-Options: nosniff, X-Frame-Options: DENY (ou SAMEORIGIN com justificativa) e um Content-Security-Policy mínimo. Middleware como helmet é aceito — a configuração é o que importa, não a origem.
  • Rate limiting no login a partir da Sprint 4: limite por IP e/ou identificador (e-mail), com resposta 429 Too Many Requests quando excedido. Implementação em memória já atende ao baseline; a ausência total de limite é falha.

6. Testes

  • Jest + Supertest, conforme combinado em aula. Setup e teardown de banco configurados.
  • Padrão AAA (Arrange, Act, Assert) visível em todo teste.
  • Pelo menos um teste por regra de negócio (RN) a partir da Sprint 3. RN sem teste = RN não implementada.
  • Testes determinísticos: não dependem de ordem de execução, de relógio do sistema, de rede externa, de dados residuais.
  • Cobertura cobrada apenas na Sprint 4, restrita à camada de Service: mínimo ≥80%, medido com npm test -- --coverage e relatório versionado como evidência. Sprints anteriores não são cobradas em cobertura, e as demais camadas (Controller, Repository, Model, utilitários) também não têm meta — não serão cobradas em nenhuma sprint.
  • Análise de complexidade ciclomática e linters de boas práticas (ex.: ESLint com regras de complexidade, SonarLint, eslint-plugin-sonarjs) são cobrados apenas a partir da Sprint 4. Relatórios e configurações devem estar versionados no repositório.

Estratégia de teste por camada

  • Service — testes unitários white-box (conhecem a implementação, cobrem ramos, exceções, regras de negócio). É aqui que mora a regra de negócio e é aqui que se cobra cobertura.
  • Controller — apenas testes black-box end-to-end (E2E): o teste envia uma requisição HTTP via Supertest e verifica a resposta (status, body, efeito observável). Não se testa a "implementação" do controller — testa-se o contrato.
  • Repository / camada de dados — sem cobrança de cobertura. Testes opcionais quando houver lógica não-trivial de query.
Mock de banco

Mock de banco é aceito nesta fase do curso — ainda não cobramos Docker nem banco de teste isolado. O aluno pode mockar o Repository ou a camada de acesso a dados nos testes unitários de Service. Mock/stub/fake/spy usados com intenção clara (documentada no teste) e não por preguiça. Quando usar SQLite em memória ou banco real disponível, melhor — mas não é obrigatório.

  • Casos negativos obrigatórios: validação falha, recurso não encontrado, regra violada, conflito (409). Não teste só o caminho feliz.

7. API e contratos

  • REST com status codes corretos: 200, 201, 204, 400, 401, 403, 404, 409, 422, 500. 500 só para erro genuíno do servidor — nunca para validação.
  • Contrato documentado: método, rota, parâmetros, body, resposta de sucesso, respostas de erro com formato.
  • Respostas de erro com corpo consistente ({ "mensagem": "..." } ou equivalente), legível ao usuário final.
  • Nenhum detalhe interno vaza em resposta de erro. Stack traces, mensagens brutas de driver de banco, caminhos absolutos de arquivo, nomes de tabela/coluna e versão de framework nunca chegam ao cliente. A mensagem pública é genérica; o detalhe técnico vai para o log do servidor (via logger estruturado, seção 3).
  • Convenção REST consistente: substantivos no plural para recursos, verbos HTTP com semântica correta (GET não muta estado).
  • Idempotência respeitada em PUT e DELETE. POST não idempotente é esperado.

8. Frontend (a partir da Sprint 4)

  • Sem framework de UI que resolva tudo pronto (Material-UI full-template, Tailwind-UI copy-paste sem entender). Componentes e estilos construídos pelo aluno. Tailwind/CSS puro/CSS Modules são aceitos.
  • Estados de requisição explícitos: loading, success, error. Tela que trava em branco durante fetch = entrega inválida.
  • 10 heurísticas de Nielsen verificadas nas telas principais.
  • Sem uso direto do localStorage para token sem justificativa — entender os riscos (XSS).
  • Acessibilidade mínima: label em inputs, contraste legível, navegação por teclado nas ações principais.

9. Git e colaboração

  • Commits atômicos, mensagem no imperativo em português ("adiciona endpoint de login", não "adicionando" nem "added login endpoint").
  • Conventional Commits obrigatório (conventionalcommits.org). Formato: <tipo>(<escopo opcional>): <descrição>.
    • Tipos aceitos: feat, fix, docs, style, refactor, test, chore, build, ci, perf, revert.
    • Exemplos válidos: feat(auth): adiciona endpoint de login, fix(db): corrige constraint de e-mail único, docs(sprint-01): atualiza matriz de rastreabilidade, test(service): cobre RN03 de estoque negativo.
    • Breaking change sinalizado com ! após o tipo/escopo ou rodapé BREAKING CHANGE:.
  • Sem commits do tipo "wip", "ajustes", "fix" (sem descrição), "teste", "aa", "ok". Descrição explica a mudança.
  • Branches nomeadas por feature/sprint (sprint-03/endpoint-login), não main-afonso-2.
  • Sem binários pesados no histórico (datasets, vídeos, PDFs acima de ~5MB sem justificativa). Use .gitignore.
  • README atualizado a cada sprint com instruções reais de instalação, execução e teste. Se o avaliador não consegue rodar seguindo o README, a entrega está quebrada.

10. Dependências e autoria

  • Dependências justificadas. Cada pacote em package.json deve ter razão de existir. Adicionar lodash para usar lodash.isEmpty é desnecessário.
  • Stdlib antes de biblioteca: fetch nativo, crypto nativo, fs/promises nativo. Só adicione biblioteca quando o custo de escrever for claramente maior que o benefício pedagógico.
  • Autoria real. Uso de IA para apoio é esperado, mas o aluno responde pelo código: precisa saber explicar linha por linha o que entregou. Se não consegue explicar, o artefato não foi feito por você.
  • Sem código copiado de colega sem atribuição explícita e sem compreensão. Isso é desonestidade acadêmica.

11. RNFs, rastreabilidade e os 8 eixos

  • Os 8 eixos (USAB, CONF, DES, SUP, SEG, CAP, REST, ORG) aparecem em TODOS os artefatos, evoluindo do conceitual (Sprint 1) ao técnico mensurável (Sprint 5).
  • Todo RNF é verificável. Frases como "o sistema deve ser rápido" são rejeitadas. Use métrica, limite ou critério concreto ("endpoints de leitura respondem em <300ms com até 100 registros").
  • RTM sem lacunas a partir da Sprint 3: Persona → RF → RN → Endpoint → Teste → Evidência. Um elo quebrado invalida a rastreabilidade.
  • Ausência de RNF em algum eixo deve ser justificada explicitamente, não omitida.

12. Organização do artefato

  • Estrutura de pastas respeita o padrão do template (artefatos/sprint_0X_artefato.md).
  • Imagens e diagramas em pasta de assets, referenciados por caminho relativo.
  • Sem arquivos soltos, sem "copia-final-v2-definitivo.md". Versionamento é o Git.
  • Link entre documentos funcional (Markdown links relativos testados).

13. Aplicabilidade por sprint

Nem todo critério é cobrado desde a Sprint 1. A tabela abaixo consolida quando cada item do baseline passa a ser exigido — antes disso, é recomendação; a partir disso, é falha de baseline.

Critério A partir de Observação
Português impecável, conventional commits, notação correta de diagramasSprint 1Vale desde a primeira entrega.
SQL cru via driver nativo, migrations em .sql versionado, modelo físico à mão — sem ORM nem query builderSprint 2Quando a persistência entra.
Consultas formalizadas em álgebra relacionalSprint 2Aluno deve saber explicar a consulta.
Evolução visível da modelagem estática e dinâmicaSprint 3Diagramas repetidos = ausência de evolução.
Pelo menos um teste por RN, padrão AAA, determinísticoSprint 3RN sem teste = RN não implementada.
RTM sem lacunas (Persona → RF → RN → Endpoint → Teste → Evidência)Sprint 3Elo quebrado invalida rastreabilidade.
Autenticação construída do zero, hash bcrypt/argon2, sessão com expiraçãoSprint 3Quando autenticação entra no escopo.
Cobertura ≥80% na camada de ServiceSprint 4Medida com --coverage, relatório versionado.
Complexidade ciclomática e linters (ESLint, SonarJS)Sprint 4Config versionada no repositório.
Logger estruturado (pino/winston), sem console.log no códigoSprint 4Debug local não sobrevive ao commit.
CORS com origens explícitas, headers de segurança, rate limiting no loginSprint 4Helmet ou equivalente aceito.
Frontend: estados loading/success/error, Nielsen, acessibilidade mínimaSprint 4Quando frontend entra.
RNFs técnicos mensuráveis nos 8 eixosSprint 5Evolução conceitual → mensurável.

14. Severidade e consequências

Consolida, em um único lugar, as infrações ao baseline e suas consequências. Serve tanto para o aluno calibrar o que é crítico quanto para fundamentar devoluções objetivas. A coluna Evidência esperada indica o que o avaliador deve anexar na devolução.

Infração Severidade Consequência Evidência esperada
Senha armazenada em texto plano no banco Crítica Entrega inválida / devolvida sem correção de mérito Print do SELECT na tabela de usuários
.env com credenciais reais commitado (mesmo que removido depois) Crítica Entrega inválida; exige rotação de credenciais Link do commit + git log -- .env
Credenciais de produção expostas no repositório (chaves, tokens) Crítica Entrega inválida Trecho do arquivo com a credencial (redigida)
Código copiado de colega ou IA sem compreensão/atribuição Crítica Desonestidade acadêmica; tratamento conforme regulamento Trechos comparados + arguição ao aluno
ORM ou query builder em uso (Prisma, Sequelize, TypeORM, Mongoose, Knex, Drizzle, Kysely, etc.) — inclusive só para conexão ou migration Alta Reprovação do artefato na dimensão de persistência Trecho do package.json + import no código
Biblioteca pronta de autenticação (passport, next-auth, auth0, etc.) Alta Reprovação do artefato na dimensão de segurança Trecho do package.json + import no código
SQL injection explorável (concatenação de input em query) Alta Reprovação do artefato na dimensão de segurança Trecho do código com a query vulnerável
Nenhum teste presente na Sprint 3+ Alta Reprovação do artefato na dimensão de testes Resultado de npm test + listagem de /tests
Senha ou token retornado em resposta de API Alta Reprovação do artefato na dimensão de segurança Print do corpo da resposta JSON
Stack trace / detalhe interno vazando em resposta de erro Média Desconto significativo na dimensão de API/segurança Print do corpo da resposta de erro
Ausência de validação de entrada em rotas críticas Média Desconto significativo na dimensão de API Requisição com payload inválido retornando 500
CORS permissivo, sem headers de segurança, sem rate limiting (Sprint 4+) Média Desconto na dimensão de segurança Headers da resposta + ausência de middleware
Cobertura de Service <80% na Sprint 4 Média Desconto na dimensão de testes Relatório de cobertura versionado no repo
README não permite rodar o projeto do zero Média Desconto na dimensão de organização Log da tentativa de execução seguindo o README
Diagramas idênticos entre sprints (Sprint 3+) Média Desconto na dimensão de modelagem Diff entre diagramas das sprints consecutivas
console.log esquecido no código (Sprint 4+) Baixa Observação / desconto leve grep -rn "console\." src/
Commits fora de Conventional Commits, mensagens vagas Baixa Observação / desconto leve git log --oneline
Comentários descritivos desnecessários, imports não usados Baixa Observação / desconto leve Trecho do arquivo com o problema
Diagrama sem título/legenda, português com pequenos erros Baixa Observação / desconto leve Print do diagrama + linha do texto
Como ler esta tabela

Severidade é cumulativa: múltiplas infrações médias na mesma dimensão podem escalar para alta. E uma infração crítica não é compensada por acertos em outras dimensões — baseline é piso, não média.

Resumo operacional

Antes de submeter qualquer artefato, o aluno deve conseguir responder sim a todas estas perguntas:

  • A documentação está em português correto, sem erros e sem "slop" de IA?
  • Os diagramas usam a notação correta da ferramenta proposta?
  • A modelagem estática e dinâmica evoluiu em relação à sprint anterior (a partir da Sprint 3)?
  • O código se lê sozinho, sem comentários descritivos desnecessários?
  • Estou usando SQL cru via driver nativo, sem ORM e sem query builder (nem para conexão, nem para migration)?
  • As migrations são arquivos .sql numerados, aplicados por script próprio ou ferramenta que lê SQL puro?
  • Senhas estão com hash bcrypt/argon2, nunca em texto plano?
  • .env está no .gitignore e nunca foi commitado em nenhum ponto do histórico?
  • Autenticação e sessão foram construídas à mão, sem biblioteca pronta de auth?
  • Toda RN tem teste associado, padrão AAA, determinístico?
  • Na Sprint 4: cobertura ≥80% na camada de Service, complexidade ciclomática e linters configurados?
  • Na Sprint 4: logger estruturado configurado, sem console.log no código entregue?
  • Na Sprint 4: CORS com origens explícitas, headers de segurança e rate limiting no login?
  • Status codes HTTP estão corretos em todos os endpoints?
  • Nenhum stack trace ou detalhe interno vaza em respostas de erro?
  • Os 8 eixos de RNF estão presentes e mensuráveis?
  • A RTM está sem lacunas (Persona → RF → RN → Endpoint → Teste → Evidência)?
  • Consigo explicar cada linha do que entreguei?
  • O README permite que outra pessoa rode o projeto do zero?
Atenção

Se alguma resposta for "não", a entrega ainda não está pronta.

Inteli Logo