Documento Visión general Vista general Componentes Capas del backend Flujos principales Visión general Plantilla de ADR ADR-0001: Monolito modular con capas limpias en el backend ADR-0002: CQRS ligero: escrituras por dominio, lecturas optimizadas ADR-0003: Frontend modular por funcionalidad con capas ADR-0004: TypeScript en el frontend ADR-0005: Quasar como librería de interfaz ADR-0006: Contrato de la API: REST versionada, respuestas y errores ADR-0007: MySQL 8.4 LTS como base de datos ADR-0008: Estado y prioridad como tablas catálogo ADR-0009: Sin relaciones polimórficas: toda referencia es una FK ADR-0010: ULID público y BIGINT interno ADR-0011: Borrado lógico, usuarios desactivados y FK con RESTRICT ADR-0012: Bloqueo optimista en incidentes ADR-0013: Búsqueda por texto con índice FULLTEXT ADR-0014: Estrategia de crecimiento por etapas, sin particionamiento ADR-0015: Autenticación con Laravel Sanctum y token Bearer ADR-0016: Argon2id y política de contraseñas ADR-0017: MFA con TOTP para todos los usuarios ADR-0018: Recuperación de contraseña por correo y TOTP ADR-0019: Cifrado en tránsito y en reposo ADR-0020: El backend como única autoridad ADR-0021: Roles construidos sobre permisos granulares ADR-0022: Logs del sistema: solo eventos relevantes, agrupados por huella ADR-0023: Acciones de sistema dentro del alcance de la aplicación ADR-0024: Tiempo real con Reverb y mensajes sin datos ADR-0025: Contenedores: gateway de origen único y una sola imagen de Laravel ADR-0026: Despliegue en VPS con el mismo docker compose ADR-0027: Diseño por tokens, mobile first y estilos por bloque de vista ADR-0028: Identidad visual de Trazo ADR-0029: Gráficos con componentes SVG propios ADR-0030: Dashboard personalizable guardado en el servidor ADR-0031: Estrategia de pruebas ADR-0032: Análisis estático, estilo y seguridad automatizada ADR-0033: Flujo de Git con cuatro ramas ADR-0034: CI/CD con GitHub Actions y promoción de la misma imagen ADR-0035: Documentación en Markdown, con ADR y trazabilidad al código ADR-0036: Exportación en CSV ADR-0037: Idempotency-Key en la creación de incidentes ADR-0038: Versiones del stack ADR-0039: Quasar integrado como plugin de Vite ADR-0040: Axios como base del cliente HTTP ADR-0041: El CI prueba el backend dentro del stack de Docker ADR-0042: Duración de la sesión y bloqueo progresivo por huella del correo ADR-0043: Reglas de acceso a incidentes en una sola clase de dominio ADR-0044: Listado de incidentes filtrado en SQL con la misma regla de visibilidad ADR-0045: Listado en el front con los filtros en la URL y una presentación por vista ADR-0046: Pruebas E2E en las cuatro vistas, con axe bloqueante y sesión por la API ADR-0047: Métricas del dashboard con la visibilidad del listado y caché invalidada por cambios ADR-0048: Diseño del dashboard guardado widget por widget, con los ocultos en su lugar ADR-0049: La sesión solo se cierra cuando la API la rechaza ADR-0050: Editor del dashboard con grid-layout-plus, sin sus estilos inyectados y con alternativa de teclado ADR-0051: MFA en la práctica: token de un ingreso a medias, sin atajo local y avisos por correo ADR-0052: Recuperación y cambio de contraseña: pase de un solo uso, HMAC, Have I Been Pwned y segundo factor ADR-0053: Administración de usuarios: jerarquía por nivel, permisos por persona y reautenticación ADR-0054: La matriz de permisos se siembra solo para roles y permisos nuevos ADR-0055: Edición de roles: rol de la cima bloqueado, nivel único, roles de sistema y sin correo masivo ADR-0056: Auditoría global: dos registros con permisos separados, alcance por jerarquía y paginación por cursor ADR-0057: Tiempo real en la práctica: canales por alcance, avisos sin datos y Reverb detrás del gateway ADR-0058: Exportación en la práctica: CSV para Excel en español, tope de filas y registro en la auditoría ADR-0059: Sistema en la práctica: salud medida desde la app, eventos agrupados y acciones con reautenticación ADR-0060: Pasada de calidad: CSP estricta, CORS cerrado, contrato OpenAPI, ZAP y cobertura exigida ADR-0061: Entrega verificada desde cero ADR-0062: Correos cifrados en la cola ADR-0063: Pantalla que no se descarga ADR-0064: Respaldo diario de MySQL ADR-0065: Documentación de funciones ADR-0066: Llave de la app sin depender del entrypoint ADR-0067: Pantallas precompiladas en desarrollo ADR-0068: El modo final es el que arranca por defecto ADR-0069: Al cambiar de rol, la persona queda con los permisos exactos del rol nuevo ADR-0070: Rechazar contraseñas predecibles aunque sean largas ADR-0071: Nota al cambiar de estado y reapertura con aprobación ADR-0072: Asignarse el incidente al crearlo ADR-0073: Largo del título de un incidente ADR-0074: Código del incidente por año ADR-0075: Menús que se abren donde caben ADR-0076: Conversación del incidente ADR-0077: Centro de notificaciones ADR-0078: Mis incidentes (Kanban, Lista, Calendario y Mi día) ADR-0079: Menú en un dock abajo y centrado, sin encabezado ADR-0080: Listado de incidentes como lista agrupada con el avance del plazo ADR-0081: Dashboard centrado en el riesgo ADR-0082: Formulario del incidente que guía mientras se escribe ADR-0083: Detalle del incidente con su camino, el siguiente paso y una sola actividad ADR-0084: Detalle con historial reciente, ficha a la par y un panel de chat y actividad ADR-0085: Avisos de coordinación para quienes reparten el trabajo ADR-0086: Nombres y apellidos por separado, con el nombre completo calculado por la base ADR-0087: Cuentas por rol creadas desde el entorno del servidor ADR-0088: Despliegue detrás del proxy de TLS que ya existe en el servidor ADR-0089: Incidentes de muestra en el sitio de evaluación ADR-0090: Una validación por ruta Visión general Mejoras aplicadas Mejoras propuestas
Estado: Aceptada
Fecha: 2026-10-31
Contexto
El sistema debe crecer en datos y en usuarios sin romperse ni volverse difícil de mantener. La tabla que más crece es la de actividades, porque cada incidente genera varias.
Alternativas evaluadas
Optimizar solo cuando aparezcan problemas.
Particionar las tablas grandes desde el inicio.
Una estrategia por etapas, con lo esencial desde el primer día.
Decisión
Una estrategia por etapas.
Desde el primer día:
Ids BIGINT.
Paginación obligatoria, con un máximo de registros por página impuesto en el backend.
Índices validados con EXPLAIN sobre más de 100.000 registros.
Caché del dashboard.
Registro de consultas lentas.
API sin estado, que escala de forma horizontal.
Documentado para etapas siguientes: réplica de lectura, tabla resumen del dashboard, archivado de registros antiguos y motor de búsqueda externo.
Migraciones: solo aditivas, con el patrón expand/contract .
Alternativas descartadas
Optimizar sobre la marcha: los problemas de rendimiento aparecen cuando ya hay usuarios afectados.
Particionamiento: en MySQL, las tablas particionadas no admiten claves foráneas, y eso rompería la integridad definida en el ADR-0009. El archivado cumple el mismo objetivo y conserva las FK.
Consecuencias
El costo inicial es bajo, y cada etapa siguiente ya tiene un camino definido.