Files
project.linkedcorp.net/ESTADO.md
T
Milton Gonzalez 7557dffc52 feat: autorregistro con verificacion de correo + aprobacion, superadmin y SMTP
- POST /api/auth/register: primer usuario del sistema -> superadmin con sesion
  directa (bootstrap, sin correo ni aprobacion); los siguientes quedan
  pending_verification y reciben un correo con enlace de un solo uso (24h).
- GET /api/auth/verify-email: pasa a pending_approval y notifica in-app a los
  admin/superadmin activos.
- admin/superadmin aprueban (POST /api/users/:id/approve, eligen rol y
  departamento) o rechazan (POST /api/users/:id/reject, borra y audita el
  email) desde Organizacion -> Usuarios (nuevo badge de estado + acciones).
- login() da mensaje especifico segun el status de la cuenta en vez del
  generico "credenciales invalidas".
- Recuperacion de clave (forgot/reset-password): respuesta siempre generica,
  token de 1 hora de un solo uso.
- Nuevo modulo settings: SMTP configurable SOLO por superadmin desde
  Configuracion -> Correo (SMTP); clave cifrada AES-256-GCM (ENCRYPTION_KEY)
  en la tabla 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 envio tumbe al que lo llama.
- Migracion 002_registration_and_smtp.sql: rol superadmin, columnas de ciclo
  de vida en users (status, tokens), tabla system_settings, y promueve al
  usuario mas antiguo del sistema a superadmin.
- Fix: React.StrictMode disparaba el efecto de VerifyEmailPage dos veces; la
  segunda llamada (token ya consumido) mostraba "enlace invalido" pese a que
  la verificacion ya habia funcionado. Se agrega una guarda por token.
- Fix (deuda tecnica v1.0.0): se reordena el montaje de rutas en app.js —
  subtasksRoutes (mount generico en /api) va al final, para no interceptar
  con su requireAuth interno una request sin token dirigida a un router mas
  especifico registrado despues.
- Documentacion actualizada: AGENTS.md, SPEC.md, API.md, BASE_DE_DATOS.md,
  CONFIGURACION.md, ESTADO.md, CHANGELOG.md. Version 1.1.0.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 23:28:46 -05:00

9.0 KiB
Raw Blame History

ESTADO — project.linkedcorp.net

Ultima actualizacion: 2026-09-06 Fase actual: En produccion (https://project.linkedcorp.net, v1.1.0). MVP fase 1 operativo + autorregistro/aprobacion/SMTP.

Como retomar

  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

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.
  • Pendiente: desplegar esta versión a producción (migración 002 sobre .32 + redeploy de ambos servicios) — ver DEPLOY_WEB.md. El superadmin de producción deberá cargar el SMTP real desde la UI cuando lo tenga; hasta entonces el sistema sigue en modo dev (logueando enlaces).

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 configurables por modulo × accion desde la UI (hoy: roles fijos codificados).
  • 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.