Ejecución y despliegue¶
La validación del backend y la prueba smoke nativa se ejecutan en el runner Linux ARM64 gestionado por el propietario, sin alternativa alojada por GitHub. Las pull requests solo pueden acceder a estos jobs self-hosted cuando la rama de origen pertenece al mismo repositorio; las pull requests de forks no se ejecutan en la máquina del propietario. La prueba smoke selecciona HTTP explícitamente para evitar que el sondeo de disponibilidad y la dirección del navegador difieran por un certificado de desarrollo heredado. Se mantienen el plazo de seis minutos y las pruebas del navegador.
La CI compartida limita la preparación de dependencias Python con UV_CONCURRENT_DOWNLOADS=4,
UV_CONCURRENT_INSTALLS=2, UV_HTTP_TIMEOUT=120 (segundos por lectura HTTP) y
UV_HTTP_RETRIES=3.
Esta política solo afecta a las dependencias: conserva los locks congelados,
las cachés aisladas por tarea y los plazos existentes de pruebas y arranque.
Las desconexiones de los runners siguen siendo errores de infraestructura;
estos parámetros no hacen pasar un runner desconectado.
Esta página recoge los contratos revisados en el código en la fecha de verificación. Docker es un destino de despliegue compatible y opcional; el desarrollo nativo sigue siendo el predeterminado. Ni revisar el código ni configurar un destino de publicación acredita la aceptación por plataforma. Consulte el manual de operaciones para las órdenes, la conservación de datos y el diagnóstico.
Ejecución nativa¶
Inicie los dos wrappers del repositorio desde terminales. Los LaunchAgents de macOS son una configuración opcional del host, no un requisito:
| Proceso | Wrapper en scripts/runtime/ |
Dirección predeterminada | Recarga del código |
|---|---|---|---|
| Backend | run_native_dev.sh 5002 |
127.0.0.1:5002 |
uvicorn observa backend/. |
| Frontend | run_native_frontend.sh --config vite.config.js --host 127.0.0.1 |
HTTP(S) 127.0.0.1:5173 |
Vite recarga el código. |
El backend utiliza uv run --project "$BASE" --frozen --no-sync con el
entorno Python existente de la raíz. Las únicas autoridades de entorno y datos
son load_env() y resolve_data_dir() de Python, no un analizador dotenv en
el shell. La precedencia por variable es: entorno del proceso, .env del
repositorio y archivo compartido seleccionado explícitamente mediante
GNOSI_SHARED_ENV_FILE; no se infiere ningún .env_shared de los directorios
padre. El resolutor de datos selecciona GNOSI_DATA_DIR, después
GNOSI_LOCAL_DATA, después LOCAL_DATA_DIR y finalmente el valor
predeterminado de la plataforma. El wrapper no elige un vault si no está
configurado ni fuerza OneDrive, un proveedor, HOME_HOST_PATH, una zona
horaria, un modelo o un endpoint de traducción.
El frontend establece COREPACK_ENABLE_NETWORK=0 y ejecuta
corepack pnpm --filter @gnosi/frontend dev. El ejemplo pasa explícitamente
la configuración de Vite y el host loopback; en otro caso se aplica el host
configurado en Vite. El wrapper conserva los valores explícitos de
VITE_BACKEND_HOST y VITE_BACKEND_PORT (predeterminados: localhost y
5002). Vite gestiona sus dotenv; el wrapper deja VITE_FRONTEND_PORT sin
definir si no está presente, para no ocultarlos. También conserva las etiquetas
explícitas del checkout y puede avisar cuando el checkout servido es un
antepasado ya integrado de origin/main.
Ambos wrappers validan los puertos proporcionados entre 1 y 65535, transmiten
los argumentos y propagan las salidas. No instalan ni sincronizan dependencias;
el gestor de paquetes fijado y los entornos bloqueados ya deben estar
preparados. La recarga del código no actualiza dependencias. uv.lock es la
autoridad, pero sus selecciones por plataforma no acreditan la pila de ML en
todos los sistemas operativos o arquitecturas.
Autoalojamiento Docker¶
El docker-compose.yml base proporciona backend, frontend y translation-server
de Zotero sin exigir rutas de vault del host ni herramientas privadas:
| Almacenamiento | Volumen con nombre | Ruta del backend |
|---|---|---|
| Estado por dispositivo | gnosi_local_data (clave existente) |
/data; GNOSI_DATA_DIR=/data |
| Vaults | gnosi_vaults (nuevo) |
/vaults; GNOSI_VAULTS_ROOT=/vaults, DIGITAL_BRAIN_VAULT_PATH=/vaults/default |
Conserve el nombre existente del proyecto Compose y ambos volúmenes de datos al
actualizar; el nombre del proyecto determina la identidad de los volúmenes.
Un volumen nuevo de vaults no importa los vaults existentes del host. Nunca
utilice docker compose down -v ni una purga generalizada de volúmenes para
reparar dependencias; conserve las bases de datos, credenciales y contenido
de los vaults antes de migrar.
Los puertos se publican en loopback por defecto: 127.0.0.1:5002 y
127.0.0.1:5173. GNOSI_BIND_ADDRESS, GNOSI_BACKEND_PORT y
GNOSI_FRONTEND_PORT controlan la publicación en el host. Los puertos internos
siguen siendo 5002/5173; el frontend utiliza HTTP y actúa como proxy del tráfico
API/WebSocket hacia backend:5002. Revise el acceso y TLS antes de exponer
otra dirección. Se exige un GNOSI_JWT_SECRET privado y robusto durante la
interpolación de Compose, mediante el shell o el .env local; un env_file
del servicio no puede proporcionarlo por sí solo. GNOSI_REQUIRE_AUTH=1
es explícito.
Compose lee opcionalmente el archivo compartido seleccionado mediante
GNOSI_SHARED_ENV_FILE (alternativa .env.shared.disabled) y después el
.env local opcional. Los valores locales prevalecen sobre los compartidos;
environment explícito del servicio prevalece sobre ambos. Los valores
arbitrarios del shell del host no se convierten automáticamente en variables
del contenedor. Estos archivos no se montan ni se incluyen en las imágenes.
Compose vacía GNOSI_SHARED_ENV_FILE dentro del backend tras cargar sus valores.
El translation-server de Zotero sigue siendo interno en 1969.
GNOSI_TRANSLATION_IMAGE selecciona su imagen; TRANSLATION_SERVER_URL toma
http://translation-server:1969 solo si no está definida, y conserva un valor
vacío explícito. La traducción es opcional para la aplicación; el Compose
actual incluye el servicio auxiliar sin un perfil opcional.
La sobrescritura explícita compose.vaults.yml exige ambas rutas existentes
del host: VAULT_HOST_PATH para el vault activo y VAULTS_ROOT_HOST_PATH para
su padre. Ambos montajes utilizan create_host_path: false. La fusión según
el destino en el contenedor sustituye el volumen /vaults, añade /vault,
establece DIGITAL_BRAIN_VAULT_PATH=/vault y conserva gnosi_local_data:/data.
Las dos rutas del host se transmiten explícitamente para las acciones sobre
archivos. Las relativas se resuelven desde el directorio del Compose base;
prefiera rutas absolutas. Esta sobrescritura no migra datos ni configura
servicios auxiliares del host.
No hay montajes implícitos del directorio personal, .antigravity privado,
directorio de secretos, socket Docker, código fuente o dependencias del host.
Solo la sobrescritura explícita añade sus dos montajes de vaults. Un CLI Docker
dentro de la imagen del backend no proporciona acceso al motor del host sin un
socket o endpoint configurado explícitamente. El código y las dependencias
pertenecen a las imágenes: no hay recarga del código del host ni volúmenes
anónimos node_modules. Reconstruya las imágenes si cambian el código o los
archivos de bloqueo.
La imagen del frontend fija Node 22.22.2 y pnpm 11.19.0, instala con
--frozen-lockfile y ejecuta Vite en el puerto estricto 5173. El backend
exporta uv.lock con --frozen, instala el wheel fijado de Torch solo para
CPU antes de los requisitos exportados y ejecuta uvicorn sin --reload.
La disponibilidad del wheel y la compilación y arranque reales son requisitos
de aceptación por plataforma. Los tests estáticos de contratos no sustituyen
la fusión real de Compose, las compilaciones de imágenes, las pruebas básicas
de los contenedores ni la aceptación por plataforma.
La prueba nativa inicia Uvicorn normalmente, sin un hilo de trazas en segundo
plano. La comprobación externa scripts/ci/wait_native_services.py exige HTTP
200 tanto de /api/health como del frontend en el mismo ciclo. Cada petición
tiene un máximo de dos segundos, dentro de un plazo monotónico de seis minutos;
el paso de arranque tiene un límite externo de siete minutos. Los errores
muestran el último resultado de cada endpoint y conservan ambos registros.
Los anuncios de arranque o los identificadores de procesos envoltorio no
acreditan disponibilidad; después sigue ejecutándose la suite de navegador.
Paquetes Electron¶
Electron gestiona el ciclo de vida de la aplicación empaquetada. Inicia el backend Python incluido, expone una interfaz IPC limitada mediante preload, abre el renderer y gestiona el estado de las actualizaciones manuales. El renderer se suscribe a las actualizaciones y puede consultar su estado más reciente para no perder eventos emitidos antes de que React se monte.
El proceso de escritorio instala un menú nativo explícito en lugar del menú de desarrollo predeterminado de Electron. React es la fuente de verdad de las etiquetas traducidas: cuando se resuelve el idioma configurado, el renderer transmite un conjunto validado de etiquetas mediante preload y repite el intercambio cuando cambia el idioma. Las órdenes nativas de configuración vuelven al modal existente de Configuración global. Los menús de producción excluyen la recarga y las herramientas de desarrollo.
Las ventanas principales de Gnosi se gestionan de forma independiente. Archivo → Nueva ventana crea otro renderer contra el mismo backend incluido; cerrar una ventana solo elimina esa ventana, y la activación desde el Dock de macOS recrea una ventana principal cuando se ha cerrado la última. Las órdenes de menú destinadas al renderer enfocan una ventana existente o esperan a que el nuevo renderer esté disponible antes de entregarlas.
Los jobs de candidatos producen instaladores y metadatos para electron-updater
después de que pase la CI compartida en el mismo commit. Conservan un artefacto
de Actions cinco días, no un borrador ni una release de GitHub. La publicación
queda desactivada hasta la aceptación completa y la revisión de un proceso separado;
véase la distribución de candidatos. Los
destinos configurados y los contratos estáticos no acreditan una instalación
limpia, el primer arranque, la actualización, la reversión, la firma ni la
conservación de datos; cada plataforma exige pruebas propias.
Servicios auxiliares del host¶
Los servicios host-open pueden ofrecer apertura de archivos, búsqueda Spotlight, selectores nativos y acciones de papelera. Los servicios de archivos en la nube pueden hidratar archivos solo en línea; la recuperación de cada proveedor corresponde a su adaptador. Son integraciones opcionales que requieren configuración explícita, no requisitos de arranque portable.
Los 15 scripts históricos del runtime del host (instaladores, watchdogs y
herramientas del host), junto con los lanzadores obsoletos run_brain.sh y
run_prod.sh, se han retirado del repositorio público. Las operaciones del host
pertenecen al repositorio privado WorkspaceTools. El instalador histórico
install_native_startup.sh detiene los procesos que escuchan en 5002/5173 y
recarga LaunchAgents. Una copia conservada de native_watchdog.sh puede matar
procesos multiprocessing con una selección amplia y reiniciar mediante launchd;
no ejecute ninguno como diagnóstico genérico. Revise la configuración real
instalada y los procedimientos privados. Esta limpieza del checkout no modifica,
migra ni desinstala los servicios instalados del host. Los wrappers portables
siguen siendo el contrato de arranque nativo.
Invariantes de puertos y procesos¶
- Solo un proceso puede escuchar en cada dirección/puerto elegido; 5002/5173 son valores predeterminados, no un permiso para que nativo y Docker compartan la escucha.
- Vite utiliza
strictPort; pasar silenciosamente a otro puerto es un fallo de QA. - La recarga nativa no actualiza dependencias ni versiones inyectadas al arrancar; los cambios de código de los contenedores exigen reconstruir la imagen.
- La QA en el navegador sigue el protocolo del Vite activo. Sin certificados
locales legibles se utiliza HTTP; HTTPS automático los utiliza,
VITE_DEV_HTTPS=falsefuerza HTTP yVITE_DEV_HTTPS=truelos exige.
Comprobaciones de salud y aceptación¶
/api/health informa del estado del proceso, el modo, la política efectiva de
autenticación y la configuración del vault. Verifique /api/config y
/api/vault/pages con una sesión autorizada; que el proceso responda no
demuestra que se pueda leer el vault.
La aceptación nativa debe probar el registro real, la creación de un workspace
y del primer vault, el inicio de sesión, /api/auth/me, las cookies HttpOnly
y la preparación de autenticación de Playwright, con arranque y parada limpios.
En el navegador hay que crear/editar una página desechable, recargarla/reabrirla
para verificar la persistencia del título y del cuerpo, revisar la consola y
comprobar el cierre de sesión. La preparación exige GNOSI_TEST_EMAIL y
GNOSI_TEST_PASSWORD explícitos de una cuenta desechable existente, deriva
la identidad y la pertenencia al workspace de la sesión verificada y no registra
cuentas ni inventa privilegios de administrador. GNOSI_TEST_WORKSPACE_ID
debe corresponder a una pertenencia; si no se indica, debe haber exactamente
una. GNOSI_TEST_VAULT_ID es opcional y no concede acceso. Mantenga privadas
las credenciales, las cookies y GNOSI_TEST_STORAGE_STATE.
backend/tests/test_vault_creation_membership.py cubre la creación autorizada
del primer vault, los rechazos por autenticación/rol/workspace, el confinamiento
de rutas y los listados de organización sin registrar almacenamiento personal.
Estas comprobaciones acotadas no acreditan toda la suite E2E, la matriz
Docker/Electron ni una publicación. El responsable de integración realiza
las comprobaciones restantes de navegador real, CI, SOP, generación de
documentación y aceptación por plataforma.