Saltar al contenido principal

arquitecture


Arquitectura del Sistema

Enfoque Database-Centric

Este sistema rompe el paradigma tradicional donde el backend contiene las reglas de negocio. Aquí toda la lógica vive en la base de datos.

Regla de oro: el backend es "tonto" y la base de datos es "inteligente". Ninguna validación compleja, cálculo o flujo de negocio se escribe en el servidor de aplicaciones.

Roles de cada componente

Motores de Base de Datos

El sistema usa dos motores, cada uno con un propósito distinto:

  • SQL Server (ControlDB) — base de control interna. Guarda usuarios, referencias de aprovisionamiento, auditoría y métricas. Ejecuta el 100% de su lógica mediante Stored Procedures, Views y Functions.
  • MySQL — motor donde se aprovisionan las bases de datos reales de los estudiantes. Su propio Stored Procedure crea la base física, el usuario MySQL, genera la contraseña y asigna permisos — todo dentro del motor, sin lógica en el backend.

Backend (.NET Web API)

  • Middleware de paso: expone endpoints HTTP.
  • Gestiona autenticación/autorización (JWT, OAuth Google/GitHub).
  • Aplica Rate Limiting (particionado por usuario autenticado, con fallback a IP).
  • Invoca los Stored Procedures/Functions/Views correspondientes.
  • Mapea resultados de la base de datos hacia el cliente. No transforma ni decide reglas de negocio.

Únicas excepciones de lógica en el backend (justificadas por seguridad, no por conveniencia):

  • Hasheo de contraseñas locales con BCrypt (nunca deben llegar en texto plano a la base).
  • Generación de la contraseña aleatoria de MySQL antes de invocar el SP de aprovisionamiento.
  • Construcción y validación del JWT.

Patrón de diseño

Se usa Repository Pattern + Dependency Inversion Principle (DIP): Controller → IRepository (interfaz, en Domain) → Repository (implementación, en Infrastructure) → SP/Function/View

El controlador y los servicios del backend solo conocen la interfaz — nunca la implementación concreta ni el motor de base de datos por debajo. Esto permite, por ejemplo, tener IDatabaseProvisioningRepository (SQL Server) e IMySqlProvisioningRepository (MySQL) coexistiendo sin que el resto del sistema necesite saber cómo cada uno habla con su motor.

Flujo de autenticación y aprovisionamiento

  1. El usuario se registra/inicia sesión (local, Google o GitHub).
  2. El backend valida credenciales o intercambia el code de OAuth por los datos del usuario.
  3. Un Stored Procedure (sp_RegisterUser, sp_UpsertOAuthUser) crea o reconoce al usuario — fusionando cuentas si el mismo email se usa en distintos proveedores, para no duplicar usuarios.
  4. Si es la primera vez que el usuario obtiene acceso, el backend invoca al SP de MySQL para aprovisionar automáticamente su base de datos.
  5. Se registra la referencia en ControlDB y un evento de auditoría.
  6. Se devuelve un JWT al cliente (frontend), que lo usa en cada petición autenticada posterior.

Seguridad aplicada

  • Contraseñas locales: hash con BCrypt.
  • Contraseñas de MySQL: generadas criptográficamente, mostradas una sola vez al usuario, nunca almacenadas.
  • SQL Server y MySQL corren en Docker, aislados; SQL Server solo accesible en localhost. MySQL se expone controladamente (ver servidor.md) porque los estudiantes necesitan conectarse directo a sus bases.
  • Cada usuario MySQL tiene permisos únicamente sobre su propia base (verificado: un usuario no puede ver ni tocar la base de otro).
  • Rate limiting por usuario/IP en endpoints sensibles.
  • Todos los secretos (JWT key, connection strings, OAuth secrets) viven fuera del repositorio, como variables de entorno en el servidor.