Saltar a contenido

ADR-020 — Gate de análisis estático del backend (Checkstyle, PMD, SpotBugs, FindSecBugs)

  • Status: accepted (operador aprobó el gate, 2026-08-22)
  • Context: el ledger uscha (QA-LEDGER.json) marcaba backend.static_gate como UNMEASURED — el placeholder java-qa-gate quedó pendiente desde el bootstrap del proyecto (CLAUDE.md §"Project adapter", línea "Static gate: <e.g. mvn -q verify -Pqa → ...>"). landing y gestor ya reportan static-gate real (eslint + tsc, QA-LEDGER.json), pero backend no tenía ningún linter/SAST corriendo. Este es un sistema con actas legales de sorteo (ver ADR-004) y datos personales de clientes (padrón, DNI, celular) — necesita un piso de linting + SAST, no solo tests unitarios.
  • Alternatives:
  • Sin gate — descartada: es exactamente el estado actual (UNMEASURED) que este ADR viene a cerrar; el ledger no puede medir lo que no se ejecuta.
  • SonarQube — hay integración disponible en el toolkit (skill sonarqube:sonar-*), pero requiere levantar/mantener un server (SonarQube Community o Cloud) y autenticar el repo contra él; para un backend de un solo módulo Maven es una pieza de infraestructura adicional a operar y actualizar, desproporcionada frente al problema (medir el backend, no correr una plataforma).
  • Plugins Maven locales (elegida)maven-checkstyle-plugin + maven-pmd-plugin
    • spotbugs-maven-plugin + findsecbugs-plugin: corren dentro del build existente, sin servicio externo, producen XML que el ledger ya sabe parsear (qa_ledger.py ingest-gate busca exactamente target/checkstyle-result.xml, target/pmd.xml, target/spotbugsXml.xml), y son la misma familia de herramientas que ya usa el ecosistema Java/Maven sin agregar infraestructura.
  • Decision: agregar un perfil Maven qa a backend/pom.xml, atado a la fase verify (no a test, para que mvn test — el comando de todos los días — siga rápido y sin este costo). El perfil corre:
  • maven-checkstyle-plugin con un ruleset propio de alta señal (backend/config/checkstyle.xml), no sun_checks (demasiado ruidoso para este tamaño de proyecto): imports con wildcard, catch vacío, pares equals/hashCode, llaves obligatorias, imports sin usar, System.out/System.err prohibidos en prod. Magic numbers y javadoc quedan OFF (no aportan señal aquí).
  • maven-pmd-plugin con ruleset propio (backend/config/pmd-ruleset.xml): bestpractices + errorprone núcleo, excluyendo reglas ruidosas para este codebase (LawOfDemeter, OnlyOneReturn, guard de log statements, reglas de comentarios).
  • spotbugs-maven-plugin (con el plugin findsecbugs-plugin sumado a su classpath), effort=Max, threshold=Medium, salida XML.
  • Ninguno de los tres falla el build (failOnViolation=false / failOnError=false): el ledger es el gate, no Maven — el perfil solo tiene que producir las tres XML; la severidad se evalúa en qa_ledger.py ingest-gate (FindSecBugs pisa a HIGH/SECURITY, SpotBugs prio1→HIGH, Checkstyle error→HIGH, PMD prio1→BLOCKER, prio2→HIGH), igual que ya ocurre con eslint/tsc en landing/gestor.
  • Consequences:
  • mvn test no cambia: sigue sin correr análisis estático, mismo tiempo que hoy.
  • mvn verify -Pqa (o -Pqa explícito en CI/ledger) es el único comando nuevo, y es el que documenta CLAUDE.md §"Project adapter" → "Static gate".
  • Los hallazgos nuevos entran al gate del ledger: los normalizados a BLOCKER/CRITICAL/HIGH se arreglan en el mismo cambio (ver Verification); el resto (MEDIUM/LOW) va a ISSUES-DEFERRED.md bajo "static-gate backend (ADR-020, 2026-08-22)", sin bloquear.
  • Una falsa alarma verificada (no un hallazgo real) puede suprimirse con @SuppressFBWarnings/suppression file puntual, siempre con una razón de una línea junto a la supresión — nunca para ocultar un hallazgo real.
  • spotbugs-maven-plugin corre sobre bytecode target Java 17 (maven.compiler.release =17) aunque el JDK de build sea 25; se fija la versión de com.github.spotbugs: spotbugs compatible con ambos (4.8.x) para evitar el mismo tipo de fricción de versión que ya se resolvió en ADR-018 con Jackson 3/Boot 4.

Implementation Plan

  • backend/pom.xml: perfil qa (activation manual, -Pqa) atado a verify, con maven-checkstyle-plugin, maven-pmd-plugin, spotbugs-maven-plugin (+ findsecbugs-plugin como dependencia del plugin).
  • backend/config/checkstyle.xml (ruleset de alta señal, nuevo).
  • backend/config/pmd-ruleset.xml (ruleset enfocado bestpractices/errorprone, nuevo).
  • CLAUDE.md §"Project adapter" → línea "Static gate" actualizada al comando real.
  • Hallazgos ≥HIGH del primer run: arreglados en el mismo cambio (con test de regresión si aplica); MEDIUM/LOW documentados en ISSUES-DEFERRED.md.

Verification

  • [x] mvn -q test verde (mismo set de tests, sin regresión de tiempo).
  • [x] mvn -q verify -Pqa genera target/checkstyle-result.xml, target/pmd.xml y target/spotbugsXml.xml, los tres no vacíos y parseables.
  • [x] qa_ledger.py ingest-gate --repo backend --iteration 6 corre limpio a nivel gate (0 hallazgos HIGH/CRITICAL/BLOCKER sin resolver tras el pase de fixes).
  • [x] qa_ledger.py readiness --record refleja backend.static_gate medido (deja de estar UNMEASURED).