Convierte recordaLexia de una sola familia a multi-familia, con cuentas propias y persistencia de preferencias. Backend: - Tenant Family (email único + contraseña BCrypt + PIN + prefs de cuenta); family_id en child/activity/material_item/reward; aislamiento por familia (acceso cruzado responde 404). - Auth propia (sin Keycloak): registro/login email+contraseña, sesiones de familia persistidas en BD (sobreviven a reinicios), panel de padres tras PIN. - Liquibase 002-multitenant; seeder crea una familia demo. - Tests de aislamiento entre familias, registro/login y gate del panel. Frontend: - Login, registro y pantalla de cuenta; guards (sesion + PIN) e interceptor de sesion global; perfiles scopeados a la familia. Preferencias: - OpenDyslexic persistida por nino (child.dyslexiaFont) y default de cuenta. Decisiones en docs/adr/0004.
2.1 KiB
2.1 KiB
ADR 0004 — Multi-tenant + registro/login propio (email/contraseña)
- Estado: aceptada
- Fecha: 2026-06-21
- Supersede (parcialmente): ADR 0002/0003 en lo relativo a "auth ligera sin cuentas".
Contexto
El contrato original definía la app como una sola familia, con auth ligera (PIN de padres) y datos globales. El usuario pide convertirla en multi-familia (multi-tenant) con registro/login propio y persistencia de preferencias.
Decisión
- Tenant =
Family(cuenta con email único + contraseña BCrypt + PIN + prefs). Las entidades raíz (child,activity,material_item,reward) llevanfamily_id. El resto cuelga del niño. - Aislamiento: toda consulta raíz se filtra por la familia de la sesión; las operaciones por id verifican pertenencia y, si no, responden 404 (no 403, para no filtrar existencia).
- Sesión de familia ligada al dispositivo, persistida en BD (
family_session) para sobrevivir a reinicios (clave para el kiosko). CabeceraX-Auth-Session. Toda la API exige sesión válida; el niño NO se loguea (el adulto deja la sesión abierta en la tablet). - Panel de padres: además de la sesión, exige desbloqueo con PIN
(
POST /api/parents/unlock), que concede el rol PARENT durante 30 min. - Sin Keycloak: auth propia encapsulada en el paquete
security(AuthService,SessionAuthService,SessionAuthFilter). - Preferencia OpenDyslexic pasa a campo por niño (
child.dyslexia_font) + un default de cuenta (family.default_dyslexia_font).
Consecuencias
- Registro abierto (cualquiera crea una familia). Rate-limiting y verificación de email quedan como mejora futura (homelab).
- La migración del esquema (
002-multitenant.yaml) añadefamily_idNOT NULL; en BD ya poblada habría que hacer backfill (en este proyecto se parte de BD limpia condocker compose down -v). - La sesión de 30 días en el dispositivo es un compromiso UX/seguridad razonable
para un kiosko doméstico; revocable borrando la fila de
family_session. - Sustituir la auth por un IdP externo (Keycloak) solo afectaría al paquete
security.