Files
admin-edu-space/CHANGELOG_MVP.md
T

17 KiB

CHANGELOG MVP — Admin Edu-Space (UniCABA)

Nota de Unificación: Este archivo documenta la progresión de los hitos y entregables de las Fases del ROADMAP_MVP.md. Para el historial técnico exhaustivo conforme a Keep a Changelog y Semantic Versioning, consultar el archivo oficial unificado: CHANGELOG.md.


[Fase 5: Integración Auth, Email & Moodle Backend] — v3.0.0 (2026-09-23)

Estado: ✅ 100% Completada

Épica 1: Panel de Configuración Global (Perfil ADMIN)

  • Cifrado Simétrico Fernet: Creación de CryptoService (backend/app/services/crypto_service.py) derivando de forma determinística una clave Fernet de 32 bytes a partir de SECRET_KEY.
  • Modelo SystemSetting Extendido: Soporte para columnas category y flag is_encrypted. Almacenamiento seguro de secretos con métodos polimórficos get_decrypted_value() y enmascaramiento con get_masked_value().
  • Endpoints Administrativos:
    • GET /api/v1/admin/settings/all: Retorna la configuración completa organizada por categorías (smtp, auth_providers, google_oauth, moodle) con secretos enmascarados.
    • POST /api/v1/admin/settings/smtp: Configuración dinámica de Host, Puerto, Usuario, Contraseña cifrada, Protocolo de Seguridad (TLS/SSL/NONE), y Remitente.
    • POST /api/v1/admin/settings/smtp/test: Handshake SMTP en vivo y envío opcional de correo de prueba con plantilla HTML oficial.
    • POST /api/v1/admin/settings/auth-providers: Activación y desactivación de proveedores de acceso (local, google, moodle).
    • POST /api/v1/admin/settings/google-oauth: Guardado de Client ID, Client Secret cifrado, Dominios autorizados y Callback URL.
    • POST /api/v1/admin/settings/moodle: URL base del servidor, Token Web Services cifrado, timeout y frecuencia de sincronización.
  • Interfaz de Usuario Web: Nueva pantalla responsiva frontend/views/admin/settings/global_config.html con pestañas navegables, validación en vivo, spinners y monitores de estado (100% adaptada para resoluciones desde 720p hasta 1080p).
  • Navegación: Integración de enlace directo "Config. Global" en el menú lateral bajo Administración en frontend/views/base.html.

Épica 2: Infraestructura Asíncrona y Caché

  • Capa de Caché Híbrida: Creación de CacheService (backend/app/services/cache_service.py) con soporte nativo de Redis y fallback transparente en memoria con TTL para sesiones de usuario y perfiles de Moodle.
  • Cola Persistente de Sincronización: Modelo MoodleSyncTask (backend/app/models/sync_task.py) y servicio MoodleQueueService (backend/app/services/moodle_queue_service.py) para registrar operaciones de sincronización (CREATE_USER, UPDATE_USER, ENROL_USER, UNENROL_USER, ASSIGN_ROLE).
  • Tolerancia a Fallos y DLQ: Política de Exponential Backoff ($2^{\text{intentos}} \times 30$s) ante indisponibilidad de Moodle. Si se superan los intentos máximos, la tarea se traslada automáticamente a la Dead Letter Queue (DLQ) (status = 'FAILED').
  • Endpoints de Cola & DLQ:
    • GET /api/v1/admin/moodle/queue/stats: Métricas en tiempo real (Pendientes, En Proceso, Reintentando, Completadas, Fallidas DLQ).
    • GET /api/v1/admin/moodle/queue/tasks: Lista paginada con filtrado por estado.
    • POST /api/v1/admin/moodle/queue/process-now: Disparo manual inmediato de sincronización.
    • POST /api/v1/admin/moodle/queue/tasks/<id>/retry: Reintento de tarea individual de DLQ.
    • POST /api/v1/admin/moodle/queue/retry-all: Reintento masivo de todas las tareas en DLQ.

Épica 3: Sistema de Autenticación Híbrida (SSO & Local)

  • Login Local Refactorizado: Endpoint /api/v1/auth/login respeta la configuración global. Si auth_local_enabled está desactivado, sólo admite acceso de contingencia a usuarios con rol ADMIN.
  • Google OAuth 2.0 (Arquitectura AlumnosLS): Endpoint POST /api/v1/auth/google con validación estricta de dominios institucionales (google_allowed_domains), aprovisionamiento automático de perfil y emisión de tokens JWT.
  • Moodle Delegated Login: Endpoint POST /api/v1/auth/moodle validando contra /login/token.php de Moodle 4.1 (moodle_mobile_app), obtención de datos de usuario con Web Services, caché en Redis y emisión de JWT.
  • Mapeo y Desacople de Roles: Si el usuario es nuevo y posee rol de manager/admin en Moodle, se le asigna rol local ADMIN; en caso contrario se asigna Docente o Alumno. La administración y cambio de roles posterior permanece 100% local e independiente de Moodle.
  • Frontend Login: Vista frontend/views/auth/login.html adaptada para consultar /api/v1/auth/providers y renderizar dinámicamente el botón de Google Workspace, el botón desplegable de Moodle y el formulario tradicional.

Épica 4: Integración Bidireccional Moodle 4.1 (Backend)

  • Cliente REST Moodle 4.1: MoodleClient (backend/app/services/moodle_client.py) con métodos para:
    • core_user_create_users, core_user_update_users, core_user_get_users.
    • enrol_manual_enrol_users, enrol_manual_unenrol_users, core_enrol_get_enrolled_users.
    • core_role_assign_roles, core_role_unassign_roles.
    • test_connection() contra core_webservice_get_site_info.
  • Desacople en CRUD Local: Creación y edición de usuarios en backend/app/routes/api/admin.py encola automáticamente la sincronización sin bloquear las peticiones locales.

Épica 5: Motor de Notificaciones (Email Server)

  • Cliente SMTP Dinámico: Creación de EmailService (backend/app/services/email_service.py) que obtiene credenciales en tiempo de ejecución de la base de datos (con desencriptación de contraseña al vuelo).
  • Plantillas Transaccionales Profesionales:
    • notify_teacher_assignment: Notificación a profesores sobre asignación a comisiones y horarios.
    • notify_exam_schedule: Convocatoria y citación a mesas de examen final.
    • test_smtp_connection: Verificación de handshake y autenticación SMTP con feedback claro.

Cobertura de Pruebas

  • Suite completa en backend/tests/test_phase6_integration.py con 7 pruebas unitarias e integrales que validan cifrado Fernet, SystemSetting, CacheService, MoodleQueueService (Backoff & DLQ), EmailService dinámico, y autenticación híbrida (Google & Moodle). 30/30 pruebas pasando en verde en la suite global de regresión.

[Fase 4: UI/UX Avanzada para Bedelía & Modo Impersonación] — v2.8.0 (2026-09-23)

Estado: ✅ 100% Completada

Estadio 4.1 — Grilla Semanal Interactiva (Drag-and-Drop) con Detección de Colisiones

  • FullCalendar Interactivo: Habilitación de editable: true y droppable: true en el calendario general de Bedelía (/schedule/calendar).
  • Sidebar de Comisiones Pendientes: Panel lateral dinámico con catálogo de comisiones que aún no tienen aula asignada (unassigned_commissions), permitiendo arrastrarlas directamente hacia los bloques horarios del calendario.
  • Validación de Choques en Tiempo Real: Integración con POST /api/v1/reservations/drag-update. Al mover o soltar una clase, el backend somete la nueva posición a la matriz integral de conflictos (ReservationService.check_full_conflicts_matrix):
    • Conflicto físico de aula (doble asignación simultánea).
    • Conflicto docente (profesor ocupado en otra aula).
    • Conflicto de aforo (capacidad de aula insuficiente).
  • Manejo de Respuestas: Si hay colisión, devuelve HTTP 409 (status: conflict), FullCalendar revierte automáticamente el movimiento (info.revert()) y se dispara un Toast de alerta detallando el motivo del bloqueo. Si está libre, persiste la reserva y confirma con Toast de éxito.

Estadio 4.2 — Modo Impersonación del Superadmin con Trazabilidad

  • Cabecera X-Impersonate-User: Inyección y soporte en backend/app/utils/jwt_decorators.py dentro de jwt_required para usuarios administradores. Asigna g.jwt_user al usuario objetivo preservando g.real_admin_user y marcando g.is_impersonating = True.
  • Endpoints de Control: POST /api/v1/admin/impersonate y POST /api/v1/admin/stop-impersonating en Backend Flask con auditoría inmutable en AuditLog (IMPERSONATE_START e IMPERSONATE_END).
  • Integración en BFF Node.js: Middleware authMiddleware.js y proxy /api en app.js configurados para propagar cookies seguras impersonate_user_id e inyectar X-Impersonate-User en todas las peticiones a la API Flask.
  • Banner Visual Institucional: Banner de advertencia permanente en base.html con fondo de alerta ámbar, spinner de estado, identificación del usuario y rol adoptado, y botón de salida inmediata.
  • Acceso de un Clic: Botón directo de impersonación (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

  • Turnos Académicos Reales: ReservationOptimizer._calculate_preferred_time sincronizado con las franjas horarias de UniCABA (Mañana: 08:00 a 12:00, Tarde: 14:00 a 18:00, Vespertino/Noche: 18:30 a 22:30).
  • Persistencia Segura: Endpoint POST /api/genetic/apply-optimization adaptado con parseo riguroso de strings ISO y prevención de colisiones físicas en guardado masivo.

Cobertura de Pruebas

  • Suite completa en backend/tests/test_phase4_interactive_impersonation.py validando los 6 criterios de aceptación (impersonación de docente, impersonación de alumno, trazabilidad en auditoría, rechazo a no-admins, bloqueo 409 por colisión en drag-drop y actualización exitosa 200). 18/18 tests aprobados en suite global de Fases 2, 3 y 4.

[Fase 3: Gestión de Hitos Evaluativos y Libro de Calificaciones] — v2.7.0 (2026-09-23)

Estado: ✅ 100% Completada

Estadio 3.1 — Calendario de Evaluación por Comisión y Notificaciones Preventivas

  • Modelo MilestoneGrade: Tabla relacional milestone_grades para registrar calificaciones por estudiante y reserva evaluativa, con validación de unicidad (student_id, reservation_id), notas en escala 1.0 a 10.0, estado de inasistencia (is_absent) y devoluciones pedagógicas (feedback).
  • Consulta de Hitos del Alumno: Endpoint GET /api/v1/students/my-upcoming-milestones que detecta dinámicamente exámenes parciales, recuperatorios y entregas de TP de las comisiones del estudiante con cálculo automático de días restantes (days_remaining).
  • Dashboard del Alumno: Widget interactivo de próximos exámenes en /dashboard?role=alumno con badges visuales de urgencia (¡Hoy!, ¡Mañana!, Faltan X días) y acceso directo desde el Launchpad a "Mis Calificaciones".

Estadio 3.2 — Libro de Calificaciones (Gradebook) y Cierre Formal de Actas

  • Extensiones en Commission: Incorporación de columnas grades_closed (boolean), grades_closed_at (datetime), grades_closed_by (foreign key) y acta_number (identificador oficial generado).
  • Servicio GradebookService: Motor centralizado para matriz de notas por comisión, guardado asíncrono individual y por lote (bulk_save_grades), cálculo dinámico de promedios ponderados y condiciones académicas en tiempo real (Promocionado ≥ 7, Regular ≥ 4, Libre < 4).
  • Cierre Formal de Actas: Sellado institucional con código único (ACTA-YYYY-Sem-ID), auditoría inmutable en audit_logs con acción CLOSE_ACTA y bloqueo total contra modificaciones posteriores.
  • Reapertura Excepcional: Endpoint para Bedelía/Administración (POST /api/v1/commissions/<id>/gradebook/reopen) con justificación administrativa obligatoria asentada en auditoría.
  • Interfaz Docente & Bedelía (/schedule/gradebook/:id): Matriz interactiva de carga rápida con autoguardado asíncrono debounced (500ms), indicador visual flotante de sincronización, recálculo instantáneo de promedios en el cliente y modales de sellado y reapertura de actas.
  • Portal del Alumno (/schedule/my_grades / /mis-materias/mis-notas): Vista consolidada de todas las materias del estudiante, notas de parciales, condición final y número de acta emitida, con soporte de impresión de certificado de regularidad.
  • Acceso Directo en Comisión: Botón destacado "Libro de Calificaciones (Actas)" y badge de acta sellada incorporados en /admin/commission_detail.

Cobertura de Pruebas

  • Suite completa en backend/tests/test_phase3_gradebook.py validando los 6 criterios de aceptación: estructura de matriz bidimensional, persistencia y autoguardado de notas, validación estricta de notas inválidas (fuera del rango 1-10), cierre formal de acta e inmutabilidad estricta ante intentos de edición, consulta integral del alumno y cuenta regresiva de próximos hitos. 6/6 tests aprobados (12/12 en conjunto con Fase 2).

[Fase 2: Co-docencia, Matriz de Conflictos y Regla Diaria] — v2.6.0 (2026-09-19)

Estado: ✅ 100% Completada

Estadio 2.1 — Modelo y Gestión Integral de Co-docencia

  • Modelo CommissionTeacher: Soporte para múltiples docentes por comisión en base de datos (commission_teachers), admitiendo roles académicos diferenciados (Titular, Adjunto, JTP, Ayudante) y flag is_primary.
  • API REST de Cátedras: Endpoints POST /api/v1/commissions/<id>/teachers y DELETE /api/v1/commissions/<id>/teachers/<user_id> con serialización completa de cátedra en comisiones.
  • Interfaz de Gestión: Tarjeta interactiva "Equipo Docente / Cátedra" en /admin/commission_detail para incorporar y desvincular profesores con rol dinámico, y visualización de badges en /admin/commissions_list.

Estadio 2.2 — Matriz de Conflictos y Validación Integral

  • Conflicto Físico: Bloqueo estricto e infranqueable de superposiciones de reservas en la misma aula física (ReservationRepository.find_overlapping).
  • Conflicto Docente: Detección de doble asignación simultánea para un mismo docente en diferentes aulas o formatos.
  • Excepción Justificada por Co-docencia: Si un docente asignado presenta solapamiento pero la comisión cuenta con co-docentes registrados en CommissionTeacher, la matriz de validación autoriza la reserva validando la cobertura del equipo de cátedra.
  • Conflicto de Aforo: Bloqueo estricto cuando expected_attendees > classroom.capacity en espacios físicos.
  • Endpoint de Pre-validación: POST /api/v1/reservations/check-conflicts para validación asíncrona de conflictos físicos, docentes y de aforo antes del commit.

Estadio 2.3 — Regla de Restricción Diaria del Alumno y Motor de Excepciones

  • Servicio EnrollmentService: Lógica de matriculación académica con análisis de días de cursada por comisión y verificación de cupos.
  • Regla Restrictiva: Un alumno no puede cursar dos asignaturas regulares el mismo día de la semana.
  • Excepción Automática por Curso Corto: Atributo is_short_course en modelo Subject; si una de las materias es un taller o curso corto, el sistema autoriza la cursada simultánea en el mismo día.
  • Excepción Expresa de Bedelía: Campos allow_same_day_exception y exception_reason en StudentEnrollment. La oficina de Bedelía puede autorizar la matriculación simultánea mediante switch justificado en la interfaz.
  • Endpoints de Matrícula: GET/POST /api/v1/commissions/<id>/enrollments, DELETE/PUT /api/v1/commissions/<id>/enrollments/<student_id>.
  • UI en Detalle de Comisión: Formulario de matriculación con toggle de autorización de Bedelía, motivo de excepción y tabla de inscriptos con badges de estado.

Cobertura de Pruebas

  • Suite completa en backend/tests/test_phase2_rules.py validando los 6 criterios de aceptación (conflicto físico, aforo, co-docencia, restricción diaria, bypass de curso corto y bypass de Bedelía). 6/6 tests aprobados con 100% de éxito.

Complementos y Seguridad Transversal

  • Dashboard de Bedelía: Integración de paneles en tiempo real para análisis de Comisiones Sin Reserva y grilla de Aulas Disponibles (Filtros Semana/Mes) conectando frontend UI con el servicio analítico backend.
  • Auditoría Automatizada (Fase 1): Implantación de un pipeline de seguridad local/Gitea que aísla dependencias de desarrollo (requirements-dev.txt) y ejecuta controles SAST, DAST y SCA (Bandit, pip-audit, njsscan y Schemathesis) sin vulnerabilidades detectadas.
  • Optimizador Genético de Reservas: Reparación de enrutamiento 404, migración a JWT (@jwt_required), corrección de UI de métricas dinámicas de algoritmo, y refactorización de layout para superposición de herramientas.
  • UI/UX General: Ajustes de CSS en modo claro (soporte dinámico de contraste de isologotipo blanco a rosa institucional mediante filtros) y traducciones de menús de usuario en base.html.

[Fase 1: Paridad Legacy y Estabilización] — v2.5.0 / v2.4.0 (2026-09-19)

Estado: ✅ 100% Completada

  • Seguridad automatizada SAST/DAST/SCA (Bandit, pip-audit, schemathesis, njsscan, npm audit).
  • Tipificaciones de documentos argentinos y extranjeros, perfiles extendidos de usuarios con email personal e institucional.
  • Gestión completa de aulas físicas vs virtuales con percentiles de asignación y métricas de ocupación real.
  • Reingeniería del modal de edición y eliminación segura de asignaturas.

[Fase 0: Desacople y Arquitectura Base] — v2.0.0 (2026-09-18)

Estado: ✅ 100% Completada

  • Desacople arquitectónico completo: Backend Flask RESTful (/api/v1/) + Frontend BFF Node.js/Express con Nunjucks.
  • Autenticación basada en tokens JWT con sincronización de estado de sesión.