Arquitectura del Software de UnoSportClub

Este documento describe la arquitectura completa del sistema UnoSportClub, basada en el modelo OSI (Open Systems Interconnection) de 7 capas adaptado para aplicaciones web modernas. Su objetivo es proporcionar una comprensión clara de la estructura, componentes, flujos de datos y decisiones arquitectónicas del sistema.

1. Visión General

1.1 Stack Tecnológico

El sistema está construido con las siguientes tecnologías principales:

  • Frontend: Angular 21.x (5 aplicaciones independientes)

  • Backend: Node.js 24.x con Express.js 5

  • Base de datos: PostgreSQL principal + base contable (DB_NAME_ACCOUNTING)

  • Autenticación: OAuth2 local (OIDC + JWT RS256)

  • API REST: functions/server.js montado en /api

  • Realtime: Socket.io (Relay)

  • Infraestructura: Imagen Docker unificada (nginx + Node) → GHCR; Caddy opcional en borde TLS

1.2 Modelo Arquitectónico

El sistema sigue una arquitectura basada en el modelo OSI (Open Systems Interconnection) de 7 capas, adaptado para aplicaciones web modernas. Esta estructura permite una separación clara de responsabilidades y facilita la escalabilidad, mantenibilidad y seguridad del sistema.

2. Arquitectura por Capas (Modelo OSI)

2.1 Capa 7: Aplicación (Application Layer)

La capa de aplicación contiene la lógica de negocio y las interfaces de usuario del sistema.

2.1.1 Frontend - Aplicaciones Angular

El frontend está organizado en 5 aplicaciones Angular independientes:

Aplicación Principal (src/, puerto 6100)

Interfaz para usuarios finales (clientes)

Rol: client

Panel Operador (projects/panel/, puerto 6101)

Gestión operativa: reservas, agenda, eventos, tickets, caja, reportes

Rol: operator, admin

Panel Entrenador (projects/trainer/, puerto 6102)

Clases, alumnos e inscripciones

Rol: trainer

Panel Sudo (projects/sudo/, puerto 6103)

Superusuario: usuarios, roles, auditoría

Rol: sudo

Contabilidad (projects/accounting/, puerto 6104)

NIIF: períodos, asientos, estados financieros

Rol: accounting, admin

Librería común (projects/common/)

Modelos, guards, utilidades (reservation-wall-time, interfaces compartidas)

Diagrama actualizado: Diagramas de ingeniería.

Tecnologías Frontend: * Angular 21.x con componentes standalone * Signals para gestión de estado reactivo * Tailwind CSS para estilos * Service Workers para funcionalidad offline * RxJS para programación reactiva

2.1.2 Backend - API REST

El backend está implementado con Express.js:

Estructura de Rutas:

/api
├── /admin/*        - Operaciones administrativas (operator, admin)
├── /account/*      - Operaciones de cuenta de usuario (client)
├── /trainer/*      - Operaciones de entrenador (trainer)
├── /sudo/*         - Operaciones de super usuario (sudo)
├── /accounting/*   - Contabilidad NIIF
├── /public/*       - Endpoints públicos (sin autenticación)
├── /bot/*          - Bot / integraciones
└── /api-docs       - Documentación Swagger

Middleware: * Verificación JWT RS256 (functions/utils/oauth-local-auth.js) * requireAdminAccess, requireSudoAccess, requireAccountAccess, requireTrainerAccess

Servicios Backend: * OAuth2 local IdP: emisión y validación de tokens; tabla user con local_id * RelayHelper: notificaciones en tiempo real * Pool PostgreSQL principal + conexión opcional a DB_NAME_ACCOUNTING

2.1.3 Sistema Realtime (Relay)

Arquitectura Relay:

El sistema utiliza Relay (implementado con Socket.io) para notificaciones y comunicación en tiempo real. Relay es un gateway inmutable y agnóstico que permite a los clientes definir su propia lógica de negocio.

Componentes del Sistema Relay:

  1. Socket.io Server:

    • Servidor WebSocket basado en Socket.io

    • Namespace /realtime para todas las conexiones

    • Autenticación mediante Bearer Token

    • Soporte para múltiples transportes (websocket, polling)

  2. Redis Adapter:

    • Escalado horizontal mediante Redis

    • Distribución de mensajes entre múltiples instancias

    • Caché de sesiones WebSocket

    • Sistema pub/sub para notificaciones

    • Configurado mediante variable de entorno REDIS_URL

  3. Apache Kafka:

    • Cola de mensajes para procesamiento asíncrono

    • Streaming de eventos del sistema Relay

    • Persistencia de mensajes para garantizar entrega

    • Procesamiento de eventos en tiempo real

    • Topics para diferentes tipos de eventos

  4. RelayHelper:

    • Clase helper para emitir eventos desde rutas Express

    • Métodos principales:

    • notificar(data, destino): Envía notificaciones

    • mensaje(data, destino): Envía mensajes

    • notificarUsuario(userId, data): Notifica a usuario específico

    • mensajeRoom(room, data): Envía mensaje a sala específica

API Relay (Inmutable):

El sistema Relay implementa una API inmutable con 4 eventos y 4 destinos:

Eventos: * identificar: Identificación de usuario en el sistema * unirse: Unirse a una sala (room) específica * notificar: Envío de notificaciones en tiempo real * relay: Mensajería general en tiempo real

Destinos: * yo: Mensaje al mismo socket que emite * ustedes: Broadcast a todos los demás sockets (excepto el emisor) * nosotros: Broadcast a todos los sockets conectados * room: Mensaje a una sala específica (requiere room en data)

2.1.4 Almacenamiento de Datos

PostgreSQL (Cloud SQL):

PostgreSQL almacena todas las entidades del modelo de datos:

  • Todas las entidades del modelo de datos (RESERVATION, PAYMENT, CLIENT, etc.)

  • Relaciones entre entidades mediante claves foráneas

  • Índices para optimizar consultas de disponibilidad

  • Transacciones para garantizar consistencia de datos

  • Connection pooling para optimización de conexiones

Ver Modelo de Datos para más detalles.

Redis:

Redis es utilizado por el sistema Relay para:

  • Caché de sesiones WebSocket: Almacenamiento de sesiones activas

  • Adapter para Socket.io: Distribución de mensajes entre múltiples instancias del servidor Relay

  • Escalado horizontal: Permite que múltiples instancias de Relay compartan estado

  • Pub/Sub: Sistema de publicación/suscripción para notificaciones en tiempo real

  • Configuración: Mediante variable de entorno REDIS_URL

Apache Kafka:

Kafka es utilizado por el sistema Relay para:

  • Cola de mensajes: Procesamiento asíncrono de eventos del sistema Relay

  • Streaming de eventos: Captura y procesamiento de eventos en tiempo real

  • Persistencia de mensajes: Almacenamiento temporal de mensajes para garantizar entrega

  • Escalabilidad: Permite procesar grandes volúmenes de mensajes en tiempo real

  • Integración con Relay: Los eventos del sistema Relay se publican en topics de Kafka para procesamiento posterior

2.2 Capa 6: Presentación (Presentation Layer)

Serialización de Datos: * JSON para intercambio de datos entre frontend y backend * Content-Type: application/json; charset=utf-8 * Validación y sanitización de datos de entrada

Cifrado y Seguridad: * HTTPS/TLS para todas las comunicaciones * Certificados SSL gestionados por API reverse proxy y Caddy * Headers de seguridad: * X-Content-Type-Options: nosniff * X-Frame-Options: DENY * X-XSS-Protection: 1; mode=block * Referrer-Policy: strict-origin-when-cross-origin * Strict-Transport-Security (HSTS)

Compresión: * Gzip/Brotli para compresión de respuestas HTTP * Optimización automática por API reverse proxy y Caddy

2.3 Capa 5: Sesión (Session Layer)

Gestión de Sesiones: * OAuth2 local authentication para autenticación de usuarios * JWT (JSON Web Tokens) para gestión de sesiones * Tokens Bearer en header Authorization: Bearer <token> * Verificación de tokens JWT RS256 con claves públicas del IdP local (/.well-known/jwks.json) * Renovación automática de tokens expirados * Custom Claims para roles y permisos: * operator: Operador/Recepcionista * admin: Administrador * sudo: Super Usuario * trainer: Entrenador * user: Usuario regular (implícito)

Sesiones WebSocket (Realtime): * Socket.io para conexiones WebSocket persistentes * Sistema Relay para notificaciones en tiempo real * Namespace /realtime para eventos en vivo * Autenticación de sockets mediante Bearer Token

Middleware de Autenticación: * JWT OAuth2 middleware: Verificación de tokens JWT en cada request * Extracción de claims (roles) del token decodificado * Validación de expiración y formato del token * Manejo de errores de autenticación (401 Unauthorized)

Middleware de Autorización: * requireAdminAccess: Control de acceso para roles operator, admin, sudo * requireSudoAccess: Control de acceso exclusivo para rol sudo * requireAccountAccess: Control de acceso para usuarios regulares (sin roles administrativos) * requireTrainerAccess: Control de acceso para rol trainer * Validación de permisos antes de procesar requests (403 Forbidden)

2.4 Capa 4: Transporte (Transport Layer)

Protocolos de Transporte: * HTTP/1.1 y HTTP/2 para comunicación REST * WebSocket (WS/WSS) para comunicación en tiempo real * TCP para conexiones persistentes

Balanceo de Carga: * Caddy como reverse proxy y load balancer * Balanceo de carga entre instancias de Node.js * Terminación SSL/TLS automática * Health checks para instancias backend * Rate limiting y protección DDoS * Configuración automática de certificados Let’s Encrypt * Routing inteligente basado en paths y headers

Gestión de Procesos Backend: * PM2 para gestión del servicio Node.js * Gestión de procesos Node.js en producción * Auto-restart en caso de fallos * Balanceo de carga entre instancias PM2 * Monitoreo de recursos (CPU, memoria) * Logs centralizados * Zero-downtime deployments * Cluster mode para aprovechar múltiples cores

2.5 Capa 3: Red (Network Layer)

Protocolo IP: * IPv4 e IPv6 * DNS para resolución de nombres de dominio * Dominios configurados: * app.unosportclub.com.co - Aplicación principal * panel.unosportclub.com.co - Panel de operador * trainer.unosportclub.com.co - Panel de entrenador * control.unosportclub.com.co - Panel de control

API reverse proxy: * CDN global para distribución de contenido estático * Caché inteligente de assets * Redirecciones y rewrites configurables

Protocolos de Enlace: * Ethernet para conexiones cableadas * WiFi (802.11) para conexiones inalámbricas * Gestionado por infraestructura de red del proveedor

2.7 Capa 1: Física (Physical Layer)

Infraestructura Física: * Contenedor Docker unificado (nginx + Node) publicado en GHCR * PostgreSQL en host o servicio gestionado * TLS en borde (Caddy, reverse proxy del proveedor o certificado propio)

3. Componentes del Sistema

3.1 Frontend (Angular)

El frontend está organizado en 5 aplicaciones independientes:

  • src/ — App cliente (6100)

  • projects/panel/ — Panel operador (6101)

  • projects/trainer/ — Panel entrenador (6102)

  • projects/sudo/ — Panel sudo (6103)

  • projects/accounting/ — Contabilidad NIIF (6104)

  • projects/common/ — Librería compartida

Características: * Componentes reutilizables * Servicios de comunicación con API REST * Guards e interceptores para autenticación y autorización basada en rol * Signals para gestión de estado reactivo * Lazy loading para optimización de bundles

3.2 Backend (Node.js/Express)

El backend está implementado con Node.js y Express.js:

  • functions/server.js — Punto de entrada de la API REST

  • Express.js para rutas y middleware

  • PostgreSQL mediante driver nativo (+ BD contable opcional)

  • Autenticación OAuth2 local (OIDC + JWT)

  • Swagger/OpenAPI en /api-docs

Organización por Namespaces: * /admin/ - Operaciones administrativas * /account/ - Operaciones de cuenta de usuario * /trainer/ - Operaciones de entrenador * /sudo/ - Operaciones de super usuario * /public/ - Endpoints públicos * /accounting/ — Contabilidad NIIF

3.3 Almacenamiento de Datos

PostgreSQL: Almacena todas las entidades del modelo de datos (RESERVATION, PAYMENT, CLIENT, etc.), relaciones mediante claves foráneas, índices para optimizar consultas, transacciones ACID y connection pooling optimizado.

Redis: Utilizado por el sistema Relay para caché de sesiones WebSocket, adapter para Socket.io, escalado horizontal y sistema pub/sub.

Apache Kafka: Utilizado por el sistema Relay para cola de mensajes, streaming de eventos, persistencia de mensajes y procesamiento asíncrono de eventos.

3.4 Autenticación (OAuth2 local IdP)

OAuth2 local IdP proporciona autenticación (email, teléfono según configuración), emisión de JWT RS256, verificación en backend y claims de rol (operator, admin, sudo, trainer, accounting). La tabla user almacena local_id como vínculo con el IdP.

4. Estructura del Proyecto

unosportclub/
├── src/                      # Aplicación principal (Cliente)
│   └── app/
│       ├── pages/           # Páginas de la aplicación
│       ├── services/         # Servicios Angular
│       ├── components/       # Componentes reutilizables
│       ├── guards/           # Route guards
│       └── interceptors/      # HTTP interceptors
├── projects/
│   ├── panel/
│   ├── trainer/
│   ├── sudo/
│   ├── accounting/
│   └── common/
├── functions/
│   ├── server.js
│   ├── routes/
│   ├── db/
│   └── utils/
├── docs/
├── docker/
└── Dockerfile

5. Flujos de Datos

5.1 Flujo de Autenticación

  1. Usuario ingresa credenciales en frontend

  2. Frontend llama a OAuth2 local IdP

  3. OAuth2 local IdP valida y retorna token JWT

  4. Frontend almacena token

  5. Frontend envía token en header Authorization: Bearer <token>

  6. Backend verifica JWT con claves del IdP local

  7. Backend extrae claims (roles) del token

  8. Middleware valida permisos según ruta

  9. Si autorizado, procesa request

  10. Retorna respuesta al frontend

5.2 Flujo de Reserva

  1. Usuario selecciona tipo de cancha

  2. Frontend consulta disponibilidad (/account/courts)

  3. Backend consulta PostgreSQL para disponibilidad

  4. Usuario selecciona fecha/hora

  5. Frontend valida disponibilidad localmente

  6. Usuario completa detalles de reserva

  7. Frontend envía creación de reserva (/account/bookings)

  8. Backend valida disponibilidad en BD

  9. Backend crea reserva en transacción

  10. Backend notifica vía Relay (si está habilitado)

  11. Frontend actualiza UI con nueva reserva

5.3 Flujo de Pago

  1. Usuario inicia proceso de pago

  2. Frontend consulta tipos de pago (/account/payment-types)

  3. Usuario selecciona tipo y completa datos

  4. Frontend envía pago (/account/payments)

  5. Backend procesa pago

  6. Backend actualiza estado de reserva relacionada

  7. Backend notifica vía Relay

  8. Frontend actualiza UI

5.4 Flujo de Registro

  1. Usuario completa formulario de registro

  2. Frontend valida datos localmente

  3. Frontend llama a AuthService.register()

  4. Se crea usuario en OAuth2 local IdP

  5. Se obtiene token JWT

  6. Frontend llama a /account/client con token

  7. Backend crea registro en PostgreSQL

  8. Backend sincroniza con tabla user

  9. Frontend redirige a dashboard

5.5 Flujo de Creación de Cliente con Usuario IdP Existente

Cuando el usuario ya existe en OAuth2 local IdP:

  1. Administrador accede al formulario de creación de cliente

  2. Administrador proporciona email o identificador del IdP

  3. Backend verifica existencia en IdP y obtiene local_id

  4. Backend busca o crea fila en user vinculada por local_id

  5. Backend crea registro en client con el user_id obtenido

  6. Retorna 201 Created o error (400, 409) según validaciones

6. Seguridad

6.1 Autenticación

  • OAuth2 local IdP maneja la autenticación de usuarios

  • Tokens JWT para sesiones

  • Validación de tokens en cada petición a la API

  • Refresh tokens para renovación automática

  • Bearer Token Authentication mediante header Authorization: Bearer <token>

6.2 Autorización

  • Roles y permisos por usuario (OPERATOR, ADMIN, SUDO, TRAINER, USER)

  • Validación en backend

  • Guards en frontend (Angular)

  • Verificación de permisos antes de operaciones sensibles

  • Middleware de autorización por namespace

Sistema de Roles: * operator: Operador/Recepcionista * admin: Administrador * sudo: Super Usuario * trainer: Entrenador * user: Usuario regular (implícito, sin claim)

6.3 Base de Datos

  • Conexiones seguras mediante SSL/TLS

  • Prepared statements para prevenir SQL injection

  • Validación de datos en múltiples capas

  • Transacciones para operaciones críticas

  • Connection pooling optimizado

6.4 Protección contra Ataques Comunes

  • SQL Injection: Prevenido mediante prepared statements

  • XSS (Cross-Site Scripting): Prevenido mediante sanitización y Content Security Policy

  • CSRF (Cross-Site Request Forgery): Protegido por OAuth2 local IdP y SameSite cookies

  • DDoS: Rate limiting mediante Caddy

  • Man-in-the-Middle: Prevenido mediante HTTPS/TLS obligatorio

7. Escalabilidad

7.1 Frontend

  • Lazy Loading: Carga diferida de módulos

  • Code Splitting: División automática de bundles

  • Service Workers: Caché y funcionalidad offline

  • Optimización de Imágenes: NgOptimizedImage

  • CDN: API reverse proxy con distribución global

7.2 Backend

  • PM2 Cluster Mode: Aprovecha múltiples cores del servidor

  • Connection Pooling: Pool de conexiones PostgreSQL optimizado

  • Caching: Caché de consultas frecuentes (disponibilidad) mediante Redis

  • Rate Limiting: Límites de requests configurables mediante Caddy

  • Caddy Load Balancing: Distribución de carga entre instancias

  • Auto-scaling: Escalado horizontal mediante PM2 y Caddy

7.3 Base de Datos

  • Índices: Optimización de consultas frecuentes

  • Transacciones: Consistencia de datos ACID

  • Escalado Vertical/Horizontal: PostgreSQL escalable (Cloud SQL)

  • Connection Pooling: Gestión eficiente de conexiones

  • Backups Automáticos: Cloud SQL gestiona backups automáticos

7.4 Sistema Realtime

  • Redis Adapter: Distribución de mensajes entre múltiples instancias del servidor Relay

  • Apache Kafka: Procesamiento asíncrono de eventos y streaming de mensajes

  • Load Balancing: Caddy distribuye conexiones WebSocket entre instancias

  • Escalado Horizontal: Redis y Kafka permiten escalar el sistema Relay horizontalmente

  • TODO: Implementar métricas de conexiones activas y monitoreo

8. Integraciones

8.1 Gateway de Pagos

  • Webhook para recibir notificaciones de pagos

  • Procesamiento asíncrono de pagos huérfanos

  • Alineación automática de pagos con reservas

  • TODO: Documentar integración específica de gateway de pagos

8.2 WebSocket (Sistema Relay)

  • Notificaciones en tiempo real de:

  • Pagos recibidos

  • Cambios de estado de reservas

  • Disponibilidad actualizada

  • Mensajería en tiempo real entre usuarios

  • Salas (rooms) para comunicación grupal

8.3 OAuth2 local (IdP)

  • Emisión y validación de JWT RS256

  • Endpoints OIDC (/oauth/, /.well-known)

  • Integración con tabla user.local_id

9. Infraestructura de Despliegue

Despliegue principal v0.4: imagen Docker unificada (nginx + Node) publicada en GHCR; tags staging y vX.Y.Z. Ver Despliegue y Diagramas.

9.1 Imagen unificada (producción v0.4)

Internet / DNS
  ↓
Caddy o proxy TLS (opcional)
  ↓
Contenedor unosport (puerto 80)
  ├── Nginx → SPAs estáticas por Host
  └── Node :5000 → /api, /oauth/, /socket.io
      ↓
PostgreSQL (+ DB_NAME_ACCOUNTING)

9.2 Referencia legado (pre-v0.4)

Algunos entornos antiguos usaban PM2 + Caddy con varias imágenes. No es el modelo recomendado para nuevos despliegues.

10. Diagrama de Arquitectura

┌─────────────────────────────────────────────────────────────┐
│                    CAPA 7: APLICACIÓN                        │
├─────────────────────────────────────────────────────────────┤
│  Frontend Angular (5 aplicaciones)                          │
│  ├── src/ (Cliente)                                         │
│  ├── projects/panel/ (Operador)                            │
│  ├── projects/trainer/ (Entrenador)                        │
│  ├── projects/sudo/ (Sudo)                                   │
│  └── projects/accounting/ (Contabilidad)                   │
│                                                             │
│  Backend Express.js (functions/server.js)                  │
│  └── /api/* (admin, account, trainer, sudo, accounting)    │
│                                                             │
│  Sistema Relay (Socket.io)                                  │
│  └── /realtime (WebSocket para notificaciones)             │
└─────────────────────────────────────────────────────────────┘
                            │
                            │ HTTP/REST + WebSocket
                            │
┌─────────────────────────────────────────────────────────────┐
│                    CAPA 4: TRANSPORTE                       │
├─────────────────────────────────────────────────────────────┤
│  Docker (nginx :80 + Node API) o Caddy delante              │
└─────────────────────────────────────────────────────────────┘
                            │
                            │ TCP/IP
                            │
┌─────────────────────────────────────────────────────────────┐
│                    CAPA 3: RED                               │
├─────────────────────────────────────────────────────────────┤
│  DNS: app / panel / trainer / control / accounting          │
└─────────────────────────────────────────────────────────────┘
                            │
                            │
┌─────────────────────────────────────────────────────────────┐
│                    CAPA 5: SESIÓN                           │
├─────────────────────────────────────────────────────────────┤
│  OAuth2 local authentication                                    │
│  ├── JWT Tokens                                             │
│  ├── Custom Claims (Roles)                                  │
│  └── Token Verification                                     │
└─────────────────────────────────────────────────────────────┘
                            │
                            │
┌─────────────────────────────────────────────────────────────┐
│                    CAPA 7: APLICACIÓN (BD)                   │
├─────────────────────────────────────────────────────────────┤
│  PostgreSQL (Cloud SQL)                                     │
│  ├── Connection Pooling                                     │
│  ├── Transactions (ACID)                                    │
│  └── Indexes                                                │
│                                                             │
│  Redis                                                      │
│  ├── Caché de sesiones WebSocket                           │
│  ├── Socket.io Adapter                                      │
│  └── Pub/Sub para Relay                                     │
│                                                             │
│  Apache Kafka                                               │
│  ├── Cola de mensajes                                       │
│  ├── Streaming de eventos                                   │
│  └── Procesamiento asíncrono                               │
└─────────────────────────────────────────────────────────────┘