Files
ObsiGate/docs/features/spark-vault-dir.md
T

3.9 KiB

Vault DIR « Spark » — exclusions par vault et lecture seule déclarable

Objectif

Permettre d'exposer dans ObsiGate des répertoires techniques (code du service d'agents, workspaces du compagnon, coquilles d'exécuteurs) sous un vault DIR monté en lecture seule — le vault « Spark » — sans jamais rendre visibles leurs zones sensibles (profils et clés des exécuteurs, .home des workspaces, .venv, etc.).

Avant ce chantier, deux manques le bloquaient proprement :

  1. Les exclusions n'existaient qu'au niveau de l'indexeur (IGNORED_DIRS, global) : la navigation et la lecture montraient le disque tel quel.
  2. La lecture seule d'un vault n'était ni déclarable ni affichée : les menus contextuels proposaient renommer / déplacer / supprimer, qui échouaient ensuite côté serveur (montage :ro).

Contrat de configuration (vaults DIR seulement)

Lues par load_vault_config() (backend/indexer.py, boucle DIR_N), rangées dans le dict config du vault ; les vaults VAULT ne sont pas touchés et les défauts (vide / faux) conservent le comportement actuel :

Variable Forme Effet
DIR_N_READONLY true / false Mutations refusées en 403 read_only ; readonly: true exposé par /api/vaults ; l'UI masque les actions d'écriture
DIR_N_IGNORED_DIRS .home,.venv Noms de dossiers cachés à toute profondeur, en plus du global
DIR_N_IGNORED_PATHS Executeurs/*/data,Executeurs/*/.env Motifs fnmatch sur le chemin relatif POSIX ; un dossier qui matche cache tout son sous-arbre

Exemple visé pour le vault Spark :

DIR_1_NAME=Spark
DIR_1_PATH=/vaults/Spark
DIR_1_READONLY=true
DIR_1_IGNORED_DIRS=.home,.venv,__pycache__,node_modules,.git
DIR_1_IGNORED_PATHS=Executeurs/*/data,Executeurs/*/.env,*/compagnon.json

(le montage lui-même — volume :ro, arborescence assemblée sur l'hôte — relève de la configuration de déploiement, pas d'ObsiGate.)

Implémentation

  • Helper central : chemin_exclu(vault_name, rel_path) et chemin_exclu_dans_config(config, rel_path) dans backend/services/vaults.py — segment présent dans ignoredDirs, ou fnmatch du chemin ou d'un de ses préfixes contre ignoredPaths. Tolérant si vault / config absents. vault_readonly(vault_name) au même endroit.
  • Navigation : browse_directory filtre les items exclus (et leurs compteurs d'enfants) ; naviguer directement dans un chemin exclu répond 404. list_all_files et list_paths filtrent aussi.
  • Lecture : un chemin exclu est indiscernable d'un chemin inexistant (404, sans détail sur la règle) — read_raw_file / read_file_text (backend/services/files.py), route GET /api/file/{vault} et route de téléchargement (backend/routers/files_read.py).
  • Indexation : le scan (_scan_vault, qui reçoit le vault_cfg) élague les dossiers exclus et saute les fichiers exclus, en plus du global IGNORED_DIRS inchangé.
  • Lecture seule : _ensure_writable(root, vault_name) dans backend/services/mutations.py refuse d'abord sur la déclaration (DIR_N_READONLY), avant le garde filesystem existant — toutes les mutations du service (créer, éditer, renommer, déplacer, supprimer, upload, xlsx/csv) passent par ce point.
  • API / UI : VaultInfo.readonly (backend/schemas.py) rempli par list_accessible_vaults ; côté frontend, vaultIsReadonly(nom) dans frontend/js/sidebar.js alimente ContextMenuManager, attachTreeItemActionButton et attachTreeItemLongPress pour le vault et ses dossiers / fichiers (aucun autre fichier JS touché).

Tests

tests/test_spark_vault_dir.py : parsing des trois variables, helper chemin_exclu (noms et motifs), navigation filtrée, lectures exclues en 404 (vue fichier, raw, téléchargement), fichier non exclu lisible, indexation filtrée, mutation refusée en 403 sur vault readonly et /api/vaults exposant readonly=true.