Files
recordalexia/docs/adr/0003-dominio-y-seguridad-fase2.md
Jaume Garriga Maestre 52e559a159 feat: app completa recordaLexia (fases 1-5)
App web familiar de rutinas visuales para niños con TDAH: muestra cada día el
material del cole y las rutinas de tarde, con gamificación por monedas y tienda
de recompensas. Multi-niño y bilingüe ES/CA. Uso doméstico/homelab.

Backend (Spring Boot 3.5 / Java 21 / Gradle):
- Dominio por capas, PostgreSQL + Liquibase, datos semilla.
- API REST con DTOs: /today, toggle con monedas y bonos de bloque/día, monedero,
  tienda/canje, ajustes y CRUD del panel de padres.
- Seguridad ligera por PIN (BCrypt + sesion en memoria), sin Keycloak.
- Tests JUnit: generacion del dia, monedas/bonos con reversion, canje, seguridad.

Frontend (Angular 19, standalone + signals):
- Perfiles, Home (Tablero y Foco), Tienda y panel de padres (5 pestañas).
- Tipografia OpenDyslexic conmutable (accesibilidad), i18n ES/CA, TTS y sonido.
- Tokens de diseño fieles al handoff (paleta, animaciones, monedas voladoras).

Empaquetado:
- Docker multi-stage + docker-compose (PostgreSQL + backend + Nginx).
- Decisiones de arquitectura documentadas en docs/adr.
2026-06-21 10:48:57 +02:00

2.4 KiB

ADR 0003 — Decisiones de dominio y seguridad (Fase 2 backend)

  • Estado: aceptada
  • Fecha: 2026-06-21
  • Fase: 2 (dominio + API + seguridad)

Contexto

El contrato de backend deja varias decisiones "a tu criterio". Se documentan aquí las tomadas al implementar el dominio, la lógica de negocio y la seguridad.

Decisiones

  1. i18n por columnas embebidas label_es / label_ca (no tabla de traducciones). Encaja con el shape de los DTOs y simplifica las consultas.

  2. Capas, sin hexagonal completa. Entidad JPA como modelo de dominio (con comportamiento donde aporta: monedero en Child, marcado en DailyTask), DTOs tipo record en el borde. Nunca se exponen entidades.

  3. Mañana vs. tarde. La mañana se modela con Activity (catálogo) + WeeklyTemplateEntry (asignación por día). La tarde con AfternoonRoutine directa por día. Se evita una FK polimórfica.

  4. Eventos = banner, no tareas. Los SpecialEvent (examen/deberes) se muestran en el banner informativo del día (specialEvents[]), NO se materializan como DailyTask marcables (coherente con el prototipo). El enum TaskOrigin.EVENT queda disponible por si se decide lo contrario más adelante.

  5. Bonos reconciliables. El bono de bloque y el de día se modelan como transacciones de monedas con el mismo motivo: +importe al otorgar, -importe al revertir. "Suma neta > 0" indica bono activo. Hace el marcar/desmarcar robusto ante cualquier secuencia.

  6. Seguridad ligera. PIN de padres con hash BCrypt; al validarlo se abre una sesión en memoria identificada por un valor opaco (cabecera X-Parent-Session). /api/parents/** exige rol PARENT; el resto (kiosko del niño) es abierto. Todo encapsulado en el paquete security para poder sustituirlo por Keycloak.

  7. Semilla por DataSeeder (ApplicationRunner, solo si la BD está vacía), no por Liquibase. Más mantenible y tipado. Desactivable con recordalexia.seed.enabled=false (lo usan los tests).

  8. Tests sobre H2 (modo PostgreSQL) con Liquibase. Se valorará Testcontainers en una iteración posterior para fidelidad total con PostgreSQL.

Consecuencias

  • Los textos visibles siempre viajan en ES y CA; el frontend elige idioma.
  • Cambiar a Keycloak no afecta a controladores ni servicios de negocio.
  • La zona horaria del negocio (Europe/Madrid) se centraliza en un Clock inyectable.