326 lines
37 KiB
Markdown
326 lines
37 KiB
Markdown
# Changelog Oficial — Admin Edu-Space (UniCABA)
|
|
|
|
Todas las modificaciones notables a este proyecto serán documentadas en este archivo.
|
|
El formato está basado en [Keep a Changelog](https://keepachangelog.com/es-ES/1.1.0/) y este proyecto se adhiere a [Semantic Versioning](https://semver.org/lang/es/).
|
|
|
|
---
|
|
|
|
## [Unreleased]
|
|
### Planificado (Fase 6 del Roadmap MVP)
|
|
- **Despliegue e Infraestructura (Fase 6):** `docker-compose.yml` productivo orquestando Flask (Gunicorn), Node.js BFF (PM2) y PostgreSQL 15, con proxy inverso Nginx, SSL/TLS y compresión.
|
|
- **Sincronización Continua Moodle (Fase 6):** Automatización de workers persistentes en background para el procesamiento continuo de la cola de Web Services Moodle 4.1.
|
|
- **Pruebas de Carga y Hardening (Fase 6):** Pruebas de estrés de concurrencia y validación final de producción.
|
|
|
|
---
|
|
|
|
## [3.1.0] - 2026-09-23
|
|
### Añadido
|
|
- **ABM Integral de Ciclos Lectivos (`AcademicTerm`):**
|
|
- **Gestión End-to-End de Períodos Académicos:** Implementación de ciclo de vida completo para ciclos lectivos: Alta, Edición, Establecimiento de Ciclo Actual, Toggle de Habilitación rápida y Eliminación protegida (`DELETE /api/v1/admin/academic-terms/<id>` y `POST /api/v1/admin/academic-terms/<id>/toggle`).
|
|
- **Integridad Relacional Protegida:** Bloqueo de eliminación si el ciclo es el activo corriente, y fallback seguro a desactivación (`is_active = False`) si el ciclo tiene comisiones históricas asociadas.
|
|
- **Interfaz Enriquecida en Bedelía / Admin:** Botones de acción contextuales, switches y modales interactivos de confirmación (`#modalDeleteTerm`) en `frontend/views/admin/academic_terms/list.html`.
|
|
- **ABM Completo de Espacios y Aulas (`Classroom`):**
|
|
- **Control de Estado y Borrado Seguro:** Incorporación de toggle activo/inactivo (`POST /api/v1/classrooms/<id>/toggle`) y endpoint de baja de aulas integrado con el frontend BFF (`/classrooms/toggle_classroom` y `/classrooms/delete_classroom`).
|
|
- **Acciones Rápidas en Vista Lista y Ficha:** Botones de edición, alternancia de estado y eliminación con modales de advertencia en las vistas de cuadrícula/tabla (`list.html`) y detalle (`view.html`).
|
|
- **ABM Completo de Reservas (`Reservation`):**
|
|
- **Eliminación Definitiva (Hard Delete):** Soporte en backend para purga física de reservas (`DELETE /api/v1/reservations/<id>?hard=true` y `POST /api/v1/reservations/<id>/delete`) complementando el flujo de cancelación lógica (`CANCELLED`).
|
|
- **Control Operativo en Vista Detalle:** Botón de "Eliminar Reserva Definitivamente" con diálogo modal de confirmación en `/schedule/view.html`.
|
|
- **Auditoría y Cobertura 100% de ABMs en la Plataforma:**
|
|
- Verificación y garantía de operaciones ABM completas en todos los componentes centrales: **Sedes/Edificios** (`Building`), **Aulas** (`Classroom`), **Ciclos Lectivos** (`AcademicTerm`), **Carreras** (`Career`), **Materias** (`Subject`), **Comisiones** (`Commission`) y **Reservas** (`Reservation`).
|
|
- **Circuito Integral y Simplificado de Bedelía:**
|
|
- **Flujo Operativo Ágil para Bedelía:**
|
|
- Circuito intuitivo de 3 pasos: Catálogo de Aulas (`/classrooms/list_classrooms`) -> Creación/Edición con validación física/virtual y aforo real -> Asignación de Comisiones (`/schedule/add_reservation`).
|
|
- Botón de acción rápida `Asignar Aula` (`bi-calendar-plus`) en cada fila de `/admin/commissions_list`, permitiendo asignar espacio y horario a cualquier comisión en 1 solo clic.
|
|
- Sincronización bidireccional de parámetros por URL (`?commission_id=...` y `?classroom_id=...`) precargando automáticamente en el formulario de reserva la materia, código, cupo máximo de alumnos y enlace virtual de Google Meet / Teams.
|
|
- Selectores inteligentes en cascada en `/schedule/add.html` con autoselección de Edificio, Piso y Aula al navegar desde el catálogo de espacios.
|
|
- **Conexión REST en Vivo para Reservas:**
|
|
- Sustitución de listas fijas/mockeadas en `frontend/src/routes/schedule.js` por consulta dinámica a `/commissions` en vivo, permitiendo reservar aulas para cualquiera de las comisiones reales de la plataforma.
|
|
- **Soporte Multisede Consistente en Aulas:**
|
|
- Resolución robusta de `building_id` y flag `is_virtual` en `frontend/src/routes/classrooms.js`, eliminando hardcodes y asegurando que las aulas físicas pertenezcan a la sede seleccionada.
|
|
- **Personalización de Interfaz y Saludo en Dashboard (Configuración Global):**
|
|
- **Nueva Pestaña de Interfaz & Dashboard (`/admin/settings`):** Módulo en el panel de configuración global para personalizar elementos visuales del sistema.
|
|
- **Desactivación Opcional del Saludo y Selector de Rol:** Switch interactivo para habilitar o deshabilitar el banner superior `¡Hola, {Usuario}!` y el selector de perspectiva de roles en `dashboard.html`. Al deshabilitarlo, el usuario accede directamente a los indicadores y accesos operativos de su rol sin distracciones ni dudas de contexto.
|
|
- **Persistencia y Endpoint REST:** Parámetro `dashboard_role_banner_enabled` administrado vía `POST /api/v1/admin/settings/ui`, respaldado por `SystemSetting` y registrado en `AuditLog`.
|
|
|
|
### Corregido
|
|
- **Motor de Purga y Reinicio de Datos Académicos:**
|
|
- **Solución al botón inerte de Purga:** En `/admin/google_sheets_import`, el botón *"Ejecutar Purga de Datos Seleccionados"* llamaba a `openPurgeModal()`, el cual no ejecutaba ninguna acción por ausencia del modal `#purgeConfirmModal` en el DOM. Se incorporó el modal interactivo completo con desglose dinámico de elementos marcados para borrado, advertencia de preservación de usuarios y estado de carga (spinner).
|
|
- **Integridad Referencial en Purga Backend:** En `backend/scripts/reset_academic_data.py`, se reordenó la secuencia de borrado para respetar las restricciones de clave foránea (FK): `Reservation` -> `MilestoneGrade` / `AcademicMilestone` -> `CommissionTeacher` -> `StudentEnrollment` -> `Commission` -> `Subject` -> `Career` -> `ClassroomResource` / `Classroom`. Esto previene fallos silenciosos por FK y garantiza que las carreras, asignaturas y comisiones se eliminen de manera limpia cuando son seleccionadas.
|
|
- **Preservación de Usuarios y Roles:** La purga garantiza que ningún usuario (`User`), contraseña administrativa ni rol (`Role`) sea alterado o eliminado durante el reseteo académico.
|
|
- **Saneamiento de Métricas y Edición de Edificios:**
|
|
- Corrección de métricas de edificios en `/buildings/list_buildings`: la capacidad virtual (9999) ya no distorsiona el cómputo de bancos físicos ni los percentiles de ocupación institucional.
|
|
- Formulario de edición de sedes (`/buildings/edit/:id`) corregido y persistido adecuadamente.
|
|
- **Instalador `install.sh`:**
|
|
- Inclusión de banderas `--keep-db` y `--keep-users` para evitar sobreescritura de contraseñas y usuarios en reinstalaciones o actualizaciones.
|
|
|
|
---
|
|
|
|
## [3.0.0] - 2026-09-23
|
|
### Añadido
|
|
- **Fase 5 — Integración Auth, Email & Moodle Backend:**
|
|
- **Épica 1: Panel de Configuración Global (Perfil ADMIN):**
|
|
- Cifrado simétrico de credenciales y secretos con Fernet (`CryptoService` en `backend/app/services/crypto_service.py`).
|
|
- Migración y extensión de `SystemSetting` con columnas `category` e `is_encrypted`, junto con métodos polimórficos `get_decrypted_value()` y `get_masked_value()`.
|
|
- Endpoints REST `/api/v1/admin/settings/*` para administración dinámica de parámetros SMTP, toggles de proveedores SSO, Google OAuth y Web Services de Moodle 4.1.
|
|
- Nueva vista responsiva `frontend/views/admin/settings/global_config.html` con soporte optimizado para pantallas 720p, 1360x768 y 1080p, y enlace integrado en el menú de navegación lateral.
|
|
- **Épica 2: Infraestructura Asíncrona y Caché:**
|
|
- Servicio híbrido de caché `CacheService` con integración Redis y fallback en memoria/TTL.
|
|
- Modelo `MoodleSyncTask` y procesador asíncrono `MoodleQueueService` con Exponential Backoff y Dead Letter Queue (DLQ).
|
|
- Métricas en vivo y reintentos manuales individuales y masivos para tareas en DLQ.
|
|
- **Épica 3: Autenticación Híbrida (SSO & Local):**
|
|
- Login nativo como fallback con contingencia para cuentas con rol ADMIN.
|
|
- Integración de Google OAuth 2.0 basada en la arquitectura de AlumnosLS con filtrado estricto por dominios institucionales (`google_allowed_domains`).
|
|
- Autenticación delegada contra Moodle 4.1 vía `/login/token.php`, mapeo inicial de roles (Admin/Docente/Alumno) y gestión de roles 100% desacoplada en Edu-Space.
|
|
- **Épica 4: Integración Bidireccional Moodle 4.1:**
|
|
- Adaptador `MoodleClient` con Web Services de Moodle 4.1 (`core_user_*`, `enrol_manual_*`, `core_enrol_*`, `core_role_*`).
|
|
- Encolado no bloqueante de sincronización al crear o editar usuarios en Edu-Space.
|
|
- **Épica 5: Motor de Notificaciones (Email Server):**
|
|
- Cliente SMTP dinámico en `EmailService` con desencriptación en caliente de contraseñas.
|
|
- Plantillas HTML transaccionales para asignación de comisiones a profesores, citación a exámenes y pruebas en vivo de conectividad.
|
|
- **Pruebas y Verificación:**
|
|
- Suite de integración automatizada `backend/tests/test_phase6_integration.py` con 7 pruebas aprobadas al 100%. Regresión completa de 30 pruebas en verde en los módulos core.
|
|
|
|
---
|
|
|
|
## [2.8.0] - 2026-09-23
|
|
### Añadido
|
|
- **Fase 4 del Roadmap MVP — UI/UX Avanzada para Bedelía & Modo Impersonación:**
|
|
- **Estadio 4.1 — Grilla Semanal Interactiva (Drag-and-Drop) con Detección de Colisiones:**
|
|
- Activación de arrastre y edición interactiva en FullCalendar (`editable: true`, `droppable: true`, `eventDurationEditable: true`).
|
|
- Panel lateral integrado de comisiones sin aula asignada (`unassigned_commissions`) con arrastre fluido hacia la grilla semanal o diaria.
|
|
- Endpoint REST `POST /api/v1/reservations/drag-update` con validación previa de la matriz integral de conflictos (`ReservationService.check_full_conflicts_matrix`): colisión física de aula, colisión de horario docente y aforo de estudiantes.
|
|
- Si existe colisión, retorna HTTP 409 (`status: conflict`), revierte automáticamente la posición del evento en la grilla (`info.revert()`) y notifica al usuario con un Toast detallado del motivo del choque.
|
|
- Si el espacio está disponible, actualiza o crea la reserva en base de datos, asienta la acción en `AuditLog` y muestra confirmación visual de éxito.
|
|
- **Estadio 4.2 — Modo Impersonación del Superadmin:**
|
|
- Soporte completo de cabecera `X-Impersonate-User` en el decorador JWT del Backend Flask (`jwt_required`) para administradores.
|
|
- Endpoints administrativos `POST /api/v1/admin/impersonate` y `POST /api/v1/admin/stop-impersonating` con registro estricto en `AuditLog` bajo las acciones `IMPERSONATE_START` e `IMPERSONATE_END`.
|
|
- Inyección contextual de impersonación en el Frontend BFF (`authMiddleware` y proxy transparente `/api`) mediante cookies seguras `impersonate_user_id` e `impersonate_user_data`.
|
|
- Banner de advertencia visual permanente en la barra superior (`base.html`) indicando el usuario y rol impersonado, con botón de salida inmediata hacia la sesión del administrador.
|
|
- Botón de acceso directo para impersonar (`bi-incognito`) en cada fila de usuario activo en `/admin/users_list`.
|
|
- **Estadio 4.3 — Acople del Optimizador Genético a Datos y Turnos Reales:**
|
|
- Algoritmo genético (`ReservationOptimizer`) adaptado a las franjas horarias y turnos institucionales reales de UniCABA (`Mañana` 08:00-12:00, `Tarde` 14:00-18:00, `Vespertino`/`Noche` 18:30-22:30).
|
|
- Soporte de guardado masivo en base de datos (`POST /api/genetic/apply-optimization` y `apply_optimized_reservations`) con prevención de solapamientos físicos y conversión estricta de fechas ISO.
|
|
- **Suite de Pruebas Unitarias de Fase 4:**
|
|
- Archivo `backend/tests/test_phase4_interactive_impersonation.py` con 6 tests unitarios cubriendo los criterios de aceptación: impersonación como docente y estudiante, trazabilidad en auditoría, rechazo de impersonación para usuarios no administradores, finalización de impersonación, drag-update con bloqueo por colisión 409 y drag-update exitoso 200.
|
|
- Regresión global de 18 tests (Fases 2, 3 y 4) aprobada al 100% (18/18 OK).
|
|
|
|
---
|
|
|
|
## [2.7.0] - 2026-09-23
|
|
### Añadido
|
|
- **Fase 3 del Roadmap MVP — Gestión de Hitos Evaluativos y Libro de Calificaciones (*Gradebook*):**
|
|
- **Estadio 3.1 — Calendario de Evaluación y Notificaciones Preventivas:**
|
|
- Modelo relacional `MilestoneGrade` (`milestone_grades`) asociado a estudiantes (`User`) y reservas de tipo hito (`Reservation`).
|
|
- Servicio `GradebookService.get_student_upcoming_milestones`: consulta inteligente de exámenes parciales, recuperatorios y entregas de TP de las comisiones en las que el alumno está matriculado.
|
|
- Endpoint REST `GET /api/v1/students/my-upcoming-milestones` con cálculo de días restantes (`days_remaining`).
|
|
- Cartelera y Widget de Próximos Exámenes en el Dashboard del Alumno (`/dashboard?role=alumno`) con badges dinámicos de cuenta regresiva (*¡Hoy!*, *¡Mañana!*, *Faltan X días*).
|
|
- **Estadio 3.2 — Libro de Calificaciones (*Gradebook*) y Cierre de Actas:**
|
|
- Extensiones al modelo `Commission`: campos `grades_closed` (booleano), `grades_closed_at` (timestamp), `grades_closed_by` (ID usuario) y `acta_number` (código oficial de acta).
|
|
- Servicio académico `GradebookService` (`backend/app/services/gradebook_service.py`):
|
|
- `get_commission_gradebook`: matriz bidimensional consolidada de alumnos inscriptos y notas por hito evaluativo.
|
|
- `save_single_grade` y `bulk_save_grades`: registro y actualización de calificaciones con validación estricta de escala (1.0 a 10.0), flag de ausente (`is_absent`) y soporte de retroalimentación pedagógica (`feedback`).
|
|
- Bloqueo por inmutabilidad: rechazo de modificaciones cuando el acta se encuentra cerrada.
|
|
- `close_gradebook`: sellado oficial del acta con generación de identificador inmutable (`ACTA-YYYY-Sem-ID`), registro de auditoría en `AuditLog` y congelamiento de calificaciones.
|
|
- `reopen_gradebook`: reapertura excepcional para Bedelía/Admin con justificación administrativa obligatoria y registro en auditoría.
|
|
- `get_student_grades`: consolidado para el alumno de todas sus materias cursadas, notas por evaluación, promedio general y condición académica final (*Promocionado*, *Regular*, *Libre*).
|
|
- Endpoints REST de Calificaciones:
|
|
- `GET /api/v1/commissions/<id>/gradebook`: estructura completa para la matriz del libro de calificaciones.
|
|
- `PUT /api/v1/commissions/<id>/gradebook/grades`: guardado masivo o individual de notas vía JSON.
|
|
- `POST /api/v1/commissions/<id>/gradebook/close`: cierre formal de acta.
|
|
- `POST /api/v1/commissions/<id>/gradebook/reopen`: reapertura justificada de acta.
|
|
- `GET /api/v1/students/my-grades`: consulta individual de notas y regularidad del estudiante.
|
|
- Interfaz de Usuario y Vistas Frontend BFF:
|
|
- Vista `/schedule/gradebook/:id`: matriz interactiva con cálculo de promedio en tiempo real en el DOM, asignación de condición en vivo, autoguardado asíncrono debounced (500ms) con indicador flotante de estado (*Guardando...*, *✓ Todos los cambios guardados*), filtro de búsqueda instantánea por alumno/legajo, modal de cierre formal de acta y modal de reapertura.
|
|
- Vista `/schedule/my_grades` (`/mis-materias/mis-notas`): portal del estudiante para consultar calificaciones por hito, promedios finales, condición de cursada y actas emitidas, con soporte de impresión de certificado de cursada.
|
|
- Acceso directo integrado al Libro de Calificaciones en la tarjeta de comisión de `/admin/commission_detail`.
|
|
- Acceso directo a "Mis Calificaciones" en el launchpad de navegación del alumno en `/dashboard`.
|
|
- Script de migración de base de datos SQLite `backend/migrate_phase3_fields.py`.
|
|
- **Suite de Pruebas Unitarias de Fase 3:**
|
|
- Archivo `backend/tests/test_phase3_gradebook.py` con 6 tests unitarios cubriendo los criterios de aceptación de Fase 3: estructura de matriz, autoguardado de notas, validaciones de rango numérico, cierre formal de acta e inmutabilidad, consulta individual de notas y cuenta regresiva de próximos exámenes. 100% de tests aprobados (12/12 en suite global Fase 2 + Fase 3).
|
|
|
|
---
|
|
|
|
## [2.6.1] - 2026-09-23
|
|
### Modificado
|
|
- **Optimización de Espacio Vertical y Compatibilidad de Pantallas (720p / 1360x768 y 1080p):**
|
|
- **Navbar Compacta:** Reducción de altura a 46px eliminando desperdicio de espacio superior para maximizar el área visible de trabajo de Bedelía.
|
|
- **Botón de Toggle de Sidebar:** Reingeniería visual del botón de alternancia del menú lateral con diseño circular limpio, micro-animación en hover y centrado perfecto.
|
|
- **Soporte Multipantalla:** Media queries CSS especializadas para resoluciones compactas habituales en puestos de trabajo de administración y bedelía argentina (1360x768 / 1366x768) y escalado equilibrado a 1920x1080 Full HD.
|
|
- **Densidad de Información:** Espaciados y márgenes optimizados para evitar scrolling innecesario en formularios y catálogos de comisiones y aulas.
|
|
|
|
---
|
|
|
|
## [2.6.0] - 2026-09-19
|
|
### Añadido
|
|
- **Fase 2 del Roadmap MVP — Co-docencia, Matriz de Conflictos y Regla Diaria:**
|
|
- **Estadio 2.1 — Modelo y Gestión Integral de Co-docencia:**
|
|
- Modelo relacional `CommissionTeacher` (`commission_teachers`) con roles de cátedra (`Titular`, `Adjunto`, `JTP`, `Ayudante`) y flags de docente principal.
|
|
- Endpoints REST de cátedra: `POST /api/v1/commissions/<id>/teachers` y `DELETE /api/v1/commissions/<id>/teachers/<user_id>` con control de duplicados y asignación dinámica.
|
|
- Integración visual en el detalle de la comisión (`/admin/commission_detail`) con tarjeta interactiva para vincular/desvincular integrantes del equipo docente y badges de rol en la grilla general (`/admin/commissions_list`).
|
|
- **Estadio 2.2 — Matriz de Conflictos y Validación Integral:**
|
|
- **Conflicto Físico Estricto:** Bloqueo estricto de superposición horaria en la misma aula física (`ReservationRepository.find_overlapping` & `check_physical_conflicts`).
|
|
- **Conflicto Docente Inteligente:** Detección de doble reserva simultánea para un mismo profesor (`ReservationRepository.find_teacher_conflicts` & `check_teacher_conflicts`).
|
|
- **Excepción Justificada por Co-docencia:** Si un docente asignado presenta solapamiento pero la comisión cuenta con co-docentes registrados en `CommissionTeacher`, el motor de conflictos autoriza la reserva validando la cobertura del equipo de cátedra.
|
|
- **Conflicto de Aforo:** Bloqueo estricto cuando la cantidad de asistentes esperados (`expected_attendees`) excede la capacidad física declarada del aula (`classroom.capacity`).
|
|
- Endpoint unificado `POST /api/v1/reservations/check-conflicts` para pre-validación asíncrona de conflictos físicos, docentes y de capacidad antes del guardado.
|
|
- **Estadio 2.3 — Regla de Restricción Diaria del Alumno y Motor de Excepciones:**
|
|
- Servicio académico `EnrollmentService` (`backend/app/services/enrollment_service.py`) para control de cupos, inscripciones activas y análisis de días de cursada.
|
|
- **Regla Diaria:** Un alumno no puede matricularse en dos materias regulares programadas para el mismo día de la semana.
|
|
- **Excepción Automática por Curso Corto:** Indicador `is_short_course` en modelo `Subject`; si una de las asignaturas es un taller, seminario o curso corto, el sistema autoriza automáticamente la cursada simultánea en el mismo día.
|
|
- **Excepción Expresa de Bedelía:** Parámetros `allow_same_day_exception` y `exception_reason` en el modelo `StudentEnrollment`, permitiendo a Bedelía inscribir alumnos con justificación administrativa expresa (cambio de plan, equivalencias, etc.).
|
|
- Endpoints de gestión de matrículas por comisión: `GET /api/v1/commissions/<id>/enrollments`, `POST /api/v1/commissions/<id>/enrollments`, `DELETE /api/v1/commissions/<id>/enrollments/<student_id>` y `PUT /api/v1/commissions/<id>/enrollments/<student_id>`.
|
|
- Adaptación completa de UI en `/admin/commission_detail` con selector de estudiantes, toggle interactivo de excepción de Bedelía, campo de motivo justificado, y tabla de estudiantes matriculados con badges de excepción.
|
|
- **Suite de Pruebas Unitarias e Integrales de Reglas de Negocio:**
|
|
- Archivo `backend/tests/test_phase2_rules.py` con 6 tests completos verificando: bloqueo físico, conflicto de aforo, detección docente con bypass de co-docencia, restricción diaria de cursada, excepción por curso corto y excepción por autorización manual de Bedelía. 100% de tests aprobados.
|
|
- **Mejoras UI/UX en Dashboard de Bedelía:**
|
|
- Paneles interactivos para visualizar **Comisiones Sin Reserva de Aula** y **Aulas Disponibles** con soporte de filtrado temporal (Semana/Mes) directamente consumiendo estadísticas en tiempo real del motor backend.
|
|
- **Fase 1: Auditoría y Seguridad Automatizada:**
|
|
- **Control de Entorno Dev:** Aislamiento de herramientas de seguridad en `requirements-dev.txt`.
|
|
- **Automatización Local e Integración Continua:** Correcciones de evaluación en `security_audit.bat` para Windows y actualización de `.gitea/workflows/security-audit.yaml` para asegurar la correcta ejecución del stack de auditoría (Bandit, pip-audit, njsscan y Schemathesis).
|
|
## [2.5.0] - 2026-09-19
|
|
### Añadido
|
|
- **Auditoría y Seguridad Automatizada Completa (Python & Node.js):**
|
|
- **Python SAST (`bandit`):** Escaneo estático del backend Flask de más de 8.400 líneas. Corrección de vulnerabilidad B310 en `sheets_importer.py` mediante validación estricta de esquema HTTP/HTTPS para prevenir ataques de tipo SSRF. Resultado: 0 fallos detectados.
|
|
- **Python SCA (`pip-audit`):** Análisis de dependencias con base OSV; detección de 24 CVEs históricas en paquetes desactualizados y actualización completa a versiones seguras (`Flask>=3.1.3`, `Werkzeug>=3.1.8`, `requests>=2.34.2`, `bleach>=6.4.0`, `python-dotenv>=1.2.3`). Resultado: 0 CVEs activas.
|
|
- **Python DAST / Fuzzing (`schemathesis`):** Especificación OpenAPI 3.0.3 en `backend/app/routes/api/openapi.py` (`/api/v1/openapi.json`). Ejecución de 114 casos de prueba dinámicos con mutación de datos. Detección y corrección de caída 500 por payload de tipo JSON inválido en `/auth/login`. Resultado: 114/114 pruebas aprobadas con 0 errores de servidor.
|
|
- **Node.js SAST (`njsscan`):** Análisis de patrones de código inseguro en el BFF Express (`frontend/src`). Resultado: 0 hallazgos.
|
|
- **Node.js SCA (`npm audit`):** Auditoría continua de paquetes npm con 0 vulnerabilidades reportadas.
|
|
- **Blindaje Activo (`helmet` & `express-rate-limit`):** Incorporación de cabeceras HTTP defensivas (`HSTS`, `nosniff`, `SAMEORIGIN`, `X-Permitted-Cross-Domain-Policies`) y limitadores de tasa ante fuerza bruta en `/auth/login` (30 req / 15 min) y `/api` (180 req / min).
|
|
- **Script Unificado de Auditoría (`security_audit.bat`):** Ejecutable centralizado para correr los 5 controles en un solo comando.
|
|
- **Documento Formal de Seguridad (`SECURITY_AUDIT_REPORT.md`):** Reporte ejecutivo de auditoría y controles continuos.
|
|
|
|
---
|
|
|
|
## [2.4.0] - 2026-09-19
|
|
### Añadido
|
|
- **Perfil Extendido de Usuarios y Tipificaciones de Documentos Oficiales (Argentina y Extranjeros):**
|
|
- Incorporación en el modelo `User` de los campos: `first_name` (Nombre), `last_name` (Apellido), `email` (Email Institucional de acceso), `personal_email` (Email Personal/Particular de contacto), `phone` (Teléfono con código de área), `address` (Domicilio/Dirección), `document_type` (Tipo de documento) y `document_number` (Número de documento validado).
|
|
- Catálogo formal de reglas de negocio en `backend/app/constants/document_types.py` con tipificaciones oficiales de Argentina y extranjeros (DNI, CUIL, Pasaporte Argentino, Pasaporte Extranjero, DNI Extranjero, Cédula de Identidad PFA, Cédula Mercosur, Libreta Cívica y Libreta de Enrolamiento).
|
|
- Validaciones de formato, expresiones regulares, y verificación de unicidad de documento por tipo en endpoints `POST /api/v1/users` y `PUT /api/v1/users/<id>`.
|
|
- Búsqueda dinámica en `/admin/users_list` habilitada para filtrar por número de documento o email personal/institucional además de nombre.
|
|
- Rediseño del formulario `/admin/users/form` estructurado en secciones: Identidad y Documentación, Contacto y Domicilio (con Teléfono, Email Personal y Dirección), y Cuenta y Rol Institucional (con Email Institucional y Clave), permitiendo al Administrador General gestionar la totalidad de los datos.
|
|
- Script de migración SQLite `backend/migrate_user_profile_fields.py` para agregar las columnas e inicializar nombres desglosados de los usuarios existentes.
|
|
- **Co-Docencia y Cátedras Múltiples en Comisiones:**
|
|
- Creación del modelo relacional `CommissionTeacher` (`commission_teachers`) para asociar múltiples docentes a una misma comisión con roles académicos diferenciados (`Titular`, `Adjunto`, `JTP`, `Ayudante`).
|
|
- Nuevos endpoints en la API REST: `POST /api/v1/commissions/<id>/teachers` y `DELETE /api/v1/commissions/<id>/teachers/<user_id>`, junto con la serialización completa de cátedras en `GET /api/v1/commissions`.
|
|
- Nueva tarjeta interactiva *"Equipo Docente / Cátedra"* en el detalle de la comisión (`/admin/commission_detail?id=...`) permitiendo agregar y desvincular docentes con sus respectivos roles.
|
|
- Actualización de la grilla de comisiones (`/admin/commissions_list`) para exhibir a todos los profesores asignados con badges distintivos de rol.
|
|
- **Eliminación y Gestión Segura de Asignaturas:**
|
|
- Incorporación de botón y modal interactivo de confirmación de eliminación de asignaturas en `/admin/subjects_list`.
|
|
- Implementación de regla de negocio de integridad académica: eliminación física si la materia no tiene comisiones asociadas, o desactivación automática si posee historial o cursadas vinculadas.
|
|
|
|
### Corregido
|
|
- **Bug Visual en Modificación de Asignaturas (`/admin/subjects_list`):**
|
|
- Solucionado el problema de modales recortados o cubiertos por el fondo oscuro (`modal-backdrop`), originado por la presencia de 206 modales inline dentro de celdas `<td>` en una tabla con `overflow` (`.table-responsive`). Se refactorizó hacia un único modal global `#modalEditSubject` instanciado fuera de la tabla e inicializado dinámicamente con JavaScript.
|
|
### Añadido
|
|
- **Monitoreo y Percentiles de Asignación de Aulas Físicas (Admin & Bedelía):**
|
|
- Panel analítico *"Estado y Percentiles de Asignación de Aulas Físicas"* incorporado en los dashboards de Administrador (`/dashboard?role=admin`) y Bedelía (`/dashboard?role=bedelia`).
|
|
- Cálculo dinámico en tiempo real de **Aulas Asignadas** en número y percentil (**26 aulas · 96.3%**) con enlace directo a cursadas activas.
|
|
- Cálculo dinámico en tiempo real de **Aulas Sin Asignar / Libres** en número y percentil (**1 aula · 3.7%**) con enlace directo al formulario de asignación de espacios.
|
|
- Barras de progreso visuales con desglose dual: **Planificación Cuatrimestral** (96.3% asignado vs 3.7% disponible) y **Ocupación Operativa del Día** (aulas con clases hoy vs aulas libres).
|
|
- Exposición de métricas de asignación y percentiles en el endpoint de la API REST `GET /api/v1/dashboard/stats`.
|
|
- **Módulo de Cursadas Asignadas y Métricas Reales en Catálogo Presencial (`/classrooms/list_classrooms?view_mode=physical`):**
|
|
- Incorporación de la sección *"Cursadas Asignadas"* dentro de cada tarjeta de aula física y columna en vista de tabla, detallando asignaturas, comisiones y turnos.
|
|
- Métricas de ocupación física real por período (Día, Semana, Mes) con porcentajes calculados dinámicamente (6%, 11%, 17%, 22% según la carga horaria del aula).
|
|
- Botones de acción directa con ID dinámico: **Ficha** (`/classrooms/view_classroom?id=...`), **Horarios en Calendario** (`/schedule/calendar_view?classroom_id=...`) y **Editar**.
|
|
- Conexión de la tabla *"Próximas Clases y Reservas"* en la ficha individual del aula (`/classrooms/view_classroom`) con las reservas reales del cuatrimestre y enlaces a cada reserva (`/schedule/view_reservation?id=...`).
|
|
|
|
### Modificado
|
|
- **Dashboard Docente (`/dashboard?role=docente`):**
|
|
- Eliminado el botón flotante *"Reservar Aula / Solicitar espacio para clase"* (`/schedule/add_reservation`) a petición de los requerimientos funcionales del cuerpo docente.
|
|
- Reorganizada la grilla superior a 3 columnas simétricas (`col-md-4`) para las tarjetas de *Mis Clases Hoy*, *Mis Reservas Activas* y *Aulas Virtuales*.
|
|
|
|
### Corregido
|
|
- **Fallo Crítico de Renderizado en Nunjucks (`memberLookup` con `.items`):**
|
|
- Solucionada la incompatibilidad de `nunjucks/src/jinja-compat` que interceptaba la propiedad `.items` convirtiendo `classrooms.items` en una función interna en lugar de un array, lo que impedía dibujar las tarjetas de aulas presenciales en `frontend/views/classrooms/list.html`.
|
|
- Implementado interceptor en `memberLookup` en `frontend/src/app.js` para preservar arrays intactos.
|
|
- **Clasificación Errónea de Reservas Físicas como Virtuales (`is_virtual`):**
|
|
- Corregida la propiedad `@property is_virtual` en `Reservation` (`backend/app/models/reservation.py`) para garantizar que si una reserva tiene aula física asignada (`self.classroom and not self.classroom.is_virtual`), siempre sea clasificada como presencial (`is_virtual = False`), evitando falsos positivos cuando la comisión posee un enlace virtual predeterminado.
|
|
- **Excepción de SQLAlchemy en Estadísticas de Dashboard:**
|
|
- Corregido el error de ejecución generado al invocar `.ilike()` sobre la propiedad Python `@property Classroom.room_number` en `backend/app/routes/api/dashboard.py`, migrando la clasificación de aulas presenciales y virtuales a una evaluación robusta en memoria Python (`Classroom.code` y `Classroom.building`).
|
|
|
|
---
|
|
|
|
## [2.2.0] - 2026-09-19
|
|
### Añadido
|
|
- **Herramienta de Purga y Reinicio de Datos Académicos (`reset_academic_data`):**
|
|
- Script CLI `backend/scripts/reset_academic_data.py` con argumentos de limpieza granular (`--all`, `--reservations`, `--classrooms`, `--careers`, `--yes`).
|
|
- Endpoint de API `POST /api/v1/admin/reset-academic-data` protegido por JWT (rol `admin`) con registro en `AuditLog`.
|
|
- Panel interactivo "Zona de Reinicio y Purga Académica" en `/admin/google_sheets_import` con checkboxes independientes para reservas, aulas, comisiones, asignaturas y carreras.
|
|
- Modal modal de confirmación con advertencias de seguridad para prevenir purgas accidentales.
|
|
- Preservación íntegra de usuarios del sistema, credenciales de acceso, roles RBAC y registros de auditoría.
|
|
- **Configuración Global Dinámica de Google Sheets:**
|
|
- Nuevo modelo `SystemSetting` (`backend/app/models/setting.py`) para almacenamiento persistente clave-valor en base de datos.
|
|
- Endpoints `GET /api/v1/admin/sheets-config` y `POST /api/v1/admin/sheets-config`.
|
|
- Normalizador de enlaces en `GoogleSheetsImporter` compatible con URLs compartidas de edición (`/spreadsheets/d/.../edit`) o enlaces publicados (`/pub?output=csv`).
|
|
- Interfaz web con formulario de edición de URL, botón de guardado en caliente, restauración a URL oficial predeterminada y acceso directo a Google Docs.
|
|
- **Visualización de Asignaturas Reales:**
|
|
- Tabla de asignaturas recientemente sincronizadas conectada a la base de datos real en lugar de datos de muestra (*mock*).
|
|
|
|
### Corregido
|
|
- **Fallo por Timeout en Google Sheets Academic Sync:**
|
|
- Solucionado el corte prematuro de conexión en el BFF (`frontend/src/services/apiClient.js`), aumentando el timeout base a 25s y el timeout específico de sincronización a 90s (anteriormente limitado a 5s en operaciones que toman ~6.7s).
|
|
- Eliminado el enmascaramiento silencioso de errores en el BFF, permitiendo reportar fallos reales o éxitos detallados (+carreras, +aulas, +materias, +comisiones, +reservas).
|
|
|
|
---
|
|
|
|
## [2.1.0] - 2026-09-19
|
|
### Añadido
|
|
- **Ficha Detallada de Reserva (`schedule.view_reservation`):**
|
|
- Implementación en BFF Node.js de la ruta `/schedule/view_reservation` (soportando parámetros `:id`, `?id=` o selección automática del primer registro).
|
|
- Vistas y controladores para modificar reservas con selectores en cascada (`/schedule/edit_reservation`).
|
|
- Endpoints de acción rápida en backend y BFF: `POST /schedule/confirm_reservation` y `POST /schedule/cancel_reservation`.
|
|
- Actualización de enlaces en `today.html`, `list.html`, `dashboard.html` y `view.html` para navegar directamente con el identificador de la reserva (`?id=...`).
|
|
- **Creación y Asociación de Comisiones a Asignaturas (`admin/commissions_list`):**
|
|
- Botón destacado `+ Nueva Comisión` en el encabezado y en el estado vacío de la tabla.
|
|
- Modal interactivo `#modalAddCommission` con selección obligatoria y clara de la **Asignatura / Materia Asociada** (`<select name="subject_id" required>`), mostrando código oficial, nombre y carrera.
|
|
- Campos completos de cursada: cuatrimestre (1C/2C/Anual), año lectivo, turno, docente a cargo, cupo máximo y días/horarios.
|
|
- Generación y configuración automática de enlace a Google Meet institucional cuando no se ingresa un enlace personalizado.
|
|
- Alerta de confirmación visual (`?created=1`) al registrar y vincular una comisión exitosamente.
|
|
- Tabla de comisiones actualizada con visualización explícita del código de materia, nombre y badge de carrera.
|
|
- **Enriquecimiento de la API REST:**
|
|
- Endpoint `GET /api/v1/reservations/<id>` ampliado con objetos relacionales anidados: `classroom` (código, edificio, piso, capacidad, descripción, virtualidad), `commission` (código, código compuesto, materia), `user` (docente, nombre, apellido, correo), duración en minutos y enlaces virtuales.
|
|
- Endpoint `POST /api/v1/admin/commissions` con validación estricta de existencia de asignatura y resolución inteligente de unicidad.
|
|
|
|
---
|
|
|
|
## [2.0.0] - 2026-09-18
|
|
### Añadido
|
|
- **Reingeniería de Arquitectura Fullstack (Desacople Monolito -> Backend + BFF):**
|
|
- Desacople completo del backend Python/Flask como una **API REST pura** bajo `/api/v1/` retornando exclusivamente JSON.
|
|
- Implementación del **Frontend BFF** en Node.js + Express con renderizado de servidor mediante Nunjucks.
|
|
- Autenticación sin estado (*Stateless*) basada en tokens JWT firmados con algoritmo HS256.
|
|
- Almacenamiento seguro del token de acceso en cookies del navegador con directivas `HttpOnly`, `SameSite=Lax` y `Secure`.
|
|
- Inyección transparente del token `Bearer` en peticiones internas mediante cliente Axios centralizado.
|
|
- **Dashboards Personalizados por Rol Institucional:**
|
|
- **Dashboard de Bedelía (`/dashboard?role=bedelia`):** Métricas operativas de campus físico y virtual, cartelera del día y panel de aprobación de solicitudes pendientes.
|
|
- **Dashboard de Docente (`/dashboard?role=docente`):** Sesiones del día con botones directos para ingresar a reuniones virtuales (Meet/Teams/Zoom) y formulario de solicitud de aulas.
|
|
- **Dashboard de Alumno (`/dashboard?role=alumno`):** Brújula de cursada *"¿Dónde curso hoy?"* con ubicación por piso/aula o enlace virtual, junto al calendario de exámenes y entregas.
|
|
- **Dashboard de Administrador (`/dashboard?role=admin`):** Cockpit institucional de capacidad, usuarios, auditoría RBAC y distribución de comisiones.
|
|
- Selector dinámico de vista previa de roles en el banner superior para administradores.
|
|
- **Cartelera del Día Interactiva (`/schedule/today_schedule`):**
|
|
- Grilla estructurada en bloques horarios (07:00 a 21:00 hs) con métricas en tiempo real de ocupación y reservas confirmadas/pendientes.
|
|
- Filtro dinámico para ocultar clases virtuales (`hide_virtual=1`) y segmentación por pisos o turnos.
|
|
- **Seguridad Enterprise (SecurityFilterChain):**
|
|
- Pipeline centralizado de cabeceras de blindaje OWASP (`nosniff`, `SAMEORIGIN`, `X-XSS-Protection`, `Strict-Transport-Security`).
|
|
- Rate limiting dinámico contra ataques de fuerza bruta en endpoints de autenticación.
|
|
|
|
### Corregido
|
|
- **Resolución de Colisión de Horarios en Clases Virtuales (Importador de Google Sheets):**
|
|
- Corrección de la búsqueda de duplicados en `sheets_importer.py` que limitaba indebidamente la unicidad a `(classroom_id, start_time, end_time)`.
|
|
- Habilitación de concurrencia ilimitada para el aula virtual (`Campus Virtual · VIRTUAL`) mediante discriminación por `commission_id`.
|
|
- El total de reservas registradas aumentó de **363 a 643** (incorporando **280 clases virtuales** que eran descartadas por falso conflicto).
|
|
- Generación y guardado automático de enlaces institucionales de Google Meet (`https://meet.google.com/edu-{materia}-{comision}`).
|
|
|
|
---
|
|
|
|
## [1.0.0] - 2026-09-04
|
|
### Añadido
|
|
- **Versión Monolítica Base (`legacy_admin-edu-space`):**
|
|
- Aplicación monolítica en Flask con plantillas Jinja2 y persistencia SQLAlchemy (SQLite / PostgreSQL).
|
|
- Modelado de datos inicial para sedes, aulas físicas, materias, comisiones, usuarios y reservas.
|
|
- Sistema de roles inicial (Admin, Bedelía, Docente, Alumno) basado en sesión tradicional de Flask-Login.
|
|
- Calendario de reservas mensual y semanal con FullCalendar.
|
|
- Prototipo experimental de algoritmo genético para optimización de ocupación áulica.
|
|
- Módulo de sincronización inicial con planillas de Google Sheets.
|