Clients d’escriptori i complementaris¶
Responsabilitats i modes de desenvolupament¶
Electron empaqueta el frontend React i el backend Python en una sola aplicació d’escriptori. El procés principal gestiona el procés fill del backend, les finestres, el protocol de l’aplicació, l’estat de les actualitzacions i les accions privilegiades. El renderer utilitza una API de preload limitada, mai accés sense restriccions a Node.js o al sistema de fitxers.
El desenvolupament natiu al navegador i el desenvolupament amb Electron tenen punts d’entrada diferents:
| Mode | Frontend | Responsable del backend |
|---|---|---|
| Navegador natiu | Vite a http://localhost:5173 |
pnpm dev, des de l’arrel, inicia Vite i uvicorn |
| Desenvolupament amb Electron | Vite iniciat de manera independent a http://localhost:5173 |
pnpm desktop:dev inicia el seu propi procés fill d’uvicorn al port 5002 |
| Electron empaquetat | Frontend inclòs al paquet a app://gnosi/index.html |
python/cervell_backend inclòs al paquet, o cervell_backend.exe a Windows |
No executis el backend natiu alhora que el desenvolupament amb Electron: el
supervisor d’escriptori no adopta cap altre procés al port 5002. El desenvolupament
amb Electron no inicia Vite ni sol·licita la recàrrega d’uvicorn. Inicia’l amb
uv run --frozen --no-sync pnpm desktop:dev després de sincronitzar l’entorn
Python, perquè el seu python3, o python a Windows, es resolgui dins d’aquest
entorn. L’origen de confiança per al desenvolupament és localhost:5173 amb HTTP;
configura VITE_DEV_HTTPS=false per a aquella sessió de Vite. Una sessió HTTPS
del complement de Word és una configuració separada i no és intercanviable amb
l’origen d’escriptori.
El README d’escriptori
conté instruccions de configuració i recuperació. Les vinculacions dels menús
React i l’avís d’actualització pertanyen a frontend/src/app/desktop/; la
presentació de les notes de versió pertany a la funcionalitat del centre de
control. Canviar la distribució interna de responsabilitats no ha d’alterar els
noms IPC, les accions d’actualització ni les destinacions de descàrrega.
Arrencada, finestres i IPC¶
Abans d’obrir Chromium o iniciar serveis, profile-startup.js obté el bloqueig
d’instància única i prepara el perfil existent. Un conflicte o un estat de
recuperació ambigu atura l’arrencada; no autoritza a esborrar fitxers.
Cada arrencada del backend proporciona un valor nou de GNOSI_DESKTOP_INSTANCE.
El supervisor exigeix que el procés fill propi continuï actiu i que la resposta
de salut sigui completa, acotada i satisfactòria, amb una capçalera
x-gnosi-desktop-instance coincident. Aquesta capçalera permet correlacionar el
procés; no autentica cap usuari ni modifica el JSON públic de salut. Els temps
d’espera exhaurits, les redireccions, les respostes malformades, la finalització
prematura i les respostes HTTP 200 alienes fan fallar l’arrencada i provoquen
l’aturada i la neteja del procés fill propi. Si falta l’executable empaquetat,
mai no es recorre al Python del sistema.
Nova finestra, Configuració, l’activació des del Dock i la visualització diferida de finestres no poden eludir la comprovació que el backend estigui preparat ni l’aturada. Tancar l’última finestra a macOS no tanca l’aplicació; sortir de l’aplicació atura el seu backend. A les altres plataformes, tancar totes les finestres tanca l’aplicació. Els missatges d’error d’arrencada estan disponibles en anglès, català, castellà i francès abans que es carregui React; els detalls tècnics queden als registres.
Les finestres principals utilitzen contextIsolation: true, sandbox: true i
nodeIntegration: false. Només el marc de nivell superior actual d’una finestra
registrada, a l’origen de confiança de desenvolupament o del paquet, pot invocar
IPC privilegiat. La navegació i les redireccions no poden conservar aquest pont
en un altre origen. Els enllaços HTTP(S) que se sol·liciten en una finestra nova
s’obren externament.
L’emplenament de formularis només accepta una URL inicial HTTPS sense
credencials i en fixa l’origen exacte abans de carregar-la. Els controls de
navegació i redirecció s’instal·len abans d’iniciar la càrrega; es bloquegen les
destinacions sense xifrar i les d’un altre origen. La URL final de webContents
es torna a comprovar immediatament abans de cada injecció del perfil sintètic,
de manera que el contingut redirigit no rep cap byte del perfil.
El protocol del paquet serveix els recursos del frontend i fa de proxy de
/api/ cap al backend local. Valida l’autoritat de l’aplicació, impedeix recórrer
el sistema de fitxers fora de les rutes permeses i utilitza el magatzem de galetes
de la sessió en lloc de reenviar les capçaleres de galetes en brut del renderer.
Conserva aquest comportament quan canviïs l’encaminament o els adaptadors de
transmissió en continu.
El mòdul empaquetat backend-proxy.js limita les peticions individuals
GET /pages/:pageId/preview a 15 segons, incloses les capçaleres de resposta i
tot el cos JSON. Una previsualització encallada d’un fitxer al núvol retorna
HTTP 504 i allibera la connexió HTTP, de manera que les previsualitzacions de
la galeria no poden deixar el desament de vistes indefinidament en espera de
connexions ocupades. Aquest límit no interromp una lectura bloquejada del
sistema de fitxers al backend ni garanteix la disponibilitat dels fitxers al núvol.
La cancel·lació del renderer es propaga a les peticions cap al backend. Les altres respostes de l’API, incloses les transmissions dels agents i les escriptures, conserven la durada i el comportament de transmissió habituals. El contracte d’empaquetatge exigeix el mòdul proxy; les proves de regressió cobreixen sis previsualitzacions encallades simultànies, cossos bloquejats, cancel·lació i transmissions en continu.
Els vuit gestors extrets tenen contractes de petició i resposta comprovats.
L'emplenament de formularis és a ipc-handlers.js, que ja s'empaquetava; el procés
principal aporta la fàbrica nativa de finestres i el registre de missatges.
La validació de l'emissor continua precedint l'accés al payload i l'obertura d'una
finestra separada i aïllada sense pont de preload. La validació d'URL, l'ordre dels
esdeveniments, la serialització del perfil i el programa injectat no canvien i
tenen proves diferencials sintètiques. El programa dins la cadena no es comprova
estàticament. Això no acredita el comportament en webs reals, el tipatge complet
del procés principal, l'acceptació d'instal·ladors ni l'autorització de destinacions
arbitràries de formularis.
Les subscripcions de preload retornen funcions de cancel·lació
idempotents; els mètodes de cancel·lació per compatibilitat continuen disponibles
per als renderers antics.
Dades locals i recuperació del perfil¶
El backend empaquetat selecciona el primer valor no buit en aquest ordre:
GNOSI_DATA_DIR, GNOSI_LOCAL_DATA, LOCAL_DATA_DIR i, finalment, el directori
userData existent d’Electron. Estableix la variable canònica i conserva un àlies
de compatibilitat existent. El valor per defecte d’escriptori no és necessàriament
el valor natiu de Python per a la plataforma i no trasllada una instal·lació
antiga. Utilitza rutes absolutes per als valors explícits i conserva tant el perfil
d’Electron com qualsevol directori separat de dades del backend abans d’una
actualització.
El nom de paquet amb àmbit @gnosi/desktop es torna a mapar al nom històric
d’execució gnosi; les ubicacions explícites de perfil i sessió es continuen
utilitzant. L’identificador del paquet continua sent com.gnosi.cervell-digital.
La protecció del perfil conserva els directoris obsolets databases com a bytes
opacs a .<profile-name>.gnosi-electron-recovery/databases.saved, al costat de
cada perfil. Els moviments atòmics sense substitució i els registres de
recuperació impedeixen sobreescriure una destinació existent. Es comproven els
perfils separats de dades d’usuari i de sessió. Les operacions primitives del
sistema de fitxers no compatibles, els mòduls natius absents, les rutes de dades
superposades o els registres de recuperació ambigus aturen l’arrencada. Això
conserva els bytes, no la funcionalitat WebSQL eliminada. No restauris aquest
arbre amb el nom antic mentre executis una versió més nova d’Electron, ni
esborris els registres de recuperació per forçar l’arrencada.
Per als esquemes de galetes coneguts 19–22, la migració prepara només la base de
dades de galetes, en valida la integritat, l’esquema, el nombre de files i un
resum criptogràfic de la projecció que té en compte els bytes, i després activa
l’esquema 23 abans que Chromium l’obri. L’original exacte es conserva a
.Cookies.gnosi-cookie-recovery/original.sqlite, al costat de Cookies.
Els magatzems desconeguts, corruptes, amb conflictes o amb xifratge personalitzat
provoquen una aturada segura. No es copia tot el perfil, no s’endevina cap clau
de desxifratge ni es recorre a text en clar.
La reversió explícita de galetes exigeix que els clients estiguin aturats i que
la migració inicial s’hagi completat. Conserva les galetes més noves a
rollback.current.sqlite, restaura un original verificat mitjançant el seu
propi registre de recuperació i impedeix que es repeteixi automàticament la
migració. Conserva tots els fitxers de recuperació fins a l’acceptació; no forcis
mai els números de versió dels esquemes ni esborris bases de dades de galetes.
El README descriu la recuperació interrompuda i les proves aïllades
antiga → objectiu → objectiu. L’èxit amb dades de prova no demostra la migració
real del perfil, del magatzem de secrets del sistema operatiu o de la base de
dades de l’aplicació en una altra màquina.
Actualitzacions i accions de l’usuari¶
En producció es comproven les versions després de l’arrencada i cada sis hores
mentre l’actualitzador està inactiu. En desenvolupament es desactiven les comprovacions;
autoDownload i autoInstallOnAppQuit continuen a false. El botó compacte mostra
el percentatge baixat. Clicar-lo autoritza la descàrrega, la substitució verificada
i el reinici. El procés principal gestiona la seqüència, rebutja accions repetides
i atura el backend abans de la instal·lació.
A macOS s’utilitzen el pont Sparkle inclòs i signatures ad-hoc, sense subscripció
Apple Developer. La clau pública fixada verifica el canal signat i el ZIP abans
d’extreure’l. No es permet recórrer a un canal sense signatura. update-policy.js
conserva l’alternativa del DMG de l’arquitectura correcta per a instal·lacions
ad-hoc antigues sense el pont. La primera versió amb Sparkle s’instal·la manualment;
Apple encara pot demanar autorització per obrir una aplicació no notaritzada.
La verificació correcta amb codesign no demostra una actualització completa.
Windows utilitza la substitució amb NSIS i el reinici automàtic. Linux admet la substitució d’AppImage i la instal·lació DEB amb el gestor de paquets, que pot demanar permisos d’administrador. Els instal·ladors Windows sense signar poden rebre avisos o bloquejos del sistema. Es mantenen les proteccions del sistema operatiu.
La prova real aïllada de macOS substitueix i reinicia una aplicació temporal; un arxiu modificat es rebutja abans d’instal·lar-lo. Les proves de Windows i Linux verifiquen el comportament amb l’execució de processos simulada. Els instal·ladors reals, els perfils existents i la migració de dades 2.x encara requereixen acceptació.
L’enllaç de versió del panell de control obre l’historial públic localitzat a https://ismigar.github.io/changelog.html, amb un fragment per a la versió triada. Les comprovacions en segon pla no l’obren. El web només inclou versions publicades.
Cadena d’eines i límits de l’empaquetatge¶
L’espai de treball fixa Node 22.22.2 i pnpm 11.19.0. Les dependències
d’escriptori fixen actualment Electron 43.4.1, electron-builder 26.15.3 i
ASAR 4.3.0. L’entorn d’execució Node integrat a Electron és independent de
l’entorn de construcció de l’espai de treball. La comanda explícita
install:runtime instal·la el binari d’Electron; no habilitis tots els scripts
d’instal·lació de dependències per corregir l’absència de l’entorn d’execució.
Construeix el frontend abans d’empaquetar l’aplicació d’escriptori.
build-python.sh exigeix exactament Python 3.11, accepta GNOSI_PYTHON_CMD
quan es configura explícitament i crea un entorn temporal únic amb el fitxer
uv.lock congelat de l’arrel i el grup de dependències desktop. Genera una
especificació de PyInstaller, valida l’anàlisi i el paquet, copia el resultat
verificat a desktop/dist-python/ i executa la prova bàsica aïllada del backend
empaquetat. No utilitza cap fitxer de requisits separat ni l’entorn existent del
desenvolupador.
La política de recursos llegeix el codi font sense importar l’aplicació. Conserva
els recursos d’Alembic, les instruccions dels agents, les skills de traducció
dinàmiques, els complements d’exemple i els estils de citació. Rebutja recursos
absents, modificats, no revisats o insegurs, en lloc d’incloure recursivament
vaults, bases de dades, configuració, secrets o eines generades. El hook
afterPack comprova l’ASAR i els recursos Python reals abans de signar. L’escaneig
complet en fred continua sent fail-closed i té un límit de procés de deu minuts
perquè els paquets Windows acabats de copiar no morin durant la primera inspecció.
Els recursos gràfics pertanyen a desktop/assets/; els paquets generats
pertanyen a desktop/dist/ i desktop/dist-python/.
Els esquemes de genogrames carreguen
backend/domains/genograms/option_labels.json durant l’arrencada. El pla explícit
de recursos inclou aquest JSON revisat al costat del seu mòdul. Una prova amb el
pla traslladat crea els esquemes de persones i relacions en els quatre idiomes
sense accés al codi original; l’executable empaquetat real ha de superar també
la prova d’arrencada en cada plataforma.
El projecte arrel declara els required-environments d’uv per a macOS arm64 i
x64, Linux arm64 i Windows x64. Regenera uv.lock amb uv perquè els marcadors
de resolució puguin seleccionar versions de dependències diferents i compatibles
amb els wheels de cada destinació; no editis mai el lock manualment. Cada
dependència binària seleccionada ha de publicar un wheel per a la destinació
abans de començar l’empaquetatge.
PyInstaller informa dels paquets d’espai de noms implícits amb l’origen -. La
política de recursos només accepta aquest sentinella per a arrels de tercers. Un
espai de noms desconegut sota les arrels pròpies backend, pipeline, config,
frontend o extensions continua fallant de manera tancada, mentre que un espai
de noms d’una dependència com jaraco no es classifica erròniament com a codi
del repositori.
El verificador de plugins empaquetat importa l’arrel pública de confiança immutable
des de backend/security/plugin_trust_root.py. Les eines de release del marketplace
reutilitzen aquesta constant, però el carregador de la clau privada queda fora del
pla de recursos desktop. L’anàlisi de PyInstaller ha de fallar si el mòdul de
signatura del marketplace entra al paquet de runtime.
| Destinació configurada | Arquitectura del runner | Instal·lador i artefactes d’actualització |
|---|---|---|
| macOS arm64 | macOS ARM64 autoallotjat | Gnosi-<version>-arm64.dmg, ZIP, latest-mac.yml, appcast-arm64.xml |
| macOS x64 | macOS X64 autoallotjat | Gnosi-<version>-x64.dmg, ZIP, latest-mac.yml, appcast-x64.xml |
| Linux arm64 | Linux ARM64 autoallotjat | AppImage, DEB, latest-linux-arm64.yml |
| Windows x64 | Windows X64 autoallotjat | Gnosi-<version>-Setup.exe, latest.yml |
Fes que el backend congelat coincideixi amb l’arquitectura de destinació. Les
destinacions macOS no han d’empaquetar silenciosament totes dues arquitectures
amb un únic backend natiu de l’amfitrió. Linux passa --arm64; Windows utilitza
NSIS x64. Aquests jobs no fixen cap versió del sistema operatiu macOS i no
cobreixen Linux x64 ni Windows arm64. Els dos jobs de macOS s’executen en sèrie;
Windows espera macOS, mentre que Linux pot executar-se alhora. La concurrència
es limita per referència Git, no mitjançant un bloqueig global que acrediti la
capacitat de l’amfitrió.
Windows rep una excepció de la política d’execució de PowerShell limitada al
job i prepara Git abans del checkout quan cal; no debilitis la política de tota
la màquina. La construcció del backend utilitza arguments de l’intèrpret entre
cometes, estructures d’entorns virtuals temporals específiques de cada plataforma
i una neteja que s’intenta fer sense garantir-ne l’èxit. El manifest Python
restringeix actualment cryptography a la sèrie 48.x per a macOS x86_64; la
invocació actual d’uv no imposa una instal·lació exclusivament binària. Verifica
la procedència dels wheels i de l’ABI al runner real, en lloc de donar per feta
aquesta restricció o substituir-ne el Python/OpenSSL.
Tots els scripts de construcció d’escriptori, inclosos els àlies
package:desktop i build:desktop de l’arrel, desactiven la publicació del
constructor amb --publish never. Preparen artefactes locals; no certifiquen
ni publiquen cap versió.
Preparació de versions i distribució només de candidats¶
L’historial inclòs al paquet és
frontend/src/features/control-center/releases/releases.json.
Els manifests de l’arrel, del frontend i de l’escriptori, les metadades Python,
els fitxers de bloqueig, les notes localitzades i el registre de canvis han de
coincidir abans de publicar una versió. sync-release-version.cjs prepara les
quatre entrades abans d’escriure només els camps de versió. Les entrades
il·legibles, les assignacions no compatibles i els duplicats ambigus provoquen
un error abans de qualsevol escriptura. Es conserven les versions dins d’objectes
JSON, els comentaris i els finals de línia; una versió idèntica no reescriu cap
fitxer. El localitzador TOML admet [project].version entre cometes en una sola
línia, però no valida tot el TOML. L’actualització del fitxer de bloqueig encara
ha de validar el projecte Python. Les escriptures separades no són una
transacció resistent a interrupcions: un error d’entrada/sortida o un tall pot
deixar canvis parcials. Revisa les diferències respecte de la base registrada
de la branca de preparació abans de reintentar-ho. Encara cal validar el catàleg
i el registre de canvis i revisar els fitxers de bloqueig actualitzats.
desktop/release.sh té els modes explícits prepare, package i promote.
La preparació exigeix un arbre net, només actualitza la versió revisada i les
metadades pendents, genera el registre de canvis transaccionalment i no altera
cap lock. L’empaquetatge exigeix l’arbre net i commitat, consumeix els locks de
pnpm i uv en mode congelat i fora de línia, i no pot mutar versions, locks,
catàleg ni registre de canvis. Les caches s’han de preparar fora d’aquest pas
immutable. La promoció és un commit de metadades posterior a la publicació:
exigeix el tag local coincident, els quatre grups d’artefactes verificats i l’URL
exacte de la release publicada abans de marcar-la com a estable i afegir-hi
l’enllaç. Així, el paquet etiquetat mai anuncia una release estable inexistent.
desktop/release-version.js és la frontera compartida de versió de release per
a l’actualitzador i el col·lector d’artefactes. Utilitza la implementació SemVer
fixada amb electron-updater, accepta metadades de build canòniques i rebutja
espais adjacents, prefixos v i versions invàlides o no canòniques. La política
d’actualització i l’empaquetatge no han d’introduir un segon parser.
Build Release Candidate és un workflow opcional i exclusivament manual.
Enviar una etiqueta de versió no inicia Actions allotjades. Quan s’executa
explícitament, verifica que l’etiqueta sol·licitada existeixi i es resolgui al
commit exacte del checkout, github.sha. Una entrada malformada, etiquetes absents,
destinacions que no siguin commits o discrepàncies aturen el procés abans
d’instal·lar dependències. L’eina auxiliar d’identitat utilitza Git local i no
mou referències ni recupera dades remotes pel seu compte. La protecció de les
etiquetes remotes continua sent un requisit separat.
La publicació sense pressupost allotjat construeix i verifica localment els quatre
grups de plataforma i publica només aquells artefactes exactes; no executis el
workflow allotjat opcional sense una aprovació explícita de pressupost.
Com que el repositori és públic, cada job del CI compartit només permet execució
autoallotjada quan la branca d'una PR pertany al repositori canònic. Les PRs de
forks no poden arribar a les màquines del propietari; un mantenidor les ha de
revisar i reproduir el canvi en una branca interna de confiança abans d'executar
les comprovacions protegides.
El mateix preflight també exigeix que la versió de l’etiqueta coincideixi amb
els manifests de l’arrel, del frontend, de l’escriptori i de Python abans
d’iniciar la CI o qualsevol construcció per arquitectura.
A continuació, el workflow crida la CI existent al mateix commit sense heretar secrets. Les construccions per arquitectura exigeixen que aquesta CI passi. La CI inclou documentació, frontend, backend, proves bàsiques natives i construcció d’imatges Docker. La documentació de les PR es comprova contra la base exacta de la PR; els candidats comproven els catàlegs actuals i tots els portals d’idioma en mode estricte al seu propi SHA, no una revisió fictícia de l’impacte d’una PR.
La recollida baixa només els quatre artefactes d’arquitectura identificats pel
nom i exclou els candidats anteriors en les reexecucions. Instal·la les
dependències congelades del procés de recollida amb els scripts de cicle de
vida desactivats, comprova la versió, les referències i els resums SHA-512,
rebutja fitxers absents o amb col·lisions i fusiona els dos manifests
d’actualització de macOS. La generació d’índexs, la generació de les notes de
versió i la pujada del candidat es fan després de la validació.
La generació del marketplace és obligatòria i falla tancada: la clau de
signatura ha de correspondre a la clau pública gnosi-official inclosa. Un
verificador independent previ a la pujada comprova les dues signatures
separades dels índexs, totes les signatures i els resums SHA-256 dels paquets,
el conjunt exacte de ZIP anunciats i unes notes de versió no buides.
L’artefacte final d’Actions és candidate-<tag>-<sha>-<attempt> i es conserva
durant cinc dies. Conté instal·ladors, metadades d’actualització, índexs i notes
de versió. No és un emmagatzematge confidencial i no ha de contenir mai dades
d’usuari ni secrets. El workflow té permisos de només lectura sobre el
repositori i no crea esborranys de GitHub, no publica versions ni modifica
recursos públics existents o canals d’actualització.
La distribució pública continua desactivada fins a completar l’acceptació nativa, de Docker, dels instal·ladors i de l’actualització des de 2.x, i fins que es revisi separadament un procés de publicació. Un candidat correcte no autoritza a publicar 3.0.0.
Clients web i ofimàtics¶
El capturador web envia POST /api/public/clip amb un token d’accés personal
i llegeix la configuració dels camps sol·licitats i del destí des de
GET /api/public/clip/config. El backend tria la destinació al vault;
l’extensió no obté accés arbitrari al sistema de fitxers. El seu token i l’URL
del backend es desen a l’emmagatzematge local de l’extensió. L’empaquetatge per
al navegador i l’acceptació a les botigues són independents de l’acceptació
dels instal·ladors d’escriptori.
El panell de tasques de Word és a frontend/public/word-addin/ i utilitza
Office.js. Les seves crides a l’API utilitzen l’origen del panell i un token
bearer configurat explícitament; un endpoint públic que respon correctament no
demostra que l’accés a les citacions estigui autoritzat. L’origen HTTPS del
manifest i el certificat de confiança han de coincidir amb el desplegament.
Les eines d’extensions/office/word-cite/ modifiquen les referències del
document o del paquet, o la plantilla de Word de l’usuari, per permetre la
persistència opcional del panell. Són modificacions explícites de documents
o de configuració, no una acció normal d’arrencada de Gnosi.
El client de LibreOffice és un gestor de protocol Python/UNO que utilitza
urllib de la biblioteca estàndard. Llegeix api_token de la seva pròpia
configuració o de GNOSI_API_TOKEN; no pressuposis que comparteix la sessió
del navegador. Tots dos clients utilitzen els endpoints de format de citacions
del vault i el pipeline Pandoc/CSL del backend. El format sensible al context
requereix les claus del document en ordre, incloses les citacions repetides.
L’actualització de Writer recorre les taules imbricades; les capçaleres i els
peus de pàgina aporten claus bibliogràfiques, però l’actualització ordenada no
els reescriu. El comportament d’Office s’ha de provar a l’aplicació amfitriona
real compatible, no deduir-lo de les dades de prova dels recorreguts.
Acceptació i resolució de problemes¶
La prova bàsica del backend empaquetat exigeix una resposta de salut HTTP 200
acotada, amb status: ok, mode: FastAPI i la identitat nova de la prova a
gnosi_mode. Utilitza rutes de dades i de vault d’un sol ús, desactiva les
automatitzacions operatives i finalitza i recull el seu procés fill tant si
té èxit com si falla. GNOSI_VALIDATION_ROOT valida tots els selectors i
bloqueja els fitxers d’entorn locals i compartits i l’accés als magatzems de
credencials. La generació d’OpenAPI utilitza el mateix aïllament. No estableixis
mai aquest indicador per al desenvolupament normal ni per a aplicacions
instal·lades.
Els contractes del codi font, els amfitrions simulats i una execució de FastAPI des del codi font no acrediten un instal·lador amb el backend congelat ni una actualització real. Abans de la distribució pública, verifica en cada destinació real la instal·lació, la primera arrencada, l’IPC, la conservació de galetes i perfils, la integritat de la base de dades, el procés d’actualització i la recuperació, a més dels fluxos autenticats del navegador i l’arrencada i la persistència de Docker. L’èxit local a macOS no pot certificar cap altra destinació.
| Símptoma | Què cal revisar a continuació | Què no s’ha de fer |
|---|---|---|
| El desenvolupament amb Electron es queda en blanc | Origen HTTP de Vite, PATH de l’entorn Python congelat, registre d’arrencada del backend propi | Iniciar un segon backend al port 5002 |
| La protecció del perfil atura l’arrencada | Error exacte, rutes originals i de recuperació, clients aturats | Esborrar registres de recuperació, galetes o dades antigues |
| Falta el backend empaquetat | Resultat de PyInstaller i política final de recursos | Recórrer al Python del sistema |
| macOS ofereix un DMG | Pont Sparkle absent o instal·lació antiga; arquitectura | Tractar la verificació de la signatura com a acceptació de l’actualització automàtica |
| Office arriba a l’endpoint de salut però fallen les citacions | Token bearer, origen de l’API i resposta protegida real | Desactivar l’autenticació per amagar una fallada del client |
Executa les proves de contracte d’escriptori del repositori, la comprovació estricta d’IPC, el control de documentació i les comandes pertinents de proves bàsiques aïllades. Inspecciona el resultat al navegador i a l’escriptori i els registres, no només els codis de sortida. Mantén separades les evidències de cada plataforma de destinació i les proves sintètiques.
Correcció de la instal·lació després de 3.0.0¶
L’Electron empaquetat selecciona un port local lliure. Python accepta
BACKEND_PORT amb una GNOSI_DESKTOP_INSTANCE vàlida, escolta a 127.0.0.1 i
desactiva la recàrrega. Els serveis natius conserven els seus ports. La prova
d’arrencada aporta una configuració contradictòria per comprovar que preval el
port del procés pare i continua exigint la identitat del procés propi. Una
segona obertura recrea la finestra principal si s’havia tancat.
Els traçats del favicon, independents de les fonts, generen les icones a
desktop/assets. El DMG té un fons llis i una mida de 540 × 320. La icona del
disc a l’escriptori desapareix en expulsar-lo; no és un accés directe. Es manté
la signatura local gratuïta, que no equival a la notarització d’Apple. Les
instruccions d’instal·lació són a desktop/README.md.
La release 3.0.1 prepara la correcció integrada de la instal·lació d’escriptori per generar nous paquets natius a les quatre plataformes. La preparació manté el catàleg sense publicar, conserva els dos fitxers de dependències fixades i no substitueix cap fitxer de 3.0.0. Es manté la distribució gratuïta amb signatura local de macOS.
La versió del backend i el contracte OpenAPI generat han de coincidir amb els manifests preparats; la validació de la release en comprova la igualtat abans de generar els paquets.
Ajuda a l’usuari¶
El menú Ajuda de la barra lateral obre el centre, els primers passos, la secció
actual i la documentació tècnica al navegador extern. El menú natiu ofereix el
centre, els primers passos i la documentació d’usuari. L’idioma opcional de
set-application-menu manté la compatibilitat; el procés principal en valida el
tipus i normalitza les variants regionals i els idiomes no disponibles. Els dos
clients utilitzen desktop/help-links.json per a destinacions fixes i temes
admesos. Els URL d’ajuda no inclouen identificadors de registres, noms de Vaults
ni contingut privat. Les seccions desconegudes obren la portada. Català, castellà
i francès tenen rutes pròpies; l’anglès és l’alternativa. El menú participa en la
pila de teclat modal perquè Escape tanqui l’ajuda abans que la barra lateral mòbil.
Les guies es mantenen a docs/learn/ i es construeixen separadament de la
documentació tècnica. Cal publicar i verificar el portal abans de distribuir una
versió amb els enllaços nous. El web redirigeix /learn/ cap a /Gnosi/learn/.
L’ajuda oberta des de la barra lateral rep la preferència d’aparença de Gnosi. El portal respecta els modes clar, fosc i sistema i conserva la preferència entre articles i idiomes. Els enllaços del web públic s’obren en un context de navegador separat.
La versió 3.0.2 inclou el centre d’ajuda multilingüe, els menús d’ajuda contextual i els enllaços que conserven l’aparença. Les versions de l’escriptori, la interfície i el backend es mantenen sincronitzades; el catàleg continua pendent fins a publicar els instal·ladors verificats.
Primer inici sense biblioteca¶
El procés principal empaquetat llegeix vault_configured de la resposta de
salut validada del seu servei. Si és fals, vault-startup.js atura aquest procés
i obre el selector natiu de carpetes abans d’iniciar la interfície o les
actualitzacions. L’usuari pot triar una biblioteca existent o crear una carpeta.
Cancel·lar tanca l’aplicació; tornar-la a obrir ofereix de nou la configuració.
Després de reiniciar correctament amb DIGITAL_BRAIN_VAULT_PATH, desa només la
tria a GNOSI_DATA_DIR/desktop-vault.json. Les variables explícites de biblioteca
tenen prioritat; una carpeta desada que falta no es recrea automàticament.
Les proves focalitzades cobreixen la tria, la cancel·lació, l’aturada dels processos, el reinici, les traduccions i la persistència. L’acceptació de la versió també ha d’instal·lar el DMG candidat amb un perfil buit i sense una biblioteca injectada, recórrer el selector visible i un segon inici, i provar l’actualització des de 3.0.1 amb dades sintètiques. Preparar la biblioteca abans d’arrencar no acredita l’acceptació del primer inici.
Una tria nativa correcta desa també un selectionId opac. El preload aïllat
l’aplica abans de les peticions de la interfície: esborra només l’ID, el slug,
el nom i el catàleg de la biblioteca activa anterior i la seva galeta. Les
altres preferències i galetes es conserven. El marcador s’aplica una sola vegada
per perfil, de manera que els canvis normals de biblioteca sobreviuen a noves
finestres i reinicis. Els fitxers antics sense marcador continuen sent vàlids.
Cancel·lar la recuperació conserva la tria anterior. Triar una altra carpeta
no reescriu les identitats registrades. Cal repetir l’acceptació del DMG per
canvi de ruta i actualització amb la mateixa ruta, i reconstruir el backend congelat.
El candidat 3.0.4 inclou la correcció de preservació del desament automàtic integrada a la PR 96. Substitueix el candidat no publicat 3.0.3 sense moure’n el tag ni reutilitzar les seves validacions d’acceptació. Els quatre camps de versió estan sincronitzats, els fitxers de dependències fixades no canvien i el catàleg es manté sense publicar fins que els nous instal·ladors superin l’acceptació.
La constant del backend GNOSI_VERSION també indica 3.2.0; la prova del contracte de l’API de salut la compara amb els quatre manifestos de versió.
Cal regenerar el document OpenAPI desat i el seu SHA-256 després de canviar la versió del backend. En aquest candidat, la diferència revisada de l’esquema es limita a la versió de l’aplicació; les rutes i les dades no canvien.
La CI de Docker reintenta la neteja dels contenidors de prova i la repeteix en un pas independent que sempre s’executa abans d’eliminar les imatges de CI, per evitar que una neteja fallida bloquegi la construcció següent.
La llista de recursos revisats de l’aplicació d’escriptori inclou personal_memory_0002, de manera que les versions instal·lades conserven els records existents en afegir la memòria per àmbits i els projectes privats d’aprenentatge.
Acceleració limitada de CI¶
Les còpies comprimides de paquets Python continuen desactivades: comprimir tot l’entorn havia retardat les comprovacions obligatòries. CI ara reutilitza la cache nativa de paquets uv de cada runner, separada per repositori, sistema operatiu, arquitectura i versió de Python. uv gestiona l’accés concurrent; la preparació mai esborra aquesta cache. Cada job continua tenint un entorn virtual nou amb fitxers copiats i dependències fixades. Si falta la configuració de cache del runner, es descarrega en una cache exclusiva del job. pnpm ja reutilitza el seu magatzem local; les pujades de cache remotes continuen desactivades. Docker retira les etiquetes d’imatge de CI després de netejar els contenidors de prova, però conserva les capes mentre quedin almenys 12 GiB lliures; si falta espai, s’aplica la neteja limitada existent. La primera execució de cada runner descarrega les dependències, i les següents només els artifacts que falten. Encara cal mesurar els temps als runners. La restauració i creació d’arxius comprimits continuen desactivades.
Si Docker encara no disposa de 12 GiB després de netejar les capes i les còpies antigues, uv allibera les rodes precompilades descarregades de la cache de paquets pròpia; conserva les rodes compilades des del codi font. La recuperació utilitza l’ordre de cache d’uv, rebutja directoris simbòlics o aliens i s’atura quan hi ha prou espai. Un runner petit pot haver de tornar a descarregar paquets després de quedar-se sense espai; reutilitzar paquets no substitueix tenir prou capacitat de disc.
ESLint utilitza una cache basada en el contingut i mypy conserva l'anàlisi incremental entre jobs; els canvis de plataforma, dependències i configuració invaliden la cache. Les proves del frontend utilitzen dos processos. La comparació local de 27 proves representatives ha passat amb un i dos processos; encara cal avaluar el temps i la memòria de la suite completa al runner. Es manté l'ordre dels jobs pesants.
Només les peticions de canvi de confiança que modifiquen exclusivament Markdown dels quatre portals d'enginyeria poden ometre els passos d'execució. Els cinc noms de comprovació obligatoris continuen visibles i el job de documentació valida tots els idiomes. Els diffs buits o desconeguts, els moviments de codi i els canvis de codi, configuració o dependències requereixen la validació completa. Les publicacions de commits i les validacions de versions sempre conserven totes les comprovacions d'execució.
Com que l'anàlisi del frontend utilitza els tipus de TypeScript, qualsevol canvi de fonts o regles locals del frontend invalida tota la seva cache, inclosos els resultats dels fitxers que els importen sense haver canviat. Els canvis exclusius del backend la poden reutilitzar. Si es desconeix l'estat de les fonts, es repeteix l'anàlisi.
La composició d'anotacions PDF executa els 57 contractes en cadascun de dos ordres d'importació aïllats. Cada grup té un límit de 300 segons que cobreix la càrrega inicial del backend i totes les comprovacions. El progrés detallat, els temps de les proves més lentes i la pila després de 60 segons de bloqueig d'una prova individual permeten distingir una arrencada lenta d'una prova bloquejada. Un timeout del grup o qualsevol error del procés fill continua fent fallar la validació, que inclou la sortida parcial.
La validació local prèvia a la PR i CI invoquen el mateix punt d’entrada pnpm lint:frontend. El llançador compartit sempre comprova tot el frontend sense permetre avisos; només afegeix les opcions de cache de contingut quan es defineix GNOSI_ESLINT_CACHE. Les rutes de cache es passen com a arguments literals sense intèrpret d’ordres i els errors d’anàlisi continuen sent fatals. La prova de paritat prèvia a la PR continua rebutjant qualsevol validació de CI absent del pla local complet.
La candidata 3.1.0 empaqueta l’assistent principal compartit, la selecció de models segons la tasca, la memòria amb àmbit definit, l’aprenentatge reutilitzable i la lectura contextual de fonts. Les dades existents es conserven mitjançant les migracions revisades. Tots els manifests i GNOSI_VERSION coincideixen; el contracte OpenAPI regenerat només canvia la versió respecte del codi preparat. Els dos fitxers de dependències fixades es mantenen intactes. El catàleg continua sense publicar fins que els instal·ladors del mateix codi superin les proves d’instal·lació inicial, persistència i actualització als quatre destins.
La candidata 3.2.0 afegeix equips d’assistents i rols especialitzats, comparació de models per proveïdor i plantilles multilingües d’espais de treball. Coincideixen les versions de l’arrel, el frontend, l’escriptori, Python i el backend en execució. Es regenera OpenAPI amb la nova versió; els dos fitxers de dependències fixades es mantenen intactes. El catàleg continua sense publicar fins que els instal·ladors del mateix codi superin l’acceptació d’instal·lació inicial, persistència i actualització en els quatre destins compatibles.
Configuració del primer inici empaquetat¶
Abans de seleccionar un vault, el servei empaquetat desa la configuració i les migracions de referències de proveïdors a GNOSI_DATA_DIR/config/params.yaml. Els recursos signats de l’aplicació es mantenen de només lectura; les peticions posteriors continuen desant al fitxer .gnosi/params.yaml del vault actiu. Les proves del primer inici i del reinici han de comprovar la firma de la instal·lació després de sortir de l’app, perquè l’arrencada correcta per si sola no detecta escriptures dins del paquet.
La imatge Docker del frontend inclou el verificador compartit dels recursos PDF que importa Vite i comprova que es carregui durant la construcció. Això evita que una imatge construïda correctament falli en arrencar el servidor perquè falta el verificador.