Vista de datos e información
Propósito y alcance
Esta vista explica qué datos administra SportApp, cuál dominio es su fuente de verdad, cómo se relacionan sin compartir bases, cómo se construyen las lecturas CQRS y qué controles requieren los datos personales y de salud.
La vista reúne el modelo conceptual completo y el estado conocido de implementación. No reemplaza las migraciones, los contratos OpenAPI, los esquemas de eventos ni el diccionario físico que deberá publicar cada microservicio.
Principios de datos
- Cada microservicio es propietario de su persistencia y de la evolución de su esquema.
- Ningún servicio consulta o modifica tablas pertenecientes a otro dominio.
- Las relaciones entre dominios se conservan como identificadores lógicos y se validan mediante API o eventos versionados.
- PostgreSQL es la tecnología de persistencia seleccionada; Cloud SQL es el destino administrado previsto en GCP.
- Usuarios, entrenamientos y eventos separan escritura y lectura mediante CQRS.
- La base de escritura es la fuente de verdad; las proyecciones de lectura son reconstruibles y eventualmente consistentes.
- El cambio del agregado y su evento se confirman juntos mediante outbox transaccional.
- Las integraciones intercambian el mínimo dato necesario; no replican perfiles completos por conveniencia.
- Contraseñas, tokens y secretos nunca forman parte de proyecciones, eventos públicos, logs o respuestas no autorizadas.
- Toda decisión sobre retención, eliminación, consentimiento o datos clínicos debe quedar explícita y auditable.
- Las capacidades de un plan son datos maestros versionados; los clientes no autorizan comparando el nombre del plan.
Panorama de propiedad y relaciones
flowchart LR
subgraph U[Usuarios]
UA[Cuenta e identidad]
UP[Perfil demográfico y fisiológico]
UH[Hábitos]
end
subgraph A[Afiliación]
AP[Planes]
AC[Versiones y capacidades]
AS[Suscripciones]
end
subgraph S[Servicios complementarios]
SC[Catálogo]
SD[Disponibilidad]
SR[Contratación y citas]
end
subgraph T[Entrenamientos]
TP[Planes]
TS[Sesiones y mediciones]
TH[Historiales e indicadores]
TN[Alimentación]
end
subgraph E[Eventos]
EE[Eventos y tarifas]
EI[Inscripciones]
EC[Calendario y alertas]
end
subgraph X[Terceros]
XC[Conexión OAuth]
XS[Sincronización]
XA[Actividad normalizada]
end
UA -. usuario_id .-> AS
UA -. usuario_id .-> SR
UA -. deportista_id .-> TP
UA -. usuario_id y organizador_id .-> EE
UA -. usuario_id .-> XC
AP --> AC --> AS
AC -. capacidades vigentes .-> SR
AC -. capacidades vigentes .-> TP
XA -. actividad normalizada .-> TS
SR -. referencia de calendario .-> EC
TP -. referencia de calendario .-> EC
Las flechas punteadas son referencias o contratos entre dominios, no claves foráneas entre bases de datos.
Matriz de propiedad
| Dominio |
Fuente de verdad |
Lectura separada |
Agregados o datos principales |
Referencias externas |
Estado |
| Usuarios |
PostgreSQL de escritura |
Sí |
cuenta, credencial protegida, perfil, hábitos, versión y auditoría |
catálogos geográficos |
HU001 implementada localmente; resto conceptual |
| Afiliación |
PostgreSQL único |
No |
plan, versión, capacidades, suscripción, inbox/outbox y estado de cuenta ratificado |
usuario_id, identificadores de servicios |
Migración, catálogo, alta FREE, inbox/outbox y consulta interna integrados en backend por PR #7; despliegue y aceptación pendientes |
| Servicios complementarios |
PostgreSQL único |
No |
servicio, disponibilidad, contratación y cita |
profesional_id, usuario_id, plan/capacidad |
Diseñado; implementación pendiente |
| Entrenamientos y alimentación |
PostgreSQL de escritura |
Sí |
planes, sesiones, registros, mediciones, alimentación, indicadores e historiales |
deportista, profesional, servicio y actividad externa |
Diseñado; contratos físicos pendientes |
| Eventos |
PostgreSQL de escritura |
Sí |
evento, capacidad, tarifa, inscripción, estado y solicitud de alerta |
organizador_id, usuario_id, beneficio de plan |
Diseñado; contratos físicos pendientes |
| Integraciones de terceros |
Persistencia protegida por definir |
No confirmado |
conexión, autorización, token cifrado, sincronización y deduplicación |
usuario_id, identificador externo |
Diseño funcional; modelo físico pendiente |
“Persistencia por servicio” expresa propiedad lógica y credenciales separadas. La cantidad definitiva de instancias de Cloud SQL, bases y esquemas físicos se decide mediante infraestructura y capacidad, sin conceder acceso cruzado.
Catálogo conceptual por dominio
Usuarios
| Entidad o agregado |
Información principal |
Clasificación |
Observaciones |
| Cuenta de usuario |
identificador, nombre, correo normalizado, tipo de actor, estado y versión |
Personal |
Fuente de identidad de SportApp. |
| Credencial |
hash de contraseña, revocación y metadatos de autenticación |
Secreto restringido |
Nunca se proyecta ni publica. |
| Aceptación de políticas |
versión aceptada, instante y evidencia |
Personal/auditable |
Requerida por el registro implementado. |
| Perfil demográfico |
residencia, estado civil, ocupación, ingresos, raza/etnia y religión cuando sean aprobados |
Personal sensible |
Requiere minimización, consentimiento y finalidad. |
| Perfil fisiológico |
peso, altura, IMC, presión, frecuencia, temperatura, química sanguínea, función pulmonar, fuerza y flexibilidad |
Salud altamente sensible |
No se anuncia en eventos generales. |
| Hábitos deportivos |
deportes, frecuencia y preferencias declaradas |
Personal sensible |
Propiedad de usuarios; recomendaciones pertenecen a otros dominios. |
| Hábitos alimenticios |
hábitos, restricciones y preferencias declaradas |
Salud/personal sensible |
Acceso mínimo y finalidad explícita. |
| Catálogo geográfico |
país y ciudad |
Referencia |
Puede normalizarse sin compartir la tabla del dominio. |
Afiliación
| Entidad o agregado |
Información principal |
Reglas relevantes |
| Plan de afiliación |
código estable, nombre, nivel, estado, seleccionable y predeterminado |
FREE es el predeterminado exclusivo de athlete. |
| Versión de plan |
plan, versión, vigencia, precio informativo y moneda |
Un cambio conserva la versión aplicada a suscripciones existentes. |
| Capacidad |
código estable, nombre, dominio y estado |
Referencia lógica; no copia el catálogo operativo. |
| Capacidad de versión |
versión de plan, capacidad y límites configurables |
Los niveles superiores heredan los inferiores según ADR-024. |
| Suscripción |
usuario_id, versión de plan, origen, inicio, estado y versión de concurrencia |
Solo una combinación activa compatible por usuario. |
| Inbox/outbox |
evento, correlación, procesamiento o publicación |
Deduplica el alta gratuita y publica cambios confiablemente. |
| Estado de cuenta |
estado aprobado para la experiencia |
Pago y conciliación no se asumen como propiedad. |
El despliegue ejecuta una migración idempotente que precarga FREE, INTERMEDIATE y PREMIUM con código, nombre, descripción, nivel, orden, estado, indicador predeterminado, indicador seleccionable, versión, vigencia, precio, moneda, ciclo de cobro, textos, capacidades y límites. FREE tiene precio cero y ciclo NONE; los planes pagos solo se publican como seleccionables cuando sus valores comerciales hayan sido aprobados e incluidos en esa misma migración. Las réplicas no reescriben estos datos al arrancar: verifican la versión esperada y su readiness falla si el catálogo está ausente o incompleto.
No existe una HU, pantalla ni API CRUD para administrar planes. Los clientes solo consultan el catálogo y las capacidades, y HU016 cambia la suscripción. Cualquier modificación futura se realiza mediante una migración revisada en código y, cuando altera condiciones aceptadas, crea una nueva versión del plan para conservar la trazabilidad de las suscripciones existentes.
Servicios complementarios
| Entidad o agregado |
Información principal |
Reglas relevantes |
| Servicio |
nombre, descripción, costo, estado y profesional_id |
Un borrador no aparece en el catálogo público. |
| Disponibilidad |
intervalos, zona horaria, vigencia y propietario |
Debe impedir solapamientos inválidos. |
| Contratación o asociación |
usuario_id, servicio_id, fecha y estado |
Elegibilidad por plan se valida por contrato. |
| Cita o sesión |
servicio, usuario, profesional, intervalo y estado |
Dos solicitudes no reservan el mismo espacio. |
Entrenamientos y alimentación
| Entidad o agregado |
Información principal |
Reglas relevantes |
| Deporte |
nombre, descripción e indicadores aplicables |
Catálogo del dominio. |
| Plan de entrenamiento |
deportista, profesional, versión, vigencia y actividades |
Debe conservar historial y control de concurrencia. |
| Sesión o registro |
plan, inicio, fin, estado y zona horaria |
Una sesión no se inicia/finaliza dos veces. |
| Medición |
dispositivo/origen, instante, unidad, calidad y valor |
Deduplicación por origen e identificador estable. |
| Indicador |
nombre, unidad, valor, algoritmo/versión y fecha |
No debe presentarse como diagnóstico médico. |
| Molestia, lesión o incapacidad |
tipo, intervalo, estado y evidencia autorizada |
Dato de salud con acceso restringido. |
| Alimento |
nombre, descripción y referencia nutricional aprobada |
Catálogo del dominio. |
| Plan o registro alimenticio |
deportista, alimento, cantidad, instante y estado |
Historial protegido; no mezcla la declaración de hábitos de usuarios. |
| Recomendación |
resultado, motivo, insumos mínimos y versión |
Derivada; no reemplaza los datos fuente ni ejecuta acciones automáticamente. |
Eventos
| Entidad o agregado |
Información principal |
Reglas relevantes |
| Evento |
organizador, descripción, fechas, duración, capacidad y ciclo de vida |
Solo el organizador autorizado modifica o publica. |
| Tarifa |
valor y vigencia histórica aplicable |
No equivale a pago procesado. |
| Inscripción |
usuario_id, evento_id, estado, tarifa aplicada y versión |
Debe impedir duplicidad y sobrecupo. |
| Calendario |
proyección de eventos visibles y referencias autorizadas |
Es lectura, no fuente de verdad. |
| Solicitud de alerta |
evento, motivo, destinatario lógico y estado |
El proveedor/canal final de notificación está pendiente. |
| Estado financiero conceptual |
pendiente, parcial o pagado |
No es definitivo hasta decidir pagos, conciliación y propietario. |
Integraciones de terceros
| Entidad o agregado |
Información principal |
Reglas relevantes |
| Conexión externa |
usuario, proveedor, identificador externo, scopes y estado |
No sustituye la identidad SportApp. |
| Autorización OAuth |
estado antifalsificación, consentimiento y expiración |
La aplicación móvil no almacena tokens del proveedor. |
| Token externo |
acceso/renovación protegidos y metadatos de rotación |
Cifrado y acceso exclusivo de la carga autorizada. |
| Sincronización |
inicio, fin, cursor, estado, error seguro e intentos |
Reintentos solo para operaciones seguras. |
| Actividad importada |
identificador externo, deporte, tiempo, distancia, elevación, unidades, origen y versión de mapeo |
Se deduplica y se entrega a entrenamientos en un contrato neutral. |
Referencias lógicas entre dominios
| Consumidor |
Identificador o dato mínimo |
Propietario |
Mecanismo permitido |
Acceso prohibido |
| Afiliación |
usuario_id e identidad validada |
Usuarios |
API/evento aprobado |
tabla de usuarios |
| Servicios |
usuario_id, profesional_id |
Usuarios |
API/BFF o evento mínimo |
perfil completo |
| Servicios |
capacidad del plan |
Afiliación |
API/evento versionado |
tabla de suscripciones |
| Entrenamientos |
deportista, profesional y hábitos mínimos autorizados |
Usuarios |
contrato con consentimiento |
base de perfiles |
| Entrenamientos |
beneficios aplicables |
Afiliación |
API/evento versionado |
base de afiliación |
| Entrenamientos |
actividad normalizada |
Terceros |
evento/API neutral |
token o JSON de Strava |
| Eventos |
organizador_id, usuario_id y rol |
Usuarios |
validación por contrato |
base de identidad |
| BFF web/móvil |
vistas necesarias para la pantalla |
Cada dominio |
APIs versionadas |
acceso directo a PostgreSQL |
No existen transacciones ACID entre dominios. Las operaciones distribuidas usan idempotencia, eventos, estados explícitos y compensaciones solamente cuando se apruebe el flujo.
Modelo físico implementado para HU001
El alcance comprobado localmente de registro de usuario contiene:
| Tabla |
Campos principales |
Propósito |
Estado |
user_account |
user_id, full_name, email, actor_type, status, password_hash, política aceptada, instantes y version |
Cuenta y credencial inicial |
Migración local implementada |
outbox_event |
evento, agregado, versión, tipo, esquema, correlación, payload, publicación, arrendamiento e intentos |
Publicación confiable |
Migración local implementada |
idempotency_key |
clave, operación, huella de solicitud, recurso, respuesta y expiración |
Evitar registros duplicados |
Migración local implementada |
| Modelo de lectura |
proyecciones y processed_event |
Consultas CQRS |
Línea base vacía; proyección pendiente |
La implementación usa hash Argon2id y restricción única de correo. Esta evidencia es local: todavía no constituye despliegue remoto ni validación en GitHub Actions.
CQRS, outbox y modelos de lectura
flowchart LR
C[Comando]
subgraph BW[Base de escritura del dominio]
W[(Agregado y versión)]
O[(outbox_event)]
end
P[Publicador outbox]
T[Tópico Pub/Sub]
S[Suscripción de proyección]
J[Proyector idempotente]
D[DLQ]
subgraph BR[Base de lectura del dominio]
R[(Proyecciones)]
I[(processed_event)]
end
Q[Consulta]
C -->|TX1| W
C -->|misma TX1| O
O -. lote y arrendamiento .-> P
P --> T --> S --> J
S -. intentos agotados .-> D
J -->|TX2| R
J -->|misma TX2| I
Q --> R
No existe una transacción distribuida entre PostgreSQL y Pub/Sub. TX1 garantiza agregado más evento; TX2 garantiza proyección más deduplicación. El ACK se envía después del COMMIT de TX2.
Topología por dominio CQRS
| Dominio |
Publicador |
Tópico |
Proyector |
Suscripción |
DLQ |
Clave de orden inicial |
| Usuarios |
usuarios-outbox-publisher |
sportapp.usuarios.v1 |
usuarios-read-projector |
proyector-usuarios-v1 |
propia del dominio |
usuario_id |
| Entrenamientos |
entrenamientos-outbox-publisher |
sportapp.entrenamientos.v1 |
entrenamientos-read-projector |
proyector-entrenamientos-v1 |
sportapp.entrenamientos.proyeccion.dlq |
plan_id, sesion_id o indicador_id según evento |
| Eventos |
eventos-outbox-publisher |
sportapp.eventos.v1 |
eventos-read-projector |
proyector-eventos-v1 |
sportapp.eventos.proyeccion.dlq |
evento_id o inscripcion_id según evento |
Cada fila representa recursos, credenciales, métricas y capacidad independientes. No existe un sincronizador central con acceso a todas las bases.
Sobre mínimo de evento
| Campo |
Uso |
event_id |
deduplicación global del mensaje |
event_type y schema_version |
contrato y evolución compatible |
occurred_at |
instante del hecho confirmado |
producer |
dominio emisor |
aggregate_id y aggregate_version |
orden y detección de brechas |
correlation_id y causation_id |
trazabilidad del flujo |
payload |
mínimo dato autorizado para consumidores |
Estados de una actualización
| Momento |
Escritura |
Outbox |
Pub/Sub |
Lectura |
Interpretación |
| Antes del comando |
versión 6 |
sin evento |
sin mensaje |
versión 6 |
modelos alineados |
Después de TX1 |
versión 7 |
pendiente |
sin mensaje |
versión 6 |
cambio confirmado, aún no visible en consultas |
| Después de publicar |
versión 7 |
publicado |
pendiente o entregado |
versión 6 |
evento en tránsito |
Después de TX2 |
versión 7 |
publicado |
ACK |
versión 7 |
proyección actualizada |
El intervalo entre TX1 y TX2 es consistencia eventual. La respuesta del comando devuelve el resultado confirmado y su aggregate_version; no espera la proyección. El contrato min_version con 202 ProjectionPending y Retry-After permanece como mecanismo propuesto para lecturas que exijan una versión mínima.
Eventos candidatos y proyecciones
Los nombres siguientes orientan el diseño; no son contratos definitivos hasta aprobar payload, versión y compatibilidad.
| Dominio |
Eventos principales candidatos |
Lecturas derivadas |
| Usuarios |
usuario.registrado.v1, usuario.actualizado.v1, perfiles y hábitos actualizados, usuario desactivado |
perfil autorizado, hábitos y estado de cuenta visible |
| Entrenamientos |
plan creado, entrenamiento iniciado/finalizado, medición recibida, indicador calculado, riesgo detectado |
planes, sesión activa, historiales, tablero e indicadores |
| Eventos |
evento creado/publicado/actualizado, usuario inscrito, inscripción actualizada, alerta solicitada |
catálogo, detalle, calendario, inscripción y conteos reconciliables |
| Afiliación |
suscripcion.activada.v1; suscripción cambiada/cancelada |
alta gratuita aprobada por ADR-024; cambios sujetos al contrato de HU016; no habilitan CQRS por sí solos |
| Servicios |
servicio creado/publicado, disponibilidad actualizada, servicio contratado, sesión programada |
pendientes de contrato; base única en la línea base |
| Terceros |
tercero vinculado, actividad importada, sincronización fallida, autorización revocada |
estado de conexión y actividad normalizada |
Reglas de integridad y concurrencia
| Área |
Regla |
| Identidad |
correo normalizado y único; no revelar si una cuenta existe mediante errores inseguros |
| Suscripciones |
una operación idempotente no crea dos suscripciones activas incompatibles |
| Disponibilidad |
una cita no puede ocupar dos veces el mismo intervalo |
| Sesiones de entrenamiento |
inicio, mediciones y finalización conservan orden por sesión y deduplicación |
| Eventos |
no duplicar inscripción ni superar cupo usando un contador eventualmente consistente |
| Versiones |
el comando verifica la versión esperada; no sobrescribe conflictos silenciosamente |
| Eventos repetidos |
processed_event(event_id) produce un solo efecto lógico |
| Brechas |
una versión mayor a la esperada se reintenta y luego se reconcilia; no se aplica fuera de orden |
| Fallos permanentes |
el mensaje va a la DLQ con reproducción controlada y trazabilidad |
| Referencias externas |
se validan por contrato; nunca mediante claves foráneas o consultas a otra base |
Clasificación y protección
| Clasificación |
Ejemplos |
Controles mínimos |
| Pública |
planes publicados, catálogo de servicios, eventos públicos |
integridad, versión y protección contra modificación no autorizada |
| Interna |
estados operativos, identificadores técnicos, métricas y configuración no secreta |
mínimo privilegio, trazabilidad y no exposición innecesaria |
| Personal |
nombre, correo, identificación, residencia, inscripciones y agenda |
finalidad, autorización por recurso, auditoría y cifrado |
| Sensible |
demografía, hábitos, actividad, ubicación y afiliación |
consentimiento, minimización, acceso restringido y retención definida |
| Salud altamente sensible |
fisiología, lesiones, mediciones, indicadores y alimentación |
segregación, auditoría reforzada, cifrado y prohibición de uso no autorizado |
| Secreto |
hash de contraseña, JWT, refresh token, token OAuth y claves |
Secret Manager/configuración segura; nunca logs, eventos ni proyecciones |
Controles obligatorios
- autenticación y autorización por rol y propiedad del recurso;
- TLS en tránsito y cifrado administrado en reposo;
- identidad de carga y credenciales mínimas por servicio;
- ambientes separados y datos de prueba sintéticos;
- auditoría de autenticación, acceso privilegiado y cambios sensibles;
- eventos, logs y métricas sin contraseñas, tokens o payloads médicos innecesarios;
- consentimiento y revocación para integraciones y tratamiento sensible;
- respaldo, restauración y pruebas de recuperación acordes con RPO/RTO.
Ciclo de vida, respaldo y recuperación
| Elemento |
Regla de diseño |
Estado de definición |
| Datos maestros |
permanecen en la fuente de verdad y evolucionan mediante migraciones compatibles |
patrón definido; retención por entidad pendiente |
| Proyecciones |
se pueden reconstruir desde fuente consistente y eventos posteriores a un punto de control |
mecanismo definido; runbooks por dominio pendientes |
| Outbox |
un evento no publicado no se elimina; los publicados requieren política de purga segura |
retención pendiente |
processed_event |
se conserva durante la ventana necesaria para impedir duplicados |
ventana pendiente |
| Pub/Sub y DLQ |
retención, reintentos, alertas y reproducción controlada |
valores pendientes por dominio |
| Tokens externos |
rotación, revocación y eliminación al desvincular según política |
almacenamiento físico y periodos pendientes |
| Datos personales y de salud |
acceso, rectificación, eliminación o anonimización según finalidad y norma aplicable |
análisis regulatorio y periodos pendientes |
| Backups de Cloud SQL |
copias, restauración puntual y pruebas periódicas |
RPO/RTO y configuración pendientes |
Una eliminación en la fuente de verdad debe propagarse de manera autorizada a proyecciones, caches, eventos derivados y datos importados. No se define una eliminación física automática hasta aprobar retención, obligaciones legales y estrategia de auditoría.
Estado de implementación
| Elemento |
Estado al 09/10/2026 |
| Propiedad de datos por servicio |
Decisión aceptada en ADR-003 |
| CQRS selectivo |
Aceptado para usuarios, entrenamientos y eventos |
| Patrón outbox/proyector independiente |
Aceptado en ADR-016 |
| Registro HU001 |
Cuenta, Argon2id, idempotencia y outbox verificados localmente |
| Proyección de usuarios |
Modelo de lectura aún vacío; implementación pendiente |
| Afiliación |
ADR-024 y catálogo conceptual aceptados; migración, consumidor y autorización por capacidades pendientes |
| Servicios, entrenamientos y eventos |
Diseño conceptual; esquema/migraciones completos pendientes |
| Integración Strava |
Contrato y persistencia protegida pendientes |
| Cloud SQL en GCP |
Objetivo documentado; despliegue y evidencia remota pendientes |
| Retención, anonimización y clasificación final |
Pendiente de decisión y validación regulatoria |
Decisiones y artefactos pendientes
- diccionario físico, claves, cardinalidades, índices y restricciones finales por dominio;
- dueño y versión de cada esquema y migración;
- payload, compatibilidad, retención y consumidores de cada evento;
- SLA de frescura y umbral de alerta por proyección;
- tamaño de lote, arrendamiento, reintentos, pools y capacidad;
- tratamiento de claves calientes en eventos y mediciones de alta frecuencia;
- modelo financiero de pagos, conciliación, reembolso e impuestos;
- consentimiento, finalidad, retención, eliminación y anonimización por categoría;
- cifrado y rotación de tokens de terceros;
- RPO, RTO, backups, restauración y continuidad;
- matriz verificable de permisos por rol, recurso y dato.
Fuentes de la vista
arquitectura/04-datos-y-persistencia.md;
arquitectura/08-seguridad.md;
- ADR-002, ADR-003, ADR-015 y ADR-016;
- CMP-001, CMP-002, CMP-003 y CMP-004;
- guías de desarrollo de usuarios, afiliación, servicios, entrenamientos, eventos y terceros;
- migraciones y modelos locales de
users_management para HU001.
Volver a Arquitectura de la solución