Vault i fitxers¶
L’autoguardat serialitza les escriptures de pàgina dins del client web. Una versió obsoleta retorna un conflicte (409), no un error de pàgina inexistent (404), encara que la lectura condicional ometi el cos. Les pàgines inexistents continuen retornant 404; els conflictes no sobreescriuen silenciosament contingut més recent.
Es pot retirar del registre un àlies inactiu si una altra entrada del mateix espai de treball conserva la carpeta. L’eliminació fa servir la mateixa identitat seleccionada que el catàleg i continua protegint l’entrada activa i l’última entrada del vault principal. Retirar una entrada compartida conserva la carpeta, les bases de dades locals, les memòries cau i l’índex de fitxers; no es permet esborrar els fitxers mentre un altre vault registrat faci servir la mateixa ruta, encara que pertanyi a un altre espai de treball.
Contractes de comentaris i traduccions¶
La persistència de comentaris valida només el diccionari o llista arrel desat;
conserva les claus desconegudes, els valors imbricats i la identitat dels registres.
Els models HTTP continuen validant les respostes. comments/composition.py
construeix dependències resoltes en el moment d’ús al punt de registre original
i admet importar primer la façana o els comentaris. La importació Markdown
preserva el tall natiu de l’ID en col·lisions de noms. Les subscripcions SSE
continuen limitades al vault i retiren la seva pròpia cua en cancel·lar-se.
Els helpers de traducció, la cerca, els efectes de metadades i els serveis de files i pàgines utilitzen metadades obertes sense suposar claus YAML només textuals. El cicle de vida comprova els responsables reals dels callbacks i un protocol de connector carregat quan cal; manté les dependències capturades i resol tard els membres substituïbles. Els resultats de creació de pàgines usen un contracte de lectura de camps, diferent de les metadades mutables. Els handlers d’escriptura registrats conserven el retorn asíncron i el context injectat opcional. Els resultats de Web Clipper passen pel model de resposta existent sense coerció de camps.
Aquests canvis preserven els límits de captura d’errors dels proveïdors, la recuperació ordenada del disc, els idiomes de destí duplicats i l’ordre d’escriptura d’estats. Les proves sintètiques utilitzen dobles de proveïdor, no comptes reals del núvol. La composició Drupal i l’HTTP de traducció ara comproven els responsables reals de les dependències; això no certifica tot el backend, un servidor Drupal real ni una migració de proveïdor del núvol.
Contractes del transport Drupal i de l’HTTP¶
El mapatge de camps Drupal, la preparació multimèdia, la descoberta d’idiomes, la coincidència de títols i la sincronització de files conserven metadades obertes i identificadors opacs del connector. Les respostes construïdes tenen tipus explícits; els valors descodificats del transport no pressuposen un esquema de l’aplicació. Es preserven l’ordre dels camps, els errors parcials, la identitat dels identificadors en memòria cau i els errors natius d’entrada. Les factories capturen el connector i les classes d’error, però resolen els membres substituïbles en cridar-los. Pillow continua sent opcional i es carrega quan cal.
Les rutes de traducció preserven els esquemes de petició i resposta existents. La publicació massiva Drupal converteix cada identificador a text i conserva duplicats; la traducció massiva filtra identificadors no textuals i elimina duplicats després de retallar espais. Publicar una fila continua enviant multimèdia per defecte. Les entrades textuals mantenen els valors alternatius per a entrades buides i els errors natius davant JSON malformat. Els cridadors Python no JSON amb una operació strip personalitzada que retorna un valor no textual reben un error de tipus explícit; aquesta comprovació només HTTP no normalitza YAML ni metadades de plugins. El JSON generat vàlid amb una forma de resposta incorrecta arriba a la validació HTTP, no al resultat alternatiu per error de proveïdor. Transports sintètics i fitxers temporals verifiquen aquests contractes sense llegir credencials, publicar contingut ni cridar proveïdors externs.
Responsabilitat¶
El domini Vault relaciona el Markdown portable i els recursos amb pàgines, carpetes, adjunts, cerques, esquemes, historials, paperera, exportacions, citacions i selecció entre múltiples vaults. És el domini més gran i el principal responsable de la sobirania de les dades.
El reconeixement local de text manuscrit és un adaptador d'ingestió opcional al límit del domini Vault. Els objectes del model i del processador es mantenen aïllats com a valors de tercers en temps d'execució; el servei exposa un resultat tipat que conté el text, el reconeixement en brut, els valors de les línies, la identitat del model i l'estat de correcció, sense canviar el contracte públic de pujada. Models de resposta Pydantic específics validen els diccionaris d'estat, preescalfament i reconeixement abans de conservar-ne l'estructura històrica per als consumidors directes i la superfície OpenAPI estable byte a byte.
El catàleg de Vaults marca una sola identitat del registre com a activa, encara que diversos àlies antics comparteixin carpeta. La selecció segueix la capçalera de la petició, el paràmetre de consulta i després la galeta, limitada a les entrades que coincideixen amb la carpeta activa resolta. La selecció actual del navegador té prioritat sobre els indicadors desats a la memòria cau, mantenint sincronitzats el menú, el selector de configuració i el nom del Vault mostrat. Canviar de Vault no reescriu els àlies del registre ni les metadades dels favorits.
Cicle de vida de les pàgines¶
sequenceDiagram
participant UI as Vault UI or editor
participant R as Vault domain API
participant C as Vault context
participant F as File provider
participant I as Page and link indexes
UI->>R: Read page by stable id
R->>C: Resolve authorized active vault
C->>I: Resolve id to current path
I->>F: Read Markdown when cache is insufficient
F-->>R: Content, metadata, and ETag
R-->>UI: Editable representation
UI->>R: Save with expected ETag
R->>F: Atomic write if ETag still matches
R->>I: Refresh page and relationship entries
La identitat d'una pàgina és independent del títol i de la ruta. El frontmatter
es normalitza als punts d'escriptura i es conserven les claus creades per
l'usuari. L'estat exclusivament intern es desa en fitxers auxiliars de
.gnosi quan exposar-lo al frontmatter contaminaria o desestabilitzaria el
contingut portable.
Les lectures i escriptures dels fitxers auxiliars utilitzen un únic contracte explícit de mapatge de metadades, que inclou els resultats de separació, fusió i persistència portable. El mecanisme alternatiu compartit de lectura tolerant del frontmatter retorna els valors escalars del primer nivell com a objectes tipats quan cal recuperar YAML; el contingut niat mal format s'ignora deliberadament. Aquests contractes no forcen conversions dels valors de l'usuari ni canvien les proteccions existents dels fitxers del núvol.
La lectura dels fitxers auxiliars admet plataformes com Windows, on les
estadístiques dels fitxers no inclouen st_blocks. Si el recompte de blocs no
està disponible, es llegeix el JSON local normalment; un zero explícit continua
evitant la lectura d’un fitxer només al núvol per no bloquejar-se durant la
descàrrega. Les pàgines desades i els seus indicadors interns han de continuar
essent llegibles després de reiniciar l’aplicació.
pages/markdown_writer.py és el límit canònic de serialització: recupera o crea
l'identificador estable si falta, transforma les claus de l'esquema en noms
d'emmagatzematge, elimina els camps virtuals, escriu l'estat intern al fitxer
auxiliar, enriqueix les relacions portables i materialitza instantànies de les
vistes abans de l'escriptura atòmica del fitxer.
services/field_resolver.py és responsable d'aquest contracte de mapatge de
claus d'esquema. Accepta identificadors de camp immutables, noms actuals i àlies
històrics, resol els conflictes de manera determinista i emet només els noms
actuals llegibles per humans als límits d'emmagatzematge i resposta, tot
preservant les metadades locals que no hi estan relacionades.
pages/save_helpers.py és responsable de preparar les metadades dels desaments
complets, seleccionar la destinació, reutilitzar els identificadors existents
i crear una versió abans d'escriure.
pages/patch_helpers.py és responsable de les lectures amb ETag, la preparació
de metadades PATCH, la reubicació de fitxers i les actualitzacions coordinades de
les memòries cau de pàgines, cossos, citacions i documents analitzats. Els vuit
noms històrics de funcions auxiliars privades es mantenen com a façanes mínimes
de compatibilitat, i cada col·laborador substituïble o memòria cau mutable es
resol mitjançant un port tipat amb vinculació tardana.
Metadades obertes i HTTP validat¶
Els documents interns del registre i de les pàgines utilitzen dict[object, object]:
el YAML històric pot contenir claus no textuals i valors d'extensions sense un
esquema declarat. Les comprovacions de diccionari preserven la identitat; les
fusions de fitxers auxiliars i el mapatge de noms conserven els camps desconeguts.
Això és diferent de la validació HTTP pública. PageInfo manté la validació
original de claus textuals i l'esquema OpenAPI, mentre que la construcció i
l'assignació de l'índex preserven el document obert. Les memòries cau de resposta
guarden els objectes de pàgina existents sense clonar metadades ni bloquejos.
backend/utils/open_values.py aïlla les operacions natives sobre entrades opaques.
Les excepcions de tipatge, només a l'entrada, preserven els protocols d'iteració,
conversió numèrica, longitud i mapatge de Python i els seus errors; mai afirmen
la forma d'un registre retornat. Les proves comparen el moment de les crides,
les seqüències antigues, els valors malformats i la identitat dels objectes
compartits. Això elimina espais de noms dinàmics amplis de la composició del
registre i dels fonaments de pàgines, no tots els tipus heretats del backend.
Contractes de previsualització i escriptura¶
pages/preview_routes.py comprova les dependències de la façana amb els seus
responsables reals. Les respostes curta i completa comparteixen una estructura
de memòria cau tipada i preserven els valors opacs de títol, icona i portada.
La materialització precedeix la lectura; només errno 35 usa la seqüència de
reintents existent. Les peticions simultànies comparteixen el mateix resultat,
i la memòria cau s'actualitza abans d'avisar les peticions que esperen.
Els desaments complets i parcials mantenen metadades obertes, ETags anul·lables, el moment de les còpies superficials i la resolució del callback abans d'avaluar els arguments. Els auxiliars de cites preserven la identitat del diccionari amb claus textuals o no textuals. L'inventari de documents i el resolutor de rutes conserven les mutacions i el comportament davant d'entrades malformades.
Dos casos històrics queden caracteritzats, sense canviar-los en aquesta refactorització: un conflicte d'ETag a l'auxiliar PATCH arriba al 404 existent abans de la branca 409 del servei; cancel·lar el propietari d'una previsualització retira l'entrada en curs sense completar-ne el futur compartit. Són limitacions de compatibilitat, no una validació reeixida de concurrència. Els esquemes públics i el comportament ordinari d'escriptura no canvien.
Límits del backend¶
La lectura i escriptura de pàgines, les previsualitzacions, la duplicació,
l'historial i la paperera s'implementen a backend/domains/vault/pages, mentre
que la pujada de recursos, les icones i el servei d'imatges són a
backend/domains/vault/assets. El servei de fitxers restringit a les rutes
permeses, les rutes Library/raw/thumbnail, els tokens de fitxers locals, les
pujades associades a propietats, els enllaços portables i l'eliminació física
són a backend/domains/vault/files. Aquests paquets separen els esquemes
estrictes de petició, els adaptadors de rutes, els serveis d'aplicació, els
repositoris i els responsables únics dels bloquejos mutables, les memòries cau
i els magatzems de tokens. El nou comportament de Vault pertany al límit de
domini corresponent.
El límit transitori pages/runtime.py preserva l'estat dinàmic del mòdul
històric de rutes i exigeix un Vault actiu abans de construir rutes del sistema
de fitxers o motors de regles. Els seus models de petició ara es vinculen
directament a Pydantic, cosa que evita classes base dependents del temps
d'execució sense canviar la seva identitat pública de mòdul ni el contracte
HTTP generat.
backend/domains/media és responsable de resoldre les arrels multimèdia,
de l'escaneig recursiu adaptat al proveïdor i la seva memòria cau derivada
persistent, dels fitxers auxiliars de metadades sincronitzades i vistes desades,
dels filtres, la paginació, l'arbre de carpetes de càrrega diferida, les pujades
restringides a les rutes permeses, l'extracció EXIF i la serialització estable
dels fitxers. backend/services/media_service.py continua sent la façana Python
compatible: conserva la classe històrica, la instància única, la forma
d'invocació, els descriptors, l'estat i els errors, i resol amb vinculació
tardana l'estat mutable i els col·laboradors substituïbles. El seu constructor
intern ara té una anotació explícita de retorn None, que elimina l'antiga
excepció de tipatge d'aquest constructor sense canviar el
comportament de construcció. La façana valida que hi hagi un vault actiu abans
de travessar un límit del sistema de fitxers i utilitza els contractes multimèdia
tipats per a arrels, escanejos, consultes, pujades, dades EXIF i informació
serialitzada dels fitxers. Els mòduls de domini no importen mai l'encaminador
HTTP ni la façana de compatibilitat.
Les rutes HTTP multimèdia importen directament l'encaminador compartit i els
serveis estables. media/composition.py conserva la resolució tardana del servei
i dels callbacks de duplicació mitjançant ports amb nom; els tokens de fitxer i
els bloquejos mantenen els seus propietaris canònics. El servei concret es
comprova contra el contracte de les rutes sense conversions de resultats.
Els valors JSON del proveïdor no canvien per als clients Python, mentre que els
models HTTP existents validen la resposta pública. La conversió única de façana
i les anotacions heretades de metadades continuen sent deute explícit.
Les rutes de dibuixos importen directament l'encaminador compartit i els serveis
tipats de dibuixos i historial. drawings/composition.py limita els col·laboradors
amb vinculació tardana a DrawingVaultPort: rutes, paperera, serialització i
callbacks d'historial. El port no té membres Any; la seva única conversió de
compatibilitat és transitòria fins a separar la composició dels proveïdors
heretats. No acredita el tipatge complet de la façana ni del model de petició
històric compartit. No es normalitzen els resultats només per tipar-los: les
crides directes conserven les dades originals i els models HTTP imposen el
contracte existent. Es preserven còpies, recuperació, permisos, moment de
resolució dels callbacks, valors de metadades i ordre de les rutes.
La composició de previsualització i desament de pàgines també comparteix un únic encaminador de tipus concret per resoldre títols i delegar el registre de previsualitzacions i escriptures. La identitat de les memòries cau, la coincidència d'àlies, les comprovacions de vault actiu i els esquemes generats de les rutes no canvien.
Les rutes de traducció i sincronització amb Drupal també concreten el tipus del seu encaminador de vinculació tardana al límit del mòdul. Les operacions sobre una sola fila, en bloc, de coincidència, de botons generats i de traducció de pàgines preserven les comprovacions de rols, la feina en segon pla i el mapatge d'errors externs, alhora que continuen sent visibles per al tipatge estricte.
L'emmagatzematge vinculat a les taules té responsables explícits.
assets/table_paths.py és responsable de les rutes de recursos restringides
als límits permesos, els directoris per propietat, les revisions i les funcions
de canvi de nom segures davant de col·lisions; assets/persistence.py és
responsable de la ingestió recursiva de metadades i de l'eliminació de recursos
de registres dins dels límits permesos; assets/quarantine.py és responsable
de l'eliminació de taules resistent a fallades i de la recuperació en arrencar.
tables/folders.py és responsable de crear i migrar el directori físic
BD/<database>/<table> de la taula. Aquests mòduls reben ports acotats del
sistema de fitxers i del registre des de la façana de compatibilitat i no
importen mai l'encaminador HTTP.
tables/routes.py és ara responsable de les 23 operacions històriques de
bases de dades, taules, catàlegs d'opcions, vistes desades i esquemes de carpetes,
en l'ordre original. Els seus gestors estrictes deleguen en els serveis
existents de files, cicle de vida, propietats, opcions i vistes;
tables/composition.py és el conjunt immutable de dependències d'aquestes
rutes i de la consulta de files i l'enriquiment de metadades.
tables/security.py exposa només les dues fàbriques tipades d'autorització
d'espais de treball, evitant una dependència estàtica del domini de taules
respecte de l'àmplia composició d'autenticació heretada. L'encaminador heretat
registra les rutes de domini en una estructura plana per mantenir la
compatibilitat amb els consumidors de l'inventari de rutes i reexporta els
elements invocables de Python admesos.
backend/api/vault_routes.py és un mòdul d'arrencada de compatibilitat,
sense assumir la implementació del domini. Els mòduls tipats
de backend/domains/vault són responsables del comportament restant d'API,
anotacions, citacions, dibuixos, Drupal, fitxers, coneixement, enllaços,
multimèdia, pàgines, registre, taules i traducció. El mòdul d'arrencada carrega
i registra aquests responsables en l'ordre històric del codi font, mentre que
facade_bridge.py preserva els imports admesos, les variables globals mutables
i els punts de substitució per a monkeypatch amb vinculació tardana.
L'encaminador pare continua exposant el mateix inventari pla d'APIRoute
i un OpenAPI determinista idèntic byte a byte. Per tant, la façana no necessita
cap excepció als controls del codi font.
pages/foundation.py declara les funcions abans de carregar la façana. El punt
d'entrada initialize_foundation vincula els proveïdors existents una sola vegada
en la posició original de l'arrencada, també quan s'importa primer el mòdul de
pàgines. Les crides repetides conserven els mateixos objectes de dependències,
callbacks capturats i ordre de rutes; es rebutja vincular una altra façana. Les
proves aïllades comparen els dos ordres d'importació, les anotacions resoltes i
l'OpenAPI complet del Vault, i comproven claus YAML antigues, sidecars i trasllats
de fitxers. Això elimina un cicle d'inicialització; no acredita el tipatge complet
dels contractes de metadades heretats que encara queden.
El comportament del cicle de vida de les traduccions pertany a
backend/domains/vault/translation: la càrrega opcional de proveïdors,
la recuperació de fitxers del núvol, la traducció de files i de pàgines
completes, els efectes mínims sobre les metadades i la propagació de
l'obsolescència als elements fills són serveis tipats separats. El límit
compartit de funcions auxiliars pures canonitza les identitats d'origen, detecta
canvis traduïbles i camps d'idioma, reutilitza les etiquetes d'opció existents
i tradueix només els subcamps textuals de les imatges tot conservant-ne el
recurs original. La publicació de files a Drupal pertany a
backend/domains/vault/drupal, que separa el mapatge de camps i identitats,
la preparació de recursos multimèdia locals, la conversió de Markdown i
wikilinks, les memòries cau d'idiomes, la coincidència per títol i la
sincronització idempotent de nodes. L'encaminador de compatibilitat conserva
els decoradors FastAPI originals, les docstrings de les rutes i els punts de
substitució Python amb vinculació tardana, mentre que el connector de Drupal
continua sent el límit de transport extern. Aquests trasllats no canvien les
rutes, els payloads, els codis d'estat, les tasques en segon pla ni l'ordre
de les rutes.
Els proveïdors de traducció es carreguen dins dels blocs existents de gestió d'errors en fer la petició, amb imports dels propietaris tipats reals i sense afirmacions de tipus sobre mòduls. Les funcions retornades conserven la identitat, els arguments per nom originals i la substitució tardana. Els protocols de pàgina descriuen el contracte posicional compartit de contingut i idiomes i l'argument de credencial només per nom. Els mòduls o membres absents mantenen els mateixos errors HTTP; les credencials no disponibles mantenen el retorn de clau buida. Carregar aquests adaptadors no carrega models de traducció ni llegeix credencials durant l'arrencada de l'aplicació.
L'autorització de les taules utilitza els tipus reals de workspace_service.
La dependència get_workspace_context capturada inicialment i les consultes
posteriors de require_role mantenen la identitat i el moment de resolució
originals; les comprovacions retornen la mateixa instància de WorkspaceContext
o el mateix error de permisos. No canvien els llindars dels rols, les regles
d'autenticació ni la selecció del workspace.
Índexs i memòries cau¶
L'índex de pàgines accelera el llistat, la resolució d'identificadors, l'accés al frontmatter i la cerca. L'índex de wikilinks resol els enllaços entrants perquè els canvis de nom de les pàgines puguin actualitzar les referències. Les memòries cau de cossos i documents analitzats eviten lectures repetides. Totes les memòries cau són derivades i han de tolerar una reconstrucció des de zero.
links/document_inventory.py és responsable de l'inventari amb TTL per vault
que utilitzen els enllaços globals. Exclou l'historial i la paperera, aïlla els
fitxers il·legibles, inclou els quadres de comandament JSON i recorre el disc
com a alternativa mentre l'índex del proveïdor no està disponible.
links/document_cache.py és responsable de les memòries cau persistents del
cos Markdown i del frontmatter analitzat, indexades per mtime. L'encaminador
només proporciona les rutes actives de les memòries cau, l'analitzador i
l'escriptor JSON segur, de manera que el comportament de la memòria cau és
independent del proveïdor de fitxers.
links/relation_sync.py és responsable de les actualitzacions idempotents del
sistema de fitxers i de les memòries cau quan els canvis en una relació directa
afecten la inversa. La correspondència pura d'esquemes continua sent un port
tipat de regles separat: resol els camps de relació a partir dels noms actuals
normalitzats i dels àlies, exigeix un únic camp invers inequívoc i emet només
operacions d'addició o eliminació sobre identificadors canònics de relació.
L'encaminador de compatibilitat proporciona l'entrada/sortida de pàgines amb
vinculació tardana.
L'arrencada carrega primer les instantànies vàlides del disc i després inicia les tasques d'actualització. Un escaneig parcial del proveïdor de fitxers es marca com a parcial i no pot substituir una memòria cau que se sap que és completa. Les fallades s'aïllen per fitxer perquè un únic marcador de posició només disponible en línia o orfe no faci desaparèixer la resta del vault d'una resposta.
pages/index_entries.py és responsable de les lectures acotades de
frontmatter, els reintents davant de bloquejos del núvol i la normalització
d'entrades de memòria cau. pages/index_service.py és responsable del
descobriment, l'actualització, els mapes inversos d'identificadors i les
instantànies deduplicades. pages/resolver.py és responsable de resoldre
identificadors estables, UUID canònics, títols indexats i escanejos acotats
sense memòria cau prèvia.
pages/tags.py és responsable de l'agregació independent del proveïdor de les
etiquetes del frontmatter i de les etiquetes semàntiques de taula, inclosa la
deduplicació per pàgina. L'encaminador de compatibilitat injecta els ports de
vault actiu, registre, calendari i memòria cau, de manera que cap d'aquests
serveis importa la façana HTTP.
El mòdul d'execució del registre referencia els propietaris tipats reals dels callbacks i de l'estat, utilitza el decorador estàndard de gestor de context per als cicles de mutació i tracta l'absència d'un Vault actiu com l'absència d'una arrel d'adjunts del núvol. L'ordre de les rutes de registre i taules, els bloquejos, les memòries cau i els candidats d'adjunts específics de cada proveïdor no canvien.
L'API principal de Vault importa directament l'encaminador i els serveis i
limita els col·laboradors de vinculació tardana a CoreVaultPort. La creació
de pàgines admet metadades obertes sense coercions; la inserció a l'índex
actualitza el propietari existent de la memòria cau. Els noms d'usuari conserven
l'alternativa de nom, correu i identificador. La creació de notes diàries passa
l'usuari de l'espai de treball ja autoritzat al servei canònic de pàgines, en
lloc d'invocar un gestor HTTP amb una dependència pendent de resoldre. Els
callbacks explícits dels plugins conserven els dos arguments històrics.
Els permisos, els controls de plugins, la recuperació de notes existents,
el bloqueig de creació i els esquemes HTTP públics no canvien.
La composició del format, la cerca, el catàleg i l'exportació de citacions utilitza
contractes explícits de registres i callbacks sense conversions de resultats.
Les propietats del registre conserven la identitat; els consumidors de lectura
admeten interfícies de mapatge i seqüència. Les referències importades reben el
context de l'usuari autoritzat quan utilitzen el gestor canònic de pàgines;
els callbacks tardans de dos arguments continuen admesos. La deduplicació, els
formats, les descàrregues i els errors de Pandoc no canvien. Tots els entorns desen
la designació bibliogràfica a GNOSI_DATA_DIR/config/references.json. La configuració
antiga requereix scripts/migrate-reference-config.py: la migració explícita sense
sobreescriptures conserva els bytes, camps desconeguts i l'original, amb diari
privat i reversió recuperable. L'arrencada ho comprova abans de migrar bases de
dades o iniciar tasques. La validació temporal no consulta mai fitxers antics.
La consulta de metadades, el reconeixement de PDF, la traducció d'URL, la promoció de Zotero, les actualitzacions massives i el registre del catàleg i la cerca de citacions comparteixen aquest mateix límit HTTP de tipus concret. Les alternatives de proveïdor, els permisos d'edició i la unicitat de les claus de citació continuen resolent-se amb vinculació tardana i preserven el comportament compatible.
La consulta bibliogràfica importa els serveis directament i declara sota
TYPE_CHECKING àlies comprovats dels propietaris reals dels callbacks, sense
conversions de mòduls ni resultats. La substitució tardana continua funcionant.
Les proves cobreixen els dos ordres d'importació, els esquemes HTTP exactes,
la substitució de callbacks durant una consulta i la preservació de metadades
desconegudes. citations/title_regex.py conserva
els errors natius de Python: l'única excepció documentada del verificador valida
entrades incorrectes i mai afecta dades retornades. Els tipus heretats dels
proveïdors de registre i pàgines continuen sent feina pendent separada.
La importació de Markdown, els comentaris en línia, els blocs sincronitzats, la navegació per enllaços i les mencions sense enllaç comparteixen un encaminador tipat de sincronització de pàgines. Els models de petició utilitzen Pydantic directament i conserven la seva identitat històrica de mòdul, preservant els noms dels esquemes, el comportament SSE i la sortida OpenAPI.
El CRUD d'anotacions PDF importa directament l'encaminador compartit i les
dependències d'autorització i persistència. Els payloads TypedDict amb nom
descriuen els diccionaris retornats als consumidors Python sense conversions
de tipus ni Any. Els rectangles desats conserven la descodificació JSON
original; els models de resposta HTTP continuen validant-ne la forma. No canvien
les identitats dels esquemes, el filtratge per URI, l'ordre per pàgina i data de
creació, els permisos, les actualitzacions amb camps nuls o omesos ni l'esquema
SQLite. Les proves aïllades SQLite i HTTP cobreixen els dos ordres d'importació:
primer la façana o primer el domini.
L'administració de Vault ara falla explícitament amb una resposta de servei
no disponible quan falta la ruta del Vault principal, en lloc de construir una
ruta a partir de None. Les anotacions de resposta heretades continuen
congelades, i el canvi de nom lògic travessa l'antic límit dels descriptors
de l'ORM sense modificar les carpetes del disc, els slugs, les regles de purga
ni les comprovacions de confinament de rutes.
El catàleg, la instal·lació, l'exportació i l'enviament moderat de plantilles de Vault exposen límits tipats de petició i resposta. Els gestors validen cada mapatge abans de retornar-lo i desactiven la publicació del model de resposta a les rutes de compatibilitat, de manera que els esquemes FastAPI congelats i el contracte de diccionari de les crides directes no es desvien. Les comprovacions de signatures, les troballes de privadesa, els paquets deterministes i la reversió en cas de fallada del registre no canvien.
Proveïdors de fitxers¶
En iniciar o canviar de Vault es demana la descàrrega de totes les metadades del núvol de .gnosi, incloses habilitats, plugins, sidecars, estat de Wiki, icones i còpies de seguretat. El lector també demana els fitxers individuals quan calen. Dos processos auxiliars i terminis de deu segons acoten el treball del proveïdor; les lectures concurrents comparteixen una petició i les fallades tenen una espera de trenta segons abans del reintent. Les lectures asíncrones retornen un 503 recuperable sense bloquejar el bucle d’esdeveniments. No se substitueixen metadades remotes per valors per defecte: els lectors propaguen la indisponibilitat i les escriptures atòmiques exigeixen tenir el fitxer original local. Els fitxers inexistents es poden crear normalment. La descàrrega en segon pla exclou els arbres amb enllaços simbòlics. Si el proveïdor falla, no es garanteix la disponibilitat; la configuració crítica es manté tancada per seguretat.
L'abstracció de proveïdor selecciona el comportament local o l'adaptat al
File Provider genèric de macOS, OneDrive, iCloud Drive, Google Drive, Nextcloud
o Dropbox. El codi habitual del domini continua treballant amb Path;
l'adaptador hi afegeix detecció de marcadors de posició, hidratació,
disponibilitat i mapatge de rutes. Establiu GNOSI_FILES_PROVIDER
explícitament quan la detecció automàtica de rutes sigui ambigua.
El sistema d'execució de fitxers a demanda és independent del proveïdor. A macOS
s'utilitza per defecte un auxiliar de només lectura basat en NSFileCoordinator,
compilat i signat a Contents/Resources/native/gnosi-file-access. Cada invocació
demana un fitxer, llegeix com a màxim 64 KiB i no retorna contingut del document.
El límit de dues descàrregues simultànies i la unificació de peticions per camí
acoten la càrrega; el temps límit o la cancel·lació finalitzen el procés auxiliar.
Aquest camí no obre aplicacions gràfiques, fixa fitxers al disc, descarrega
recursivament ni reinicia clients de núvol. Docker conserva l'auxiliar configurat
a l'amfitrió. Els modes antics open i direct requereixen una selecció explícita;
només l'adaptador antic de OneDrive pot activar una recuperació específica.
La detecció de l'índex utilitza els indicadors de fitxer sense dades per conservar marcadors accessibles sense obrir tots els documents del núvol. Les entrades existents més completes es conserven si un fitxer no es pot llegir; la descàrrega no necessita canviar el mtime per actualitzar un marcador. Una exploració inicial fallida no es marca com a inicialitzada. La navegació lateral i la taula demanada obtenen les metadades necessàries, mentre que les lectures de pàgines i adjunts materialitzen el fitxer seleccionat. Els fitxers no disponibles retornen 503 amb Retry-After en lloc d'una lectura buida correcta. L'escalfament massiu de l'arbre crític està desactivat per defecte amb l'accés coordinat natiu.
La validació del codi del 14 de setembre inclou proves sintètiques de fallada, cancel·lació, deduplicació i absència de lectures massives, més una lectura real d'un marcador de OneDrive. Aquesta descàrrega va trigar 2,2 segons; les lectures directes posteriors del mateix fitxer de 3,9 KiB van trigar 0,24–1,03 ms, no pas el temps total de renderització de la pàgina.
El canvi està empaquetat al DMG local amb signatura ad hoc
Gnosi-3.0.2-on-demand-arm64.dmg, i instal·lat des d'aquesta imatge. El backend
empaquetat ha superat una prova aïllada de vaults, pàgines i favorits. Un PDF real
de OneDrive de 428.327 bytes ha passat de no tenir dades ni blocs locals a estar
disponible mitjançant l'endpoint Library de l'aplicació instal·lada. Una petició
HTTP Range de 16 bytes va trigar 3,5959 segons el primer cop i 14,8 ms en repetir-la;
totes dues van retornar 206 i una capçalera PDF. No són mesures de renderització
del document complet. L'aplicació instal·lada llista els tres vaults existents;
la barra lateral retorna 2.672 pàgines i 19 favorits, i la interfície obre un
favorit amb el contingut de la pàgina. També s'ha provat correctament l'opció
d'expulsar només la imatge. No és una release publicada ni notaritzada per Apple;
altres proveïdors de núvol i Windows no s'han provat en viu. Mostrar tots els
favorits immediatament en un dispositiu nou encara requereix metadades portables
de navegació: els noms dels fitxers no permeten deduir favorits que només consten
dins d'un document no descarregat.
Les rutes de Dropbox File Provider es detecten explícitament. Un servei
desconegut sota ~/Library/CloudStorage de macOS utilitza l'adaptador
fileprovider, sense efectes secundaris; qualsevol carpeta completament
sincronitzada o muntada de manera ordinària utilitza local. Només cal un nou
adaptador amb nom propi quan hi ha un senyal diferent de marcador de posició
o un mecanisme d'hidratació específic del proveïdor. GNOSI_DATA_DIR es manté
local independentment del proveïdor del vault.
Només el Markdown portable de Vault i els adjunts poden residir en un arbre
sincronitzat. Les bases de dades SQLite, els bloquejos, les memòries cau
derivades, els secrets i GNOSI_DATA_DIR es mantenen a l'emmagatzematge local
de l'aplicació. Una carpeta Nextcloud completament sincronitzada es comporta
com a local; els desplegaments amb fitxers virtuals utilitzen el proveïdor
corresponent o l'adaptador genèric fileprovider. WebDAV i les API directes
del núvol són transports de transferència o de còpia de seguretat, no
emmagatzematge actiu per a SQLite. La destinació de les còpies de seguretat
i el proveïdor de Vault es configuren de manera independent.
Adjunts i propietats amb fitxers com a valor¶
Les escriptures trien una destinació permesa dins del vault actiu, normalitzen els noms, eviten col·lisions i retornen metadades portables. L'arrel dels enllaços a fitxers es reajusta en llegir-los per adaptar-la a l'amfitrió actual. Les operacions de pujada i eliminació comproven el confinament de les rutes; una ruta proporcionada pel client mai no és autorització suficient.
Els gestors de rutes de recursos i fitxers són exportacions canòniques del
domini. L'encaminador heretat de Vault els registra en les posicions històriques
i injecta ports acotats per a consultes del registre, resolució de rutes i
selecció del proveïdor. No ha de mantenir un segon mapatge de tokens locals,
bloqueig d'icones personalitzades o semàfor de fluxos de fitxers. Els
decoradors repetits /local-file/{token} conserven el seu ordre original de
rutes, de baix a dalt, i qualsevol canvi estructural ha de preservar les
capçaleres de transmissió en flux i el document OpenAPI exacte.
Les metadades amb fitxers com a valor es normalitzen recursivament sense canviar
la seva estructura de llista o objecte. Les rutes Assets/ existents i els
URL HTTP remots continuen sent referències; els URL de dades i els fitxers
locals autoritzats es copien atòmicament al directori de recursos de la
propietat. La neteja física resol cada candidat dins de l'arrel Assets del
Vault actiu abans d'eliminar-ne l'enllaç, de manera que una cadena de
recorregut de directoris al frontmatter no pugui sortir del Vault.
Paperera i operacions destructives¶
drawings/service.py és responsable del descobriment de Tldraw i de
l'Excalidraw heretat, les lectures, les instantànies d'historial limitades per
un interval mínim, les escriptures atòmiques i l'eliminació recuperable. La
feina del sistema de fitxers s'executa fora del bucle d'esdeveniments, i
l'eliminació reutilitza el mateix contracte de fitxers auxiliars de la
paperera de Vault que les pàgines.
L'eliminació ordinària és recuperable: les pàgines i els recursos relacionats
passen pel model de paperera de Vault. La purga és diferent i elimina el
contingut, les metadades derivades i les relacions inverses.
trash/purge.py és responsable del pas irreversible sobre el sistema de
fitxers i de la neteja de l'historial, els fitxers auxiliars de metadades i els
comentaris mitjançant ports de la façana amb vinculació tardana. L'eliminació
del registre de Vault suprimeix per defecte la fila lògica del registre;
l'eliminació física de la carpeta requereix un senyal explícit separat i
comprovacions de confinament més estrictes.
En eliminar una taula, primer es mou atòmicament cada arbre de recursos que
li pertany a .gnosi/pending-cleanup/table-assets/in-progress-* i s'escriu un
manifest restringit als límits permesos. La confirmació de la transacció del
registre canvia llavors el nom d'aquest directori a ready-* abans d'una
purga en segon pla. La recuperació en arrencar restaura una quarantena en curs
quan la taula encara existeix, la purga quan el registre persistent acredita
l'eliminació i deixa intactes les entrades il·legibles o desconegudes. Les
revisions dels recursos inclouen els enllaços simbòlics sense seguir-ne les
destinacions i impedeixen l'eliminació després d'una previsualització obsoleta.
Plantilles de Vault¶
El repositori de plantilles és un catàleg signat disponible en temps d'execució; els recursos dels paquets no es versionen al repositori Git de l'aplicació. La creació a partir d'una plantilla verifica la signatura separada de l'índex, el SHA-256 del paquet, la signatura de l'editor, el manifest, l'inventari de fitxers, els límits de l'arxiu, les rutes, els tipus de fitxer i els enllaços abans d'escriure. L'extracció es fa en un directori temporal germà sota l'arrel de Vaults. El directori complet es mou atòmicament a la seva ubicació definitiva i només llavors es registra a la base de dades de gestió, de manera que una fallada no pugui exposar un Vault parcial.
La validació de l'arxiu es descompon en validació acotada d'entrades, descodificació del manifest, comparació de l'inventari i comprovacions d'integritat del payload. Aquests passos purs i tipats conserven el mateix contracte de paquet, que rebutja l'operació davant d'errors, i mantenen cada funció auxiliar per sota del límit de complexitat del backend.
L'exportació es basa en una llista d'elements permesos i és determinista.
Exclou .gnosi, plugins, magatzems de confiança, correu, paperera, historial,
contingut executable, fitxers d'entorn, enllaços, fitxers il·legibles i
contingut de mida excessiva. Una previsualització enumera tots els fitxers
inclosos i exclosos i analitza fitxers de text de mida acotada per detectar
valors que semblin credencials. Les troballes requereixen confirmació explícita.
Els plugins recomanats són identificadors al manifest; el codi executable
dels plugins mai no es transporta dins d'una plantilla de Vault.
L'enviament públic és independent de l'exportació i requereix accés d'administrador. Utilitza un intermediari de moderació opcional en lloc d'una credencial de GitHub incrustada a Gnosi. Els camps addicionals del justificant específics de l'intermediari es conserven sense pèrdues mitjançant un model de resposta que admet camps extres; els payloads de fallada del catàleg conserven la seva estructura heretada per a la recuperació sense connexió i davant d'errors de signatura.
Invariants de concurrència¶
daily/service.py és responsable del descobriment de carpetes i taules
independent del proveïdor, la normalització de dates, la inicialització a
partir de plantilles, el llistat i el flux atòmic d'obtenció o creació de
notes diàries. L'encaminador de compatibilitat manté els decoradors FastAPI
públics i injecta ordres de pàgina amb vinculació tardana perquè els plugins
i les proves existents conservin els seus punts de substitució.
- Els ETags obsolets impedeixen les sobreescriptures.
- La creació de registres i de notes diàries utilitza comprovacions repetides segures davant de condicions de cursa.
- Les actualitzacions de pàgines, registres, índexs d'enllaços i fitxers auxiliars es mantenen coherents després d'un canvi de nom o d'una eliminació.
- Les rutes absolutes rebudes d'un client es resolen dins d'arrels autoritzades.
- Els enllaços simbòlics i el recorregut de directoris no poden sortir dels límits del vault seleccionat.
- L'extracció de plantilles no pot publicar un directori parcial ni registrar-lo abans d'hora.
- Les exportacions de plantilles no poden incloure estat d'execució ni contingut executable de plugins.
- Els cicles d'anada i tornada de Markdown preserven el contingut sensible als caràcters d'escapament i la sintaxi de wikilinks.
Frontend¶
VaultDashboard és responsable de l'historial de navegació i selecciona les
interfícies de pàgina, taula, dibuix, galeria, tauler, calendari, cronologia,
canal o lector. VaultShell proporciona l'estructura; els components
especialitzats implementen els editors i les vistes. El frontend desa en
memòria cau l'estat d'interacció, però considera el contingut de les pàgines
del backend i els ETags com a font de veritat.
El trasllat revisat situa VaultDashboard.tsx a l'arrel de la feature i
la seva orquestració a features/vault/dashboard/. La composició de taules
i l'edició de cel·les són a features/vault/views/vault-table/; els camps
i les opcions d'esquema, a features/vault/schema/schema-config/; i les
propietats de pàgina, els documents enriquits, els efectes i la persistència,
a features/vault/editor/block-editor/. El renderitzat, els hooks de
registres i els controls de vista reutilitzables pertanyen a shared/editor/,
shared/records/ i shared/record-views/; mai no importen UI del Vault.
Un mòdul només és públic mitjançant l'arrel de la feature o la seva entrada
exacta revisada al manifest; ser un fitxer de composició no el fa públic.
Els canvis de propietat conserven les rutes API i els formats d'emmagatzematge;
la verificació d'integració continua sent un pas separat.
Les transicions de Markdown a la vista visual publiquen els esborranys pendents abans de muntar l'editor enriquit, evitant que el contingut obsolet del component pare substitueixi una edició encara no desada. Els desaments només de metadades ometen el cos; les fórmules per defecte preserven els valors niats de relacions i plugins. Les proves de regressió cobreixen aquests traspassos, a més dels identificadors d'opció de l'esquema, la identitat de les files de taula i les extensions de metadades desconegudes.
Continuïtat de les pestanyes de documents¶
Les pestanyes obertes de pàgina, taula i PDF conserven les seves vistes muntades després de la primera visita, també quan un document passa entre el panell principal i els panells dividits. Tancar una pestanya allibera la seva vista. Tornar del PDF d'una cita restaura el focus a la targeta d'origen de la galeria i les posicions dels scrolls niats sense desplaçar-se en donar el focus; la navegació amb fletxes continua des d'aquella targeta. Els desplaçaments pendents del layout no poden substituir la posició desada, i una entrada de teclat o punter cancel·la qualsevol frame de restauració pendent.
Els panells ocults són inerts. Les seves dreceres globals de selecció, edició i navegació cedeixen als panells visibles, i els menús renderitzats en portals s'oculten amb la pestanya propietària. L'expansió dels grups de galeria es desa per sessió, pàgina i vista d'ancoratge desada, en lloc dels identificadors de bloc regenerats de l'editor. Aquest estat d'interacció no modifica el contingut de les pàgines, les definicions de vista desades ni els ETags.
Aspectes que cal verificar¶
Executeu proves de concurrència amb ETag, confinament de rutes, entrada/sortida segura, condicions de cursa del registre, canvis de nom, paperera i purga, numeració d'adjunts, relacions, actualització de l'índex i fluxos representatius de Vault amb Playwright. Els incidents dels proveïdors del núvol també requereixen llegir un marcador de posició real, perquè les proves amb dades locals de prova no poden reproduir el comportament de File Provider.
Recuperació de metadades de la barra lateral¶
El resum i l’arbre compacte de la barra lateral recuperen les entrades incompletes de l’arrel, Wiki i els taulells mitjançant el proveïdor de fitxers actiu abans de rellegir-ne les metadades. Això també s’aplica a les instantànies en memòria cau. La recuperació restaura els identificadors canònics i dels pares, les marques de base de dades, els favorits i les icones, actualitza la cerca per identificador i reconstrueix la instantània versionada per eliminar duplicats. Les entrades completes i els catàlegs de taules no activen aquesta recuperació. Les lectures parcials de la capçalera reintenten els dos codis d’error transitori del núvol (11 i 35), començant amb el buffer i els delimitadors buits cada vegada que es reobre el fitxer. Les lectures fallides conserven les metadades existents en memòria cau.
Canviar de biblioteca amb una nota oberta tanca el seu editor. BlockNote pot destruir la vista ProseMirror abans que React executi la neteja de navegació dels elements incrustats. Aquesta neteja restaura els gestors de teclat anteriors només si la vista continua viva i conserva els gestors instal·lats; mai crida setProps sobre una vista destruïda. Les proves de regressió utilitzen una vista ProseMirror real i cobreixen els dos ordres de tancament per evitar que una excepció elimini tota la interfície.
Recuperació de creacions per abast i descàrregues de manuscrits¶
Les peticions de creació persisteixen un rebut privat i checkpoints abans dels efectes recuperables. La recuperació conserva l’ID original de la pàgina i les entrades tipades congelades, verifica les revisions del document i la configuració, i comprova l’accés abans de cada efecte. Només es repeteix feina no iniciada. Un pas d’índex iniciat només es pot reconciliar després de verificar les entrades registrades i la postcondició actual; els altres efectes incerts continuen bloquejats. La recuperació no selecciona codi executable a partir de dades emmagatzemades. El navegador consulta la petició guardada i obre la pàgina existent, sense crear-ne una de duplicada quan es perd la resposta.
El vault efectiu seleccionat per capçalera, query o cookie és també la identitat emprada per l’autorització. Un vault explícitament inexistent, sense accés o sense muntar falla sense recórrer a un altre vault.
Obrir el canvas de dibuix no descarrega ni carrega automàticament un model d’OCR. L’estat distingeix pesos absents, descàrrega, descarregat, càrrega, cancel·lació i error. La cancel·lació queda limitada al propietari i afecta la transferència, no una inferència activa. Els fitxers només es fan visibles a la caché després de verificar-ne la mida i el checksum; s’eliminen els fitxers parcials. La interfície mostra la mida transferida i l’estat traduït. Les proves sintètiques de transferència i canvas verifiquen aquests contractes, però no la precisió amb manuscrits reals ni fitxers del núvol sense materialitzar.
Notes generades, referències llegibles i revisió del Coneixement¶
El tipus d’idea és una assignació per IA per defecte mitjançant l’ID de propietat, independent dels camps d’índex. El contracte existent de dimensions transmet les etiquetes traduïdes permeses i una justificació breu classification_reason; els valors buits representen una abstenció explicada. Les assignacions explícites copiades, fixes i buides tenen prioritat. La interpretació, la revisió i el desament conserven el valor, i llm_wiki_idea_classification en registra la versió, el mètode i la procedència. El reprocessament preserva els valors modificats manualment. La classificació antiga absent s’ha de completar, sense aplicar Concepte implícitament.
El Cervell ja no crea, vincula ni omple l’estat de verificació o la data d’última revisió. L’estat de treball i les dates del sistema pertanyen a l’aplicació; les assignacions del recurs no els poden sobreescriure. Les notes de lectura noves són esborranys. L’estat existent i la data de creació es conserven en reprocessar. Es retira la categoria de notes antigues basada en dates; l’API conserva stale com a llista buida i el recompte a zero per compatibilitat. Les notes generades substituïdes continuen sent una incidència diferent.
L’ordre explícita de migració és python -m backend.domains.llm_wiki.note_migration --vault /path/vault --output /private/report --action preview. Les accions classify, apply i rollback separen el treball governat del model de la modificació de dades. La simulació només llegeix; la classificació reutilitza els resultats de notes que no han canviat i els pressupostos de lectura existents sense reiniciar la despesa. L’aplicació retira els camps i les referències en vistes i configuració per ID i rol, conserva el cos i les altres metadades, verifica una còpia comprimida, compara cada original abans d’escriure i registra el progrés per recuperar-se. Les còpies i els informes han de quedar fora del vault sincronitzat i de Git. La migració d’esquema registra note_fields_revision i repetir-la és idempotent. L’acció opcional retire aplica només la retirada de camps i la neteja de l’estat de treball, informa de la classificació pendent i no crida cap model; cal usar una carpeta de sortida diferent per a cada fase aplicada.
El processament de recursos crea notes de lectura amb l'estat Esborrany i les dates canòniques de creació i modificació de la taula. El reprocessament conserva la data de creació i l'estat de treball existent, actualitza la modificació i manté els identificadors estables i el text escrit per l'usuari.
Els enllaços interns mostren els títols actuals de les pàgines als editors, relacions, taules, galeries, kanban, cerca, grafs, mencions i predecessors de planificació. El resolutor compartit admet identificadors, rutes de pàgina, els dos ordres de wikilink i cites de recursos gnosi-cite:. Les referències desconegudes mostren un text provisional localitzat mentre es carrega el títol. Els índexs de relacions conserven les claus gestionades i els identificadors desats amb etiquetes llegibles.
Les previsualitzacions de lectura oculten els comentaris HTML de processament, inclosos els límits <!-- ... -->. Els comentaris literals dels blocs de codi i del codi en línia continuen visibles; el Markdown desat es conserva.
Les connexions del Coneixement demanen els textos en l'idioma actiu mitjançant el paràmetre de consulta opcional locale. L'agent del Coneixement tradueix només els títols i les explicacions i desa cada idioma per proposta. Les evidències i els identificadors de les notes es conserven. La lectura de la memòria cau evita noves crides al model, i una proposta descartada durant la traducció no es restaura.
El diàleg de revisió agrupa les notes i els recursos afectats en categories desplegables amb enllaços per títol i lots de vint entrades. Obrir un resultat tanca el diàleg i obre el registre. La comprovació de notes òrfenes reconeix tant [[id|title]] com [[title|id]]. La revisió no reprocessa recursos automàticament ni crea notes permanents.
A l'escriptori, la selecció de fitxers i carpetes utilitza la capacitat IPC fiable i validada pick-filesystem i el diàleg natiu del sistema operatiu. Cancel·lar tanca el selector sense aplicar cap selecció; les seleccions múltiples conserven el tipus de fitxer o carpeta de cada ruta. Windows i Linux mostren primer una tria nativa entre fitxers i carpetes per a la selecció combinada. El navegador de fitxers intern continua disponible per als clients web sense el pont d'escriptori.
La capçalera d’un sol document només mostra Tancar pestanya quan l’identificador actiu correspon a una pestanya oberta. Conservar una pestanya inactiva no ha de mostrar l’acció de tancar a la pantalla de benvinguda. Els controls d’obertura i cerca continuen disponibles i tancar l’última pestanya activa elimina el seu botó de tancar.
Afegiu --resource-id <id> a preview per classificar només un recurs; les accions posteriors reutilitzen aquesta selecció desada. La classificació vincula el propietari personal verificat, exclou els contextos adjunts i les memòries revisades, desactiva les delegacions i reserva com a màxim 4.096 tokens de sortida per lot sense canviar els límits de despesa.
Els encapçalaments plegables admeten Alt/Opció+Retorn amb el cursor dins del títol. El botó natiu es pot enfocar amb Tab i activar amb Retorn o Espai, amb focus visible, etiqueta traduïda i estat de desplegament. L’activació conserva el cursor o el focus del botó i l’estat de desplegament desat. Retorn sense modificadors conserva el comportament d’edició; els paràgrafs fills, els controls incrustats i la composició de text no pleguen una secció pare.