Saltar a contenido

ADR-005 — Entrega 2: tablero, retención y exportación de auditoría, marca blanca en runtime

Status: accepted (adr-refine 2026-09-04, preguntas de negocio respondidas por el operador)

Contexto

La entrega 1 (v1.0.0, 2026-09-06) dejó fuera por fecha lo que el brief comercial promete y lo que las revisiones difirieron (deuda D-01..D-24). La entrega 2 tiene fecha 2026-09-30. Dos decisiones dependían del negocio y se cerraron el 2026-09-04: retención de auditoría y alcance del tablero.

Alternativas

  • Retención: (A) ilimitada con archivado externo; (B) 90 días en línea, purga nocturna, CSV como archivo (elegida); (C) 30 días.
  • Tablero: (A) solo hoy; (B) hoy por defecto con rango de hasta 90 días (elegida); (C) rango libre.
  • Marca blanca: (A) por build; (B) por configuración externa en runtime (elegida, patrón del Sistema de Premios).
  • Contrato para el gateway: (A) solo SPEC en prosa; (B) springdoc OpenAPI con test de contrato (elegida).

Decisión

  • Retención: bc.auditoria.retencion-dias (por defecto 90). Job programado nocturno borra en lotes de 5 000 las consultas anteriores al límite; publica auditoria.purgadas; nunca corre sobre el período vigente. La exportación CSV es el mecanismo de archivo antes de la purga.
  • Tablero: GET /api/admin/tablero?desde&hasta (ambos roles), rango máximo 90 días, hoy por defecto en la consola. KPIs: consultas, porcentaje con beneficio, p99 de latencia, cinco beneficios más aplicados, sucursales desconocidas con conteo. Apoyado en un índice compuesto (recibida_en, branch_id).
  • Exportación: GET /api/admin/consultas/export con los filtros de la búsqueda, CSV en streaming, UTF-8 con BOM, separador ;, rango máximo 90 días.
  • Marca blanca: GET /api/branding (permitAll) desde la configuración externa; la consola inyecta el color primario en runtime. El logo se sirve desde una ruta estática configurable, nunca desde un CDN externo.
  • PWA: manifest e iconos como archivos estáticos, service worker con fallback de navegación y precache del bundle con hash.
  • Contrato: springdoc expone /v3/api-docs; un test compara el esquema generado del resolver con una respuesta real.
  • Assets: /gestor/assets/** con Cache-Control: public, max-age=31536000, immutable; index.html con no-cache.
  • Deuda: CRUD compartido en la consola. El rename a inglés fue cancelado el 2026-09-04: el dominio en castellano es la convención del proyecto.

Nota (AC-67): el default y la frecuencia de bc.auditoria.retencion-dias/bc.auditoria.purga-cron decididos acá cambiaron más adelante — ver los valores vigentes (365 días, purga semanal, cubre también resultado_pago) en Configuración y Base de datos.

Consecuencias

  • ✅ Tabla consulta acotada; tablero rápido sobre 90 días con índice compuesto.
  • ✅ Un jar sirve a varios clientes cambiando solo la configuración.
  • ⚠️ La purga es destructiva por diseño: el RUNBOOK documenta exportar antes de bajar la retención.

Plan de implementación

  • Backend: PurgaAuditoriaJob, TableroService + TableroController, ConsultaExportController, ConsultaRepository con Specification/Criteria, migración de índice compuesto, BrandingController + BrandingProperties, springdoc-openapi-starter-webmvc-api, resource handler con cache para assets.
  • Consola: página de tablero, hook de branding, manifest + service worker + instalación PWA, casillas A/B/C en el formulario de beneficio, validación de negativos, hook y cliente CRUD compartidos.
  • Prueba de carga: script tools/load/load.py (stdlib, hilos) con reporte en reports/.
  • Corpus: tools/gateway-sim/corpus/ + flag --corpus en el simulador (AC-41, depende de DINO).

Verificación

  • AC-29..AC-43 en ACCEPTANCE.md cerrados por tests con su id.
  • Readiness vuelve a 100 con la suite completa y la IT contra SQL Server.