# ObsiGate — Roadmap
> **Version :** 2.16.6 | **Dernière mise à jour :** 2026-09-22
> **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact
> vers les fonctionnalités livrées.
> - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)**
> - Historique des versions : [CHANGELOG.md](../CHANGELOG.md)
> - Détail des fonctionnalités livrées : [docs/archive/COMPLETED_v1-v2.md](./archive/COMPLETED_v1-v2.md)
> - Fiches détaillées par feature : [docs/features/](./features/)
> - Bugs / TODO : [ISSUES_TODOLIST.md](./ISSUES_TODOLIST.md)
---
## Légende
| Icône | Signification |
|---|---|
| ✅ | Terminé |
| 🔵 | En cours |
| ⚪ | Prévu / Backlog |
| 🔴 Impact | Critique / Bloquant |
| 🟡 Impact | Utile / Attendu |
| 🟢 Impact | Nice-to-have / Confort |
> **Convention :** chaque item porte un **ID stable `#NN`** (clé de jointure entre roadmap,
> changelog et commits). Une fonctionnalité livrée sort de ce fichier et entre dans l'index
> « Complété » ci-dessous, avec son détail dans `docs/features/` ou l'archive.
---
## 🔵 En cours
### 77. Application Desktop native — Tauri (Windows / Linux / macOS)
- **Effort :** 8-12 jours | **Impact :** 🟡 | **Framework :** Tauri v2 (Rust + Webview)
- **Statut :** livré (A→F) — projet Tauri, backend Python embarqué, fonctionnalités natives, jumplist vaults, bannière 1er lancement, build CI, UX, 24 tests Rust. Détail complet : [features/desktop-tauri.md](./features/desktop-tauri.md)
- **Reste à faire :**
- [x] **Signature de l'updater Tauri** (gratuit) : paire de clés générée, `pubkey` renseignée, `createUpdaterArtifacts` activé, secrets CI câblés
- [x] **Manifeste `latest.json`** généré par `scripts/updater_manifest.py` (intégré à `publish_release.py`), endpoint updater pointé sur `main`
- [ ] **Signature de code Windows** : non retenue (pas de certificat) — alternatives : livrer non signé, SignPath.io (OSS gratuit), Certum OSS, Azure Trusted Signing, certificat EV
- [ ] Exécuter les 6 tests E2E **manuels** — protocole documenté : [DESKTOP_E2E_CHECKLIST.md](./DESKTOP_E2E_CHECKLIST.md)
---
## ⚪ Backlog — Priorité 4 (P4)
### 73. Synchronisation multi-appareils — Obsidian Sync compatible
- **Effort :** 6-8 jours | **Impact :** 🟢
- **Description :** Synchronisation des vaults entre plusieurs instances d'ObsiGate via un protocole de synchronisation décentralisé ou compatible Obsidian Sync. Alternative self-hosted à Obsidian Sync.
- **Sous-tâches :**
- [ ] Protocole : évaluation CRDT vs OT vs diff/patch pour fichiers markdown
- [ ] Transport : WebSocket ou polling HTTPS avec compression
- [ ] Merge strategy : LWW (Last Writer Wins) avec historique des deux versions
- [ ] Détection de changements : hash SHA-256 par fichier, journal des modifications
- [ ] UI : page « Synchronisation » avec statut par appareil, historique des syncs
- [ ] Conflits : UI de résolution manuelle (diff côte à côte entre version locale et distante)
- [ ] Chiffrement : optionnel, chiffrement AES-256-GCM avant transmission
- [ ] Pairing : échange de clé publique + code QR pour appairage des appareils
---
## ⚪ Backlog — Priorité 2 (P2)
### 83. Barre d'outils d'édition mobile — style Obsidian Android
- **Effort :** 3-5 jours | **Impact :** 🟡 | **Zone :** frontend (mobile)
- **Statut :** ✅ livré — ruban horizontal défilable ancré au-dessus du clavier, commandes étendues et personnalisation persistée. Détail : [archive/COMPLETED_v1-v2.md](./archive/COMPLETED_v1-v2.md) (section #83).
- **Description :** remplacer la barre de mise en forme Markdown actuelle par un **ruban horizontal
défilable** ancré juste au-dessus du clavier virtuel, reprenant l'ergonomie de l'app Android
Obsidian : fond anthracite aux coins arrondis, insertion/enrobage de la syntaxe au curseur ou sur
la sélection, et personnalisation des commandes via une icône clé à molette.
- **Sous-tâches :**
- [x] Ruban horizontal défilable (glissement tactile gauche/droite) ancré au-dessus du clavier
- [x] Actions rapides : annuler, refaire, `[[ ]]` (lien interne), modèle/fichiers, tag `#`, pièce jointe
- [x] Formatage : H1–H6, gras, italique, barré (`~~`), surligné (`==`), code en ligne/bloc, citation (`>`)
- [x] Liens externes, listes à puces/numérotées, case à cocher (`- [ ]`), indenter / désindenter
- [x] Personnalisation (clé à molette) : ajouter / supprimer / réordonner les commandes
- [x] i18n FR/EN + tests frontend (helpers purs) + E2E mobile
---
## ⚪ Backlog — Média (images, audio, vidéo)
### 108. Support complet des images — arborescence, visionneuse, indexation
- **Effort :** 3-4 jours | **Impact :** 🟡 | **Zone :** backend (indexer, main) + frontend (viewer, utils)
- **Statut :** ⚪ Prévu
- **Description :** parité fonctionnelle des images avec les autres fichiers du vault : apparition dans l'arborescence, ouverture directe dans une visionneuse dédiée (zoom molette, pan, navigation dossier), indexation (nom + métadonnées), miniatures. Actuellement seul l'affichage *inline* dans un document markdown (`![[image.png]]`) fonctionne ; l'image isolée est invisible dans l'arborescence et son affichage standalone est cassé.
- **Architecture actuelle (vérifiée sur `main` @ v2.16.6) :**
- `SUPPORTED_EXTENSIONS` (`backend/indexer.py:61`) : aucune extension image → images filtrées de l'arborescence et de l'index.
- `api_file_view()` (`backend/main.py:~2411`) : branche `IMAGE_EXTENSIONS` (`.png .jpg .jpeg .gif .svg .webp .bmp .ico`) qui retourne `is_image: true`, MAIS le `` généré pointe vers `/api/file/{vault}/raw?path=…` — un endpoint qui retourne du **JSON** (`FileRawResponse`, `main.py:1569`), pas des octets d'image. Affichage standalone cassé. Le frontend (`frontend/js/viewer.js:600`, branche `data.is_image`) reproduit la même URL cassée pour le bouton « Plein écran ».
- `/api/image/{vault}` (`backend/main.py:3160`) : endpoint existant et fonctionnel qui sert les octets avec le bon MIME type. C'est LUI que doivent utiliser le `` backend et le frontend. L'auth navigateur fonctionne (middleware JWT avec fallback cookie `access_token`).
- `image_processor.py` + `attachment_indexer.py` : réécriture des 4 syntaxes Obsidian (`![[img]]`, ``…) vers `/api/image` avec résolution multi-stratégie → **l'inline markdown fonctionne déjà**, aucun changement requis.
- CSP : `img-src 'self' data: blob:` — compatible, rien à assouplir.
- **Sous-tâches :**
##### A. Backend — arborescence & indexation (1 j)
- [ ] **A1.** Créer `backend/media_types.py` : constantes partagées `IMAGE_EXTENSIONS`, `AUDIO_EXTENSIONS`, `VIDEO_EXTENSIONS` (réutilisées par #109) ; remplacer le set local de `api_file_view()`.
- [ ] **A2.** Intégrer les extensions images à `SUPPORTED_EXTENSIONS` (`indexer.py:61`) **avec branche binaire** : `index_document()` ne doit JAMAIS `read_text()`/`read_bytes()` une image — indexer nom/taille/mtime uniquement, `content: ""` pour que le TF-IDF reste propre.
- [ ] **A3.** Vérifier le reindex watchdog sur création/suppression d'image (même filtre d'extensions, couvert par A2).
- [ ] **A4.** Recherche : le nom de fichier est déjà indexé (`chatScreenshot.png` trouvable par « screenshot ») ; ajouter le filtre `ext:png`/`ext:jpg` (mécanisme des filtres `ext:` existants) ; comptabiliser les images à part dans les compteurs du dashboard (#11).
##### B. Backend — correction affichage standalone (0,5 j)
- [ ] **B1.** Fix `` cassé : `api_file_view()` → `src="/api/image/{vault}?path=…"` (URL encodée) ; idem `viewer.js:600` (bouton Plein écran).
- [ ] **B2.** Métadonnées : dimensions via `` frontend (`naturalWidth/naturalHeight` — gratuit, recommandé ; Pillow seulement si C1 est retenu).
- [ ] **B3.** Sécurité SVG : sur `/api/image`, ajouter `Content-Security-Policy: sandbox` (ou `Content-Disposition: attachment`) quand `ext == .svg` — un SVG ouvert directement dans un onglet exécute son JS (XSS same-origin) ; dans une balise `` il est inoffensif.
##### C. Backend — miniatures (1 j, phase 2 tolérable)
- [ ] **C1.** Dépendance `pillow>=10.0` (wheels précompilés, rien de système dans `python:3.11-slim`).
- [ ] **C2.** `GET /api/media/{vault}/thumb` : miniature 256 px WebP, cache disque `/data/.obsigate-cache/thumbs/{sha1(path+mtime)}.webp` (invalidation naturelle par mtime). SVG : servir l'original. GIF animé : première frame.
- [ ] **C3.** Génération dans un thread pool (`run_in_executor`), fallback original si timeout 2 s.
##### D. Frontend — visionneuse (1 j)
- [ ] **D1.** `EXT_ICONS` (`frontend/js/utils.js`) : extensions images → icône Lucide `image`.
- [ ] **D2.** Visionneuse digne de ce nom dans `viewer.js` : image centrée `object-fit:contain`, **zoom molette (0,1×–8×), pan au drag, double-clic reset**, boutons +/−/reset, badge de zoom.
- [ ] **D3.** Navigation ←/→ entre images du même dossier (données `list_directory` déjà disponibles) ; bouton « Ouvrir original » (nouvel onglet, `/api/image`).
- [ ] **D4.** Barre d'outils : Télécharger (déjà fonctionnel), lightbox plein viewport (fond `rgba(0,0,0,.9)`), panneau métadonnées repliable (dimensions, taille, type, date).
- [ ] **D5.** (Optionnel 🟢) Vue galerie vignettes pour les dossiers d'images via `/api/media/thumb`, `loading="lazy"`.
- [ ] **D6.** Split View (#75) : rendu dans `getContentArea()` du panneau actif ; vérifier le cache d'onglets.
##### E. Tests (0,5 j)
- [ ] **E1.** `test_image_api.py` : `/api/image` octets + MIME ; SVG avec header sandbox ; `api_file_view` → `is_image: true` avec URL `/api/image` dans le html.
- [ ] **E2.** `test_image_indexing.py` : image visible dans `list_directory`, indexée avec contenu vide, watcher OK, rien de binaire dans le TF-IDF.
- [ ] **E3.** Playwright (#58) : clic sur une image de l'arborescence → visionneuse rendue ; zoom molette applique la transform.
- **Points d'attention / risques**
- **Ne jamais lire les octets dans l'indexeur** — dérive n°1 d'un A2 bâclé (UnicodeDecodeError de masse dans les logs, TF-IDF pollué).
- **`_attachments/`** : les vaults Obsidian réels contiennent des milliers d'images → vérifier la fluidité de l'arborescence et le coût du scan d'index.
- **HEIC (iPhone)** : non décodable par les navigateurs → hors scope v1, documenter la limitation ; `pillow-heif` en v2 si demande.
- **Parité Obsidian Desktop** : la visionneuse D2 doit atteindre le même confort zoom/pan, sinon l'utilisateur repart sur le desktop.
---
### 109. Support audio & vidéo — lecteurs intégrés HTML5
- **Effort :** 2-3 jours | **Impact :** 🟡 | **Zone :** backend (media streaming) + frontend (viewer)
- **Statut :** ⚪ Prévu — dépend du socle `media_types.py` de #108-A1
- **Description :** prise en charge des fichiers audio (`.mp3 .m4a .aac .wav .ogg .oga .opus .flac`) et vidéo (`.mp4 .webm .mov .m4v`) avec la même parité que les autres fichiers : apparition dans l'arborescence, indexation du nom, lecture directe dans le viewer via les balises HTML5 `