- Store backend `backend/file_chat.py` : messages JSON par (vault, path)
sous `data/chats/` (nom hashé SHA-256 → traversal impossible), plafond
500 messages, texte tronqué à 4000 caractères, écriture atomique.
- Routes `GET/POST /api/file/{vault}/chat` : auth + accès vault +
`resolve_safe_path`, schémas Pydantic (`response_model`), broadcast SSE
`chat_message` sur le transport existant (#62) — pas de second WebSocket.
- Panneau latéral `frontend/js/filechat.js` : bouton 💬 dans la toolbar
fichier, historique chronologique, envoi optimiste + dédoublonnage par id,
toast « Nouveau message » si le panneau est fermé/autre fichier.
- Relais SSE dans `sync.js` (import dynamique), CSS bloc #169 (plein écran
≤ 768 px, input 16 px anti-zoom), i18n FR/EN (10 clés `chat.*`).
- Tests : `tests/test_file_chat.py` (15) + `tests/frontend/filechat.test.mjs`
(6, ajouté au pipeline CI), regex toolbar-order mise à jour.
- Docs : CHANGELOG [Unreleased], ROADMAP #169 → livré + index, fiche
`docs/features/file-chat-169.md`, guide « Discuter d'un fichier ».
46 KiB
ObsiGate
Version française — ce document est le miroir synchronisé de README.md (référence complète). Dernière synchronisation : septembre 2026.
Porte d'entrée web ultra-léger pour vos vaults Obsidian — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.
Interface web d'ObsiGate : sidebar multi-vault, recherche globale, statistiques et raccourcis.
📚 Guides
Les guides d'utilisation pas à pas se trouvent dans docs/GUIDES/ :
| Guide | Contenu |
|---|---|
| 🚀 Prise en main | Premier lancement, interface, navigation, vaults, raccourcis |
| 🔍 Recherche, PDF, Excel & Excalidraw | Syntaxe de requête, recherche sémantique, lecteurs PDF/Excel, diagrammes |
| 🤖 Assistant IA & Forge | Fournisseurs, éditeur IA, BooksLM, Forge, commandes @ / / |
| 📝 Édition & collaboration | Édition simultanée, curseurs distants, persistance |
| 📱 PWA & hors-ligne | Installation, cache hors-ligne, file de synchro, notifications |
| 🔌 API REST | Authentification, clés API, endpoints, exemples curl, SSE |
| 🧩 Serveur MCP | Brancher Claude Desktop, Cursor, Cline… sur vos vaults |
| 🔒 Authentification & sécurité | Utilisateurs, MFA, permissions par vault, durcissement |
| 🐳 Déploiement Docker | docker-compose, volumes, reverse proxy, mises à jour |
| 🖥️ Desktop (Tauri) | Installation, premier lancement, build depuis les sources, dépannage |
Index complet :
docs/GUIDES/README.md.
📋 Table des matières
- ✨ Fonctionnalités
- 📚 Guides
- 🚀 Prérequis
- ⚡ Installation rapide
- ⚙️ Configuration détaillée
- 🌍 Variables d'environnement
- 🔒 Authentification
- ➕ Ajouter une nouvelle vault
- 🔨 Build & déploiement avec build.sh
- 🖼️ Rendu d'images Obsidian
- 🖥️ Desktop (Tauri) — Application native
- 📖 Utilisation
- 👥 Collaboration temps réel
- 🔌 API
- 🔍 Recherche avancée
- 🔧 Dépannage
- ⚡ Performance
- 🛡️ Sécurité
- 🏗️ Stack technique
- 🏠 Architecture
- 📝 Développement
- 📄 Licence
- 🤝 Support
- 📝 Changelog
✨ Fonctionnalités
- 🤖 AI Editor intégré — Éditeur CodeMirror 6 avec toolbar IA : amélioration, correction, traduction, génération, réécriture personnalisée, toolbox (liste, tableau, frontmatter, canvas) — multi-provider DeepSeek/OpenRouter/Gemini
- 🧩 Serveur MCP & agent IA — Serveur Model Context Protocol intégré (
/mcp) et assistant avec function calling : lisez, cherchez et modifiez vos vaults depuis Claude Desktop, Cursor… avec confirmations two-step, permissions par vault, rate limiting et redaction des secrets (guide) - 👥 Collaboration temps réel — Édition simultanée d'un même document (Yjs/CRDT) : curseurs distants colorés, indicateur de présence, fusion sans conflit, reconnexion automatique et persistance serveur (détail)
- 📖 Guide d'utilisation intégré — Aide complète en FR/EN accessible depuis le menu Options : interface, navigation, recherche, fichiers, IA, sécurité, API & intégrations (OpenAPI, MCP), hors-ligne, collaboration, desktop, plus une section Architecture avec diagramme Mermaid ; téléchargeable en Markdown et PDF dans la langue courante (détail)
- 📱 Éditeur mobile natif — Édition optimisée pour le tactile : barre d'outils Markdown flottante (gras/italique/code/liste/lien), bouton « Coller » persistant (contournement iOS), zoom par pincement et hauteur ajustable, raccourcis swipe (liens entrants / table des matières) et mode lecture plein écran avec navigation entre fichiers (détail)
- 🗺️ Vue graphe interactive — Canvas force-directed avec Barnes-Hut O(n log n), filtres (tag, type), profondeur, mode focus, historique de navigation ←→↑, export PNG, aperçu au survol (Ctrl+click)
- 🗂️ Multi-vault : Visualisez plusieurs vaults Obsidian simultanément
- 🌳 Navigation arborescente : Parcourez vos dossiers et fichiers dans la sidebar ; chaque clic sur un répertoire de l'arbre ouvre un onglet de navigation — chemin, récents, sous-répertoires cliquables, facettes Vaults · Tags · Extensions, tri Pertinence/Date et enregistrement du répertoire — qui coexiste avec vos fichiers ouverts
- 🔍 Recherche avancée : Moteur TF-IDF avec stemming français, normalisation des accents, snippets surlignés, facettes, pagination et tri — plus une recherche sémantique optionnelle (embeddings
all-MiniLM-L6-v2, fusion hybride TF-IDF + RRF) activable via le toggle~(détail) - 💡 Autocomplétion intelligente : Suggestions de fichiers, tags et historique avec navigation clavier
- 🧩 Syntaxe de requête : Opérateurs
tag:,#,vault:,title:,path:,ext:avec chips visuels - 📜 Historique de recherche : Persisté en localStorage (max 50 entrées, LIFO, dédupliqué)
- 🏷️ Tag cloud : Filtrage par tags extraits des frontmatters YAML
- 🔗 Wikilinks : Les
[[liens internes]]Obsidian sont cliquables - 🖼️ Images Obsidian : Support complet des syntaxes d'images Obsidian avec résolution intelligente
- 🎬 Audio & vidéo : Lecteurs HTML5 intégrés (
.mp3 .wav .flac .mp4 .webm…) avec streaming HTTP Range (lecture, déplacement, plein écran) et lecture persistante (mini-lecteur flottant / mini-fenêtre vidéo, retour au média ou arrêt à tout moment, contrôles écran verrouillé via Media Session), repli téléchargement si le format n'est pas lisible par le navigateur - 🎨 Diagrammes Excalidraw : Visualiseur/éditeur natif des fichiers
.excalidrawet.excalidraw.md(iframe sandboxée, auto-save, thème clair/sombre, texte des diagrammes indexé pour la recherche) - 📊 Tableurs Excel : les fichiers
.xlsxet.xlsms'ouvrent dans un visualiseur dédié — un tableau par feuille avec onglets, en-têtes A1 et édition directe des cellules (PUT /api/file/{vault}/xlsx/save, backup automatique, écriture atomique), plus le téléchargement du fichier d'origine. Le visualiseur rend polices, couleurs, cellules fusionnées et volets figés, et offre navigation et raccourcis clavier (Ctrl+S,Suppr,F2,Ctrl+Origine/Fin,PgPréc/PgSuiv,Ctrl+flèches), barre de formule avec noms de fonctions, zone Nom éditable (« Atteindre »A1:B3), presse-papiers de plage (copier/couper/coller un bloc, depuis ou vers Excel), un menu Mise en forme (gras/italique/souligné, alignements, couleurs, formats de nombre, fusions, volets figés, largeur/hauteur —PUT /api/file/{vault}/xlsx/style), tri/filtre/recherche sur toutes les feuilles, export CSV/Markdown/HTML et impression (sélection ou feuille), édition de la structure (feuilles, lignes, colonnes) et un tableau de bord du classeur (plages nommées, détection graphiques/TCD, stats par feuille) ; un.csvs'édite dans la même grille (RFC 4180) tandis que.xlset.odss'ouvrent en lecture seule. Les classeurs contenant des éléments qu'ObsiGate ne peut pas conserver (valeurs calculées, segments, contrôles de formulaire, signature…) affichent un avertissement et demandent confirmation avant l'enregistrement ; une saisie commençant par=ou@est stockée comme texte sauf activation du boutonf(x), et les écritures concurrentes d'un autre poste sont détectées (If-Match→ « Réessayer »). L'assistant IA peut lister les feuilles, injecter un tableau borné dans son contexte, rechercher dans le classeur, analyser une plage, modifier des cellules et ajouter des lignes — sur.xlsx,.xlsmet.csv. Sur mobile (≤ 768 px), la barre de menus et le ruban sont repliés par défaut — un bouton ☰ les déplie — pour que la grille occupe toute la hauteur d'écran - 🎨 Syntax highlight : Coloration syntaxique des blocs de code
- 🌓 Thème clair/sombre : Toggle persisté en localStorage
- 📡 Synchronisation temps réel : Surveillance automatique des fichiers via watchdog avec mise à jour incrémentale de l'index
- 📡 Server-Sent Events : Notifications SSE pour les changements d'index avec reconnexion automatique
- ➕ Gestion dynamique des vaults : Ajout/suppression de vaults via API sans redémarrage
- 🖥️ Application desktop native : Tauri (Rust) + backend Python embarqué, sans Docker ni navigateur
- 🐳 Docker multi-platform : linux/amd64, linux/arm64, linux/arm/v7, linux/386
- 🔒 Authentification : JWT + Argon2id, sessions persistantes, contrôle d'accès par vault
- 🛡️ Sécurité : Rate limiting, audit log, backup automatique, redaction de secrets, headers CSP, protection path traversal, utilisateur non-root
- ⚡ Performance : Compression GZip, Cache-Control immutable, index inversé incrémental, search sans I/O disque
- ❤️ Healthcheck : Endpoint
/api/healthintégré pour Docker et monitoring
🚀 Prérequis
Système requis
- Docker >= 20.10
- docker-compose >= 2.0
- Espace disque : ~200MB pour l'image Docker
Systèmes supportés
- Linux (Ubuntu, Debian, CentOS, etc.)
- macOS (Intel et Apple Silicon)
- Windows (avec Docker Desktop)
- NAS compatibles Docker (Synology, QNAP, etc.)
⚡ Installation rapide
1. Cloner le dépôt
git clone https://git.dracodev.net/Projets/ObsiGate.git
cd ObsiGate
2. Configurer vos vaults et vos secrets
Éditez docker-compose.yml pour ajouter vos vaults Obsidian :
volumes:
- /chemin/absolu/vers/votre/vault:/vaults/NomDeVotreVault:ro
Important
: Le chemin doit être absolu et le volume en lecture seule (
:ro)
Créez votre fichier .env pour l'authentification et les secrets :
cp .env.example .env
# Éditez .env pour configurer vos mots de passe et options
Ne committez jamais
.env! Il est dans.gitignore. Utilisez.env.examplecomme référence.
3. Lancer l'application
chmod +x build.sh # une seule fois
./build.sh # build + déploiement en une commande
Options utiles :
./build.sh --help,./build.sh --cache(rebuild rapide),./build.sh --build-only(construire sans démarrer).
4. Accéder à l'interface
Ouvrez votre navigateur sur : http://localhost:2020
⚙️ Configuration détaillée
Étape 1 : Préparation des vaults
- Localisez vos vaults Obsidian sur votre système
- Notez les chemins absolus vers chaque dossier
- Vérifiez les permissions : Docker doit pouvoir lire ces dossiers
Étape 2 : Configuration docker-compose.yml
services:
obsigate:
build:
context: .
image: obsigate:latest
container_name: obsigate
restart: unless-stopped
ports:
- "2020:8080" # Port local 2020 → Port conteneur 8080
volumes:
- /home/user/Documents/Obsidian-Recettes:/vaults/Recettes:ro
- /home/user/Documents/Obsidian-IT:/vaults/IT:ro
- ./data:/app/data # Persistance des données d'auth
environment:
- VAULT_1_NAME=Recettes
- VAULT_1_PATH=/vaults/Recettes
- VAULT_2_NAME=IT
- VAULT_2_PATH=/vaults/IT
- OBSIGATE_AUTH_ENABLED=true
- OBSIGATE_ADMIN_USER=admin
env_file:
- .env # Contient OBSIGATE_ADMIN_PASSWORD et autres secrets
Étape 3 : Build & déploiement
chmod +x build.sh
./build.sh
Alternative manuelle :
docker compose build --no-cache
docker compose up -d
Compatibilité Docker : l'image utilise une variante minimale d'
uvicornetfastapi 0.110.3afin d'éviter les dépendances optionnelles natives (watchfiles,uvloop, …) qui peuvent échouer au build sur Alpine, ARM ou i386.
🌍 Variables d'environnement
Les vaults sont configurées par paires VAULT_N_NAME / VAULT_N_PATH (N = 1, 2, 3…) :
| Variable | Description | Exemple |
|---|---|---|
VAULT_1_NAME |
Nom affiché de la vault | Recettes |
VAULT_1_PATH |
Chemin dans le conteneur | /vaults/Obsidian-RECETTES |
VAULT_1_ATTACHMENTS_PATH |
Dossier d'attachements (optionnel) | 06_Boite_a_Outils/6.2_Attachments |
VAULT_1_SCAN_ATTACHMENTS |
Scan d'images au démarrage (défaut : true) | true |
Règles de nommage : lettres, chiffres et tirets uniquement ; pas d'espaces ; le nom doit correspondre au chemin dans le conteneur.
🔒 Authentification
Désactivée par défaut — Compatible avec toutes les installations existantes.
Système optionnel basé sur JWT + Argon2id avec contrôle d'accès par vault.
Activer l'authentification
cp .env.example .env- Éditez
.env:OBSIGATE_AUTH_ENABLED=true OBSIGATE_ADMIN_USER=admin OBSIGATE_ADMIN_PASSWORD=votre_mot_de_passe # Laissez vide = auto-généré (voir logs) # OBSIGATE_SECURE_COOKIES=false # true si derrière HTTPS - Dans
docker-compose.yml:env_file: - .env
Ne mettez jamais de mot de passe dans
docker-compose.yml! Utilisez toujours.env.
Premier démarrage
Si aucun utilisateur n'existe, ObsiGate crée automatiquement un compte admin et affiche le mot de passe une seule fois dans les logs :
docker-compose logs obsigate | grep -A4 "PREMIER"
Gestion des utilisateurs via CLI
# Créer un utilisateur
docker exec obsigate python backend/create_admin.py create alice MonMotDePasse --role user --vaults Recettes IT
# Créer un admin avec accès total
docker exec obsigate python backend/create_admin.py create bob SecretPass --role admin --vaults "*"
# Lister / supprimer
docker exec obsigate python backend/create_admin.py list
docker exec obsigate python backend/create_admin.py delete alice
Interface d'administration
Un compte admin connecté voit une icône 🛡️ dans le header : liste, création/édition/suppression d'utilisateurs, assignation des vaults, activation/désactivation de comptes.
Contrôle d'accès par vault
| Valeur vaults | Accès |
|---|---|
["*"] |
Toutes les vaults (y compris futures) — défaut admin |
["Recettes", "IT"] |
Uniquement ces vaults |
[] |
Aucun accès |
Variables d'environnement d'auth
| Variable | Description | Défaut |
|---|---|---|
OBSIGATE_AUTH_ENABLED |
Activer l'authentification | false |
OBSIGATE_ADMIN_USER |
Nom de l'admin auto-créé | admin |
OBSIGATE_ADMIN_PASSWORD |
Mot de passe admin (vide = auto-généré) | (auto) |
OBSIGATE_SECURE_COOKIES |
Cookie Secure (HTTPS uniquement) |
false |
OBSIGATE_ACCESS_TOKEN_TTL |
Durée de vie token JWT (secondes) | 3600 |
OBSIGATE_REFRESH_TOKEN_TTL |
Durée de vie refresh token (secondes) | 2592000 |
OBSIGATE_LOGIN_MAX_ATTEMPTS |
Tentatives de login max par IP | 10 |
OBSIGATE_ACCOUNT_MAX_ATTEMPTS |
Tentatives de login max par compte | 10 |
OBSIGATE_LOGIN_WINDOW_SECONDS |
Fenêtre de rate limiting (secondes) | 900 |
OBSIGATE_TRUST_PROXY |
Faire confiance à X-Forwarded-For pour l'IP client (reverse proxy) |
false |
OBSIGATE_WEBHOOK_ALLOW_HTTP |
Autoriser les webhooks non HTTPS | false |
OBSIGATE_WEBHOOK_ALLOW_PRIVATE |
Autoriser les webhooks vers des adresses privées/boucle | false |
OBSIGATE_PDF_MAX_SIZE_MB |
Taille max des PDF extraits (text indexation) | 50 |
OBSIGATE_MEDIA_MAX_INLINE_MB |
Taille max pour la lecture audio/vidéo intégrée (au-delà : téléchargement) | 500 |
OBSIGATE_PDF_EXTRACT_TIMEOUT |
Timeout extraction PDF (secondes) | 30 |
OBSIGATE_TAVILY_API_KEY / OBSIGATE_BRAVE_API_KEY / OBSIGATE_SERPAPI_API_KEY / OBSIGATE_EXA_API_KEY |
Fournisseurs de recherche web à clé (essayés avant SearXNG) | — |
OBSIGATE_WEB_PROVIDERS |
Ordre des fournisseurs de recherche (ex. brave,searxng) |
— |
OBSIGATE_WEB_RETRY |
Réessais réseau des outils web (backoff maison) | 1 |
OBSIGATE_WEB_CACHE_TTL |
Durée du cache SQLite des résultats web (secondes, 0 = off) |
900 |
OBSIGATE_GITEA_URL / OBSIGATE_GITEA_TOKEN |
Source connectée Gitea (outil git_list_repos…) |
— |
OBSIGATE_GITHUB_TOKEN |
Jeton GitHub (outil git_list_repos…) |
— |
Ces clés peuvent aussi être saisies depuis l'interface (menu → Configurations → « Sources connectées & recherche ») : la valeur saisie est stockée dans
data/api_keys.jsonet prime sur la variable d'environnement.
Volume pour la persistance
Les données d'auth (users.json, secret.key) sont stockées dans /app/data :
volumes:
- ./data:/app/data # Persistance des utilisateurs et clé JWT
➕ Ajouter une nouvelle vault
Méthode 1 : Édition directe
docker-compose down- Ajoutez le volume :
- /nouveau/chemin/vault:/vaults/NouvelleVault:ro - Ajoutez les variables :
VAULT_4_NAME=NouvelleVault+VAULT_4_PATH=/vaults/NouvelleVault - Redémarrez :
./build.sh
Méthode 2 : Hot-reload (recommandé)
- Ajoutez volume + variables comme ci-dessus
./build.shcurl http://localhost:2020/api/index/reload
Méthode 3 : API dynamique (sans redémarrage)
curl -X POST http://localhost:2020/api/vaults/add \
-H "Content-Type: application/json" \
-d '{"name": "NouvelleVault", "path": "/vaults/NouvelleVault"}'
curl -X DELETE http://localhost:2020/api/vaults/NouvelleVault
🔨 Build & déploiement avec build.sh
Utilisation de base
chmod +x build.sh # une seule fois
./build.sh # build from scratch + démarrage
Options disponibles
| Option | Description |
|---|---|
--help, -h |
Affiche l'aide complète |
--build-only |
Construit l'image sans démarrer le conteneur |
--no-cache |
Rebuild complet sans cache Docker (défaut) |
--cache |
Utilise le cache Docker (plus rapide si peu de changements) |
--progress=plain |
Sortie verbeuse (recommandé pour le debug) |
--progress=tty |
Sortie interactive avec barres de progression |
Ce que fait le script
- Vérifie Docker et Docker Compose (versions)
- Valide
docker-compose.yml(présence + syntaxe) - Vérifie chaque volume monté (avertit si la source n'existe pas)
- Construit l'image Docker (multi-stage, ~180MB)
- Démarre le conteneur (
docker compose up -d) - Affiche statut + logs en temps réel
Arrêter / redémarrer
docker compose down # Arrêter
docker compose up -d # Redémarrer sans rebuild
docker compose logs -f # Voir les logs
🖼️ Rendu d'images Obsidian
ObsiGate supporte toutes les syntaxes d'images Obsidian avec résolution intelligente multi-stratégies.
Syntaxes supportées
- Markdown standard avec attributs HTML :
[<img width="180" src="path/to/image.svg"/>](https://example.com) - Wiki-link embed chemin complet :
![[06_Boite_a_Outils/6.2_Attachments/image.svg]] - Wiki-link embed nom de fichier :
![[image.svg]] - Markdown standard :

Résolution intelligente (7 stratégies, par priorité)
- Chemin absolu
- Dossier d'attachements configuré (
VAULT_N_ATTACHMENTS_PATH) - Index de démarrage (match unique)
- Même répertoire que le fichier markdown
- Racine du vault
- Index de démarrage (match le plus proche)
- Fallback : placeholder stylisé
[image not found: filename.ext]
Visionneuse & arborescence
Les images sont de plein droit des fichiers du vault : elles apparaissent dans
l'arborescence, sont indexées (nom + métadonnées, jamais les octets) et
s'ouvrent dans une visionneuse dédiée — zoom molette 0,1×–8×, pan au
glisser, double-clic pour réinitialiser, navigation ←/→ entre les images du
dossier (avec pellicule de miniatures WebP), panneau de métadonnées, lightbox
plein écran, ouverture de l'original et téléchargement. Le filtre de recherche
ext:png/ext:jpg est disponible. Formats décodables : PNG, JPEG, GIF, WebP,
BMP, ICO, SVG (SVG servi avec une politique CSP sandbox). HEIC/HEIF
(iPhone) n'est pas décodable par les navigateurs et n'est pas pris en charge.
Configuration
environment:
- VAULT_1_NAME=MonVault
- VAULT_1_PATH=/vaults/MonVault
- VAULT_1_ATTACHMENTS_PATH=Assets/Images # Chemin relatif
- VAULT_1_SCAN_ATTACHMENTS=true # Activer le scan (défaut)
Rescan manuel
curl -X POST http://localhost:2020/api/attachments/rescan/MonVault
🖥️ Desktop (Tauri) — Application native
📖 Guide complet : Desktop (Tauri)
ObsiGate Desktop est une application native construite avec Tauri (Rust + webview système). Elle embarque le backend Python et le frontend dans un exécutable standalone — zéro Docker, zéro ligne de commande.
🚧 Version 2.0.0 — binaires en cours de stabilisation. Pour l'instant, le build depuis les sources est recommandé.
Fonctionnalités desktop natives
| Fonctionnalité | Web | Desktop |
|---|---|---|
| Accès fichiers local | Via upload | Natif (sélecteur dossier) |
| Thème système | Manuel | Auto (suit OS dark/light) |
| Notifications | Service Worker | Natif OS |
Associations .md |
❌ | ✅ « Ouvrir avec ObsiGate » |
| Tray icon | ❌ | ✅ Barre des tâches |
| Auto-update | ❌ | ✅ Vérifie les releases Gitea |
| Mode hors-ligne | Limité | Complet (backend local) |
Téléchargement (binaires pré-buildés)
Les releases sont publiées sur Gitea :
| Plateforme | Format |
|---|---|
| Linux | .deb + .AppImage |
| Windows | .msi + .exe (NSIS) |
# Linux — .deb (Debian/Ubuntu/Deepin)
sudo dpkg -i obsigate_2.0.0_amd64.deb
# Linux — .AppImage (toute distrib)
chmod +x ObsiGate_2.0.0_amd64.AppImage && ./ObsiGate_2.0.0_amd64.AppImage
REM Windows : double-cliquer sur ObsiGate_2.0.0_x64.msi (ou le setup NSIS)
Démarrage
- Lancez l'application depuis le menu ou la ligne de commande
- Le backend Python démarre automatiquement sur
127.0.0.1:17890(splash « Démarrage… » pendant le boot) - La fenêtre s'ouvre et charge l'interface ObsiGate
- Premier lancement : sélectionnez le dossier de vos vaults Obsidian via le sélecteur natif
- Pour fermer : icône tray → Quitter (arrêt propre du backend)
Build depuis les sources
Guide détaillé : desktop/README.md.
Prérequis communs
| Outil | Version | Installation |
|---|---|---|
| Rust (cargo) | ≥ 1.75 | rustup |
| Tauri CLI | ≥ 2.0 | cargo install tauri-cli |
| Git | — | — |
| Dépendances système Linux | — | sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev |
Important — staging :
tauri.conf.jsonembarquebackend/**etfrontend/**depuis le dossierdesktop/. Les scripts de build copient automatiquement../backendet../frontenddansdesktop/avantcargo tauri build. Sans ce staging, le build échoue avec « glob pattern backend/**/* path not found ».
🪟 Windows — build-windows.bat
REM Prérequis (via Scoop) : rustup, curl, git
scoop install rustup curl git
rustup default stable
cargo install tauri-cli
cd desktop
build-windows.bat
Étapes du script :
- Tue les processus Python résiduels (
taskkill /F /IM python.exe) - Télécharge Python 3.11 embed (python.org) →
desktop\python-embed\+ activation de pip (python311._pth) pip install -r ..\backend\requirements.txtdans l'embed- Staging : copie
..\backendet..\frontenddansdesktop\ cargo tauri build --target x86_64-pc-windows-msvc --bundles nsis- Copie
python-embedà côté de l'exécutable (target\x86_64-pc-windows-msvc\release\) pour le mode dev local - Nettoie les dossiers stagés
→ Artefact : desktop\target\x86_64-pc-windows-msvc\release\bundle\nsis\ObsiGate_2.0.0_x64-setup.exe
🐧 Linux — build-linux.sh
cd desktop
chmod +x build-linux.sh
./build-linux.sh
Étapes du script :
- Vérifie Rust + Tauri CLI, installe les dépendances système (apt)
- Crée un venv Python
desktop/python-embed/venv+pip install -r ../backend/requirements.txt - Staging : copie
../backendet../frontenddansdesktop/ cargo tauri build --target x86_64-unknown-linux-gnu --bundles deb,appimage- Copie le runtime (
python-embed/,backend/,frontend/) à côté de l'exécutable
→ Artefacts :
desktop/target/x86_64-unknown-linux-gnu/release/bundle/deb/obsigate_2.0.0_amd64.debdesktop/target/x86_64-unknown-linux-gnu/release/bundle/appimage/ObsiGate_2.0.0_amd64.AppImage
🤖 Builds CI/CD — artefacts automatiques
Oui — le workflow .gitea/workflows/desktop-build.yml construit les binaires desktop à chaque push sur main touchant desktop/**, frontend/** ou backend/** (et manuellement via workflow_dispatch), sur des runners self-hosted :
| Job | Runner | Artefacts (conservés 30 jours) |
|---|---|---|
build-windows |
[self-hosted, windows, desktop] |
desktop/target/release/bundle/msi/*.msi |
build-linux |
[self-hosted, linux, desktop] |
*.AppImage + *.deb |
- Les artefacts sont téléchargeables depuis la page Actions du run Gitea.
- La publication en Gitea Release est prévue sur les tags
v*(étapePublish to Gitea Release). - Le workflow web
.gitea/workflows/ci.ymlgère de son côté lint → tests → sécurité → build Docker → e2e Playwright.
Architecture Desktop
┌────────────────────────────────────────────┐
│ Tauri (Rust) │
│ ├─ Webview (webview système) │
│ │ └─ Frontend (HTML/JS/CSS) │
│ └─ Sidecar Python │
│ └─ uvicorn backend.main:app │
│ └─ port 127.0.0.1:17890 │
└────────────────────────────────────────────┘
Cycle de vie : Tauri spawn le backend Python → health check → splash de démarrage → redirection vers la webview. À la fermeture : kill propre du backend.
📖 Utilisation
Interface web
- Navigation : Cliquez sur les vaults dans la sidebar pour les développer
- Recherche : Utilisez la barre de recherche pour chercher dans toutes les vaults
- Tags : Cliquez sur les tags pour filtrer les contenus
- Wikilinks : Les liens
[[page]]sont cliquables et navigables - Images : Toutes les syntaxes d'images Obsidian sont rendues automatiquement
- Thème : Basculez entre thème clair/sombre avec l'icône 🌙/☀️
Raccourcis clavier
| Action | Raccourci |
|---|---|
| Recherche | Ctrl + K ou / |
| Toggle thème | Ctrl + T |
| Focus recherche | Esc |
👥 Collaboration temps réel
📖 Guide complet : Édition & collaboration
Plusieurs utilisateurs peuvent éditer le même document markdown simultanément (façon Google Docs) :
- Fusion sans conflit grâce à Yjs (CRDT) : deux personnes peuvent taper au même endroit, aucune modification n'est perdue.
- Curseurs distants colorés et sélections visibles dans CodeMirror, avec le nom de chaque utilisateur.
- Indicateur de présence dans l'en-tête de l'éditeur (avatars + statut de connexion).
- Reconnexion automatique (backoff exponentiel) : l'état est fusionné au retour.
- Persistance serveur : le document est écrit sur disque 2 s après la dernière modification.
- Transport : WebSocket
ws(s)://<hôte>/ws/collab/{vault}/{chemin}, authentifié par cookieaccess_token(ou?token=) et soumis au contrôle d'accès par vault.
Aucune configuration n'est nécessaire : ouvrez le même fichier dans deux navigateurs (ou deux fenêtres) pour voir la collaboration en action.
🔌 API
📖 Guide complet : API REST · Serveur MCP
ObsiGate expose une API REST complète :
| Endpoint | Description | Méthode | Auth |
|---|---|---|---|
/api/health |
Health check (status, version, stats) | GET | Non |
/api/auth/status |
Statut auth (activé, utilisateurs présents) | GET | Non |
/api/auth/login |
Connexion (access token + cookie refresh) | POST | Non |
/api/auth/refresh |
Renouveler l'access token via cookie refresh | POST | Cookie |
/api/auth/logout |
Déconnexion + révocation refresh token | POST | Oui |
/api/auth/me |
Infos utilisateur courant | GET | Oui |
/api/auth/change-password |
Changer son mot de passe | POST | Oui |
/api/auth/admin/users |
Lister / créer des utilisateurs | GET/POST | Admin |
/api/auth/admin/users/{u} |
Modifier / supprimer un utilisateur | PATCH/DELETE | Admin |
/api/vaults |
Liste des vaults (filtrée par permissions) | GET | Oui |
/api/browse/{vault}?path= |
Navigation dans les dossiers | GET | Oui |
/api/file/{vault}?path= |
Contenu rendu d'un fichier | GET | Oui |
/api/file/{vault}/raw?path= |
Contenu brut d'un fichier | GET | Oui |
/api/file/{vault}/download?path= |
Téléchargement d'un fichier | GET | Oui |
/api/file/{vault}/save?path= |
Sauvegarder un fichier | PUT | Oui |
/api/file/{vault}?path= |
Supprimer un fichier | DELETE | Oui |
/api/search/advanced |
Recherche avancée TF-IDF (+ semantic=true pour l'hybride) |
GET | Oui |
/api/suggest / /api/tags/suggest |
Autocomplétion | GET | Oui |
/api/tags?vault= |
Tags uniques avec compteurs | GET | Oui |
/api/index/reload |
Force un re-scan des vaults | GET | Admin |
/api/events |
Flux SSE temps réel | GET | Oui |
/api/vaults/add / /api/vaults/{name} |
Gestion dynamique des vaults | POST/DELETE | Admin |
/api/image/{vault}?path= |
Servir une image | GET | Oui |
/api/media/{vault}/thumb?path=&size= |
Miniature WebP (cache disque) | GET | Oui |
/api/config |
Lire / écrire la configuration | GET/POST | Oui/Admin |
/api/diagnostics |
Statistiques index et mémoire | GET | Admin |
Quand
OBSIGATE_AUTH_ENABLED=false, tous les endpoints sont accessibles sans token. Tous les endpoints exposent des schémas Pydantic documentés ; doc interactive sur/docs(Swagger UI).
Exemples :
curl http://localhost:2020/api/health
curl http://localhost:2020/api/vaults
curl "http://localhost:2020/api/search/advanced?q=recette%20tag:cuisine&vault=all&limit=20&offset=0&sort=relevance"
curl "http://localhost:2020/api/suggest?q=piz&vault=all"
curl "http://localhost:2020/api/file/Recettes?path=pizza.md"
🔍 Recherche avancée
📖 Guide complet : Recherche, PDF, Excel & Excalidraw
Syntaxe de requête
| Opérateur | Description | Exemple |
|---|---|---|
tag:<nom> |
Filtrer par tag | tag:recette docker |
#<nom> |
Raccourci tag | #linux serveur |
vault:<nom> |
Filtrer par vault | vault:IT kubernetes |
title:<texte> |
Filtrer par titre | title:pizza |
path:<texte> |
Filtrer par chemin | path:recettes/soupes |
ext:<type> |
Filtrer par type de fichier | ext:md kubernetes |
"phrase exacte" |
Recherche de phrase | tag:"multi mots" |
Les opérateurs sont combinables : tag:linux vault:IT ext:md serveur web.
Support PDF
Les fichiers PDF de vos vaults s'affichent en ligne dans le navigateur via le visualiseur PDF natif (iframe + <embed>).
Le visualiseur streame le fichier via HTTP Range (206 Partial Content) — les gros PDF se chargent progressivement.
Le texte est extrait à l'indexation (pypdf / pymupdf) — le contenu PDF est donc recherchable via la recherche full-text.
Filtrez avec ext:pdf pour restreindre les résultats aux PDF.
Les métadonnées (pages, titre, auteur) sont disponibles via GET /api/file/{vault}/pdf/info sans transférer le document.
Limitations : pas d'OCR (les PDF scannés ne sont pas recherchables), pas d'annotation, pas d'édition du PDF lui-même.
Diagrammes Excalidraw
Les fichiers .excalidraw et .excalidraw.md s'ouvrent dans un éditeur visuel Excalidraw complet, intégré dans une iframe sandboxée — dessinez, modifiez et sauvegardez sans quitter ObsiGate.
Les modifications sont sauvegardées automatiquement (2 s) ou avec Ctrl+S ; l'éditeur suit le thème clair/sombre.
Le texte des éléments du diagramme est extrait à l'indexation : il est donc recherchable via la recherche full-text (ext:excalidraw).
Les fichiers créés avec le plugin Obsidian Excalidraw (y compris le format .excalidraw.md compressé) sont compatibles.
Raccourcis clavier
| Raccourci | Action |
|---|---|
Ctrl+K / Cmd+K |
Focaliser la barre de recherche |
/ |
Focaliser la recherche (hors champ texte) |
↑ / ↓ |
Naviguer dans les suggestions |
Enter |
Sélectionner la suggestion active ou lancer la recherche |
Escape |
Fermer les suggestions / quitter la recherche |
Fonctionnalités
- TF-IDF : scoring par fréquence pondérée des termes
- Boost titre : correspondances dans le titre ×3
- Normalisation des accents :
resumetrouverésumé - Snippets surlignés (
<mark>), facettes (compteurs par vault/tag), pagination (50/page), tri pertinence/date, chips de filtres, historique (50 recherches) - Recherche sémantique (optionnelle) : le toggle
~(ouAlt+S) fusionne le classement TF-IDF avec un classement par embeddings (RRF). Fonctionne sans dépendance avec un provider de hachage ; installezbackend/requirements-semantic.txtet/ou renseignezOBSIGATE_EMBEDDING_*pour de vrais embeddingsall-MiniLM-L6-v2. Voir docs/features/semantic-search.md.
🔧 Dépannage
Port déjà utilisé :
sudo netstat -tulpn | grep 2020
# Changer le port dans docker-compose.yml : ports: - "2021:8080"
Vault non trouvée : chemins absolus, permissions de lecture, redémarrer le conteneur après modification.
Build échoue :
docker system prune -f
docker compose down
./build.sh --progress=plain
# Si l'échec persiste :
./build.sh --progress=plain 2>&1 | tee build.log
Logs pour debugging :
docker compose logs -f obsigate
docker compose logs --tail=100 obsigate
Desktop : les logs du backend sont dans %APPDATA%\ObsiGate\logs\backend.log (Windows) / ~/.config/obsigate/logs/backend.log (Linux).
⚡ Performance
| Métrique | Estimation |
|---|---|
| Indexation | ~1–2s pour 1 000 fichiers markdown |
| Recherche avancée | < 10ms pour la plupart des requêtes (index inversé + TF-IDF) |
| Résolution wikilinks | O(1) via table de lookup |
| Mémoire | ~80–150MB par 1 000 fichiers (contenu capé à 100 KB/fichier) |
| Image Docker | ~180MB (multi-stage) |
| CPU | Non-bloquant ; recherche offloadée sur thread pool dédié |
Paramètres recommandés par taille de vault
| Taille | Fichiers | search_workers |
prefix_max_expansions |
max_content_size |
|---|---|---|---|---|
| Petit | < 500 | 1 | 50 | 100 000 |
| Moyen | 500–5 000 | 2 | 50 | 100 000 |
| Grand | 5 000+ | 4 | 30 | 50 000 |
Configurables via l'interface (Settings) ou l'API /api/config.
Optimisations clés
- Index inversé avec set-intersection + prefix matching par recherche binaire
- ThreadPoolExecutor : recherche CPU-bound hors de l'event loop asyncio
- InvertedIndex incrémental : hooks
add_document/remove_document, plus de rebuild O(N) - Compression GZip (~70% de bande passante économisée) + Cache-Control immutable (1 an)
- Race condition guard (
currentSearchId+ AbortController), progress bar, timeout 30s - Rendu Markdown singleton, debounced icon rendering, recherche sans I/O disque
🛡️ Sécurité
📖 Guide complet : Authentification & sécurité
- Path traversal : tous les endpoints fichier valident que le chemin résolu reste dans la vault
- Rate limiting : 10 tentatives de login max par IP sur 15 minutes + lockout par compte (5 tentatives)
- Audit log : écritures/suppressions/config journalisées dans
data/audit.log(JSON lines, rotation 10 MB) - Backup automatique : chaque modification/suppression sauvegardée dans
.obsigate-backup/avec timestamp - Secret redaction : masquage automatique des JWT, mots de passe, clés API (OpenAI, GitHub, Google, AWS, Slack, Stripe…), tokens dans les aperçus — cliquez sur un masque pour copier la valeur
- Utilisateur non-root : conteneur Docker sous
obsigate(UID 1000) - Volumes read-only : vaults montées en
:ropar défaut - Secrets dans
.env: jamais dansdocker-compose.yml - Atomic writes : tmp+replace pour users.json, shares.json, webhooks.json
🏗️ Stack technique
- Backend : Python 3.11 + FastAPI 0.110 + Uvicorn
- Auth : python-jose (JWT HS256) + argon2-cffi (Argon2id)
- File Watcher : watchdog 4.x (inotify natif + fallback polling)
- Frontend : Vanilla JS + HTML + CSS (zéro framework, zéro build)
- Rendu Markdown : mistune 3.x
- PDF Export : WeasyPrint 60+
- Desktop : Tauri v2 (Rust) + Python embarqué
- Image Docker : python:3.11-slim (multi-stage)
- Stockage utilisateurs : JSON local (
data/users.json) — aucune base de données - Architecture : SPA + API REST + SSE
🏠 Architecture
┌─────────────────┐ ┌─────────────────────────────────────────┐
│ Navigateur │◄───►│ FastAPI (backend/main.py) │
│ (SPA) │ REST │ ┌──────────────┐ ┌──────────────┐ │
│ │ │ │ indexer.py │ │ search.py │ │
│ app.js │ │ │ (scan+cache) │ │ (in-memory) │ │
│ style.css │ │ └───────┬────── └──────┬───────┘ │
│ index.html │ │ │ │ │
└─────────────────┘ │ ┌───┴──────────────┴───┐ │
│ │ Index en mémoire │ │
│ │ (fichiers, tags, │ │
│ │ contenu, lookup) │ │
│ └───────────────────────┘ │
└─────────────────────────────────────────┘
Flux de données :
- Au démarrage,
indexer.pyscanne tous les vaults en parallèle (thread pool, non-bloquant) - Contenu, tags (YAML + inline) et métadonnées mis en cache en mémoire
- Table de lookup O(1) pour la résolution des wikilinks
watcher.pysurveille les fichiers (watchdog natif ou polling)- Modifications → mise à jour incrémentale de l'index
- Changements notifiés au frontend via SSE
- Recherche sur l'index mémoire (zéro I/O disque)
- Le frontend SPA communique via REST + SSE
📝 Développement
🧪 Tests et CI — règles obligatoires (avant chaque push)
⚠️ Règle absolue — contributeurs humains et agents IA : ne jamais faire de
git pushsans avoir exécuté localement la séquence complète ci-dessous avec 100 % de succès. Le push ne sert pas à découvrir les échecs : la CI est un filet de sécurité, pas un outil de diagnostic.
Vérifications locales avant commit
| Étape | Commande | Job CI équivalent |
|---|---|---|
| Lint backend | ruff check backend/ |
lint |
| Validation des imports frontend | node tests/frontend/validate-imports.mjs |
lint |
| Tests unitaires frontend | node tests/frontend/unit.test.mjs |
lint |
| Tests backend | pytest tests/ -q |
test |
| E2E Playwright | npm run test:e2e (~10 min) |
e2e |
Tests E2E locaux (npm run test:e2e)
Le script scripts/run-e2e-local.sh reproduit fidèlement les conditions du
job CI e2e (.gitea/workflows/ci.yml) :
- backend démarré nativement (venv
.venv-e2e, Python 3.11 viauv) ; - authentification désactivée (
OBSIGATE_AUTH_ENABLED=false) ; - fixtures
test_vault(TestVault) ettest_dir(TestDir) ; - port
2029(baseURL deplaywright.config.ts) ; - projet Playwright
chromium-desktopuniquement (comme la CI).
Prérequis : uv, Node.js ≥ 20, navigateurs Playwright
(npx playwright install chromium). Le venv est créé automatiquement au
premier lancement. Docker n'est pas nécessaire.
npm run test:e2e # suite complète
bash scripts/run-e2e-local.sh --headed # navigateur visible
bash scripts/run-e2e-local.sh -g "reset panes" # filtre sur un test
Sous Windows, si bash n'est pas exploitable (WSL indisponible, git-bash
bloqué par une politique de contrôle d'application), utiliser le lanceur
PowerShell équivalent :
npm run test:e2e:ps
pwsh -File scripts/run-e2e-local.ps1 -PlaywrightArgs @('-g','reset panes')
La suite doit se terminer sur tous les tests passant (60 actuellement), sans échec ni dépendance aux retries. En cas d'échec : corriger et relancer localement jusqu'à 100 %, puis seulement commiter.
Règles d'écriture des tests (leçon apprise)
- Vérifier chaque sélecteur dans le DOM réel avant de l'utiliser dans un
test. Bug réel rencontré : un test ciblait
#cp-inputalors que l'input de la palette porte uniquement la classe.cp-input(aucun id) — le test ne pouvait passer dans aucun environnement. - Tout test nouveau ou modifié doit être exécuté localement (au minimum
avec
-g "nom du test") avant le push. - Pas de contournements qui masquent une instabilité (
waitForTimeoutarbitraires, fallback silencieux) : traiter la cause racine.
Commits et push
- Message de commit : sujet à l'impératif ≤ 50 caractères ; corps (72 col.) uniquement s'il apporte une information utile.
- Un commit = un changement logique (ne pas mêler fix et refactoring).
- Push uniquement quand les 5 étapes locales sont vertes. Pipeline CI :
lint → test → security → build → e2e.
Structure du projet
ObsiGate/
├── backend/ # API FastAPI
│ ├── main.py # Endpoints, Pydantic models, rendu markdown
│ ├── indexer.py # Scan des vaults, index en mémoire, lookup table
│ ├── search.py # Moteur de recherche fulltext avec scoring
│ ├── watcher.py # Surveillance fichiers (watchdog + debounce)
│ ├── auth/ # Module d'authentification (JWT + Argon2id)
│ └── create_admin.py # CLI gestion utilisateurs
├── frontend/ # Interface web (Vanilla JS, zéro framework)
│ ├── index.html # Page SPA + écran de login + splash de boot
│ ├── js/ # Modules ES (app, viewer, editor, graph, …)
│ └── style.css # Styles (CSS variables, thèmes, responsive)
├── desktop/ # Application native Tauri (Rust + Python embarqué)
│ ├── src/main.rs # Shell natif : cycle de vie backend, tray, menus
│ ├── build-windows.bat
│ └── build-linux.sh
├── data/ # Données persistantes (créé au démarrage)
├── Dockerfile # Multi-stage, healthcheck, non-root
├── docker-compose.yml # Déploiement avec healthcheck et auth env vars
├── build.sh # Build & déploiement automatisé
└── docs/ # ROADMAP, guides, audits
Contribuer
Voir docs/CONTRIBUTING.md pour les standards de code et docs/DELIVERY_WORKFLOW.md pour la méthode de livraison obligatoire.
📄 Licence
Ce projet est sous licence MIT — voir le fichier LICENSE pour les détails.
🤝 Support
- Issues : git.dracodev.net/Projets/ObsiGate/issues
- Documentation : git.dracodev.net/Projets/ObsiGate/wiki
📝 Changelog
Consultez le CHANGELOG.md pour l'historique complet de toutes les versions (v1.0.0 → v2.57.0).
Projet : ObsiGate | Version : 2.57.0 | Dernière mise à jour : Septembre 2026
