Decisiones de arquitectura (ADRs)¶
Un ADR (Architecture Decision Record) es un registro corto de una decisión de diseño importante: qué se decidió, en qué contexto y con qué consecuencias. Sirve para que quien llega nuevo entienda por qué las cosas son como son, sin tener que arqueologizar el git.
En AutoCompraMod, las decisiones de mayor peso ya están narradas en la sección Entender el sistema; esta página las resume como índice y deja lugar para futuros ADRs formales.
Decisiones tomadas¶
ADR-001 — Monolito modular en lugar de microservicios¶
Contexto. El autoservicio eran cinco microservicios (TsTicket, TsArticulos, TsPagos, TsPromos, TsEnvases) con cargas chicas que escalaban juntos.
Decisión. Consolidarlos en un monolito modular con Spring Modulith: un solo deployable con fronteras internas verificadas por el build.
Consecuencias. Un solo deploy y una sola API para la terminal; el guardrail (ModularityTests.verify()) protege las fronteras; queda abierto el camino a extraer un módulo a servicio si algún día hiciera falta. → El monolito modular
ADR-002 — Migración strangler, no big-bang¶
Contexto. Reescribir los cinco servicios de golpe era riesgoso.
Decisión. Migrar de a un módulo por vez (promos piloto → catalogo → envases → pagos → tickets host), corriendo verify() en cada paso, dejando los repos viejos como referencia.
Consecuencias. Riesgo acotado en cada paso; el guardrail caza regresiones de frontera en el acto. → Migración strangler
ADR-003 — Topología en estrella acíclica¶
Contexto. Sin reglas, los módulos terminarían llamándose entre sí en cualquier dirección.
Decisión. Sólo tickets (orquestador) llama; el resto son hojas. Cero ciclos. shared es kernel OPEN. Comunicación sólo por API pública o eventos; datos schema-por-módulo sin foreign keys cruzadas.
Consecuencias. El grafo de dependencias es trivial de razonar y el guardrail lo hace cumplir. → Arquitectura
ADR-004 — La terminal habla REST, no STOMP¶
Contexto. TiprePOS usaba STOMP/WebSocket, con un broker y suscripciones.
Decisión. Cutover a REST puro bajo /autocompras/v1: mutaciones por POST, salud por polling adaptativo (60 s / 15 s).
Consecuencias. Modelo de comunicación más simple y depurable; STOMP queda como vestigio en deprecación. → Comunicación POS ↔ Backend
ADR-005 — Seguridad app-wide con toggle¶
Contexto. Cinco servicios tenían cada uno su seguridad; al consolidar hacía falta un único modelo, y durante el parallel-run no se podía romper el runtime del POS.
Decisión. Un solo SecurityFilterChain + JwtAuthConverter. Toggle app.security.enabled (default false) y app.security.admin-role (default ADMIN); con seguridad activa se gatean sólo las mutaciones admin.
Consecuencias. Flexibilidad para dev/parallel-run, con el riesgo conocido de que enabled=false deja todo permitAll (se loguea un WARN). → Arquitectura → Autenticación
ADR-006 — Cockpit in-process, sin STOMP, snapshots @Scheduled¶
Contexto. Hacía falta observabilidad del parque de terminales y del backend sin montar un stack de monitoreo aparte.
Decisión. Un módulo monitoring que expone /monitoring/*, calcula snapshots periódicos (@Scheduled) en vez de consultar por request, persiste errores 30 días en un DataSource separado, y se sirve como SPA React desde el propio backend.
Consecuencias. Observabilidad barata y autocontenida; el Cockpit lee las APIs públicas sin acoplarse a internals. → Referencia → Cockpit
Cómo agregar un ADR nuevo
Cuando tomes una decisión de arquitectura con consecuencias duraderas, agregá una entrada acá con el mismo formato: Contexto → Decisión → Consecuencias, y enlazá a la página de explicación que la desarrolla. Un ADR es corto a propósito: si necesita tres páginas, esas tres páginas van en explanation/ y el ADR las referencia.