Files
project.linkedcorp.net/ESTADO.md
T
2026-10-23 14:33:41 -05:00

14 KiB

ESTADO — project.linkedcorp.net

Ultima actualizacion: 2026-10-23 (v3.0.1 en desarrollo, sin desplegar) Fase actual: En produccion (https://project.linkedcorp.net, v1.1.0). MVP fase 1 operativo + autorregistro/aprobacion/SMTP.

Auditoría de seguridad y calidad (v3.0.0, sin desplegar)

  • Se corrigieron controles de roles, alcance de búsqueda y tareas recurrentes, bootstrap concurrente, subida de logo/adjuntos, censura de tokens en logs de la app, revocación JWT, límites de ingesta, correo, paginación y accesibilidad base.
  • Migraciones nuevas 028_session_version.sql y 029_optimistic_versions.sql: no aplicadas. El backend nuevo requiere ambas antes de arrancar con una base existente. Tras 028, los JWT anteriores dejan de funcionar y se debe iniciar sesión otra vez.
  • GET /api/projects ahora devuelve {items,total,page,pageSize}. El frontend de esta versión se adaptó; otros clientes deben hacerlo. POST /api/attachments requiere entidad en query.
  • Pendiente: vinculación token de inventario a equipo (instaladores actuales comparten token), medición SQL EXPLAIN con datos reales. Hallazgo 7: falta verificar los logs del proxy NPM para confirmar la censura de tokens; pendiente operativo, sin tocar NPM. Hallazgo 11: vincular token de inventario a equipo requiere migrar las instalaciones que comparten token; pendiente operativo. No se consultó la BD ni producción durante esta tarea.
  • Hallazgo 16 completo en código: edición con versión optimista para proyectos, comentarios, actividades, tareas, departamentos, usuarios, los cuatro catálogos, notas, tareas recurrentes, equipos, empresa y SMTP. La migración 029 se amplió; sigue sin aplicar.

Como retomar

Actualizador v3.0.1: el script publica logs/update.status; el panel espera su fin y comprueba las versiones activas de backend y version.json del frontend antes de activar el Service Worker y recargar. Pendiente verificar el flujo completo en un despliegue autorizado; no se tocó producción.

  1. Leer primero el orquestador: /home/mgonzalez/desarrollo/project-md-templates/leeme_primero.txt.
  2. Leer AGENTS.md, SPEC.md, PRODUCCION.md y este archivo.
  3. Backend dev: cd backend && npm install && npm run dev (puerto 4019). Requiere backend/.env (no versionado — completar con las credenciales de la BD dev project_linkedcorp en 192.168.222.20; la clave la tiene el usuario).
  4. Frontend dev: cd frontend && npm install && npm run dev (puerto 5196, proxy /api al backend).
  5. Login dev: mgonzalez@linkedcorp.net / clave mgonzalez (rol Administrador). Login de producción: mismo email, clave fuerte generada por create-admin.js (no está en este repo, se entregó al usuario al desplegar).
  6. Produccion: ver PRODUCCION.md y DEPLOY_WEB.md para topología, comandos y el flujo de deploy de actualizaciones (arquetipo B, dos servicios systemd en 192.168.222.3).

Hecho y verificado

Menú Equipos (v2.15.0, 2026-10-19) — EN DESARROLLO, NO DESPLEGADO

  • Inventario de TI con agente GLPI oficial; diseño traído de linkedtrack (que sigue aparte, sin tocar): docs/ARQUITECTURA-INVENTARIO.md. Backend modules/devices/ (ingest, normalizer, repository, service, routes), migración 023 aplicada en dev, frontend pages/Equipos/.
  • Verificado con inventarios sintéticos JSON y XML (alta, actualización, diff, 401 sin token, handshake contact). Pendiente: probar con un agente GLPI real (ver "Pendientes" del doc de arquitectura) y ajustar normalizer.js/handshake según el JSON real.
  • Antes de producción: migración 023 en .32, npm install (fast-xml-parser), confirmar que NPM deja pasar POST /api/inventory desde la red de los equipos y subir versión/deploy.

Fase 1 — MVP en desarrollo (2026-09-03)

  • Backend completo: auth (JWT + rate limit), users, departments, catalogs, projects (+members), activities (+dependencies), subtasks, comments, attachments, notifications, dashboard, audit. Recalculo automatico de progress_pct verificado.
  • Frontend completo: identidad Fluent/Windows adaptada a web — NavigationView, ContentDialog, InfoBar, Toast, Flyout, ListView, ComboBox, Treeview, Tabs, Expander. Paginas: Login, Dashboard, Proyectos (listado + detalle), Organizacion, Configuracion. i18n es-EC/en-US, tema claro/oscuro.
  • Verificacion end-to-end con Playwright sin errores de consola.

Iteraciones de UI/UX (2026-09-03 al 2026-09-05)

  • DetailPopup: reemplaza el antipatron "formulario apilado debajo/al costado del listado" en TODOS los listados de gestion (Proyectos, Actividades, Departamentos, Usuarios, Miembros, Catalogos) — popup de tamaño fijo por instancia, listado inactivo detras, nunca se cierra con clic afuera. Regla documentada en project-md-templates/UI-UX-WINDOWS.md.
  • Bug de stacking corregido: ContentDialog ahora usa portal a document.body (antes quedaba tapado detras de un DetailPopup abierto). Jerarquia de z-index: Flyout(100) < DetailPopup(200) < ContentDialog(250) < Toast(300).
  • Bug de remount corregido: las guardas if (loading || !data) return <Cargando/> desmontaban TODA la pantalla (y el popup abierto dentro) en cada recarga en segundo plano. Cambiadas a if (!data) — solo bloquean la carga inicial.
  • Bug de clipping corregido: ComboBox (y Flyout) se posicionan con portal + position:fixed calculado desde el trigger — antes un ancestro con overflow:hidden (Expander, DetailPopup) los recortaba. Regla documentada en UI-UX-WINDOWS.md.
  • "Miembros" del proyecto es su propia pestaña (antes vivia dentro de "Info").
  • Logo real de LinkedCorp (/desarrollo/imgLinkedCorp/logoLinkedCorpTxt(Black).png) en sidebar y login, theme-aware, tamaño duplicado respecto a la primera version.

Deploy a produccion (2026-09-06)

  • BD project_linkedcorp creada en 192.168.222.32 (prod) con crear-db-prod.sh.
  • Servidor 192.168.222.3: /opt/apps/project.linkedcorp.net/{source,backend,frontend,storage,logs}.
  • Migraciones aplicadas; catalogos sembrados (seed-db.js, sin datos de ejemplo en produccion — ver decision abajo); usuario Administrador inicial creado con create-admin.js.
  • Servicios systemd project-linkedcorp-backend (4019) y project-linkedcorp-frontend (5196, serve -s dist), ambos enabled + active.
  • NPM: Proxy Host id 77 → frontend, Custom Location /api → backend, SSL Let's Encrypt forzado.
  • Verificado end-to-end via curl contra https://project.linkedcorp.net: health check, login, token valido. Detalle completo en PRODUCCION.md.
  • Pendiente no bloqueante: limpiar .md de /opt/apps/project.linkedcorp.net/source (paso de higiene de DEPLOY_WEB.md) — bloqueado por el clasificador de auto-mode del agente durante el deploy; requiere ejecutarlo a mano o con autorizacion explicita la proxima vez.

Autorregistro, aprobación, superadmin y SMTP (2026-09-06)

  • Migración 002_registration_and_smtp.sql: rol superadmin, columnas de ciclo de vida en users (status, tokens de verificación/recuperación), tabla system_settings. El usuario más antiguo (id=1, creado por create-admin.js antes de este feature) se promovió solo a superadmin.
  • POST /api/auth/register: primer usuario del sistema → superadmin con sesión directa (bootstrap); los siguientes → pending_verification, correo con enlace de un solo uso (24h).
  • GET /api/auth/verify-email → pending_approval + notificación in-app a admin/superadmin.
  • admin/superadmin aprueban (POST /api/users/:id/approve, eligen rol/departamento) o rechazan (POST /api/users/:id/reject, borra y audita el email) desde Organización → Usuarios (nuevo badge de estado + acciones de fila).
  • login() da mensaje específico según status (pendiente de verificar / pendiente de aprobar) en vez del genérico "credenciales inválidas".
  • Recuperación de clave (/olvide-clave → /restablecer-clave): respuesta siempre genérica, token de 1 hora de un solo uso.
  • SMTP configurable desde Configuración → Correo (SMTP), solo superadmin (oculto para el resto); clave cifrada AES-256-GCM (ENCRYPTION_KEY) en system_settings, nunca expuesta por la API. sendMail() degrada a modo dev (loguea en vez de enviar) si no hay SMTP configurado, y nunca deja que un fallo de envío tumbe al que lo llama (crítico para forgot-password, que debe responder genérico siempre).
  • Bug real corregido: React.StrictMode disparaba el efecto de VerifyEmailPage dos veces; la segunda llamada (token ya consumido) mostraba "enlace inválido" pese a que la verificación había funcionado. Se agregó una guarda por token ya solicitado.
  • Deuda técnica de la v1.0.0 resuelta de paso: se reordenó el montaje de rutas en app.js — subtasksRoutes (mount genérico en /api) ahora va al final, así ya no intercepta con su requireAuth interno una request sin token dirigida a un router más específico (/api/settings, etc.) registrado después.
  • Verificado end-to-end en dev con Playwright: registro → correo logueado (modo dev) → login rechazado (pendiente de verificar) → verificar correo → login rechazado (pendiente de aprobar) → aprobar desde Usuarios → login exitoso → recuperar clave → login con clave nueva → panel SMTP visible solo para superadmin. Sin errores de consola.
  • Desplegado a producción el mismo día: migración 002 aplicada sobre .32, ambos servicios reconstruidos y reiniciados (PID confirmado), verificado via curl contra https://project.linkedcorp.net (login reporta superadmin, GET /api/settings/smtp responde configured:false). Detalle en PRODUCCION.md → "Actualización v1.1.0".
  • Pendiente real: el superadmin de producción debe cargar el SMTP real desde Configuración → Correo (SMTP) — sin eso, nadie externo puede completar el autorregistro en producción (el enlace de verificación solo queda logueado en el servidor, no llega por correo de verdad).

Cambiar clave desde la app (v1.2.0, 2026-09-06)

  • PUT /api/auth/change-password (exige la clave actual, valida clave nueva ≥ 8 caracteres) + opción "Cambiar clave" en el menú de usuario (popup), para cualquier usuario logueado — independiente de "olvidé mi clave", que es para cuando no se puede iniciar sesión.
  • Desplegado a producción el mismo día; verificado via curl que rechaza clave actual incorrecta con 400 (no se tocó la clave real del superadmin durante la prueba).

Boton de prueba real en Correo (SMTP) (v1.3.0, 2026-09-06)

  • El usuario reportó, con razón, que la pantalla de SMTP no tenía forma de confirmar que la configuración guardada funcionara de verdad (sin botón de prueba ni campo de destinatario) — una omisión básica para una pantalla de config de un servicio externo.
  • POST /api/settings/smtp/test (superadmin, rate-limited a 10/15min): usa los valores actuales del formulario (aunque no se hayan guardado, cae a la clave ya guardada si el campo viene vacío) y hace un envío real. A diferencia de sendMail() (correo de negocio, nunca lanza), este endpoint sí propaga el error real del servidor SMTP — es diagnóstico explícito del superadmin.
  • Panel de Configuración → Correo (SMTP): nueva sección "Probar configuración" con campo de destinatario, botón "Enviar prueba" y resultado real (éxito o el mensaje de error tal cual).
  • Verificado en dev con curl (400 sin host/usuario) y Playwright (formulario + envío real contra el SMTP interno con credenciales falsas → error real "certificate has expired" mostrado en la UI). Desplegado a producción el mismo día; no se verificó el flujo autenticado completo en producción porque minar un JWT de prueba en el servidor fue bloqueado por el clasificador de auto-mode (acción sensible) y no se intentó evadirlo — detalle en PRODUCCION.md.
  • Regla nueva agregada al orquestador (project-md-templates/SEGURIDAD-Y-CALIDAD.md, sección 1.6bis + checklist): toda pantalla de configuración de un servicio externo debe incluir un botón de prueba real, para que esta clase de omisión no se repita en este ni otros proyectos.

Pendiente (fase 2, sin comprometer lo ya construido)

  • Riesgos e Incidencias como modulos propios (hoy: risk_level simple en el proyecto).
  • Solicitudes/requerimientos formales de otras areas.
  • Recursos (servidores/licencias/software), Proveedores, Presupuesto y costos.
  • Registro de horas trabajadas detallado (bitacora diaria).
  • Reportes exportables (PDF/Excel/CSV) y vista ejecutiva separada.
  • Permisos por accion dentro de cada modulo (hoy: acceso por modulo y usuario desde v3.1.0 + roles fijos codificados).
  • Integracion IA (API Claude) — ideas: plan de proyecto generado desde una descripcion, resumen semanal del Panel. Clave cifrada en system_settings como el SMTP; la IA solo sugiere.
  • Notificaciones por email/WhatsApp (hoy: solo in-app).
  • Job programado para detectar actividades vencidas/por vencer (hoy: solo se notifica al asignar).
  • DatePicker: sigue usando <input type="date"> nativo (simplificacion deliberada del MVP).
  • En producción, crear los departamentos/usuarios reales de la empresa desde la UI (arranca limpia a proposito, ver decision abajo).

Decisiones clave

  • MVP simplificado respecto al listado original de 30 areas — detalle en SPEC.md.
  • Identidad UI/UX: UI-UX-WINDOWS.md (Fluent/Windows 11), no la identidad web estandar del grupo.
  • Empresa unica (single-company): no existe tabla companies.
  • Arquetipo de despliegue B (dos servicios separados).
  • Produccion arranca sin datos de ejemplo: seed-db.js solo carga catalogos universales (roles/prioridades/estados/tipos) cuando NODE_ENV=production; los departamentos y usuarios de ejemplo (TI/Finanzas/RRHH/Comercial, admin con clave=usuario) son SOLO de dev. El admin real de produccion se crea con create-admin.js (clave fuerte generada, nunca clave=usuario).
  • Autorregistro con doble candado (correo + aprobacion admin) — decision explicita del usuario, revierte la regla inicial "sin autosuscripcion". El primer usuario del sistema es superadmin automatico; el resto pasa por verificacion + aprobacion. SMTP vive en BD (cifrado), configurable solo por el superadmin desde la UI, no en .env.

Deuda tecnica

  • npm audit: 3 vulnerabilidades moderadas en qs/body-parser, transitivas de Express 4.x (sin fix no-breaking disponible al 2026-09-06). No critico; revisar cuando Express publique el fix.