Files
project.linkedcorp.net/CHANGELOG.md
T
2026-10-23 17:37:30 -05:00

1103 lines
63 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog - project.linkedcorp.net
## [4.0.5] - 2026-10-23
### Fixed
- "No se pudo generar un plan con tareas": con 4.000 tokens de tope, una propuesta grande (con
el razonamiento del modelo) podía quedar cortada y llegar sin actividades. Tope subido a
12.000 (solo se cobra lo usado) y, si aun así se corta, se informa con un mensaje claro. El log
registra el motivo de fin de cada llamada.
## [4.0.4] - 2026-10-23
### Changed
- "Nuevo con IA" también detecta cuando lo pedido ya existe como actividad o tarea dentro de otro
proyecto (no solo proyectos): el filtro por palabras clave reúne proyectos, actividades y
tareas visibles (máx. 20 candidatos) y la IA marca lo que ya cubre el mismo objetivo. El aviso
indica el tipo y el proyecto ("tarea «...» en PRY-0005 ..."). Sigue en la misma llamada.
## [4.0.3] - 2026-10-23
### Fixed
- Las consultas a la IA ("Nuevo con IA" y "Plan con IA") muestran un indicador de proceso con
spinner, mensaje y segundos transcurridos (componente compartido `BusyPanel`); antes parecía
que el botón no hacía nada mientras la IA respondía.
## [4.0.2] - 2026-10-23
### Changed
- Detección de proyectos duplicados en "Nuevo con IA" ahora la decide la IA, dentro de la misma
llamada de la propuesta: un filtro amplio por palabras clave (sin tokens) elige hasta 20
candidatos visibles para el usuario y la IA marca solo los que persiguen el mismo objetivo,
aunque usen sinónimos u otra redacción. Costo extra fijo (~300-600 tokens de entrada).
## [4.0.1] - 2026-10-23
### Added
- "Nuevo con IA" avisa si ya existen proyectos parecidos (visibles para el usuario, fuera de la
papelera), con enlace para abrirlos. Comparación por palabras clave sin IA ni tokens: ignora
tildes/mayúsculas y palabras vacías, une singular/plural y aplica equivalencias de TI
(helpdesk = mesa de ayuda, PC = equipo, etc.). El usuario decide si crea igual.
### Changed
- La IA redacta por separado el objetivo (una oración: qué y para qué) y la descripción (alcance);
ambos se ven en la revisión. Antes el texto del usuario quedaba como objetivo.
## [4.0.0] - 2026-10-23
### Added
- Asistente "Nuevo con IA" en Proyectos (roles que crean proyectos, con la IA configurada):
1) el usuario describe el objetivo (mín. 20 caracteres), elige departamento solicitante y fecha
de inicio — validado antes de llamar a la IA; 2) una sola llamada propone nombre, objetivo
redactado, descripción (alcance), tipo, fin estimado y actividades con tareas y días; 3) el
usuario revisa, edita el nombre, desmarca y crea. El proyecto queda Planificado, con quien lo
crea como responsable y único miembro; actividades encadenadas y tareas con fecha dentro de
su actividad, todas con responsable.
- Si el texto no describe un proyecto, la IA lo rechaza ("Solo puedo ayudarte a crear
proyectos") con un consumo mínimo. Ninguna actividad se crea sin tareas.
### Fixed
- "Plan con IA" → "Crear seleccionadas" fallaba (orden por columna inexistente en prioridades) y
el diálogo no mostraba bien las tareas; ahora muestran su duración. Al aplicar, las
actividades arrancan hoy o en el inicio del proyecto si aún no empezó.
## [3.2.0] - 2026-10-23
### Added
- Integración IA (API de Anthropic): Configuración → "Inteligencia artificial (IA)", solo
superadmin. Clave cifrada AES-256-GCM en `system_settings` (migración 031), modelo Claude
Haiku 5.5 (económico, por defecto) o Sonnet 5.5, y botón "Probar conexión".
- "Plan con IA" en la pestaña Actividades de un proyecto: la IA propone actividades con duración
y tareas a partir del nombre/descripción/objetivo; el usuario revisa, desmarca y recién ahí se
crean (encadenadas desde hoy, prioridad media, primer estado abierto) con los servicios normales.
- Tope de 30 planes por hora por usuario, auditoría (`ai_plan`) y log de tokens por llamada.
### Fixed
- Campos de clave de SMTP/IA con `autocomplete="new-password"`: el gestor de contraseñas del
navegador ya no rellena la clave de login y deja el formulario "con cambios sin guardar".
## [3.1.2] - 2026-10-23
### Fixed
- Panel: un usuario sin el módulo Proyectos ya no ve KPIs ni detalle de proyectos; ve solo una
bienvenida. El backend bloquea `/api/dashboard/*` con 403 sin ese módulo.
## [3.1.1] - 2026-10-23
### Fixed
- El popup de actualización quedaba en "Reiniciando servicios" hasta agotar los 10 minutos: el
script corre en el cgroup del backend y al reiniciarlo systemd lo mataba antes de marcar el fin.
Ahora reinicia el frontend primero, marca el fin y reinicia el backend al final; el popup da por
terminado cuando el backend ya reiniciado reporta la versión nueva y el frontend sirve la misma.
- El porcentaje del popup avanza según la fase real del script, no por tiempo transcurrido.
## [3.1.0] - 2026-10-23
### Added
- Acceso por módulo y por usuario: el superadmin, desde Organización → Usuarios → menú de la
fila → "Módulos", habilita o quita Proyectos, Tareas recurrentes, Notas, Contraseñas, Equipos y
Organización. Panel lo ve todo usuario; Configuración sigue siendo solo de superadmin.
- El backend bloquea con 403 (`requireModule`) cada ruta del módulo deshabilitado; el menú lo
oculta y la ruta redirige al Panel. La búsqueda global devuelve vacío sin módulo Proyectos.
En Organización, sin el módulo no se puede gestionar (las lecturas de usuarios/departamentos
siguen abiertas porque alimentan selectores de otras pantallas).
- Migración 030 (`user_modules`): sin fila = habilitado, así que al actualizar nadie pierde acceso.
Cada cambio queda en auditoría (`update_modules`).
## [3.0.1] - 2026-10-23
### Fixed
- El diálogo de actualización permanece abierto con la fase del proceso y solo recarga al confirmar
que el script terminó y que backend y frontend sirven la versión nueva. El frontend expone
`version.json` sin caché; se fuerza la actualización del Service Worker antes de recargar.
- Se toleran los cortes durante reinicios y se muestra error o espera agotada tras 10 minutos,
con opción de reintentar la comprobación o recargar.
## [3.0.0] - 2026-10-23
### Security
- Se restringe la asignación de superadmin, la escritura de consultores y la búsqueda/tareas
recurrentes por alcance. El primer registro es atómico. Cambio/restablecimiento de clave
revoca JWT previos (migración 028).
- Logo público solo PNG/JPG/WEBP con firma comprobada y CSP; se censura `?token=` en logs de la
aplicación; los adjuntos comprueban permisos antes de recibir archivos y limpian fallos.
- La ingesta valida token antes del cuerpo, limita frecuencia/concurrencia y parsea en worker.
El vínculo token-equipo queda pendiente para no romper agentes con token compartido.
### Changed
- `GET /api/projects` devuelve páginas; frontend y selectores adaptados. La edición de proyectos
y comentarios exige versión optimista (migración 029), con rechazo 409 al competir.
- El control optimista se extiende a actividades, tareas, departamentos, usuarios, catálogos,
notas, tareas recurrentes, equipos, empresa y SMTP. Los formularios conservan la versión
del borrador y muestran el aviso de conflicto al recibir 409.
- Correos HTML escapados y recordatorios reintentables tras fallo SMTP; borradores limitados a
campos permitidos por formulario y limpiados al cerrar sesión voluntariamente.
- Diálogos, controles de lista/combo/expansor, pestañas e i18n mejorados para teclado y lectores
de pantalla.
### Deployment
- Aplicar migraciones 028 y 029 antes del backend de esta versión. Los JWT existentes caducarán;
clientes externos de proyectos/adjuntos deben adoptar los contratos descritos en `API.md`.
## [2.19.0] - 2026-10-21
### Added
- Panel: selector **Tarjetas (n/7)** junto al título, con una casilla por tarjeta para
mostrarla u ocultarla. La elección se recuerda por usuario en el navegador (sobrevive a
recargar y a cerrar sesión). Nuevo componente `CheckListDropdown` (selección múltiple con
casillas, mismo estilo que ComboBox).
## [2.18.3] - 2026-10-21
### Fixed
- Después de una actualización, un F5 normal (sin Ctrl) mostraba la versión anterior hasta la
recarga siguiente: el service worker servía el index.html viejo de su caché. Ahora la página
siempre se pide al servidor primero (la caché solo se usa sin conexión), `index.html`/`sw.js`
se sirven con `Cache-Control: no-cache` (nuevo `serve.json`), y la app revisa si hay versión
nueva cada 30 min y al volver a la pestaña. Los navegadores que tengan la versión vieja del
service worker necesitan una recarga más (la última) para tomar este cambio.
## [2.18.2] - 2026-10-21
### Removed
- Panel: se quita el bloque "Mis actividades pendientes" (el detalle ya se ve en el popup de
cada tarjeta). Queda solo "Proyectos por estado" debajo de las tarjetas.
## [2.18.1] - 2026-10-21
### Fixed
- Panel → popups de detalle: las barras de avance quedan alineadas una debajo de otra aunque la
fila no tenga etiqueta de vencimiento (la etiqueta ocupa siempre su columna).
## [2.18.0] - 2026-10-21
### Changed
- Panel: el detalle de cada tarjeta se abre en un **popup** en vez de reemplazar el bloque de
"Mis actividades". Ahora las 7 tarjetas tienen detalle, cada una con su lista: proyectos
activos, atrasados y próximos a vencer; actividades pendientes, vencidas y para hoy; y en
Avance promedio los proyectos activos ordenados por avance. Clic en una fila abre el proyecto
o la actividad.
### Fixed
- Panel → "Para hoy" contaba actividades eliminadas y de proyectos cancelados; ya no.
## [2.17.11] - 2026-10-21
### Changed
- Panel: las tarjetas con medidor tienen el medidor y sus textos centrados dentro de la tarjeta.
## [2.17.10] - 2026-10-21
### Changed
- Panel → "Avance promedio": medidor (verde) con el porcentaje al centro.
### Fixed
- Medidores del Panel: en 0% ya no aparece un punto suelto al inicio del arco, y los valores
largos (ej. "38.96%") usan letra más chica para no tocar el arco.
## [2.17.9] - 2026-10-21
### Changed
- Panel → "Actividades vencidas": mismo modelo. Medidor con el porcentaje de vencidas sobre el
total de actividades sin contar las canceladas (ni las de proyectos cancelados), "N de M"
debajo, y al hacer clic el bloque de abajo lista las actividades vencidas.
### Fixed
- El conteo de vencidas incluía actividades eliminadas y de proyectos cancelados; ya no.
## [2.17.8] - 2026-10-21
### Changed
- Panel → "Actividades pendientes": mismo modelo que las tarjetas de proyectos. Medidor con el
porcentaje de pendientes sobre el total de actividades sin contar las de proyectos
cancelados, "N de M" debajo, y al hacer clic el bloque de abajo lista las actividades
pendientes (clic abre la actividad en su proyecto).
### Fixed
- Panel → "Actividades pendientes" contaba también actividades eliminadas y de proyectos
cancelados; ya no.
## [2.17.7] - 2026-10-21
### Changed
- Panel → "Proyectos activos": mismo modelo que "Proyectos atrasados". Medidor con el
porcentaje de activos sobre el total de proyectos sin contar los cancelados (los completados
sí cuentan), "N de M" debajo, y al hacer clic el bloque de abajo muestra "Mis proyectos
activos".
## [2.17.6] - 2026-10-21
### Changed
- Panel → "Proyectos atrasados": el centro del medidor muestra el porcentaje (atrasados sobre
activos) y debajo "N de M", para que se entienda de cuántos.
## [2.17.5] - 2026-10-20
### Added
- Panel: la tarjeta "Proyectos atrasados" muestra un medidor (atrasados sobre activos) con el
número al centro. Al hacer clic, el bloque de abajo cambia de "Mis actividades pendientes" a
"Mis proyectos atrasados" (mismo criterio que el número); otro clic, o "Ver mis
actividades", lo devuelve.
## [2.17.4] - 2026-10-20
### Fixed
- Avance del proyecto: el promedio incluía actividades eliminadas (papelera), así que un proyecto
con todas sus actividades vivas al 100% podía quedar en 50%. Ahora solo cuenta actividades no
eliminadas.
## [2.17.3] - 2026-10-20
### Fixed
- ComboBox (toda la app): al hacer scroll dentro de la lista desplegada (rueda o flechas de la
barra) se cerraba, así que la última opción (ej. "Cancelado" en Estado) no se alcanzaba a ver.
Ahora el scroll interno de la lista no la cierra; el de la página sí.
## [2.17.2] - 2026-10-20
### Changed
- Proyectos → listado: el checkbox "Ocultar proyectos 100%" pasa a ser el selector **Avance**
(Todos / Ocultar 100% / Solo 100%), así no hay combinaciones contradictorias. Arranca en
"Todos", se recuerda en el navegador aunque se cierre sesión, y respeta lo que ya estaba
marcado con el checkbox anterior.
## [2.17.1] - 2026-10-20
### Added
- Proyectos → listado: checkbox "Ocultar proyectos 100%" (desmarcado por defecto). La elección
se recuerda en el navegador, aunque se cierre sesión.
## [2.17.0] - 2026-10-20
### Added
- Equipos → detalle: pestaña **Usuarios** (después de General) con el usuario que tiene sesión
iniciada, el total y la lista de usuarios locales de Windows (con SID) y los grupos locales.
Solo cuentas locales del equipo (no dominio ni Microsoft 365). Migración `027`
(`device_accounts`); los equipos la llenan en su siguiente reporte.
## [2.16.5] - 2026-10-20
### Changed
- Equipos → listado: se quita el botón "Información" del final de cada fila; el detalle del equipo
se abre solo con clic en la fila.
## [2.16.4] - 2026-10-20
### Changed
- Equipos → detalle → General: "Primer reporte" y "Último reporte" pasan a la sección de arriba,
después de Departamento (también visibles, de solo lectura, en modo edición).
## [2.16.3] - 2026-10-20
### Changed
- Equipos → detalle → General: la sección manual (Estado, Asignado a, Departamento, Notas, con su
botón Editar) pasa al principio, antes de los datos que reporta el agente.
## [2.16.2] - 2026-10-20
### Fixed
- Instalador del agente (Equipos → Agentes): ahora **verifica el token contra el servidor antes de
instalar** (token inválido o sin conexión → se detiene con un mensaje claro y no instala), y tras
instalar **escribe servidor/usuario/clave/etiqueta en el registro y reinicia el servicio**, así
funciona también en equipos que ya tenían el agente instalado (msiexec no reescribe su
configuración en ese caso).
## [2.16.1] - 2026-10-20
### Changed
- Barra superior (topbar) a la mitad de alto (84 px → 42 px).
- Nueva barra inferior fija en la columna de contenido (nunca queda contenido detrás; el sidebar no
se toca). Muestra © año + nombre y tiene un hueco a la derecha para indicadores de cada página.
- Contraseñas: la cuenta regresiva del cierre automático pasa a la barra inferior (derecha); solo
se ve con el menú desbloqueado y desaparece al pedir el PIN o cambiar de menú.
## [2.16.0] - 2026-10-20
### Added
- Equipos → Agentes: "Instalador para Windows": descarga un `.bat` (generado en el navegador, con
servidor y token ya puestos) que baja el MSI oficial del agente GLPI 1.21 y lo instala en silencio
con `SERVER/USER/PASSWORD/TAG`. Si el .msi está junto al .bat, no descarga.
- Tokens de ingesta recuperables: se guardan también cifrados (AES-256-GCM, migración `025`) y cada
token de la lista tiene un botón para descargar el instalador sin volver a pegarlo (queda en
auditoría; los tokens creados antes de esta versión no son recuperables).
- Equipos → Compartir (solo admin/superadmin): da acceso de **solo lectura** (Resumen, Equipos y
Software) a usuarios que por su rol no ven el menú. Migración `026` (`device_viewers`). Sin
editar, sin Agentes, sin inventario crudo. El menú Equipos aparece solo a quien tenga acceso.
- Contraseñas: contador visible junto al título con el tiempo que falta para el cierre automático
(se pone amarillo en los últimos 30 s y se reinicia con cada acción).
### Fixed
- Contraseñas: ya no te saca del menú en medio de escribir/editar una credencial (se perdía lo no
guardado). El cierre automático ahora es por **inactividad**: 3 minutos sin teclado, clic, toque
o rueda; cada acción reinicia el contador. El token de desbloqueo del servidor ahora se renueva
en cada request válido (antes vencía a los 30 min aunque estuvieras trabajando). Salir a otro
menú o cerrar la pestaña sigue bloqueando igual.
- Equipos → Software: las entradas con nombre de código `{GUID}` (instaladores sin nombre) ahora
cuentan como componentes y quedan ocultas por defecto.
## [2.15.0] - 2026-10-19
### Added
- Menú **Equipos**: inventario de TI alimentado por el agente GLPI oficial (sin servidor GLPI).
Ingesta `POST /api/inventory` (JSON/XML, gzip/zlib) con token de instalación, upsert por
`deviceid`, historial de cambios, KPIs, software transversal y pestaña Agentes para generar
tokens. Edición manual de estado, usuario asignado, departamento y notas.
- Migración `023_devices.sql` (devices + componentes, device_changes, inventory_tokens).
- Equipos → Software (general y por equipo): casilla "Mostrar actualizaciones, drivers y componentes
del sistema", desmarcada por defecto (solo aplicaciones). Migración `024` agrega `category` e
`is_component` a `device_software`; se decide por `system_category` del agente y por nombre.
- Dependencia backend: `fast-xml-parser`. Diseño traído de linkedtrack (que sigue aparte) en
`docs/ARQUITECTURA-INVENTARIO.md`.
## [2.14.0] - 2026-10-14
### Added
- Contraseñas: "Compartir grupo" en el menú de un grupo — comparte de una vez todas sus
credenciales (de solo lectura) con un usuario, y marca tanto cada credencial como la tarjeta
del grupo con el ícono de compartido (basta con que una sola esté compartida).
- Contraseñas: al destruir un grupo ahora hay dos opciones — "Destruir grupo" (como antes, solo
desagrupa) y "Destruir grupo y credenciales" (nueva, borra también todas sus credenciales,
con advertencia que muestra cuántas).
### Fixed
- ComboBox: el panel se cerraba solo apenas se abría si el trigger estaba cerca del borde de un
contenedor con scroll (ej. el popup de grupo) — un micro-scroll automático del navegador al
enfocar el botón disparaba el cierre por "scroll detectado". Corregido en todos los ComboBox
de la app, no solo en Contraseñas.
## [2.13.2] - 2026-10-14
### Changed
- Contraseñas (solo este módulo): borrar una credencial o un grupo ahora dice "Destruir" en vez
de "Eliminar", con una advertencia fuerte (franja roja, texto en mayúsculas) de que la
destrucción es permanente e irreversible. El registro de auditoría ya guardaba quién y cuándo
borró cada una (sin el contenido), sin cambios ahí.
## [2.13.1] - 2026-10-14
### Fixed
- ComboBox y Flyout (menu de 3 puntos): el panel desplegable se quedaba cortado por el borde
inferior/derecho de la ventana cuando el trigger estaba cerca de ese borde (ej. compartir una
credencial, "Eliminar" en una fila al final de la grilla). Ahora se mide el tamaño real del
panel y se voltea hacia arriba / se recorta hacia adentro si no cabe — siempre visible dentro
de la ventana.
## [2.13.0] - 2026-10-14
### Added
- Contraseñas: grupos de un solo nivel (ej. "Correos") para organizar las credenciales — se
muestran como tarjetas en la vista inicial, clic entra a ver solo las de ese grupo.
- Contraseñas: compartir una credencial individual (nunca un grupo completo) de solo lectura con
otro usuario registrado — puede revelar y copiar la contraseña real, pero nunca
editarla/borrarla/compartirla ni moverla de grupo.
## [2.12.1] - 2026-10-14
### Added
- Documentos (proyectos y actividades): las imágenes (.png, .jpg, .webp) también se pueden ver
en el popup con el botón "Ver", igual que ya funcionaba con .txt/.md — sin tocar ese flujo.
## [2.12.0] - 2026-10-14
### Added
- Comentarios (de proyectos y actividades): ahora se pueden editar y borrar, solo quien lo
escribió (o superadmin/admin) — antes solo se podían crear. Un comentario editado muestra
"Editado" junto a la fecha, igual que ya hacía Notas.
## [2.11.3] - 2026-10-14
### Fixed
- Popup de actividad: los badges de "Comentarios" y "Documentos" se quedaban pegados en el
número viejo al agregar/borrar algo estando parado en esa misma pestaña (recién se
actualizaban al cambiar de pestaña y volver). Mismo fix que ya se había aplicado al nivel de
proyecto, pendiente de aplicar aquí también.
## [2.11.2] - 2026-10-14
### Changed
- Badge "Tareas" del popup de actividad: pasa de mostrar pendientes/total (ej. "3/4") a
hechas/total (ej. "1/4") — confundía, parecía decir que faltaban más de las que en realidad
faltaban.
## [2.11.1] - 2026-10-14
### Fixed
- La 2.11.0 puso los contadores de dependencias/comentarios/documentos/miembros como columnas
nuevas en las grillas de Proyectos y Actividades — no era lo pedido, desbordaba la tabla.
Se quitan esas columnas y los contadores van donde correspondía: como badge junto al nombre
de cada pestaña (Miembros, Actividades, Comentarios, Documentos del proyecto; Dependencias,
Comentarios, Documentos de la actividad), al mismo estilo que ya usaba "Tareas n/n". De paso
se corrige que el badge de una pestaña se ocultaba en 0 en vez de mostrarlo.
## [2.11.0] - 2026-10-14
### Added
- Listado de Actividades (dentro de un proyecto): columnas nuevas con el número de
dependencias, comentarios y documentos de cada actividad (siempre visible, 0 si no hay).
- Listado de Proyectos: columnas nuevas con el número de miembros, actividades completas al
100% sobre el total (ej. "1/4"), comentarios y documentos de cada proyecto (siempre visible,
0 si no hay).
## [2.10.7] - 2026-10-12
### Changed
- Tarjetas de Notas: la fecha (abajo a la izquierda) queda al mismo nivel que los íconos de
compartida/arrastre (abajo a la derecha) — antes se veía más arriba.
## [2.10.6] - 2026-10-12
### Changed
- Ícono de compartida de las tarjetas de Notas: se mueve junto al de arrastre, abajo a la
derecha (antes estaba junto a la fecha).
### Fixed
- El ícono de compartida no se actualizaba en la tarjeta tras compartir/dejar de compartir
hasta recargar la página.
## [2.10.5] - 2026-10-12
### Changed
- Ícono de arrastre de las tarjetas de Notas: de la esquina superior derecha a la inferior
derecha.
## [2.10.4] - 2026-10-12
### Added
- Tarjetas de Notas: se pueden arrastrar (ícono de agarre en la esquina) para cambiar su
posición — el orden queda guardado. Solo aplica a tus propias notas (las compartidas contigo
quedan siempre al final, no son arrastrables); se desactiva mientras hay un filtro de
búsqueda activo. El clic normal sobre la tarjeta sigue abriendo la edición sin interferencia.
## [2.10.3] - 2026-10-12
### Added
- Organización → Usuarios: nueva opción "Reenviar correo" en el menú de 3 puntos para usuarios
con invitación o verificación de correo pendiente — genera un enlace nuevo (el anterior puede
haber vencido o perderse) y reenvía el mismo correo original.
### Fixed
- El estado "Invitación pendiente" se mostraba sin traducir en la tabla de usuarios.
## [2.10.2] - 2026-10-12
### Added
- Tarjetas de Notas: ícono junto a la fecha cuando la nota está compartida (ya sea que la
compartiste con alguien, o que te la compartieron a ti).
- Buscador junto al título "Notas" que filtra las tarjetas en vivo por contenido.
## [2.10.1] - 2026-10-12
### Fixed
- "Probar correo" en Configuración → Correo mostraba "Error interno" en vez de un mensaje
claro cuando la clave SMTP guardada no se podía descifrar (por ejemplo, un servidor que
restauró un dump de otro con su propia `ENCRYPTION_KEY` — el caso de exilaser). Ahora indica
que hay que volver a escribir y guardar la clave.
- El mismo problema podía tumbar silenciosamente cualquier envío real (recuperar contraseña,
verificación de registro, invitaciones) en vez de degradar a modo dev como está documentado
que debe pasar sin SMTP utilizable — ya degrada correctamente.
- `trust proxy` configurado en Express (la app corre detrás de Nginx Proxy Manager): sin esto,
el límite de intentos (login, SMTP, etc.) compartía un solo cupo entre todos los usuarios en
vez de uno por persona, y cada request dejaba un aviso de validación en los logs.
## [2.10.0] - 2026-10-12
### Added
- Rediseño del módulo "Notas": ahora se ven como tarjetas (resumen del contenido), con una
primera tarjeta fija de "+" para crear — crear y editar se hacen en un popup, ya no inline.
- Compartir una nota con otro usuario ya registrado, siempre de solo lectura: el dueño sigue
siendo el único que la edita, borra o administra a quién está compartida; quien la recibe la
ve con un aviso "Compartida por {nombre}" y sin ningún control de edición.
## [2.9.1] - 2026-10-07
### Added
- Los bloques de código dentro de un .md visto en Documentos ahora tienen resaltado de sintaxis
a color (estilo Visual Studio/VSCode, claro y oscuro según el tema de la app) — js/ts, bash,
json, python, sql, yaml, html/xml, css, ini, dockerfile, markdown.
## [2.9.0] - 2026-10-07
### Added
- Documentos (adjuntos de proyectos/actividades): los archivos de texto plano (.txt) y Markdown
(.md) ahora se pueden ver directo con el botón "Ver" (ícono de ojo), sin necesidad de
descargarlos — el .md se renderiza con formato (encabezados, negrita, listas, enlaces, bloques
de código), sanitizado para evitar HTML/JS embebido.
### Fixed
- Subir un archivo `.md` fallaba con "tipo de archivo no permitido": el navegador no manda un
mimetype confiable para esa extensión (varía según sistema operativo). Ahora se normaliza por
extensión en vez de depender solo del mimetype que manda el navegador.
## [2.8.13] - 2026-10-02
### Changed
- El logo de LinkedCorp del login se mueve debajo de "¿Olvidaste tu contraseña? / Crear cuenta",
centrado, con el texto "LinkedCorp" a la derecha del ícono (ya no arriba junto al logo de
empresa). El logo de empresa vuelve a verse solo y centrado arriba.
## [2.8.12] - 2026-10-02
### Fixed
- El ícono de LinkedCorp en el login compartía la misma clase CSS que el logo de empresa
(80px), por eso se salía de la tarjeta al intentar achicarlo. Ahora tiene su propia clase
(40px) y el layout pasa a alinear el logo de empresa a la izquierda y el de LinkedCorp a la
derecha, sin desbordar los márgenes de la tarjeta.
## [2.8.11] - 2026-10-02
### Changed
- Ajuste fino del logo de LinkedCorp en el login (junto al de empresa): sube 50px y el texto
"LinkedCorp" pasa a 0.9rem.
## [2.8.10] - 2026-10-02
### Added
- Login: cuando hay un logo de empresa configurado (caso exilaser), ahora se muestra también el
logo de LinkedCorp a la derecha, a la misma altura, con el texto "LinkedCorp" debajo del ícono.
Sin logo de empresa configurado (caso LinkedCorp), el login no cambia.
## [2.8.9] - 2026-10-02
### Changed
- Texto "LinkedCorp" del logo del sidebar: tamaño reducido de 1.3rem a 1.0rem.
## [2.8.8] - 2026-10-02
### Fixed
- Corrección del ícono de LinkedCorp del sidebar (2.8.7 usó por error un logo distinto al
correcto).
## [2.8.7] - 2026-10-02
### Changed
- Nuevo ícono de LinkedCorp en el pie del menú lateral (reemplaza el anterior), al doble de
tamaño. Como el ícono nuevo no incluye el texto, se agrega "LinkedCorp" escrito aparte con una
tipografía redondeada similar a la de los logos anteriores (Baloo 2), que se adapta sola a
tema claro/oscuro.
## [2.8.6] - 2026-10-01
### Changed
- El botón para ocultar el catálogo de logos de marca casi no se distinguía (un "−" chico) —
ahora es una flecha roja apuntando hacia arriba, mucho más visible.
## [2.8.5] - 2026-10-01
### Fixed
- Faltaba la forma de volver a ocultar el catálogo de logos de marca una vez abierto con "+" —
ahora tiene su propio botón "−" al lado del título para cerrarlo de nuevo.
## [2.8.4] - 2026-10-01
### Changed
- El catálogo de logos de marca en "Contraseñas" queda oculto por defecto, con un botón "+" para
desplegarlo — el catálogo genérico de arriba (los íconos originales) no cambia. Si una entrada
ya tiene un logo de marca asignado, el catálogo se abre solo al editarla.
## [2.8.3] - 2026-10-01
### Fixed
- El PIN de "Contraseñas" (acceso y cambio de PIN) ya no usa `type="password"` en el campo —
Chrome lo detectaba como una credencial de sitio y ofrecía "¿Quieres actualizar la contraseña?"
cada vez que se desbloqueaba el candado. Ahora se enmascara solo visualmente (sigue viéndose
como puntos) sin disparar el gestor de contraseñas del navegador.
## [2.8.2] - 2026-10-01
### Added
- Al aplicar una actualización desde Configuración → Actualizaciones, ahora se bloquea toda la
pantalla con un círculo girando y un porcentaje estimado en el centro ("Actualizando…") hasta
que el sistema termina de reiniciarse; al confirmar que ya está al día, la página se recarga
sola para traer los cambios.
### Fixed
- El seguimiento de la actualización (`pollUntilUpToDate`) nunca corría en el entorno de
desarrollo por un efecto de React mal planteado (`mountedRef` quedaba en `false` para siempre
por el doble-render de `React.StrictMode`) — no afectaba producción, pero sí ocultaba el bug al
probar en dev.
## [2.8.1] - 2026-10-01
### Added
- Catálogo de íconos de "Contraseñas" ampliado con ~70 logos de marcas conocidas (Google, GitHub,
Cloudflare, cPanel, MikroTik, WordPress, etc.), empaquetados localmente desde `simple-icons`
(licencia CC0, dominio público) — sin ninguna consulta externa por entrada, mismo criterio de
privacidad que el catálogo genérico anterior.
## [2.8.0] - 2026-10-01
### Added
- Buscador en "Contraseñas": filtra las tarjetas mientras escribís, por nombre, usuario, enlace
o **notas** — las notas están cifradas, así que se descifran solo en el servidor para comparar
contra la búsqueda; el texto nunca viaja de vuelta al navegador salvo que coincida y entres a
ver esa entrada puntual.
## [2.7.2] - 2026-10-01
### Changed
- "Contraseñas" pasa de tabla a tarjetas: cada una muestra un ícono (a elección, de un catálogo
fijo — sin usar ningún servicio externo de favicon, por privacidad) o la inicial del nombre si
no se elige ninguno, junto con el nombre y el enlace.
### Fixed
- **Bug real**: editar una credencial sin antes revelar la contraseña la dejaba vacía al guardar
(se borraba sin querer). Ahora, si no se escribe una contraseña nueva al editar, se conserva la
que ya estaba guardada.
## [2.7.1] - 2026-10-01
### Changed
- "Contraseñas" vuelve a pedir el PIN cada vez que se sale del menú (a otro, o cerrando la
pestaña) y se vuelve a entrar — antes quedaba desbloqueado el resto de la sesión del sistema.
- Si el menú queda abierto sin atención, sale solo al Panel a los 3 minutos de haberse
desbloqueado.
## [2.7.0] - 2026-10-01
### Added
- Nuevo menú "Contraseñas": repositorio personal de credenciales (nombre, enlace, usuario,
contraseña, notas), siempre privado — nadie más lo ve, ni un superadmin.
- Contraseña y notas cifradas en el servidor (AES-256-GCM, mismo mecanismo ya probado que usa la
clave SMTP) — nunca en texto plano en la base de datos.
- El menú pide un PIN de 4 dígitos para entrar, aparte de la clave de acceso normal al sistema
(que no se toca). El PIN es un candado de acceso, no la clave de cifrado. Se puede cambiar
desde el propio menú, o restablecer por correo si se olvida — restablecerlo nunca borra ni
afecta las contraseñas ya guardadas, solo cambia el candado.
- Generador de contraseñas al crear una entrada nueva.
- Queda registrado en el log de auditoría cada vez que se crea, edita, elimina o **revela** una
contraseña guardada, y cada desbloqueo del candado.
- Compartir una entrada con otro usuario queda para una próxima versión.
## [2.6.1] - 2026-09-30
### Fixed
- **Bug real en el botón "Actualizar" (auto-actualización)**: el paso final reiniciaba backend y
frontend con un solo comando (`systemctl restart back front`), pero el permiso sudo sin
contraseña solo está autorizado para cada servicio por separado — el reinicio fallaba en
silencio (sin romper el resto del proceso) y el backend se quedaba con el código viejo
indefinidamente, aunque el panel ya mostrara "actualizado". El frontend sí se veía al día
porque no necesita reiniciar el proceso para servir archivos nuevos — por eso el síntoma era
confuso (la UI nueva se veía, pero funciones nuevas del backend faltaban). Se separa en dos
comandos `sudo systemctl restart` — uno por servicio.
## [2.6.0] - 2026-09-30
### Changed
- Listado de Proyectos: el porcentaje de avance ahora va **dentro** de la barra de progreso
(antes iba aparte, a la derecha) y el fondo de la barra pasa a un gris visible sobre el fondo
oscuro (antes casi no se notaba). Libera espacio horizontal en la fila.
### Added
- Ícono de "compartido" en el listado de Proyectos: aparece solo si el proyecto tiene otros
usuarios además del dueño. Al hacer clic muestra con quién está compartido y su permiso
(Lectura/Escritura).
## [2.5.0] - 2026-09-25
### Fixed
- **Bug de seguridad real**: cualquier usuario autenticado veía TODOS los proyectos del sistema
(listado, detalle, actividades, tareas, comentarios y adjuntos), sin importar si era miembro.
Ahora nadie ve un proyecto ajeno a menos que su dueño se lo comparta — los roles de
administración (superadmin/admin/it_manager) siguen viendo todo, para poder dar soporte.
### Added
- **Compartir proyectos**: solo el dueño del proyecto puede compartirlo (ni un admin del
proyecto ni un rol global pueden hacerlo por él). Dos niveles simples: **Lectura** (solo ver)
y **Escritura** (crear/editar/eliminar actividades y tareas del proyecto — nunca el proyecto
en sí: no puede borrarlo, ni editar sus datos, ni crear proyectos nuevos).
- **Papelera de actividades**: eliminar una actividad o tarea ahora es recuperable (antes se
borraba físico, sin vuelta atrás) — el dueño del proyecto puede restaurarlas desde un nuevo
botón "Papelera de actividades" en la pestaña Actividades.
- Panel principal (KPIs, calendario, "mis actividades pendientes"): mismo criterio de
visibilidad que el listado de proyectos — ya no cuenta ni muestra información de proyectos
ajenos para roles sin acceso total.
- Filtro "Usuario" en Proyectos (junto a Estado/Prioridad), visible solo para
superadmin/admin/it_manager — filtra el listado por dueño. Se había probado solo en dev; se
incluye en esta versión al ir de la mano con el resto de este cambio.
## [2.4.0] - 2026-09-22
### Fixed
- Menú lateral en celular: antes quedaba siempre visible fijo, ocupando gran parte de una
pantalla angosta. Ahora arranca oculto, se abre como un panel superpuesto (con fondo oscuro
detrás) desde el botón de hamburguesa, y se cierra solo al elegir una opción o tocar afuera.
El escritorio no cambia — sigue con el sidebar fijo y el modo compacto de siempre.
## [2.3.0] - 2026-09-22
### Added
- Al iniciar sesión, si sos superadmin y hay una actualización pendiente, aparece un aviso con
un acceso directo al panel de Actualizaciones (abre Configuración con ese panel ya
desplegado).
## [2.2.4] - 2026-09-22
### Fixed
- El botón "Actualizar" se quedaba visible después de aplicar la actualización, hasta que se
refrescaba la pestaña a mano. Ahora, mientras se aplica, el panel consulta el estado cada
pocos segundos y en cuanto confirma que ya quedó en la última versión, el botón desaparece
solo (sin depender de la recarga automática del service worker).
## [2.2.3] - 2026-09-22
### Fixed
- Al actualizar (ya sea con el botón nuevo o por deploy manual), la pestaña abierta seguía
mostrando JS/CSS viejo hasta hacer F5 a mano, aunque el servidor ya tuviera la versión nueva
— el service worker tomaba control solo pero no refrescaba la página. Ahora se refresca sola
en cuanto el service worker nuevo toma control.
## [2.2.2] - 2026-09-22
### Fixed
- El botón "Actualizar" fallaba en el build del frontend: heredaba `NODE_ENV=production` del
backend, y con eso `npm install` salta las dependencias de desarrollo (incluida `vite`), asi
que el build nunca corría y el sistema quedaba en la versión vieja sin avisar del error. Se
fuerza `--include=dev` en ese paso puntual.
### Changed
- Tamaño de los logos de la barra lateral: el de la empresa que usa el sistema (arriba) se
duplica; el de LinkedCorp, desarrollador del sistema (abajo), se reduce a la mitad.
## [2.2.1] - 2026-09-22
### Changed
- Marca de versión sin cambios de código: primer uso real del botón "Actualizar" (auto-update)
en el servidor de exilaser, ya con el feature habilitado desde la v2.2.0.
## [2.2.0] - 2026-09-22
### Added
- Botón "Actualizar" real en Configuración → Actualizaciones: aplica la actualización sola
(backup de BD, `git pull`, migraciones, build, reinicio de servicios) en vez de solo avisar.
**Apagado por defecto** — solo aparece en un servidor donde el admin configuró explícitamente
`UPDATE_APP_DIR`/`UPDATE_BACKEND_SERVICE`/`UPDATE_FRONTEND_SERVICE` en `backend/.env` y le dio
al usuario `deploy` permiso sudo acotado para reiniciar esos dos servicios puntuales. Sin esa
configuración, el panel sigue funcionando exactamente igual que antes (solo informa).
- Nuevo `scripts/apply-update.sh`: hace el trabajo real, corre desde una copia fuera de
`source/` (nunca desde adentro, porque el propio script hace `git reset --hard` sobre
`source/` mientras se ejecuta).
## [2.1.0] - 2026-09-22
### Added
- Nuevo espacio de marca en la barra lateral (arriba a la izquierda): si el sistema tiene un
logo de empresa configurado (Configuración → Empresa), aparece ahí. El logo "LinkedCorp" de
abajo ya no es configurable — es fijo, identifica siempre al desarrollador del sistema,
independiente de qué empresa lo use.
## [2.0.2] - 2026-09-22
### Changed
- Instalación nueva en servidor de exilaser (`192.168.0.30`, `project.exilaser.net`): stack
completo (backend + frontend + MariaDB local) con todo el contenido de producción de
LinkedCorp migrado (proyectos, actividades, tareas, usuarios). Instancia independiente, con
su propia `ENCRYPTION_KEY`/`JWT_SECRET` — el SMTP debe reconfigurarse desde Configuración.
## [2.0.1] - 2026-09-17
### Changed
- Version marcada como 2.0.1 (sin cambios de código) para el proceso de instalación en un
servidor nuevo (Debian 12) — no representa una ruptura de compatibilidad real, es solo el
punto de partida acordado para esa instalación.
## [1.23.0] - 2026-09-17
### Added
- Menú "Notas" nuevo: apuntes rápidos y simples, siempre privados de cada usuario (nadie más los
ve). Crear, editar y eliminar, con fecha y hora de creación (y de última edición, si aplica).
Sin permisos especiales — cualquier usuario autenticado tiene los suyos.
- Nuevo `notes` (tabla) + `GET/POST/PUT/DELETE /api/notes`.
## [1.22.0] - 2026-09-17
### Added
- La app ahora es instalable desde el navegador (PWA): ícono propio, se abre en su propia ventana
sin barra del navegador, con `manifest.webmanifest` + service worker (`vite-plugin-pwa`). El
service worker precachea solo los assets estáticos del build (JS/CSS/íconos) — las llamadas a
`/api` nunca se cachean, siempre van a la red, así los datos nunca quedan desactualizados. Se
actualiza solo (`autoUpdate`) en cuanto hay una versión nueva desplegada, sin pedirle nada al
usuario.
- Íconos nuevos generados a partir del logo actual: `pwa-192x192.png`, `pwa-512x512.png` y una
versión "maskable" (con zona de seguridad) para Android.
## [1.21.1] - 2026-09-17
### Added
- Filtro por severidad (Alta/Media/Baja) en el panel "Errores del sistema", además del filtro por
origen ya existente. La severidad se asigna sola, sin etiquetar nada a mano: errores de backend
y errores de render de React (rompen toda la pantalla) = Alta; errores JS sueltos = Media;
promesas rechazadas sin manejar = Baja (suelen ser fallos de red puntuales, no críticos).
## [1.21.0] - 2026-09-17
### Added
- Log de errores para el administrador, panel nuevo en Configuración ("Errores del sistema",
solo superadmin): lista errores de backend (excepciones 500 no manejadas, con stack completo,
ruta, método y usuario si estaba logueado) y de frontend (errores JS y promesas sin `catch` en
el navegador del usuario, capturados automáticamente — antes solo aparecían en la consola del
navegador de esa persona, invisibles para cualquier otro). Filtro por origen y botón para
limpiar el historial.
- Error Boundary de React: si algo rompe el render de la app, ya no queda una pantalla en blanco
— se muestra un aviso simple con botón para recargar, y el error queda reportado igual.
- Nuevo `error_logs` (tabla + `GET/DELETE /api/error-logs`, solo superadmin) y
`POST /api/error-logs` (público, con rate-limit, para que el frontend pueda reportar incluso
sin sesión — ej. en la pantalla de login).
## [1.20.0] - 2026-09-17
### Added
- Convertir una actividad en proyecto (menú de tres puntos en el listado de Actividades). Como
una tarea siempre necesita una actividad contenedora, se crea un proyecto nuevo y, dentro, una
actividad nueva que recibe las tareas — y comentarios/documentos — de la actividad original; se
piden ambos nombres (proyecto y actividad, precargados con el nombre actual) antes de
confirmar. La actividad original se elimina al final, ya vacía de tareas. Nuevo endpoint
`POST /api/activities/:id/convert-to-project`, exige el mismo permiso que crear un proyecto.
## [1.19.0] - 2026-09-16
### Added
- Panel "Actualizaciones" en Configuración (solo superadmin): compara la versión instalada contra
el `CHANGELOG.md` de `main` en Gitea y muestra cada versión pendiente con su criticidad (deriva
del dígito que cambió — 1ro=Alta, 2do=Media, 3ro=Baja, sin etiquetar nada a mano), una
descripción breve, y si trae cambios de base de datos (comparando los archivos de
`backend/database/migrations/` locales contra los de `main`). Banner en rojo, siempre visible
si hay algo pendiente, avisando que la actualización requiere reiniciar el sistema. No instala
nada automáticamente — solo informa; aplicar la actualización sigue siendo manual (SSH), a
criterio del administrador de cada instalación.
- Nuevo endpoint `GET /api/updater/status` (solo superadmin). Lee el repo de Gitea de forma
anónima por HTTPS — no requiere ningún token ni credencial en el server instalado, solo que el
repo sea público y el servidor de Gitea permita vista anónima.
## [1.18.0] - 2026-09-16
### Added
- Buscador de Proyectos ahora también busca en actividades y tareas de cualquier proyecto, no
solo el nombre/código del proyecto. Los resultados aparecen en un panel bajo el buscador con la
ruta completa ("Proyecto - Actividad - Tarea"); al hacer clic navega directo al proyecto y abre
la actividad encontrada (la pestaña "Tareas" si el resultado era una tarea).
- Buscador de Actividades (dentro de un proyecto) también busca en las tareas de esa actividad,
mismo panel de resultados con "Actividad - Tarea".
- Nuevo endpoint `GET /api/search?q=...&projectId=` (global o acotado a un proyecto).
## [1.17.0] - 2026-09-16
### Added
- Mover una actividad a otro proyecto (menú de tres puntos en el listado de Actividades): se
eligen el proyecto destino y se confirma con un mensaje ("Se moverá la actividad "X" (junto con
sus tareas) al proyecto "Y". ¿Deseas continuar?", Aceptar/Cancelar) antes de ejecutar. Tareas,
comentarios y adjuntos se mueven solos (referencian la actividad, no el proyecto). Las
dependencias existentes se eliminan al mover (solo tienen sentido dentro del mismo proyecto).
Nuevo `PUT /api/activities/:id/move`, exige permiso de escritura en ambos proyectos.
## [1.16.4] - 2026-09-16
### Added
- Columna "Actualizado" (fecha y hora) en el listado de Actividades de un proyecto — mismo
formato que ya existía en Proyectos. Ordenable por columna igual que el resto; no se cambió el
orden por defecto (sigue siendo el orden manual arrastrado con el mouse), así se puede ver la
fecha sin perder el reordenamiento manual como vista predeterminada.
## [1.16.3] - 2026-09-16
### Fixed
- Arrastrar tareas para reordenar dejó de funcionar tras el fix del checkbox (v1.15.2): al mover
`draggable`/`onDragStart` del icono de agarre directamente sobre el `<svg>` (huecos entre sus
formas — un SVG solo capta el mousedown sobre lo pintado, no sobre todo su recuadro), el
navegador no siempre detectaba el inicio del arrastre. Corregido envolviendo el icono en un
`<span>` con área de agarre sólida (mismo patrón ya usado en el listado de Actividades).
## [1.16.2] - 2026-09-16
### Changed
- El contador de la pestaña "Tareas" pasa de mostrar solo las pendientes a "pendientes/total"
(ej. "2/3") — Comentarios y Documentos siguen mostrando el total simple. Se actualiza solo al
agregar, quitar o marcar/desmarcar tareas.
## [1.16.1] - 2026-09-16
### Changed
- Color del contador en las pestañas (Tareas/Comentarios/Documentos): de azul (accent) a rojo
(danger), misma intensidad — pedido explícito del usuario.
## [1.16.0] - 2026-09-16
### Added
- Contador en un circulo junto al nombre de la pestaña, dentro del detalle de una actividad:
"Tareas" muestra las tareas pendientes (sin marcar como hechas), "Comentarios" y "Documentos"
muestran el total. Se oculta cuando el contador es 0. Soporte agregado al componente `Tabs`
reutilizable (`tab.count`), disponible para cualquier otra pantalla que use pestañas.
## [1.15.2] - 2026-09-16
### Fixed
- El checkbox de "hecho" de una tarea (y el renombrado en linea) dejaba de reflejarse tras
guardar: `useDragReorder` (hook de arrastrar-para-reordenar, introducido en v1.14.0) resincronizaba
su copia local solo cuando cambiaba el CONJUNTO de ids, no cuando se editaba un campo de una tarea
ya existente (marcar hecho, renombrar) — la fila se quedaba mostrando el snapshot viejo para
siempre. Reportado por el usuario ("no se marca, debe ser por el drag de mover tareas") — tenia
razon en que era el drag, aunque la causa real no era la interferencia del arrastre con el click
sino esta resincronizacion incompleta. Corregido comparando el contenido completo, no solo los ids.
- De paso, separado `draggable`/`onDragStart` (antes en toda la fila) para que vivan SOLO en el
icono de agarre (`GripVertical`), nunca en la fila completa: un ancestro `draggable=true` le gana
el mousedown a los controles interactivos que tenga adentro en algunos navegadores. No era la
causa de este bug puntual, pero es una corrección real y necesaria para que el patrón sea seguro
de reutilizar en cualquier lista futura con controles interactivos en la fila.
## [1.15.1] - 2026-09-15
### Added
- `scripts/install.sh`: instalador para desplegar en un servidor nuevo. Verifica requisitos
(Node.js, npm, cliente mysql, systemd, espacio, puertos), pregunta dominio/puertos y base de
datos (MariaDB local auto-instalada o un servidor existente), genera `backend/.env` con
secretos aleatorios, corre migraciones + catálogos, compila el frontend y crea/arranca los
servicios systemd. No crea ningún usuario — el primer registro público se vuelve
superadministrador solo (bootstrap ya existente).
### Fixed
- Migración `006_seed_it_baseline.sql` fallaba (error de foreign key) al correr sobre una base de
datos nueva/vacía, porque insertaba proyectos de ejemplo específicos de LinkedCorp asumiendo
catálogos y un usuario ya existentes. Encontrado probando el instalador de punta a punta contra
una BD recién creada. Ahora detecta si esos prerequisitos no existen (instalación nueva, otra
empresa) y queda inerte para siempre ahí, sin afectar el comportamiento ya probado en dev/prod
(donde el marcador de "ya aplicado" sigue intacto).
## [1.15.0] - 2026-09-15
### Added
- Marca de la empresa configurable: nombre y logo editables desde Configuración → Empresa (solo
superadmin), guardados en `system_settings` (mismo patrón que SMTP, sin tabla nueva). Nuevo
endpoint público `GET /api/company` (+ `/logo`) para que login/registro/recuperación de clave
puedan mostrar la marca antes de iniciar sesión. Sin configurar, se ve "LinkedCorp" y el logo
estático de siempre — no rompe instalaciones existentes.
- **Solo desplegado en desarrollo por pedido explícito del usuario** (no se tocó producción esta
vez) — queda commiteado para poder retroceder/avanzar por git antes de decidir el despliegue.
## [1.14.1] - 2026-09-15
### Fixed
- El pie del menú lateral mostraba siempre el texto fijo "v0.1.0" en vez de la versión real de la
app (se lee ahora de `package.json` del frontend).
### Changed
- El logo de LinkedCorp en el menú lateral pasa de la parte superior a la parte inferior izquierda,
justo encima del número de versión.
## [1.14.0] - 2026-09-15
### Added
- Arrastrar con el mouse para reordenar: actividades (dentro de un proyecto) y tareas (dentro de
una actividad), ambas con el mismo mecanismo — un hook reutilizable (`useDragReorder`, drag &
drop nativo, sin librería nueva) usado tanto en `ListView` (opt-in vía `onReorder`, deshabilitado
mientras haya un ordenamiento por columna activo) como en el listado de tareas. Orden persistido
(`sort_order` en `activities`/`tasks`, migración `012`, posiciones 1..N).
## [1.13.0] - 2026-09-15
### Added
- Eliminar actividad: `DELETE /api/activities/:id` (no existía) + botón "Eliminar" en el listado
de actividades, con popup de confirmación. Si la actividad tiene tareas, se bloquea con un
mensaje claro ("Esta actividad tiene N tarea(s). Elimina primero las tareas antes de borrar la
actividad.") en vez de borrar en cascada silenciosamente.
### Changed
- Adjuntos: la lógica de borrar archivo + fila (antes solo inline en el controller) se movió a un
nuevo `attachments/service.js` reutilizable, usado tanto por el borrado individual como por el
borrado en cascada al eliminar una actividad (evita archivos huérfanos en disco).
## [1.12.5] - 2026-09-14
### Changed
- Listado de Proyectos: columna "Creado" reemplazada por "Actualizado" (fecha y hora), y es ahora
el orden por defecto — el proyecto tocado más recientemente aparece primero.
## [1.12.4] - 2026-09-14
### Added
- Botón "Editar" (lápiz) en cada tarea de una actividad — el backend ya soportaba renombrar una
tarea (`PUT /api/tasks/:id`), solo faltaba el botón en la UI. Edición en línea (input + guardar
con Enter o el ícono, cancelar con Escape o el ícono).
## [1.12.3] - 2026-09-14
### Added
- Fecha del documento en la lista de Documentos (proyecto/actividad) — el dato ya lo devolvía el
backend, solo faltaba mostrarlo junto a quién lo subió y el tamaño.
## [1.12.2] - 2026-09-14
### Fixed
- El icono nativo de calendario en campos `type="date"`/`time`/`datetime-local` salía negro sobre
fondo oscuro en tema oscuro (invisible). Se agrega `color-scheme: dark` a esos inputs cuando
`data-theme="dark"`, para que el navegador dibuje el icono en un tono claro.
## [1.12.1] - 2026-09-11
### Added
- Tareas recurrentes: campo opcional "Hasta" (fecha de fin). Vacío = se repite sin fin (como
hasta ahora). Al completar un ciclo cuyo próximo vencimiento supera "Hasta", la tarea se
desactiva sola — no requiere acción manual.
## [1.12.0] - 2026-09-11
### Added
- **Tareas recurrentes**: menú propio en la barra lateral, independiente de Proyectos. Cada tarea
recurrente tiene periodicidad configurable (cada N días/meses/años), próximo vencimiento,
responsable y proyecto de origen opcional. "Completar ciclo" avanza el próximo vencimiento
sumando la periodicidad. Recordatorio por correo automático N días antes del vencimiento
(configurable, default 7) a una hora del día configurable — un job en el propio proceso del
backend revisa cada 15 minutos, sin infraestructura nueva.
- Desde la pestaña "Tareas" de una actividad, cada tarea puntual tiene un botón "Convertir en
recurrente" que la promueve a una tarea recurrente (la tarea original no se borra).
## [1.11.0] - 2026-09-11
### Added
- Filtros en el listado de Proyectos: Estado, Prioridad (ambos ya soportados por el backend, solo
faltaba exponerlos en la UI) y "Solo próximos a vencer" (checkbox, ventana de 7 días — misma
definición que el KPI del dashboard).
## [1.10.0] - 2026-09-11
### Added
- Ordenar proyectos por Prioridad ahora usa la severidad real (Baja→Media→Alta→Crítica), no el
orden alfabético del texto. El resto de columnas (Nombre, Estado, Creado, etc.) ya se podían
ordenar con clic en el encabezado — no era nuevo, solo Prioridad tenía este detalle.
### Changed
- "Páginas web y dominios" separada en dos tareas dentro de "Inventario de servicios de
tecnología": "Páginas web" y "Dominios".
## [1.9.3] - 2026-09-11
### Added
- Nueva actividad en Infraestructura y redes: "Inventario de servicios de tecnología", con 8
tareas propuestas como checklist inicial (internet corporativo, páginas web/dominios,
certificados SSL, correo/SMTP, nube, SaaS de terceros, telefonía/VoIP, respaldos).
## [1.9.2] - 2026-09-11
### Changed
- "Revision periodica de equipos" (Gestión de equipos y activos de TI) renombrada a "Revisión de
equipos para verificar obsolescencia y mejoras" — dejaba dudas sobre qué cubría.
- Nueva actividad en Infraestructura y redes: "Reponchado de cableado de red y certificación de
los puntos".
## [1.9.1] - 2026-09-11
### Changed
- Migración de datos de una sola vez (`006_seed_it_baseline.sql`, con marcador en
`system_settings` — nunca se repite en un deploy futuro): reemplaza el proyecto de prueba
"Sistema ERP" por 6 proyectos reales de TI (Cumplimiento legal, Correos, Equipos, Credenciales
y licencias, Infraestructura y redes, Mejoras a SAGA) con sus actividades, y da de baja la
cuenta `pflores@hotmail.es` (autorregistro nunca verificado). Pedido explícito del superadmin.
## [1.9.0] - 2026-09-10
### Added
- Organización → Usuarios: ahora se puede "Rechazar" (eliminar) también a un usuario en
`pending_verification` (autorregistro que nunca confirmó su correo) — antes esa acción solo
existía para `pending_approval`, así que una cuenta abandonada antes de verificar el correo no
tenía ninguna forma de quitarse desde la UI.
## [1.8.1] - 2026-09-10
### Fixed
- "Agregar dependencia" en una actividad no daba ninguna señal cuando no había otra actividad del
proyecto disponible para elegir (proyecto con una sola actividad, o ya se agregaron todas) — el
combo quedaba vacío, no se seleccionaba nada, y el botón hacía clic sin ningún efecto visible.
Reportado como "el botón no hace nada". El mecanismo en sí funcionaba bien (verificado con curl y
Playwright con 2+ actividades); ahora, cuando no hay opciones, se muestra un mensaje explicando
por qué en vez del selector, y el botón queda deshabilitado si no hay nada seleccionado.
## [1.8.0] - 2026-09-10
### Changed
- Renombrado "Subtareas" a "Tareas" en todo el sistema (Actividad → Tarea, sin nivel "sub"
intermedio): tabla `subtasks` → `tasks` (migración `005`, `RENAME TABLE` idempotente), módulo
backend `subtasks/` → `tasks/`, rutas `/api/activities/:id/subtasks` → `/api/activities/:id/tasks`
y `/api/subtasks/:id` → `/api/tasks/:id`, servicio frontend, pestaña dentro del detalle de
actividad, i18n (es-EC/en-US) y documentación (`API.md`, `BASE_DE_DATOS.md`, `AGENTS.md`,
`README.md`, `SPEC.md`). Sin cambios de comportamiento, solo nombres.
## [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.