Clientes de escritorio y complementarios¶
Responsabilidades y modos de desarrollo¶
Electron empaqueta el frontend de React y el backend de Python en una sola aplicación de escritorio. Su proceso principal controla el proceso hijo del backend, las ventanas, el protocolo de la aplicación, el estado de las actualizaciones y las acciones privilegiadas. El proceso de renderizado usa una API de precarga limitada, nunca acceso sin restricciones a Node.js o al sistema de archivos.
El desarrollo nativo en el navegador y el desarrollo con Electron tienen puntos de entrada distintos:
| Modo | Frontend | Responsable del backend |
|---|---|---|
| Navegador nativo | Vite en http://localhost:5173 |
pnpm dev desde la raíz inicia Vite y uvicorn |
| Desarrollo con Electron | Vite iniciado por separado en http://localhost:5173 |
pnpm desktop:dev inicia su propio proceso hijo de uvicorn en el puerto 5002 |
| Electron empaquetado | Frontend incluido en app://gnosi/index.html |
python/cervell_backend incluido en el paquete, o cervell_backend.exe en Windows |
No ejecutes el backend nativo junto con el desarrollo de Electron: el
supervisor de escritorio no adoptará otro proceso que ocupe el puerto 5002.
El modo de desarrollo de Electron no inicia Vite ni solicita la recarga de
uvicorn. Inícialo con uv run --frozen --no-sync pnpm desktop:dev después de
sincronizar el entorno de Python, para que python3, o python en Windows,
se resuelva dentro de ese entorno. El origen de confianza para desarrollo es
HTTP localhost:5173; configura VITE_DEV_HTTPS=false para esa sesión de Vite.
Una sesión HTTPS del complemento de Word es una configuración distinta, no un
origen intercambiable con el del cliente de escritorio.
El README de escritorio
contiene las instrucciones de configuración y recuperación. Los enlaces de los
menús con React y el aviso de actualización pertenecen a
frontend/src/app/desktop/; la presentación de las notas de versión pertenece
a la funcionalidad del centro de control. Reorganizar estas responsabilidades
internas no debe cambiar los nombres IPC, las acciones de actualización ni los
destinos de descarga.
Inicio, ventanas e IPC¶
Antes de abrir Chromium o iniciar servicios, profile-startup.js obtiene el
bloqueo de instancia única y prepara el perfil existente. Un conflicto o un
estado de recuperación ambiguo detiene el inicio; no autoriza a borrar archivos.
Cada inicio del backend proporciona un valor nuevo de GNOSI_DESKTOP_INSTANCE.
El supervisor exige que su propio proceso hijo siga activo y que la respuesta
de estado sea satisfactoria, completa y de tamaño limitado, con la cabecera
x-gnosi-desktop-instance correspondiente. Esa cabecera permite relacionar la
respuesta con el proceso; no autentica al usuario ni cambia el JSON público de
estado. Los tiempos de espera agotados, las redirecciones, las respuestas mal
formadas, la salida prematura del proceso y las respuestas HTTP 200 ajenas hacen
fallar el inicio y provocan la terminación y recogida del proceso hijo propio.
Si falta el ejecutable empaquetado, nunca se recurre al Python del sistema.
Nueva ventana, Ajustes, la activación desde el Dock y la visualización diferida de ventanas no pueden eludir la espera a que el backend esté listo ni el cierre. Cerrar la última ventana de macOS no cierra la aplicación; salir de ella detiene su backend. En otras plataformas, cerrar todas las ventanas cierra la aplicación. Los mensajes de error de inicio están disponibles en inglés, catalán, español y francés antes de que cargue React; los detalles técnicos quedan en los registros.
Las ventanas principales usan contextIsolation: true, sandbox: true y
nodeIntegration: false. Solo el marco principal actual de una ventana
registrada, situada en el origen de confianza de desarrollo o del paquete,
puede invocar IPC privilegiado. La navegación y las redirecciones no pueden
conservar ese puente en otro origen. Los enlaces HTTP(S) solicitados en una
ventana nueva se abren externamente.
El rellenado de formularios solo acepta una URL inicial HTTPS sin credenciales
y fija su origen exacto antes de cargarla. Los controles de navegación y
redirección se instalan antes de iniciar la carga; se bloquean los destinos sin
cifrar y los de otro origen. La URL final de webContents se comprueba de nuevo
inmediatamente antes de cada inyección del perfil sintético, de modo que el
contenido redirigido no recibe ningún byte del perfil.
El protocolo del paquete sirve los recursos del frontend y actúa como proxy de
/api/ hacia el backend local. Valida el componente de autoridad de la URL de
la aplicación, impide salir de los directorios permitidos y usa el almacén de
cookies de la sesión en lugar de reenviar las cabeceras de cookies sin procesar
del proceso de renderizado. Conserva este comportamiento al modificar el
enrutamiento o los adaptadores de transmisión en continuo.
El módulo empaquetado backend-proxy.js limita las solicitudes individuales
GET /pages/:pageId/preview a 15 segundos, incluidas las cabeceras de respuesta
y todo el cuerpo JSON. Una vista previa bloqueada de un archivo en la nube
devuelve HTTP 504 y libera su conexión HTTP, de modo que las vistas previas
de la galería no pueden dejar el guardado de vistas indefinidamente a la espera
de conexiones ocupadas. Este límite no interrumpe una lectura bloqueada del
sistema de archivos en el backend ni garantiza la disponibilidad de los archivos
en la nube.
La cancelación del proceso de renderizado se propaga a las solicitudes al backend. Las demás respuestas de la API, incluidas las transmisiones de los agentes y las escrituras, conservan su duración y comportamiento de transmisión habituales. El contrato de empaquetado exige el módulo proxy; las pruebas de regresión cubren seis vistas previas bloqueadas simultáneas, cuerpos bloqueados, cancelación y transmisiones en continuo.
Los ocho gestores extraídos tienen contratos de solicitud y respuesta comprobados.
El rellenado de formularios reside en ipc-handlers.js, ya incluido en el paquete;
el proceso principal aporta la fábrica nativa de ventanas y el registro de mensajes.
La validación del emisor sigue precediendo al acceso al payload y a la apertura
de una ventana independiente y aislada sin puente de precarga. La validación de
URL, el orden de eventos, la serialización del perfil y el programa inyectado
no cambian y cuentan con pruebas diferenciales sintéticas. El programa dentro de
la cadena no se comprueba estáticamente. Esto no acredita el comportamiento en
webs reales, el tipado completo del proceso principal, la aceptación de
instaladores ni la autorización de destinos arbitrarios para formularios.
Las suscripciones de
precarga devuelven funciones de cancelación idempotentes; los métodos de
eliminación compatibles siguen disponibles para procesos de renderizado antiguos.
Datos locales y recuperación del perfil¶
El backend empaquetado selecciona el primer valor no vacío en este orden:
GNOSI_DATA_DIR, GNOSI_LOCAL_DATA, LOCAL_DATA_DIR y, por último, el
directorio userData existente de Electron. Establece la variable canónica y
conserva cualquier alias de compatibilidad existente. La alternativa de
escritorio no coincide necesariamente con el valor predeterminado de Python
nativo para la plataforma y no traslada una instalación antigua. Usa rutas
absolutas para las configuraciones explícitas y conserva tanto el perfil de
Electron como cualquier directorio de datos independiente del backend antes
de actualizar.
El nombre de paquete con ámbito @gnosi/desktop se vuelve a asociar al nombre
histórico de ejecución gnosi; se siguen usando las ubicaciones explícitas de
perfil y sesión. El identificador del paquete sigue siendo
com.gnosi.cervell-digital.
La protección de perfiles conserva los directorios obsoletos databases como
bytes opacos en .<profile-name>.gnosi-electron-recovery/databases.saved,
junto a cada perfil. Los movimientos atómicos sin reemplazo y los diarios de
operaciones impiden sobrescribir un destino existente. Se comprueban los
perfiles separados de datos de usuario y de sesión. Las operaciones primitivas
del sistema de archivos no compatibles, los módulos nativos ausentes, las
rutas de datos solapadas o los diarios ambiguos detienen el inicio. Se conservan
los bytes, no la funcionalidad WebSQL eliminada. No restaures ese árbol con el
nombre antiguo mientras se ejecute una versión más reciente de Electron ni
borres los diarios para forzar el inicio.
Para los esquemas de cookies conocidos 19–22, la migración prepara únicamente
la base de datos de cookies, valida su integridad, esquema, número de filas y
un resumen criptográfico de los datos proyectados que respeta su representación
en bytes, y activa después el esquema 23 antes de que Chromium la abra.
El original exacto se conserva en
.Cookies.gnosi-cookie-recovery/original.sqlite, junto a Cookies.
Si el almacén es desconocido, está dañado, presenta conflictos o usa un cifrado
personalizado, la operación se bloquea por seguridad. No se copia el perfil
completo, no se intenta adivinar una clave de descifrado ni se recurre a texto
sin cifrar.
La reversión explícita de cookies exige que los clientes estén detenidos y que
la migración hacia delante se haya completado. Conserva las cookies más recientes
en rollback.current.sqlite, restaura un original verificado mediante su propio
diario de operaciones e impide repetir automáticamente la migración. Conserva
todos los archivos de recuperación hasta la aceptación; nunca fuerces los
números de versión del esquema ni borres bases de datos de cookies. El README
describe la recuperación tras interrupciones y las pruebas aisladas de la
secuencia antigua → destino → destino. El éxito con datos de prueba no demuestra
la migración real de perfiles, del almacén de secretos del sistema operativo ni
de la base de datos de la aplicación en otra máquina.
Actualizaciones y acciones del usuario¶
En producción se comprueban versiones tras el inicio y cada seis horas mientras
el actualizador está inactivo. En desarrollo se desactivan las comprobaciones;
autoDownload y autoInstallOnAppQuit siguen en false. El botón compacto muestra
el porcentaje descargado. Pulsarlo autoriza la descarga, la sustitución verificada
y el reinicio. El proceso principal gestiona la secuencia, rechaza acciones repetidas
y detiene el backend antes de instalar.
macOS utiliza el puente Sparkle incluido y firmas ad-hoc, sin suscripción Apple
Developer. La clave pública fijada verifica el canal firmado y el ZIP antes de
extraerlo. Se desactiva la alternativa de un canal sin firma. update-policy.js
conserva el DMG de la arquitectura correcta para instalaciones ad-hoc antiguas
sin el puente. La primera versión con Sparkle se instala manualmente; Apple aún
puede pedir autorización para abrir una aplicación sin notarizar. La verificación
correcta con codesign no demuestra una actualización completa de la aplicación.
Windows utiliza la sustitución con NSIS y el reinicio automático. Linux admite la sustitución de AppImage y la instalación DEB con el gestor de paquetes, que puede pedir permisos de administrador. Los instaladores Windows sin firmar pueden recibir avisos o bloqueos. Se mantienen las protecciones del sistema operativo.
La prueba real aislada de macOS sustituye y reinicia una aplicación temporal; un archivo modificado se rechaza antes de instalarlo. Las pruebas de Windows y Linux verifican el comportamiento con la ejecución de procesos simulada. Los instaladores reales, perfiles existentes y migración de datos 2.x requieren aceptación.
El enlace de versión del panel de control abre el historial público localizado en https://ismigar.github.io/changelog.html, con un fragmento para la versión elegida. Las comprobaciones en segundo plano no lo abren. La web solo incluye versiones publicadas.
Herramientas y límites del empaquetado¶
El espacio de trabajo fija Node 22.22.2 y pnpm 11.19.0. Las dependencias de
escritorio fijan actualmente Electron 43.4.1, electron-builder 26.15.3 y
ASAR 4.3.0. El entorno de ejecución de Node integrado en Electron es distinto
del usado para compilar el espacio de trabajo. El comando explícito
install:runtime instala su binario; no habilites todos los scripts de
instalación de dependencias para solucionar la ausencia del entorno de ejecución.
Compila el frontend antes de empaquetar la aplicación de escritorio.
build-python.sh exige exactamente Python 3.11, acepta GNOSI_PYTHON_CMD
cuando se configura explícitamente y crea un entorno temporal único usando el
uv.lock congelado de la raíz y el grupo de dependencias desktop. Genera
una especificación de PyInstaller, valida el análisis y el paquete, copia el
resultado verificado en desktop/dist-python/ y ejecuta la prueba básica
aislada del backend empaquetado. No usa un archivo de requisitos independiente
ni el entorno existente del desarrollador.
La política de recursos lee el código fuente sin importar la aplicación.
Conserva los recursos de Alembic, las instrucciones del agente, las skills de
traducción dinámica, los plugins de ejemplo y los estilos bibliográficos.
Rechaza recursos ausentes, modificados, no revisados o inseguros, en lugar de
incluir recursivamente vaults, bases de datos, configuración, secretos o
herramientas generadas. El hook afterPack comprueba el ASAR real y los recursos
de Python antes de la firma. El escaneo completo en frío sigue siendo fail-closed
y tiene un límite de proceso de diez minutos para que los paquetes Windows recién
copiados no terminen durante la primera inspección. Los recursos gráficos pertenecen a
desktop/assets/; los paquetes generados, a desktop/dist/ y
desktop/dist-python/.
Los esquemas de genogramas cargan
backend/domains/genograms/option_labels.json durante el arranque. El plan explícito
de recursos incluye este JSON revisado junto a su módulo. Una prueba con el plan
trasladado crea los esquemas de personas y relaciones en los cuatro idiomas sin
acceso al código original; el ejecutable empaquetado real también debe superar
la prueba de arranque en cada plataforma.
El proyecto raíz declara los required-environments de uv para macOS arm64 y
x64, Linux arm64 y Windows x64. Regenera uv.lock con uv para que los marcadores
de resolución puedan seleccionar distintas versiones de dependencias compatibles
con los wheels de cada destino; nunca edites el lock manualmente. Cada dependencia
binaria seleccionada debe publicar un wheel para su destino antes de iniciar el
empaquetado.
PyInstaller informa de los paquetes de espacio de nombres implícitos con origen
-. La política de recursos solo acepta ese centinela para raíces de terceros.
Un espacio de nombres desconocido bajo las raíces propias backend, pipeline,
config, frontend o extensions sigue fallando de forma cerrada, mientras que
un espacio de nombres de una dependencia como jaraco no se clasifica por error
como código del repositorio.
El verificador de plugins empaquetado importa la raíz pública de confianza inmutable
desde backend/security/plugin_trust_root.py. Las herramientas de release del
marketplace reutilizan esa constante, pero el cargador de la clave privada queda
fuera del plan de recursos de escritorio. El análisis de PyInstaller debe fallar si
el módulo de firma del marketplace entra en el paquete de runtime.
| Destino configurado | Arquitectura del ejecutor | Instaladores y artefactos de actualización |
|---|---|---|
| macOS arm64 | macOS ARM64 en infraestructura propia | Gnosi-<version>-arm64.dmg, ZIP, latest-mac.yml, appcast-arm64.xml |
| macOS x64 | macOS X64 en infraestructura propia | Gnosi-<version>-x64.dmg, ZIP, latest-mac.yml, appcast-x64.xml |
| Linux arm64 | Linux ARM64 en infraestructura propia | AppImage, DEB, latest-linux-arm64.yml |
| Windows x64 | Windows X64 en infraestructura propia | Gnosi-<version>-Setup.exe, latest.yml |
La arquitectura del backend congelado debe coincidir con la de destino. Los
destinos macOS no deben empaquetar silenciosamente ambas arquitecturas con un
único backend nativo del equipo de compilación. Linux pasa --arm64; Windows
usa NSIS x64. Estos trabajos no fijan una versión de macOS ni cubren Linux x64
o Windows arm64. Los dos trabajos de macOS se ejecutan en serie; Windows espera
a macOS, mientras Linux puede ejecutarse en paralelo. La concurrencia se limita
por referencia Git, no mediante un bloqueo global que garantice la capacidad
del equipo anfitrión.
Windows recibe una excepción a la política de ejecución de PowerShell limitada
al trabajo y prepara Git antes de obtener el código cuando hace falta; no
debilites la política de toda la máquina. La compilación del backend pasa entre
comillas los argumentos del intérprete, usa estructuras de entornos virtuales
temporales específicas de cada plataforma e intenta limpiarlos en la medida
de lo posible. El manifiesto de Python restringe actualmente cryptography
para macOS x86_64 a la serie 48.x; la invocación actual de uv no impone la
instalación exclusiva de binarios. Verifica la procedencia de los paquetes wheel
y su ABI en el ejecutor real, sin dar por hecha esa restricción ni sustituir
su Python/OpenSSL.
Todos los scripts de compilación de escritorio, incluidos los alias de la raíz
package:desktop y build:desktop, desactivan la publicación de
electron-builder con --publish never. Preparan artefactos locales; no
certifican ni publican una versión.
Preparación de versiones y distribución exclusiva de candidatos¶
El historial incluido en la aplicación está en
frontend/src/features/control-center/releases/releases.json.
Los manifiestos de la raíz, del frontend y del escritorio, los metadatos de
Python, los archivos de bloqueo, las notas localizadas y el registro de cambios
deben coincidir antes del lanzamiento. sync-release-version.cjs prepara las
cuatro entradas antes de escribir únicamente sus campos de versión. Las
entradas ilegibles, las asignaciones no compatibles y los duplicados ambiguos
fallan antes de cualquier escritura. Conserva las versiones dentro de objetos
JSON, los comentarios y los finales de línea; una versión idéntica no reescribe
ningún archivo. El localizador TOML admite [project].version entre comillas
en una sola línea, pero no valida todo el TOML. La actualización del archivo
de bloqueo todavía debe validar el proyecto Python. Las escrituras separadas
no son una transacción resistente a interrupciones: un fallo de entrada/salida
o una interrupción puede dejar cambios parciales. Revisa las diferencias con
la base registrada de la rama de preparación antes de reintentar. Siguen siendo
necesarias la validación del catálogo y del registro de cambios y la revisión
de los archivos de bloqueo actualizados.
desktop/release.sh ofrece los modos explícitos prepare, package y
promote. La preparación exige un árbol limpio, cambia únicamente la versión
revisada y los metadatos pendientes, genera el changelog de forma transaccional
y no altera los locks. El empaquetado exige el árbol limpio y confirmado,
consume los locks de pnpm y uv congelados y sin conexión, y no puede modificar
versiones, locks, catálogo ni changelog. Las cachés se preparan fuera de este
paso inmutable. La promoción es un commit de metadatos posterior a la
publicación: exige el tag local coincidente, los cuatro grupos de artefactos
verificados y la URL exacta de la release publicada antes de marcarla como
estable y añadir el enlace. El paquete etiquetado nunca anuncia así una release
estable inexistente.
desktop/release-version.js es el límite compartido de versión de lanzamiento
para el actualizador y el recopilador de artefactos. Usa la implementación
SemVer fijada con electron-updater, acepta metadatos de compilación canónicos
y rechaza espacios adyacentes, prefijos v y versiones no válidas o no
canónicas. La política de actualización y el empaquetado no deben introducir
un segundo analizador.
Build Release Candidate es un workflow opcional y exclusivamente manual.
Enviar una etiqueta de versión no inicia Actions alojadas. Cuando se ejecuta
explícitamente, comprueba que la etiqueta solicitada existe y que, al resolverla
hasta su commit, coincide exactamente con el github.sha extraído. Las entradas mal
formadas, las etiquetas ausentes, los destinos que no son commits o las
discrepancias detienen el proceso antes de instalar dependencias. La herramienta
de identidad usa Git local y no mueve referencias ni descarga referencias por
sí sola. La protección de etiquetas remotas sigue siendo un requisito aparte.
La publicación sin presupuesto alojado construye y verifica localmente los cuatro
grupos de plataforma y publica solo esos artefactos exactos; no ejecutes el
workflow alojado opcional sin aprobación explícita de presupuesto.
Como el repositorio es público, cada trabajo del CI compartido solo permite la
ejecución en infraestructura propia cuando la rama de una PR pertenece al
repositorio canónico. Las PR de forks no pueden llegar a los equipos del
propietario; un mantenedor debe revisarlas y reproducir el cambio en una rama
interna de confianza antes de ejecutar las comprobaciones protegidas.
El mismo preflight también exige que la versión de la etiqueta coincida con
los manifiestos de la raíz, del frontend, del escritorio y de Python antes de
iniciar la CI o cualquier compilación por arquitectura.
A continuación, el flujo invoca la CI existente en el mismo commit sin heredar secretos. Las compilaciones por arquitectura requieren que la CI finalice correctamente. Incluye documentación, frontend, backend, pruebas básicas nativas y compilaciones de imágenes Docker. La documentación de las PR se comprueba contra su base exacta; los candidatos comprueban los catálogos actuales y todos los portales de idioma en modo estricto en su propio SHA, no mediante una revisión ficticia del impacto de una PR.
La recopilación descarga únicamente los cuatro artefactos de arquitectura
designados, excluyendo los candidatos anteriores al repetir una ejecución.
Instala las dependencias bloqueadas del recopilador con los scripts de ciclo
de vida desactivados, comprueba la versión, las referencias y las huellas
SHA-512, rechaza los archivos ausentes o en conflicto y combina los dos
manifiestos de actualización de macOS. La generación de índices, la
presentación de las notas de versión y la subida del candidato se realizan
después de la validación.
La generación del marketplace es obligatoria y falla de forma cerrada: la
clave de firma debe corresponder a la clave pública gnosi-official incluida.
Un verificador independiente previo a la subida comprueba las dos firmas
separadas de los índices, todas las firmas y huellas SHA-256 de los paquetes,
el conjunto exacto de ZIP anunciados y unas notas de versión no vacías.
El artefacto final de Actions es candidate-<tag>-<sha>-<attempt> y se conserva
durante cinco días. Contiene instaladores, metadatos de actualización, índices
y notas de versión. No es un almacenamiento confidencial y nunca debe contener
datos de usuario ni secretos. El flujo tiene permisos de solo lectura sobre
el repositorio y no crea borradores en GitHub, no publica versiones ni modifica
artefactos públicos existentes o canales de actualización.
La distribución pública sigue desactivada hasta completar la aceptación del modo nativo, Docker, los instaladores y las actualizaciones desde 2.x, y revisar por separado una vía de publicación. Un candidato correcto no autoriza a publicar 3.0.0.
Clientes web y ofimáticos¶
El capturador web envía POST /api/public/clip con un token de acceso personal
y lee la configuración de los campos solicitados y del destino desde
GET /api/public/clip/config. El backend elige el vault de destino; la
extensión no obtiene acceso arbitrario al sistema de archivos. Su token y la
URL del backend se guardan en el almacenamiento local de la extensión. El
empaquetado para navegadores y la aceptación en sus tiendas son independientes
de la aceptación del instalador de escritorio.
El panel de tareas de Word está en frontend/public/word-addin/ y usa Office.js.
Sus llamadas a la API usan el origen del panel y un token bearer configurado
explícitamente; que un endpoint público responda correctamente no demuestra
que el acceso a las citas esté autorizado. El origen HTTPS del manifiesto y el
certificado de confianza deben coincidir con su despliegue. Las herramientas de
extensions/office/word-cite/ modifican referencias del documento o paquete,
o la plantilla de Word del usuario, para mantener el panel de forma opcional.
Son modificaciones explícitas de documentos o configuración, no una acción
normal del inicio de Gnosi.
El cliente de LibreOffice es un gestor de protocolo Python/UNO que usa
urllib de la biblioteca estándar. Lee api_token de su propia configuración
o de GNOSI_API_TOKEN; no des por hecho que comparte la sesión del navegador.
Ambos clientes usan los endpoints de formato de citas del vault y el
procesamiento Pandoc/CSL del backend. El formato sensible al contexto necesita
las claves del documento en orden, incluidas las citas repetidas. La
actualización de Writer recorre tablas anidadas; los encabezados y pies de
página aportan claves bibliográficas, pero la actualización ordenada no los
reescribe. El comportamiento de la aplicación ofimática anfitriona debe
probarse en la aplicación compatible real, no deducirse de pruebas de recorrido
con datos simulados.
Aceptación y resolución de problemas¶
La prueba básica del backend empaquetado exige una respuesta de estado HTTP 200
de tamaño limitado con status: ok, mode: FastAPI y una identidad nueva de
la prueba en gnosi_mode. Usa rutas desechables de datos y vaults, desactiva
la automatización operativa y recoge su proceso hijo tanto si tiene éxito como
si falla. GNOSI_VALIDATION_ROOT valida todos los selectores y bloquea los
archivos de entorno locales y compartidos y el acceso al almacén de
credenciales. La generación de OpenAPI usa el mismo aislamiento. Nunca
establezcas esta opción en el desarrollo normal ni en aplicaciones instaladas.
Los contratos comprobados en el código fuente, los entornos anfitriones simulados y una ejecución de FastAPI desde el código fuente no demuestran que funcione un instalador con el backend congelado ni una actualización real. Antes de distribuir públicamente, verifica en cada destino real la instalación, el primer inicio, el IPC, la conservación de cookies y perfiles, la integridad de la base de datos, la vía de actualización y la recuperación, además de los flujos autenticados del navegador y el inicio y la persistencia de Docker. El éxito local en macOS no puede certificar otro destino.
| Síntoma | Qué revisar a continuación | Qué no hacer |
|---|---|---|
| El desarrollo con Electron se queda en blanco | Origen HTTP de Vite, PATH del entorno Python congelado y registro de inicio del backend propio | Iniciar un segundo backend en el puerto 5002 |
| La protección del perfil detiene el inicio | Error exacto, rutas originales y de recuperación, clientes detenidos | Borrar diarios de operaciones, cookies o datos antiguos |
| Falta el backend empaquetado | Resultado de PyInstaller y política de recursos finales | Recurrir al Python del sistema |
| macOS ofrece un DMG | Puente Sparkle ausente o instalación antigua; arquitectura | Considerar la verificación de firma como aceptación de la actualización automática |
| Office puede consultar el estado, pero las citas fallan | Token bearer, origen de la API y respuesta real del recurso protegido | Desactivar la autenticación para ocultar un fallo del cliente |
Ejecuta las pruebas de contratos de escritorio del repositorio, la comprobación estricta de IPC, la validación documental y los comandos pertinentes de pruebas básicas aisladas. Inspecciona la salida y los registros del navegador y del escritorio, no solo los códigos de salida. Mantén separadas las evidencias de las plataformas de destino y las pruebas sintéticas.
Corrección de la instalación después de 3.0.0¶
Electron empaquetado selecciona un puerto local libre. Python acepta
BACKEND_PORT con una GNOSI_DESKTOP_INSTANCE válida, escucha en 127.0.0.1 y
desactiva la recarga. Los servicios nativos conservan sus puertos. La prueba de
arranque aporta una configuración contradictoria para verificar que prevalece
el puerto del proceso padre y sigue exigiendo la identidad del proceso propio.
Una segunda apertura recrea la ventana principal si se había cerrado.
Los trazados del favicon, independientes de las fuentes, generan los iconos en
desktop/assets. El DMG tiene un fondo liso y un tamaño de 540 × 320. El disco
del escritorio desaparece al expulsarlo; no es un acceso directo. Se mantiene
la firma local gratuita, que no equivale a la notarización de Apple. Las
instrucciones de instalación están en desktop/README.md.
La release 3.0.1 prepara la corrección integrada de la instalación de escritorio para generar nuevos paquetes nativos en las cuatro plataformas. La preparación mantiene el catálogo sin publicar, conserva los dos archivos de dependencias fijadas y no sustituye ningún archivo de 3.0.0. Se mantiene la distribución gratuita con firma local de macOS.
La versión del backend y el contrato OpenAPI generado deben coincidir con los manifiestos preparados; la validación de la release comprueba su igualdad antes de generar los paquetes.
Ayuda al usuario¶
El menú Ayuda lateral abre el centro, los primeros pasos, la sección actual y la
documentación técnica en el navegador externo. El menú nativo ofrece el centro,
los primeros pasos y la documentación de usuario. El idioma opcional de
set-application-menu conserva la compatibilidad; el proceso principal valida su
tipo y normaliza variantes regionales e idiomas no disponibles. Ambos clientes
usan desktop/help-links.json para destinos fijos y temas admitidos. Las URL no
incluyen identificadores de registros, nombres de Vaults ni contenido privado.
Las secciones desconocidas abren la portada. Catalán, castellano y francés tienen
rutas propias; el inglés es la alternativa. El menú participa en la pila de
teclado modal para que Escape cierre la ayuda antes que la barra lateral móvil.
Las guías se mantienen en docs/learn/ y se construyen por separado de la
documentación técnica. Hay que publicar y verificar el portal antes de distribuir
una versión con enlaces nuevos. El sitio redirige /learn/ a /Gnosi/learn/.
La ayuda abierta desde la barra lateral recibe la preferencia de apariencia de Gnosi. El portal respeta los modos claro, oscuro y sistema y conserva la preferencia entre artículos e idiomas. Los enlaces del sitio público se abren en un contexto de navegador separado.
La versión 3.0.2 incluye el centro de ayuda multilingüe, los menús de ayuda contextual y los enlaces que conservan la apariencia. Las versiones de escritorio, interfaz y backend se mantienen sincronizadas; el catálogo sigue pendiente hasta publicar los instaladores verificados.
Primer inicio sin biblioteca¶
El proceso principal empaquetado lee vault_configured de la respuesta de
salud validada de su servicio. Si es falso, vault-startup.js detiene ese proceso
y abre el selector nativo de carpetas antes de iniciar la interfaz o las
actualizaciones. El usuario puede elegir una biblioteca existente o crear una
carpeta. Cancelar cierra la aplicación; volver a abrirla ofrece la configuración.
Tras reiniciar correctamente con DIGITAL_BRAIN_VAULT_PATH, guarda solo la
selección en GNOSI_DATA_DIR/desktop-vault.json. Las variables explícitas de
biblioteca tienen prioridad; una carpeta guardada ausente no se recrea sola.
Las pruebas enfocadas cubren la selección, cancelación, cierre de procesos, reinicio, traducciones y persistencia. La aceptación de la versión también debe instalar el DMG candidato con un perfil vacío y sin biblioteca inyectada, recorrer el selector visible y un segundo inicio, y probar la actualización desde 3.0.1 con datos sintéticos. Preparar la biblioteca antes de arrancar no acredita la aceptación del primer inicio.
Una selección nativa correcta guarda también un selectionId opaco. El preload
aislado lo aplica antes de las peticiones de la interfaz: borra solo el ID, slug,
nombre y catálogo de la biblioteca activa anterior y su cookie. Las demás
preferencias y cookies se conservan. El marcador se aplica una sola vez por
perfil, de modo que los cambios normales de biblioteca sobreviven a ventanas
nuevas y reinicios. Los archivos antiguos sin marcador siguen siendo válidos.
Cancelar la recuperación conserva la selección anterior. Elegir otra carpeta
no reescribe las identidades registradas. Hay que repetir la aceptación del DMG
para cambio de ruta y actualización con la misma ruta, y reconstruir el backend congelado.
El candidato 3.0.4 incluye la corrección de preservación del guardado automático integrada en la PR 96. Sustituye al candidato no publicado 3.0.3 sin mover su etiqueta ni reutilizar sus validaciones de aceptación. Los cuatro campos de versión están sincronizados, los archivos de dependencias fijadas no cambian y el catálogo permanece sin publicar hasta que los nuevos instaladores superen la aceptación.
La constante del backend GNOSI_VERSION también indica 3.2.0; la prueba del contrato de la API de salud la compara con los cuatro manifiestos de versión.
Hay que regenerar el documento OpenAPI guardado y su SHA-256 después de cambiar la versión del backend. En este candidato, la diferencia revisada del esquema se limita a la versión de la aplicación; las rutas y los datos no cambian.
La CI de Docker reintenta la limpieza de los contenedores de prueba y la repite en un paso independiente que siempre se ejecuta antes de eliminar las imágenes de CI, para evitar que una limpieza fallida bloquee la siguiente construcción.
La lista de recursos revisados de la aplicación de escritorio incluye personal_memory_0002, de modo que las versiones instaladas conservan los recuerdos existentes al añadir memoria por ámbitos y proyectos privados de aprendizaje.
Aceleración limitada de CI¶
Las copias comprimidas de paquetes Python siguen desactivadas: comprimir todo el entorno había retrasado las comprobaciones obligatorias. CI ahora reutiliza la cache nativa de paquetes uv de cada runner, separada por repositorio, sistema operativo, arquitectura y versión de Python. uv gestiona el acceso concurrente; la preparación nunca borra esta cache. Cada job conserva un entorno virtual nuevo con archivos copiados y dependencias fijadas. Si falta la configuración de cache del runner, se descarga en una cache exclusiva del job. pnpm ya reutiliza su almacén local; las subidas de cache remotas siguen desactivadas. Docker retira las etiquetas de imagen de CI después de limpiar los contenedores de prueba, pero conserva las capas mientras queden al menos 12 GiB libres; si falta espacio, aplica la limpieza limitada existente. La primera ejecución de cada runner descarga las dependencias, y las siguientes solo los artifacts que faltan. Aún hay que medir los tiempos en los runners. La restauración y creación de archivos comprimidos siguen desactivadas.
Si Docker aún no dispone de 12 GiB tras limpiar las capas y las copias antiguas, uv libera las ruedas precompiladas descargadas de la cache de paquetes propia; conserva las ruedas compiladas desde el código fuente. La recuperación usa la orden de cache de uv, rechaza directorios simbólicos o ajenos y se detiene cuando hay espacio suficiente. Un runner pequeño puede tener que descargar paquetes otra vez tras quedarse sin espacio; reutilizar paquetes no sustituye una capacidad de disco adecuada.
ESLint utiliza una caché basada en el contenido y mypy conserva el análisis incremental entre jobs; los cambios de plataforma, dependencias y configuración invalidan la caché. Las pruebas del frontend utilizan dos procesos. La comparación local de 27 pruebas representativas ha pasado con uno y dos procesos; todavía hay que evaluar el tiempo y la memoria de la suite completa en el runner. Se mantiene el orden de los jobs pesados.
Solo las solicitudes de cambio de confianza que modifican exclusivamente Markdown de los cuatro portales de ingeniería pueden omitir los pasos de ejecución. Los cinco nombres de comprobación obligatorios siguen visibles y el job de documentación valida todos los idiomas. Los diffs vacíos o desconocidos, los movimientos de código y los cambios de código, configuración o dependencias requieren la validación completa. Los envíos de commits y las validaciones de versiones siempre conservan todas las comprobaciones de ejecución.
Como el análisis del frontend utiliza los tipos de TypeScript, cualquier cambio de fuentes o reglas locales del frontend invalida toda su caché, incluidos los resultados de los archivos que los importan sin haber cambiado. Los cambios exclusivos del backend pueden reutilizarla. Si se desconoce el estado de las fuentes, se repite el análisis.
La composición de anotaciones PDF ejecuta los 57 contratos en cada uno de dos órdenes de importación aislados. Cada grupo tiene un límite de 300 segundos que cubre la carga inicial del backend y todas las comprobaciones. El progreso detallado, los tiempos de las pruebas más lentas y la pila tras 60 segundos de bloqueo de una prueba individual permiten distinguir un arranque lento de una prueba bloqueada. Un timeout del grupo o cualquier error del proceso hijo sigue haciendo fallar la validación, que incluye la salida parcial.
La validación local previa a la PR y CI invocan el mismo punto de entrada pnpm lint:frontend. El lanzador compartido siempre comprueba todo el frontend sin permitir avisos; solo añade las opciones de caché de contenido cuando se define GNOSI_ESLINT_CACHE. Las rutas de caché se pasan como argumentos literales sin intérprete de órdenes y los errores de análisis siguen siendo fatales. La prueba de paridad previa a la PR sigue rechazando cualquier validación de CI ausente del plan local completo.
La candidata 3.1.0 empaqueta el asistente principal compartido, la selección de modelos según la tarea, la memoria con ámbito definido, el aprendizaje reutilizable y la lectura contextual de fuentes. Los datos existentes se conservan mediante las migraciones revisadas. Todos los manifiestos y GNOSI_VERSION coinciden; el contrato OpenAPI regenerado solo cambia la versión respecto al código preparado. Los dos archivos de dependencias fijadas se mantienen intactos. El catálogo sigue sin publicar hasta que los instaladores del mismo código superen las pruebas de instalación inicial, persistencia y actualización en los cuatro destinos.
La candidata 3.2.0 añade equipos de asistentes y roles especializados, comparación de modelos por proveedor y plantillas multilingües de espacios de trabajo. Coinciden las versiones de la raíz, el frontend, el escritorio, Python y el backend en ejecución. Se regenera OpenAPI con la nueva versión; los dos archivos de dependencias fijadas permanecen intactos. El catálogo sigue sin publicar hasta que los instaladores del mismo código superen la aceptación de instalación inicial, persistencia y actualización en los cuatro destinos compatibles.
Configuración del primer inicio empaquetado¶
Antes de seleccionar un vault, el servicio empaquetado guarda la configuración y las migraciones de referencias de proveedores en GNOSI_DATA_DIR/config/params.yaml. Los recursos firmados de la aplicación permanecen en solo lectura; las solicitudes posteriores siguen guardando en el archivo .gnosi/params.yaml del vault activo. Las pruebas del primer inicio y del reinicio deben verificar la firma instalada después de salir de la app, ya que un arranque correcto por sí solo no detecta escrituras dentro del paquete.
La imagen Docker del frontend incluye el verificador compartido de recursos PDF que importa Vite y comprueba que se cargue durante la construcción. Esto evita que una imagen construida correctamente falle al iniciar el servidor porque falta el verificador.