Saltar a contenido

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 → catalogoenvasespagostickets 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.