Skip to content

Deuda técnica y hallazgos

Inventario de bugs, inconsistencias, código muerto y riesgos detectados durante el análisis del código. No se ha modificado ningún archivo: este documento es solo un informe.

1. Bugs probables

#UbicaciónDescripciónImpactoSugerencia
B1backend/src/controllers/ejercicio.controller.ts vs backend/src/routes/ejercicio.routes.tsLa ruta define DELETE /:ejercicioId/sedes/:id y .../sedes/:ejercicioSedeId/aulas/:id, pero el controlador leía req.params.ejercicioSedeId/req.params.ejercicioSedeAulaId (inexistentes → undefined).Quitar aula/sede podía fallar u operar sobre undefined.Renombrar el param o leer req.params.id. Resuelto: el controlador lee req.params.id.
B2backend/src/controllers/notificacion.controller.tsconst userId = (req as any).user?.id; — el middleware puebla req.currentUser, no req.user.created_by de la notificación queda null.Usar (req as AuthenticatedRequest).currentUser?.id. Resuelto.

2. Inconsistencias

#UbicaciónDescripciónSugerencia
I1AGENTS.md vs backend/src/enums/user-role.enum.tsLa guía documentaba 4 roles (superadmin, administrator, supervisor, user), pero el código implementa 3 (SUPERADMIN, ADMIN, SUPERVISOR).Actualizar AGENTS.md... Resuelto: AGENTS.md ya refleja los tres roles reales.
I2backend/src/services/user.service.ts:143-151GET /users devuelve { items, meta }, mientras el resto de listados devuelve { data, total, page, limit, totalPages }.Unificar el contrato de paginación.
I3backend/src/config/env.config.ts:63 vs deploy/podman/podman-compose.yml:30 y deploy/docker/.env.prod:31El default de RATE_LIMIT_MAX en código es 200, pero los compose usan 3000.Alinear el valor por defecto.
I4backend/src/migrations/1718300001100-InsertDefaultUsers.ts:91-109Crea siempre las cuentas de desarrollo (Laura ADMIN y Supervisor) independientemente de NODE_ENV, pese al comentario de backend/.env:20 ("NO se crean en producción").Condicionar a NODE_ENV !== "production" o eliminarlas del arranque productivo.
I5deploy/docker/desplegar_en_servidor.sh:133Genera el .env.prod remoto transformando el .env.prod local, ignorado por git (.gitignore:15); en un clon limpio falla.Versionar un .env.prod.example y documentar su creación. Resuelto: se versiona .env.prod.example y se documenta cp .env.prod.example .env.prod.
I6deploy/docker/docker-compose.yml:36-44El stack "de producción" incluye mailpit (capturador de correo) en lugar de un SMTP real.Parametrizar SMTP corporativo y excluir Mailpit en producción.
I7deploy/docker/.env.prod:28CORS_ORIGIN con IP fija 192.168.1.80 y credenciales por defecto débiles.Externalizar y rotar secretos.
I8backend/Dockerfile:1 y frontend/Dockerfile:1 (node:24) vs documentation/Dockerfile:1 (node:22)Versiones de Node diferentes entre imágenes.Unificar la versión base.
I9backend/src/migrations/1718300001000-CreateTables.ts vs backend/src/entities/email-template.entity.tsLa migración añade search_normalized a email_templates, no declarada en la entidad.Alinear entidad y esquema.
I10backend/src/entities/ejercicio.entity.tscerrado_por existe como columna sin FK ni relación.Añadir FK/relación con User o documentar la ausencia.
I11backend/src/config/swagger.config.tsLa especificación no declara components.securitySchemes.bearerAuth pese a referenciarlo en las anotaciones.Declarar el esquema de seguridad en Swagger.
I12frontend/vite.config.ts:24console.log("Proxy response:", ...) en cada petición proxyada.Eliminar o depurar tras un flag. Resuelto: eliminado.
I13deploy/local/siva.sh:79 y deploy/local/siva.sh:86Compila el backend (npm run build) y acto seguido arranca en dev (tsx watch), sin usar dist.Eliminar el build redundante.
I14backend/src/routes/tribunal-miembro.routes.ts:16-21Los handlers no usan asyncHandler (el router queda sin envolver; solo funciona porque los métodos del controlador ya están envueltos).Envolver también en el router por consistencia.

3. Mantenibilidad

Componentes y servicios monolíticos

FicheroLíneas
frontend/src/components/ejercicios/modals/GestionarVigilantesModal.vue4.699
frontend/src/components/ejercicios/modals/GestionarAsignacionesModal.vue4.560
frontend/src/components/vigilantes/modals/ImportVigilantesModal.vue2.029
frontend/src/components/ejercicios/modals/QuickAssignResultsPanel.vue2.023
frontend/src/components/ejercicios/modals/GestionarUbicacionesModal.vue1.861
frontend/src/pages/dashboard/ConfiguracionPage.vue1.058
frontend/src/components/ejercicios/modals/QuickAssignModal.vue1.056
backend/src/services/ejercicio.service.ts1.292
backend/src/services/simulation.service.ts1.289
backend/src/services/notificacion.service.ts1.047

Sugerencia: extraer subcomponentes/composables (frontend) y dividir servicios por caso de uso (backend), apoyándose en los tests existentes.

Uso de any

  • ~138 ocurrencias de as any en backend/src (p. ej. services/user.service.ts:237,397, services/vigilante.service.ts:347,676, services/asignacion.service.ts:648-649,715,838, services/simulation.service.ts:1241) y ~22 en frontend/src.
  • Sugerencia: tipar las entidades TypeORM y los req con AuthenticatedRequest; eliminar los as any de migraciones y servicios.

Dependencias y código muerto

  • supertest y @types/supertest no se usan en los tests (no hay tests de integración HTTP). Dependencia muerta. Resuelto: eliminadas junto a @types/uuid (uuid ya incluye tipos) y @vue/tsconfig en el frontend.
  • Artefactos de build presentes en disco (frontend/vite.config.js, vite.config.d.ts, *.tsbuildinfo); están en .gitignore pero conviene limpiarlos.
  • documentation/scripts/crop-modals.py sin referencia en la documentación. Resuelto: eliminado, junto a documentation/podman-compose.dev.yml y documentation/Dockerfile.dev.
  • Assets duplicados entre backend/public/ y deploy/podman/public/ (copia manual vía deploy/podman/setup.sh). Resuelto: backend/public/ es la fuente única y deploy/podman/public/ se genera con setup.sh (ignorado por git).

Ausencias notables

  • No hay lint/format: no existen .eslintrc*, .prettierrc*, .editorconfig, biome.json ni scripts lint/format. El único control estático es el typecheck.
  • No hay CI/CD (.github/workflows, .gitlab-ci.yml, etc.).
  • No hay .env.example en ningún directorio. Resuelto: se añaden backend/.env.example, frontend/.env.example y deploy/docker/.env.prod.example.
  • No hay README raíz ni LICENSE/CHANGELOG (este análisis añade el README.md).
  • El backend no tiene tests de controladores ni middleware (solo servicios y metadatos).

Tests

  • Backend: 7 ficheros, 33 casos (backend/src/__tests__/), con mocks; sin BD real.
  • Frontend: 67 ficheros, 691 casos.
  • Sugerencia: añadir tests de integración HTTP (aprovechando supertest) y cubrir los bugs B1/B2 como regresión.

4. Riesgos de seguridad / operación

#HallazgoRiesgoSugerencia
S1Cuentas de desarrollo con contraseñas conocidas creadas en cualquier entorno (I4)Acceso no autorizado en producciónNo crear en producción y forzar cambio de credenciales.
S2JWT_SECRET por defecto en compose (siva-jwt-secret-change-in-production)Falsificación de tokensExigir secreto fuerte; ya se genera aleatorio en el script de despliegue.
S3GET /api/files/download/:objectName sin autenticaciónDescarga de ficheros por quien conozca el nombreEvaluar añadir autenticación o URLs firmadas.
S4POST /api/auth/* sin verificación de email obligatoria en el altaCuentas no verificadasYa se exige is_email_verified en login.

5. Estado general

El código está tipado de forma estricta y sin TODO/FIXME/@ts-ignore en src, con buena cobertura de tests en el frontend y contrato de respuestas uniforme. Los principales focos son: los dos bugs concretos (B1, B2), la gestión de las cuentas y secretos de desarrollo, la ausencia de lint/CI y el tamaño de algunos componentes y servicios.

6. Backlog de mejoras

Este informe es un diagnóstico puntual. El plan de acción priorizado, con IDs, criterios de aceptación, dependencias y estado para ejecutar las mejoras una a una, se mantiene en MEJORAS.md. Dicho backlog recoge los hallazgos de este documento y los de las auditorías de seguridad, accesibilidad, rendimiento, testing, CI/CD y operación.

SIVA — Sistema Integral de Vigilantes de Aulas