# ObsiGate — Roadmap > **Version :** 2.0.0-dev | **Dernière mise à jour :** 2026-06-05 > Voir aussi [CHANGELOG.md](./CHANGELOG.md), [AUDIT_TECHNIQUE.md](./docs/AUDIT_TECHNIQUE_2026-05-27.md) --- ## Légende | Icône | Signification | |---|---| | ✅ | Terminé | | 🔵 | En cours | | ⚪ | Prévu / Backlog | | 🔴 Impact | Critique / Bloquant | | 🟡 Impact | Utile / Attendu | | 🟢 Impact | Nice-to-have / Confort | --- ## ✅ Complété (v1.0.0 → v2.0.0-dev) ### Fondations (v1.0.0 → v1.4.0) | # | Feature | Effort | Impact | |---|---|---|---| | 1 | FastAPI backend — CRUD fichiers, vaults, recherche full-text | 5j | 🔴 | | 2 | Moteur TF-IDF + stemming français (`snowballstemmer`) | 2j | 🔴 | | 3 | Watchdog — indexation temps réel avec debounce | 1j | 🟡 | | 4 | Interface SPA vanilla JS — sidebar, viewer, éditeur CodeMirror | 8j | 🔴 | | 5 | Sécurité : JWT + Argon2id, rate limiting, audit log, CSP headers | 3j | 🔴 | | 6 | Protection path traversal, utilisateur non-root Docker | 0.5j | 🔴 | | 7 | Compression GZip SSE-safe, Cache-Control immutable | 0.5j | 🟢 | | 8 | PWA : manifest, service worker, mode standalone | 1j | 🟡 | ### UX & Productivité (v1.5.0 → v1.6.0) | # | Feature | Effort | Impact | |---|---|---|---| | 9 | Publication publique de documents (lien partageable, token) | 1j | 🟡 | | 10 | Webhooks HTTP avec signature HMAC-SHA256 | 1j | 🟡 | | 11 | Dashboard statistiques (fichiers, tags, taille, vaults) | 0.5j | 🟡 | | 12 | Gestion des conflits Syncthing | 0.5j | 🟢 | | 13 | Index inversé incrémental (hook pattern) | 1j | 🟡 | | 14 | Backlinks panel dans le viewer | 0.5j | 🟡 | | 15 | Fichiers non-supportés → UI download | 0.3j | 🟢 | | 16 | Redaction de secrets (`secret_redactor.py`) | 0.5j | 🟡 | | 17 | Backup automatique avant écriture, restauration | 1j | 🟡 | | 18 | Vue graphe — Barnes-Hut, focus, plein écran, export PNG | 3j | 🟡 | | 19 | Header flat design, sticky panels, navigation historique ← → ↑ | 1j | 🟢 | | 20 | Ctrl+survol → aperçu contenu formaté | 0.5j | 🟢 | ### Architecture (v1.5.1) | # | Feature | Effort | Impact | |---|---|---|---| | 21 | Split `app.js` (8 875 lignes) → 16 modules ES | 3j | 🔴 | | 22 | Validateur imports/exports CI + tests unitaires frontend Node.js | 0.5j | 🟡 | ### CI/CD & Qualité (v1.6.0) | # | Feature | Effort | Impact | |---|---|---|---| | 23 | Pipeline Gitea Actions : lint → test → security → build | 1j | 🔴 | | 24 | Ruff (0 erreur) + Mypy (0 erreur) + Bandit SAST + Pip-audit | 0.5j | 🟡 | | 25 | Pytest : 285 tests, 63% coverage | 3j | 🔴 | ### AI Editor (v1.7.0) | # | Feature | Effort | Impact | |---|---|---|---| | 26 | Toolbar : Edit, Tone, Translate, Generate, Rewrite, Toolbox | 2j | 🟡 | | 27 | Multi-provider : DeepSeek, OpenRouter, Gemini | 1j | 🟡 | | 28 | 16 endpoints REST `/api/ai/{action}` + backend `ai.py` / `ai_routes.py` | 2j | 🟡 | | 29 | Auto-save silencieux (2s debounce), loading toasts | 0.5j | 🟢 | ### Fonctionnalités avancées (v1.8.0 → v1.9.0) | # | Feature | Effort | Impact | |---|---|---|---| | 30 | Export PDF via WeasyPrint (endpoint API + lien share public) | 1j | 🟡 | | 31 | Palette de commandes `Ctrl+Alt+Space` | 1j | 🟡 | | 32 | Barre d'outils mobile + palette fichiers/commandes 📱 | 1j | 🟡 | | 33 | Drag & drop de fichiers | 1j | 🟡 | | 34 | Filtres recherche avancés : `created:`, `modified:`, `size:` | 0.5j | 🟡 | | 35 | Fichiers récents par vault | 0.5j | 🟡 | | 36 | Indicateur AI Actif (header + toast) | 0.3j | 🟢 | | 37 | Page d'accueil de vault (liste récursive par date, style recherche) | 0.5j | 🟡 | | 38 | Indexation non-bloquante (background thread) | 0.5j | 🟡 | | 39 | Git tags semver (v1.8.0, v1.9.0) | 0.2j | 🟢 | ### Gestion des Backups (v1.9.0) | # | Feature | Effort | Impact | |---|---|---|---| | 40 | Diff viewer : unifié + côte à côte, restauration depuis backup | 1j | 🟡 | | 41 | Gestionnaire de backups : page complète, filtre, suppression, purge | 1.5j | 🟡 | | 42 | Purge par vault avec confirmation, preview contenu (100 Ko) | 0.5j | 🟡 | | 43 | Compression gzip des vieux backups (niveau 6) | 0.5j | 🟢 | | 44 | Backup automatique périodique (`POST /api/backups/auto`) | 1j | 🟡 | | 45 | Restauration depuis le gestionnaire (extraction timestamp, confirmation) | 0.5j | 🟡 | | 46 | Auto-nettoyage : `max_backups_per_file` (défaut 10) | 0.5j | 🟡 | ### Mermaid.js (v2.0.0-dev) | # | Feature | Effort | Impact | |---|---|---|---| | 47 | CDN mermaid@11, `securityLevel: strict`, `startOnLoad: false` | 0.5j | 🟡 | | 48 | `renderMermaidBlocks()` — parse, rendu SVG, bloc d'erreur stylisé | 1j | 🟡 | | 49 | 22 templates (flowchart → sankey-beta) | 0.5j | 🟡 | | 50 | Live preview dans l'éditeur (debounce 500ms, panneau `#mermaid-live-preview`) | 1j | 🟡 | | 51 | Thème dark/light synchronisé, export SVG + PNG | 1j | 🟡 | | 52 | Rendu inline dans le viewer Markdown | 0.5j | 🟡 | | 53 | Zoom molette + drag + boutons +/- | 0.5j | 🟢 | | 54 | Mode plein écran avec header bar (icônes zoom, copy, download, close) | 0.5j | 🟢 | | 55 | Focus mode — clic diagramme → panneau latéral 480px | 0.3j | 🟡 | | 56 | Pré-processeur Obsidian (`[[liens]]`, `![[img]]`, `==highlight==`) | 0.3j | 🟡 | | 57 | Header bar : type de diagramme + toggle Code/Preview + copy SVG + download PNG | 1j | 🟡 | --- ## 🔵 En cours (P1) ### 58. Tests E2E Playwright - **Effort :** 2-3 jours | **Impact :** 🔴 - **Description :** Tests navigateur automatisés pour les flows critiques : login, navigation vault, recherche full-text, ouverture/édition/sauvegarde de fichier, rendu Mermaid, export PDF. - **Sous-tâches :** - [ ] Installation Playwright + config (`playwright.config.ts`) - [ ] Fixtures : vault de test avec 5-10 fichiers .md variés - [ ] Test : login admin → dashboard → liste vaults - [ ] Test : navigation sidebar → ouverture fichier → viewer Markdown - [ ] Test : recherche full-text → résultats triés par pertinence - [ ] Test : éditeur CodeMirror → modification → Ctrl+S → backup créé - [ ] Test : rendu Mermaid (flowchart + sequence) dans le viewer - [ ] Test : export PDF → téléchargement vérifié - [ ] Test : mode sombre → toggle → persistence localStorage - [ ] Test : responsive mobile → toolbar + sidebar repliée - [ ] Intégration CI : job `e2e` dans `.gitea/workflows/ci.yml` --- ## ⚪ Backlog — Priorité 3 (P3) ### 59. Mode hors-ligne PWA complet - **Effort :** 3-4 jours | **Impact :** 🟡 - **Description :** Service worker avancé avec IndexedDB pour permettre la navigation et la recherche en mode hors-ligne, avec file de synchronisation au retour réseau. - **Sous-tâches :** - [ ] IndexedDB : stockage local de l'index des fichiers (paths, titles, tags) - [ ] Moteur de recherche offline via IndexedDB (cursor + filtre) - [ ] Cache des fichiers markdown récemment ouverts (derniers 50) - [ ] Stratégie de cache : Network First avec fallback IndexedDB - [ ] File de synchronisation : modifications offline → appliquées au retour réseau - [ ] UI indicateur : badge « Hors-ligne » + compteur de modifications en attente - [ ] Gestion des conflits : détection et résolution manuelle (choix version locale vs serveur) ### 60. OAuth2 / OIDC — Authentification SSO - **Effort :** 2-3 jours | **Impact :** 🟡 - **Description :** Support de fournisseurs OAuth2/OIDC externes pour permettre l'authentification via Google, GitHub, ou tout provider compatible. Complément à l'auth JWT existante (pas de remplacement). - **Sous-tâches :** - [ ] Configuration par provider : `OBSIGATE_OAUTH_GOOGLE_CLIENT_ID`, `OBSIGATE_OAUTH_GITHUB_CLIENT_ID`, etc. - [ ] Endpoint `GET /api/auth/oauth/login?provider=google` → redirection - [ ] Endpoint `GET /api/auth/oauth/callback` → échange code → token OIDC → création/liaison compte local - [ ] Mapping roles : config `OBSIGATE_OAUTH_DEFAULT_ROLE` (défaut `user`) - [ ] UI : boutons « Se connecter avec Google / GitHub » sur la page login - [ ] Sécurité : state parameter anti-CSRF, PKCE, nonce validation - [ ] Stockage : liaison `oauth_provider` + `oauth_sub` dans `users.json` ### 61. Plugins système — Extensions utilisateur - **Effort :** 4-5 jours | **Impact :** 🟢 - **Description :** Système de plugins permettant aux utilisateurs d'étendre ObsiGate avec des renderers personnalisés, des opérateurs de recherche, et des hooks d'UI. Inspiré du modèle de plugins Obsidian. - **Sous-tâches :** - [ ] Spécification du format de plugin : `plugin.json` (name, version, hooks, permissions) - [ ] API de hooks : `onFileRender`, `onSearchFilter`, `onEditorAction`, `onSidebarItem` - [ ] Sandbox d'exécution : Web Worker isolé pour le code plugin - [ ] UI : page « Plugins » dans les paramètres (installer, activer/désactiver, désinstaller) - [ ] Distribution : dépôt de plugins communautaire (fichier JSON index) - [ ] Hot-reload : activation/désactivation sans rechargement de page - [ ] Sécurité : manifest de permissions, validation de signature, CSP restrictif ### 62. Collaboration temps réel — Édition simultanée - **Effort :** 5-7 jours | **Impact :** 🟢 - **Description :** Édition collaborative de fichiers markdown via WebSocket + CRDT (Yjs). Plusieurs utilisateurs peuvent éditer le même fichier simultanément avec résolution automatique des conflits. - **Sous-tâches :** - [ ] Serveur WebSocket : endpoint `/ws/collab/{vault}/{path}` avec gestion des rooms - [ ] Intégration Yjs : `Y.Doc` partagé, `Y.Text` pour le contenu markdown - [ ] Awareness : curseurs colorés par utilisateur, sélections visibles - [ ] Synchro backend : persistance périodique du document (debounce 2s) - [ ] Gestion des droits : vérification `check_vault_access` par connexion WS - [ ] UI : indicateur de présence (avatars dans la barre d'outils éditeur) - [ ] UI : curseurs distants dans CodeMirror (extension collaborative) - [ ] Gestion des déconnexions : reconnexion automatique, merge state au retour - [ ] Tests de charge : 5+ utilisateurs simultanés sur le même fichier ### 63. Internationalisation (i18n) — Multilingue - **Effort :** 2-3 jours | **Impact :** 🟡 - **Description :** Support de l'anglais et du français via un système de clés de traduction. L'interface est actuellement en français uniquement. L'anglais est nécessaire pour une adoption plus large. - **Sous-tâches :** - [ ] Extraction des chaînes : inventaire de toutes les chaînes UI (~300) - [ ] Format : JSON `fr.json` + `en.json` dans `frontend/locales/` - [ ] Fonction `t(key, fallback)` → détection `navigator.language` - [ ] Sélecteur de langue dans les paramètres (persisté localStorage) - [ ] Traduction des messages backend (erreurs API, toasts) - [ ] Documentation multilingue (README.fr.md, README.md) ### 64. MFA — Authentification multi-facteurs - **Effort :** 2 jours | **Impact :** 🟡 - **Description :** Ajout de TOTP (Time-based One-Time Password) et WebAuthn (clés de sécurité) comme second facteur d'authentification pour les comptes admin. - **Sous-tâches :** - [ ] TOTP : génération de secret, QR code, vérification code 6 chiffres - [ ] WebAuthn : enregistrement de clé, assertion, attestation - [ ] UI : page « Sécurité du compte » avec activation/désactivation MFA - [ ] Flow login : mot de passe → challenge TOTP si activé - [ ] Recovery codes : 8 codes de backup à usage unique - [ ] Stockage : `totp_secret` + `webauthn_credential_id` dans `users.json` ### 65. Thèmes personnalisés — CSS variables - **Effort :** 1-2 jours | **Impact :** 🟢 - **Description :** Exposition de variables CSS pour permettre aux utilisateurs de créer des thèmes personnalisés. Presets inclus : light, dark, high-contrast, sepia. - **Sous-tâches :** - [ ] Audit des variables CSS existantes → liste des 30+ variables - [ ] Fichier `themes.json` avec presets (light, dark, high-contrast, sepia) - [ ] UI : sélecteur de thème dans les paramètres (aperçu live) - [ ] Import/export de thème personnalisé (JSON) - [ ] Application dynamique sans rechargement (`document.documentElement.style.setProperty`) ### 66. Export multi-formats - **Effort :** 1-2 jours | **Impact :** 🟢 - **Description :** Export de notes individuelles ou de vaults entiers en HTML standalone, bundle Markdown (.zip), et ePub pour liseuses. - **Sous-tâches :** - [ ] Export HTML standalone : CSS inliné, images en base64, navigation inter-fichiers - [ ] Export MD bundle : ZIP du vault avec structure préservée - [ ] Export ePub : conversion markdown → ePub via `markdown` + `ebooklib` - [ ] UI : bouton « Exporter » dans le viewer (fichier unique) + dans le menu vault (export complet) - [ ] Endpoints : `GET /api/export/html`, `GET /api/export/md-bundle`, `GET /api/export/epub` ### 74. Support complet des documents PDF - **Effort :** 4-5 jours | **Impact :** 🟡 - **Description :** Prise en charge native des fichiers PDF dans ObsiGate avec parité fonctionnelle complète avec les documents Markdown : apparition dans l'arborescence, indexation full-text, visualisation inline dans le navigateur, recherche TF-IDF, et téléchargement. Actuellement, les PDF sont traités comme des fichiers binaires non supportés (message « Ce fichier est binaire et ne peut pas être affiché » + bouton download). - **Architecture actuelle :** - `SUPPORTED_EXTENSIONS` (`backend/indexer.py:56`) : ne contient pas `.pdf` → les PDF sont ignorés par l'indexeur, le file watcher, et l'arborescence - `api_file_view()` (`backend/main.py:2303`) : UnicodeDecodeError sur lecture → retourne `unsupported: true` - `frontend/js/viewer.js:377` : si `data.unsupported` → affiche le message binaire + bouton download - `pdf_export.py` : exporte du MD → PDF (WeasyPrint) — aucun rapport avec la lecture de PDF existants - Icone PDF déjà présente dans `EXT_ICONS` frontend (`.pdf` → `file-text`) — inutilisée - **Sous-tâches :** ##### A. Backend — Extraction de texte PDF (1-1.5 jour) - [ ] **A1. Dépendance** : Ajouter `pymupdf` (PyMuPDF/fitz) à `requirements.txt` — bibliothèque C performante avec extraction texte + métadonnées, déjà compatible avec l'image Docker (libs système GTK/Pango déjà présentes pour WeasyPrint). Alternative légère : `pypdf` (pure Python, pas de deps système) si pymupdf pose problème. - [ ] **A2. Module `backend/pdf_reader.py`** : Créer un module dédié avec les fonctions : - `extract_pdf_text(file_path: Path) -> str` : extrait tout le texte du PDF, page par page, avec séparateur `\f` entre pages. Gère les PDF encodés, protégés par mot de passe (retourne erreur explicite), et corrompus. - `extract_pdf_metadata(file_path: Path) -> dict` : extrait titre, auteur, sujet, nombre de pages, taille. - `extract_pdf_preview(file_path: Path, max_chars: int = 100000) -> str` : extrait les N premiers caractères pour l'indexation (limité par `SEARCH_CONTENT_LIMIT`). - [ ] **A3. Fallback pypdf** : Si pymupdf non disponible (exception d'import), fallback automatique sur `pypdf` avec un log warning. Code structuré avec une interface abstraite (`PdfReader` protocol) pour swap transparent. ##### B. Backend — Indexation des PDF (1 jour) - [ ] **B1. Ajout à `SUPPORTED_EXTENSIONS`** : Ajouter `.pdf` au set dans `backend/indexer.py:56`. Déclencher un rebuild complet de l'index (incrémental via le file watcher pour les nouveaux PDFs). - [ ] **B2. Modification de `index_document()`** (`backend/indexer.py:524`) : Dans la fonction d'indexation, détecter l'extension `.pdf` et appeler `extract_pdf_text()` au lieu de `read_text()`. Le texte extrait alimente le pipeline TF-IDF existant — aucun changement nécessaire dans `search.py`. - [ ] **B3. Métadonnées PDF dans le document info** : Enrichir la structure de retour de `index_document()` avec les champs spécifiques PDF : `page_count`, `pdf_title` (titre extrait des métadonnées, prioritaire sur le nom de fichier), `pdf_author`. - [ ] **B4. Gestion d'erreur robuste** : PDF corrompu → log warning + skip (ne pas bloquer l'indexation). PDF volumineux (>50 Mo) → log info + extraction tronquée à `SEARCH_CONTENT_LIMIT`. Timeout d'extraction configurable (30s par défaut). ##### C. Backend — API endpoints PDF (0.5 jour) - [ ] **C1. Modification de `api_file_view()`** (`backend/main.py:2270`) : Avant la tentative de `read_text()`, détecter `.pdf` par extension. Pour les PDF : - Extraire le texte avec `extract_pdf_text()` - Extraire les métadonnées (pages, auteur) - Retourner une réponse structurée : `is_pdf: true`, `page_count`, `pdf_metadata`, `html` (aperçu texte formaté), `raw_length` - Le champ `html` contient un rendu texte simple (pas de markdown) : texte paginé ou première page formatée - [ ] **C2. Nouvel endpoint `GET /api/file/{vault}/pdf/stream`** : Sert le fichier PDF brut avec `Content-Type: application/pdf` et `Content-Disposition: inline` pour visualisation dans le navigateur. Supporte le `Range` header (HTTP 206 Partial Content) pour le streaming progressif des gros PDFs — essentiel pour la performance sur des documents volumineux. - [ ] **C3. Nouvel endpoint `GET /api/file/{vault}/pdf/info`** : Retourne les métadonnées seules (pages, titre, auteur) sans le contenu — permet à l'UI d'afficher les infos avant de charger le PDF lourd. - [ ] **C4. Endpoint download** : Déjà fonctionnel (`/api/file/{vault}/download`) — aucun changement nécessaire. ##### D. Frontend — Arborescence de fichiers (0.5 jour) - [ ] **D1. Icône et filtre** : L'icône PDF (`file-text` de Lucide) est déjà mappée dans `EXT_ICONS` (`frontend/js/utils.js:129`). Une fois `.pdf` dans `SUPPORTED_EXTENSIONS`, les PDFs apparaissent automatiquement dans l'arborescence via l'API `list_directory`. Aucun changement UI nécessaire. - [ ] **D2. Distinction visuelle** (optionnel) : Sous-titre léger sous le nom du fichier dans l'arborescence indiquant le nombre de pages (ex: « 12 pages ») pour différencier rapidement les PDF des MD. Donnée disponible via l'API `pdf/info`. - [ ] **D3. Drag & drop et upload** : Le mécanisme d'upload existant (`POST /api/file/{vault}/upload`) fonctionne déjà pour tout type de fichier. Vérifier que le MIME type `application/pdf` est correctement détecté et que le watcher réindexe automatiquement. ##### E. Frontend — Viewer PDF (1 jour) - [ ] **E1. Rendu inline natif** : Utiliser le visualiseur PDF intégré du navigateur via `