# Changelog - project.linkedcorp.net ## [1.7.0] - 2026-09-10 ### Added - Agregar miembro a un proyecto ahora acepta un **correo que todavía no es usuario del sistema** (campo "Invitar por correo" en el popup de Miembros, alternativo a elegir uno existente). Si el correo no pertenece a nadie, se crea una cuenta en estado `invited` y se le manda un correo con un enlace de un solo uso (`/aceptar-invitacion?token=...`, vence en 7 días) para que complete su propio registro (elige nombre y clave); la fila de `project_members` ya queda creada de una vez, así que en cuanto acepta ya aparece como miembro sin pasos adicionales. A diferencia del autorregistro público, no pasa por aprobación de un admin — quien lo agregó a su proyecto ya lo vetó. Nuevos endpoints públicos `GET /api/auth/invite` y `POST /api/auth/accept-invite`. ## [1.6.1] - 2026-09-09 ### Changed - Nuevo ícono/logo de la app derivado del ícono original de LinkedCorp (círculo azul de marca `#1C55FF` con la red de nodos): se agregó una insignia con el acento de la app (`#0078D4`) para identificar visualmente el módulo de Proyectos. Actualizados `logoLinked1.png`, `logoLinkedCorpTxt.png` y `logoLinkedCorpTxtBlack.png` (sidebar y login, temas oscuro/claro). - Favicon nuevo (`favicon.svg` + `favicon.png` + `apple-touch-icon.png`); antes la app no declaraba ninguno. ## [1.6.0] - 2026-09-09 ### Added - Un proyecto puede tener **uno o más administradores del proyecto** (`role_in_project = 'admin'` en `project_members`), sin importar el rol global del usuario — un `collaborator` puede ser administrador de un proyecto puntual. Se otorga/quita desde Miembros: casilla "Agregar como administrador del proyecto" al agregar, y un botón de escudo para promover/degradar a un miembro existente (protegido: nunca toca al `Dueño`). Nuevo `PUT /api/projects/:id/members/:userId/role`. `canWriteProject` ahora reconoce este rol por-proyecto además del comportamiento previo (admin/superadmin/it_manager global, o project_lead miembro). ### Changed - El menú "Configuración" (apariencia, catálogos, SMTP) ahora es **visible y accesible solo para el superadmin** — antes cualquier usuario logueado lo veía y podía entrar (el tema/idioma personal sigue disponible para todos desde los íconos de la barra superior, eso no cambió). Se guarda tanto en el menú lateral como en la ruta directa `/configuracion`. - Escritura de catálogos (`/api/catalogs/*`, usado por la pantalla de Configuración) restringida de `[superadmin, admin]` a solo `superadmin`, para que el backend sea consistente con que `admin` ya no ve ni puede entrar a esa pantalla — la lectura sigue abierta a cualquier usuario (los combos de prioridad/estado en el resto de la app la necesitan). ## [1.5.0] - 2026-09-09 ### Added - Eliminar proyecto: eliminación **lógica** (`deleted_at`/`deleted_by`) disponible para quien puede editar el proyecto (superadmin/admin/it_manager/project_lead dueño o miembro), con popup de confirmación (`ContentDialog`) antes de aplicarla. El proyecto desaparece del listado y del dashboard, pero sigue en la base de datos. - Papelera de proyectos, visible solo para el **superadmin** (botón "Papelera" en Proyectos): lista los proyectos eliminados lógicamente, con acciones "Restaurar" y "Eliminar definitivamente" (esta última con su propia confirmación, más severa — advierte que también borra actividades/comentarios/adjuntos). El borrado físico (`DELETE`) solo puede aplicarse sobre un proyecto que ya pasó por la eliminación lógica (nunca en un solo paso). - Columna "Creado" (fecha) en el listado de proyectos, ordenada por defecto de más nuevo a más antiguo — un proyecto recién creado aparece primero sin tener que buscarlo. `ListView` ahora soporta un orden inicial (`initialSort`) además del ordenamiento por clic en cabecera que ya tenía. ### Fixed - Los KPIs del dashboard (proyectos activos/atrasados/por vencer, avance promedio, actividades pendientes/atrasadas/de hoy, proyectos por estado) ahora excluyen proyectos eliminados lógicamente — antes de este cambio no existía el concepto, así que no aplica como regresión, pero se dejó explícito para que un futuro cambio no los vuelva a incluir por accidente. ## [1.4.0] - 2026-09-09 ### Added - Boton de revelar/ocultar clave (icono de ojo) en todos los campos de contraseña de la app: login, registro, restablecer clave, cambiar clave (usuario logueado), crear usuario y la clave SMTP en Configuración. Nuevo componente reutilizable `PasswordInput`. ### Fixed - El fix de espacios en SMTP del v1.3.0 usaba `trim()`, que solo recorta los bordes. El caso real en producción tenía el espacio a mitad del host (`"mail.linkedcorp." + " " + "net"`), asi que seguia fallando tras el primer fix. Corregido para quitar cualquier espacio, no solo los bordes. ## [1.3.0] - 2026-09-06 ### Added - Configuración → Correo (SMTP): botón "Enviar prueba" con campo de destinatario. Ejecuta un envío real (`POST /api/settings/smtp/test`, solo superadmin, rate-limited) usando los valores actuales del formulario (aunque no se hayan guardado) y muestra el resultado real — éxito o el error tal cual lo devuelve el servidor SMTP — a diferencia de `sendMail()` (correo de negocio), que nunca lanza para no romper flujos como `forgot-password`. ### Fixed - La pantalla de SMTP no tenía forma de verificar que la configuración guardada funcionara de verdad; un error de host/certificado/credenciales solo se detectaba cuando fallaba un correo real de negocio, sin ningún diagnóstico. Regla agregada a `SEGURIDAD-Y-CALIDAD.md` del orquestador: toda config de servicio externo debe incluir una acción de prueba real. ## [1.2.0] - 2026-09-06 ### Added - Cambiar clave desde la app: `PUT /api/auth/change-password` (exige la clave actual) + opción "Cambiar clave" en el menú de usuario (popup), disponible para cualquier usuario logueado. ## [1.1.0] - 2026-09-06 ### Added - Autorregistro público (`/registro`) con verificación de correo (enlace de un solo uso, 24h) y aprobación posterior por Administrador/Superadministrador (`/api/users/:id/approve|reject`). - Recuperación de clave (`/olvide-clave` → `/restablecer-clave`), respuesta siempre genérica. - Rol `superadmin`: el usuario más antiguo del sistema (bootstrap automático al primer registro). - Configuración → Correo (SMTP), solo visible/editable por el superadmin; clave cifrada (AES-256-GCM) en `system_settings`, nunca expuesta por la API. Sin configurar, los correos de verificación/recuperación se loguean en vez de enviarse (modo dev, no rompe el flujo). ### Fixed - Bug real: `React.StrictMode` disparaba dos veces el efecto de `VerifyEmailPage`, y la segunda llamada (token ya consumido) mostraba "enlace inválido" aunque la verificación sí había funcionado. Corregido con una guarda por token ya solicitado. - Reordenado el montaje de rutas del backend: `subtasksRoutes` (mount genérico en `/api`) queda al final, para no interceptar con su `requireAuth` interno una request sin token dirigida a un router más específico registrado después (ver deuda técnica de la v1.0.0). ## [1.0.0] - 2026-09-06 ### Added - Primer despliegue a producción: `https://project.linkedcorp.net` (arquetipo B, dos servicios). - `create-admin.js`: bootstrap del usuario Administrador de producción con clave fuerte generada. ### Changed - `seed-db.js` separa catálogos (universal) de datos de ejemplo (solo entornos no productivos). - Logo real de LinkedCorp (sidebar, login) en vez del placeholder "LC"; tamaño duplicado. - `ComboBox`/`Flyout` se posicionan con portal a `document.body` (ya no se recortan dentro de un `Expander` o `DetailPopup`). - Master-detail de listados unificado en `DetailPopup` (popup de tamaño fijo, no se cierra con clic afuera) en Proyectos, Actividades, Departamentos, Usuarios, Miembros y Catálogos. - "Miembros" del proyecto pasa a ser su propia pestaña (antes vivía dentro de "Info"). ## [0.1.0] - 2026-09-03 ### Added - Estructura inicial del proyecto (backend Express + frontend React/Vite + MariaDB). - Modelo de datos MVP: usuarios/roles, departamentos, proyectos, actividades, subtareas, dependencias, comentarios, adjuntos, notificaciones, auditoría, catálogos. - Identidad UI/UX Fluent/Windows 11 (UI-UX-WINDOWS) adaptada a app web.