BUG-015: l'etat actif des menus / et @ (et de la liste de modeles) utilise --bg-hover + barre d'accent a gauche, car --surface2 est identique a --bg-primary en theme sombre. Retrait de l'indice 'Entree pour envoyer...' sous la zone de saisie.
904 lines
56 KiB
Markdown
904 lines
56 KiB
Markdown
# Changelog — ObsiGate
|
||
|
||
Toutes les modifications notables d'ObsiGate sont documentées dans ce fichier.
|
||
|
||
Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/),
|
||
et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||
|
||
> **En cours de développement** : les changements non publiés sont dans la section
|
||
> [Unreleased](#unreleased). La dernière version publiée est **2.2.1**.
|
||
|
||
---
|
||
|
||
## [Unreleased]
|
||
|
||
### Ajouté
|
||
|
||
- **#82 Assistant IA — Section « Fournisseur & modèle » compacte** — la barre de sélection du
|
||
modèle devient **discrète** : la liste complète des types d'endpoints (Chat, Embeddings, Vision…)
|
||
est remplacée par un **bouton d'information ⓘ** qui affiche les capacités dans une **bulle** au
|
||
survol, au clic ou par **appui long** (mobile). Le choix du modèle passe par une **liste
|
||
déroulante avec recherche** (filtrage insensible aux accents) au lieu d'un `<select>` natif, tout
|
||
en conservant un select masqué pour les commandes admin (`/model`). Le picker partagé
|
||
(`frontend/js/ai.js`) est utilisé par l'assistant et la barre d'édition IA. Tests JSDOM
|
||
(`tests/frontend/ai.test.mjs` +1).
|
||
|
||
- **#81 Assistant IA — Commandes `@`/`/`, skills, images & capacités des modèles** — l'assistant
|
||
devient plus flexible et multimodal. **Panneau redimensionnable** à la souris (largeur 320–1000 px
|
||
persistée). **Commande `@`** pour attacher des contextes ad-hoc (fichiers, répertoires) au contexte
|
||
courant. **Commande `/`** pour lancer des **skills** réutilisables (`/research`, `/resume`,
|
||
`/actions`, `/reformuler`, `/correction`, `/brainstorm`, `/plan`, `/ask`, `/meeting-note`,
|
||
`/livrable`) ou des commandes admin (`/help`, `/providers`, `/provider`, `/model`, `/keys`) ;
|
||
`/create-new-skill` permet de créer des skills personnalisés persistés par utilisateur
|
||
(`data/skills.json`). **Analyse d'images** : coller une image dans la zone de saisie ou référencer
|
||
une image d'un répertoire (`@image.png`), avec garde-fou de compatibilité vision. **Capacités des
|
||
modèles** (Chat, Embeddings, Rerank, Images, Video, Audio Speech, Audio Transcriptions, Vision)
|
||
affichées à la sélection dans l'assistant et le panneau de configuration. Backend : table curée
|
||
`backend/model_capabilities.py`, endpoints `GET /api/ai/model-capabilities` et `GET /api/ai/skills`,
|
||
support multimodal dans `backend/ai_chat.py` et `backend/bookslm_routes.py`. Tests :
|
||
`tests/test_model_capabilities.py` (16), `tests/test_skills.py` (16), `tests/test_ai_vision.py` (12)
|
||
+ extension `tests/test_ai_models.py` et `tests/frontend/ai.test.mjs` (+9). Détail :
|
||
[docs/features/ai-assistant-commands.md](./docs/features/ai-assistant-commands.md).
|
||
|
||
- **#77 Desktop — Signature des mises à jour Tauri** — la paire de clés `minisign`
|
||
de l'updater est générée et sa clé publique est embarquée dans
|
||
`desktop/tauri.conf.json` (`plugins.updater.pubkey`, remplace le placeholder) ;
|
||
`bundle.createUpdaterArtifacts: true` produit les fichiers `.sig` par artefact.
|
||
Le workflow `.gitea/workflows/desktop-build.yml` expose les secrets
|
||
`TAURI_SIGNING_PRIVATE_KEY` / `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` aux builds
|
||
Windows et Linux, avec repli automatique en build **non signé** si le secret est
|
||
absent (CI toujours verte). Procédure complète :
|
||
[docs/DEVELOPMENT_AND_RELEASES.md](./docs/DEVELOPMENT_AND_RELEASES.md#2bis-signature-des-mises-à-jour-updater-tauri).
|
||
|
||
- **#77 Desktop — Manifeste de mise à jour `latest.json`** — nouveau
|
||
`scripts/updater_manifest.py` qui construit le document consommé par l'updater
|
||
Tauri (version, notes, `pub_date`, `platforms` Windows/Linux avec signature
|
||
`.sig` et URLs des assets). Il est généré automatiquement par
|
||
`scripts/publish_release.py` (écrit `desktop/latest.json`, l'ajoute aux assets
|
||
de la release, upload des `.sig`) et peut être lancé seul. L'endpoint de
|
||
l'updater (`desktop/tauri.conf.json`) pointe désormais sur le manifeste
|
||
versionné `.../raw/branch/main/desktop/latest.json`. Les builds locaux
|
||
(`build-windows.bat`, `build-linux.sh`) détectent automatiquement
|
||
`desktop/obsigate-updater.key` pour signer, ou désactivent les artefacts de
|
||
mise à jour s'il est absent. Tests : `tests/test_updater_manifest.py` (8).
|
||
|
||
- **#77 Desktop — Protocole de tests E2E manuels** — nouveau
|
||
[`docs/DESKTOP_E2E_CHECKLIST.md`](./docs/DESKTOP_E2E_CHECKLIST.md) : prérequis,
|
||
étapes et résultat attendu pour les 6 scénarios OS non automatisables
|
||
(installation, tray, notifications natives, association `.md`, auto-update,
|
||
désinstallation), avec emplacements des logs/config et procédure de signature
|
||
de l'updater Tauri.
|
||
|
||
- **#70 Recherche sémantique — Embeddings vectoriels** — la recherche comprend désormais le
|
||
**sens** de la requête en plus des mots-clés. **Embeddings** : chaque document est découpé en
|
||
chunks de 512 mots (recouvrement 64) puis vectorisé (384 dim) via `all-MiniLM-L6-v2`
|
||
(`sentence-transformers`), un endpoint `/embeddings` compatible OpenAI, ou un provider de repli
|
||
**sans dépendance** (hachage déterministe). **Stockage vectoriel** : `numpy`/`faiss`
|
||
(`IndexFlatIP`) si disponibles, sinon cosinus pur Python. **Recherche hybride** : fusion du
|
||
classement TF-IDF et du classement sémantique par **RRF** (Reciprocal Rank Fusion), avec
|
||
`semantic_score` par résultat. **Indexation incrémentale** branchée sur le watcher (un fichier
|
||
modifié régénère son embedding). **UI** : toggle « Recherche sémantique » (`~`, raccourci
|
||
`Alt+S`) dans la barre de résultats + affichage du score de similarité, clés i18n FR/EN.
|
||
Nouveau module `backend/semantic_search.py`, paramètre `semantic` sur
|
||
`/api/search/advanced`, dépendances **optionnelles** dans
|
||
`backend/requirements-semantic.txt`. Tests : `tests/test_semantic_search.py` (27) +
|
||
`tests/frontend/semantic-search.test.mjs` (4). Détail :
|
||
[docs/features/semantic-search.md](./docs/features/semantic-search.md).
|
||
|
||
- **#69 Éditeur mobile natif — Interface tactile optimisée** — refonte de l'expérience
|
||
d'édition sur téléphone/tablette. **Barre d'outils flottante** dans l'éditeur (gras, italique,
|
||
code, liste à puces, lien) opérant directement sur la sélection CodeMirror (ou le textarea de
|
||
secours), avec **toggle** (re-appui pour dé-formater) ; **bouton « Coller » persistant** qui
|
||
contourne la restriction presse-papiers d'iOS (repli sur un message d'aide si l'accès est
|
||
refusé). **Adaptation CodeMirror** : zoom par **pincement à deux doigts**, boutons A−/A+ et
|
||
**hauteur ajustable** via une poignée (valeurs persistées en `localStorage`). Côté lecture :
|
||
**raccourcis swipe** (gauche → liens entrants, droite → table des matières) et **mode lecture**
|
||
plein écran (masquage de l'en-tête, des barres latérales et de la barre mobile, API Fullscreen,
|
||
**swipe horizontal** pour passer au fichier suivant/précédent du même dossier). Nouveau module
|
||
`frontend/js/mobile-editor.js`, styles `frontend/style.css`, clés i18n FR/EN. Tests :
|
||
`tests/frontend/mobile-editor.test.mjs` (22 tests). Détail :
|
||
[docs/features/mobile-editor.md](./docs/features/mobile-editor.md).
|
||
|
||
- **#62 Collaboration temps réel — Édition simultanée** — plusieurs utilisateurs peuvent éditer le
|
||
même document markdown en même temps, façon Google Docs. **WebSocket** : nouvel endpoint
|
||
`/ws/collab/{vault}/{path}` (une *room* par fichier) qui relaie les changements instantanément ;
|
||
authentification manuelle (cookie `access_token` ou paramètre `token`) + `check_vault_access` et
|
||
`resolve_safe_path` par connexion. **Yjs/CRDT** côté client : `Y.Doc`/`Y.Text` fusionnent les
|
||
modifications concurrentes sans conflit ni perte. **Awareness** : curseurs distants colorés et
|
||
sélections dans CodeMirror, indicateur de présence (avatars + statut) dans l'en-tête de l'éditeur.
|
||
**Persistance serveur** : le dernier texte reçu est écrit sur disque avec un debounce de 2 s
|
||
(`backend/collab.py`). **Reconnexion** automatique avec backoff exponentiel et merge de l'état au
|
||
retour. Nouveau module frontend `frontend/js/collab.js` (provider + liaison Y.Text↔CodeMirror +
|
||
curseurs distants) et `backend/collab.py` (`CollabManager`). Tests : `tests/test_collab.py`
|
||
(17 tests, dont 5 clients simultanés) et `tests/frontend/collab.test.mjs`. Détail :
|
||
[docs/features/collaboration.md](./docs/features/collaboration.md).
|
||
|
||
- **#79 Phase F — Durcissement & documentation (rate limiting, redaction, OpenAPI/MCP, E2E)** —
|
||
clôture de la feature #79. **Rate limiting** par jeton et par outil
|
||
(`backend/tools/ratelimit.py`, fenêtre glissante ; identité = JTI du jeton sinon id/username ;
|
||
`OBSIGATE_TOOL_RATE_LIMIT`, `OBSIGATE_TOOL_RATE_LIMIT_PER_TOOL`, `OBSIGATE_TOOL_RATE_WINDOW` ;
|
||
erreur `rate_limited`). **Quotas** `BOOKSLM_MAX_*` : `BOOKSLM_MAX_TOOL_CALLS` plafonne les appels
|
||
d'outils par run d'agent (`stopped="quota_exceeded"`) et `BOOKSLM_MAX_TOOL_READ_BYTES` plafonne
|
||
`read_file`. **Redaction** systématique de **tout** résultat d'outil avant retour au LLM
|
||
(`backend/tools/redaction.py`, récursif : diffs, extraits de recherche, lectures). **OpenAPI** :
|
||
tag `MCP` + injection du path `/mcp` (Streamable HTTP) dans le schéma ; nouveau
|
||
[`docs/MCP_GUIDE.md`](./docs/MCP_GUIDE.md) (config Claude Desktop/Cursor, tools/resources/prompts,
|
||
sécurité, variables, dépannage). Tests E2E : `tests/test_ai_e2e.py` (agent read→confirm→write,
|
||
quota, rate limit, redaction, flux MCP `read`→`propose`→`apply`→`resources/read`).
|
||
|
||
- **#79 Phase E — Serveur MCP (Streamable HTTP)** — nouvel endpoint `/mcp` exposant ObsiGate à des
|
||
clients MCP externes (Claude Desktop, Cursor…) via le SDK Python `mcp==1.9.4`. Les deux fronts
|
||
(assistant in-app et MCP) consomment la même couche d'outils. **Tools** : outils de lecture/recherche
|
||
directs ; outils d'écriture/destructifs en **two-step `propose_<tool>` / `apply_<tool>`** avec
|
||
**jeton JWT signé, usage unique et TTL** (`OBSIGATE_MCP_CONFIRMATION_TTL`, défaut 300 s) et
|
||
blacklist de JTI persistée (`data/mcp_used_tokens.json`, anti-rejeu). **Resources** :
|
||
`vault://<name>` et `vault://<name>/<path>` (lecture seule, secrets redactés). **Prompts** :
|
||
`summarize-directory`, `generate-note`, `find-related`. Auth `Authorization: Bearer <JWT>` →
|
||
`get_current_user` ; permissions et toggle destructif par vault (`aiDestructiveTools`) appliqués.
|
||
Nouveaux modules `backend/mcp/server.py` et `backend/mcp/confirmations.py` ; dépendances
|
||
`mcp==1.9.4` + `sse-starlette==2.1.3` (compatibles FastAPI 0.110 / starlette 0.37). Tests :
|
||
`tests/test_mcp.py` (13 tests).
|
||
|
||
- **#79 Phase D — Catalogue d'outils mutations + confirmations two-step** — 11 nouveaux outils IA
|
||
destructifs ou d'écriture exposés par la couche partagée (`backend/tools/service.py`) :
|
||
`create_file`, `create_directory`, `edit_file`, `append_to_file`, `rename_file`,
|
||
`rename_directory`, `move_path`, `replace_in_files`, `delete_file`, `delete_directory`,
|
||
`restore_backup`. Nouveau service réutilisable `backend/services/mutations.py` (anti
|
||
path-traversal, garde lecture seule, **backup automatique** avant écriture/suppression/restauration) ;
|
||
les routes `/api/file/{vault}` (POST/PATCH/DELETE), `/api/file/{vault}/save`, `/api/directory/{vault}`
|
||
(POST/PATCH/DELETE), `/api/move/{vault}`, `/api/file/{vault}/restore` et `/api/search/replace`
|
||
délèguent désormais à cette couche. `backend/services/backups.py` expose `create_backup`
|
||
(source unique, réutilisée par `main._backup_file`). Confirmations **two-step** : tout outil
|
||
`WRITE`/`DANGEROUS` déclenche `ToolConfirmationRequired` (carte Apply in-app, `propose`/`apply`
|
||
côté MCP en phase E). **Toggle par vault** `aiDestructiveTools` (défaut : activés) pour désactiver
|
||
delete/rename/move/replace. Tests : `tests/test_tools_mutations.py` (40 tests).
|
||
|
||
- **#79 Phase C — Catalogue d'outils lecture & recherche** — 10 nouveaux outils IA exposés par la
|
||
couche partagée (`backend/tools/service.py`) : `list_all_files`, `read_file_raw`, `get_backlinks`,
|
||
`list_backups`, `diff_backup`, `get_graph`, `search_advanced`, `search_paths`, `suggest_tags`,
|
||
`list_recent`. Nouveaux services réutilisables `backend/services/backups.py`, `graph.py`,
|
||
`recent.py` et extensions de `vaults.py` (`list_all_files`) / `search.py`
|
||
(`advanced_search_vaults`, `search_paths`). Les routes `/api/recent`, `/api/vault/{vault}/files`,
|
||
`/api/file/{vault}/backups`, `/api/file/{vault}/diff`, `/api/graph/{vault}`, `/api/tree-search`
|
||
et `/api/search/advanced` délèguent désormais à ces services (source unique de vérité).
|
||
Filtrage systématique par permissions vault ; secrets redactés sur `read_file`/`read_file_raw`.
|
||
Tests : `tests/test_tools.py` (+17 tests).
|
||
|
||
- **#79 Assistant IA — Outils (function calling) & serveur MCP — Phase 0 (couche d'outils partagée)** —
|
||
nouveau paquet `backend/tools/` : `context.py` (`ToolContext`), `registry.py` (décorateur `@tool`
|
||
+ schéma JSON), `schemas.py`, `service.py`, `audit.py` (journalisation JSONL des appels), façade
|
||
`backend/tools/api.py`. Services lecture/recherche livrés (`list_vaults`, `list_directory`,
|
||
`read_file`, `search_fulltext`, `list_tags`) ; permissions `check_vault_access` + `resolve_safe_path`
|
||
appliquées par outil. Tests : `tests/test_tools.py` (30 tests).
|
||
|
||
- **#79 Phase B (partielle) — function calling in-app** — abstraction tool-calling
|
||
provider-agnostique `backend/ai_chat.py` (`chat_completion`, `ToolCall`, `LLMResponse`, OpenAI-compat
|
||
+ Gemini) ; agent loop `backend/agent/loop.py` (boucle tool→résultat→tool, limite 10 itérations,
|
||
truncation) ; endpoint opt-in `POST /api/ai/bookslm/agent` (events SSE `tool`/`message`/`confirmation`) ;
|
||
fallback automatique en chat simple si le provider rejette les tools. Tests : `tests/test_agent_loop.py`,
|
||
`tests/test_ai_chat.py`, `tests/test_bookslm.py`.
|
||
|
||
- **#79 A2/B4/B5 — services partagés, SSE streaming & confirmations UI** — extraction de la logique
|
||
lecture/recherche dans `backend/services/` (`errors.py`, `paths.py`, `vaults.py`, `files.py`,
|
||
`search.py`) : routes REST et outils IA consomment la même source ; `ServiceError` mappée vers
|
||
`HTTPException` (routes) et `ToolError` (outils). `/api/ai/bookslm/chat` **streame réellement** les
|
||
tokens (`stream_completion`, OpenAI-compat + Gemini ; GZip ignoré pour les SSE BooksLM). Mode agent
|
||
côté UI (toggle, événements `tool`/`confirmation`, carte Apply + aperçu diff LCS) et reprise
|
||
`confirm`/`confirm_messages` de l'agent loop (confirmation one-shot). Tests : `tests/test_services.py`,
|
||
`tests/test_ai_chat.py`, `tests/test_agent_loop.py`, `tests/test_bookslm.py`.
|
||
|
||
- **#79 G — Sélection fournisseur/modèle par défaut** — `ai_default_provider` + `ai_default_models`
|
||
persistés dans `data/config.json`, rechargement à chaud dans `backend/ai.py`, sélecteurs
|
||
« Fournisseur par défaut » / « Modèle par défaut » dans `#cfg-ai`, i18n FR/EN.
|
||
|
||
- **#80 Assistant IA — Rendu Markdown, liens fichiers/paths & sessions** — réponses de l'assistant
|
||
rendues en **Markdown formaté** (titres, listes, tableaux, citations, code, emphase) via un
|
||
renderer auto-contenu ; les **fichiers et chemins** mentionnés deviennent des liens cliquables
|
||
(clic fichier → ouverture dans le viewer, clic répertoire → révélation/surlignage dans
|
||
l'arborescence, outils `open_file`/`reveal_in_tree` côté in-app) ; **gestion des sessions** par
|
||
contexte (historique consultable, rechargeable, supprimable) avec migration de l'ancienne
|
||
conversation unique. Tests : `tests/frontend/ai.test.mjs`.
|
||
|
||
### Modifié
|
||
|
||
- **`scripts/bump_version.sh` — synchronisation de la version desktop** — le script met
|
||
désormais à jour `desktop/tauri.conf.json`, `desktop/Cargo.toml` et `desktop/Cargo.lock`
|
||
(`obsigate-desktop`) avant de créer un commit de release `chore(release): vX.Y.Z` puis le
|
||
tag. `--push` pousse la branche **et** le tag ; `--no-files` conserve l'ancien comportement
|
||
(tag seul) et `--dry-run` prévisualise. Indispensable au bon fonctionnement de l'updater
|
||
Tauri (dont le manifeste reprend la version de `tauri.conf.json`).
|
||
|
||
- **`.gitea/workflows/desktop-build.yml` — déclenchement manuel uniquement** — le workflow
|
||
`Desktop Build` ne s'exécute plus sur `push` (aucun runner self-hosted `[windows/linux, desktop]`
|
||
enregistré) mais uniquement via `workflow_dispatch`. Le build Windows se fait en local
|
||
(`desktop/build-windows.bat`) ; le workflow reste disponible pour un futur runner.
|
||
|
||
- **Assistant IA (`frontend/js/bookslm.js`)** — l'ancien rendu Markdown minimal est remplacé par un
|
||
renderer bloc/inline complet ; l'en-tête expose un bouton « Historique des sessions » ; les badges
|
||
de sources ouvrent désormais réellement le fichier (événement `obsigate:open-file`).
|
||
|
||
- **Assistant IA (`frontend/js/bookslm.js`)** — bouton « mode agent » dans l'en-tête (persisté en
|
||
`localStorage`) : l'envoi bascule vers `/api/ai/bookslm/agent`, affiche la trace des appels d'outils
|
||
et les cartes de confirmation (Apply + aperçu diff) ; `/chat` reste le défaut. i18n FR/EN.
|
||
|
||
### Modifié
|
||
|
||
- **#82 Assistant IA — barre latérale épurée & suivi visuel des requêtes** — la section
|
||
« Fournisseur & modèle » perd ses intitulés (titre de section et libellé « Fournisseur : »)
|
||
pour rester discrète ; la description du contexte Général n'est plus affichée (bandeau de
|
||
statut masqué, description accessible au **survol** de l'en-tête) ; le placeholder
|
||
« Posez une question sur ces documents… » est retiré ; l'indice clavier
|
||
« Entrée pour envoyer · Ctrl+Entrée… » est retiré ; le bouton « Envoyer » devient un **emoji
|
||
compact** (✈️). Un **indicateur d'activité** apparaît pendant le traitement et détaille le
|
||
workflow : envoi, réception de la réponse, appels d'outils (`Outil : X…`), attente de
|
||
confirmation, succès ou échec. i18n FR/EN (`ai.activity_*`, `ai.composer_label`). Tests JSDOM
|
||
(`tests/frontend/ai.test.mjs` +1).
|
||
|
||
### Corrigé
|
||
|
||
- **BUG-015 — Assistant IA : sélection des menus `/` et `@` invisible au clavier** — l'élément
|
||
actif utilisait `background: var(--surface2)`, or `--surface2` est **identique** à
|
||
`--bg-primary` (fond du menu) dans le thème sombre par défaut : la ligne sélectionnée par les
|
||
flèches ↑/↓ ne se distinguait pas. L'état actif (et le survol) utilise désormais
|
||
`--bg-hover` avec une **barre d'accent** à gauche (`box-shadow: inset 3px 0 0 var(--accent)`),
|
||
pour les menus de commandes/mentions **et** la liste de modèles. Test JSDOM mis à jour.
|
||
|
||
- **BUG-014 — Assistant IA : navigation clavier ↑/↓ des menus inopérante** — la navigation était
|
||
liée au `keydown` du champ de saisie : dès que le focus quittait la zone de texte (clic sur le
|
||
menu, bouton Envoyer…), les flèches ne faisaient plus défiler les items. La gestion est déplacée
|
||
au niveau du **panneau en phase de capture**, ce qui fonctionne quel que soit l'élément focalisé
|
||
dans la barre latérale. Tests JSDOM (`tests/frontend/ai.test.mjs` +1).
|
||
|
||
- **BUG-013 — Assistant IA : « Aucun vault actif pour ouvrir ce lien »** — les liens
|
||
fichiers/répertoires des réponses utilisaient `_resolveVault()` seul, nul en mode Général sans
|
||
document ouvert. `_openFileLink()` et `_revealPath()` utilisent désormais `_activeVault()` qui
|
||
retombe sur le vault de contexte, le vault sélectionné dans la barre latérale, puis le premier
|
||
vault disponible. Tests JSDOM (`tests/frontend/ai.test.mjs` +1).
|
||
|
||
- **Assistant IA — caches obsolètes** — `SW_VERSION` porté à **v6** et migration de purge élargie à
|
||
tous les caches `obsigate-*` (clé `obsigate-sw-migration` → `v3`), afin que les clients bloqués sur
|
||
une ancienne version récupèrent bien le menu `@` et les correctifs.
|
||
|
||
- **BUG-012 — Assistant IA : la commande `@` n'affichait aucun menu en mode Général** — sans vault
|
||
résolu, la détection `@` ne listait rien (menu masqué) et le backend ignorait ensuite le
|
||
contexte. Le menu est désormais **toujours rendu** et `_mentionVault()` retombe sur le vault de
|
||
contexte de la barre latérale, puis sur le premier vault disponible, avant de basculer sur
|
||
`vault=all` pour les recherches. Tests JSDOM (`tests/frontend/ai.test.mjs` +1).
|
||
|
||
- **BUG-011 — Assistant IA : noms de modèles illisibles dans la liste déroulante** — la liste
|
||
déroulante des modèles s'ouvrait alignée à gauche (`left: 0`) et pouvait dépasser le bord droit
|
||
de la barre latérale (ancrée à droite), rendant les noms tronqués/illisibles ; elle est
|
||
désormais **alignée à droite** du déclencheur, large de 340 px (bornée à `100vw - 24px`), et les
|
||
noms **reviennent à la ligne** (`overflow-wrap: anywhere`, police 0,78 rem) avec l'info-bulle
|
||
`title` complète. Tests JSDOM (`tests/frontend/ai.test.mjs`).
|
||
|
||
- **BUG-010 — Assistant IA : la commande `@` n'ajoutait pas le contexte en mode Général** — les
|
||
fichiers/répertoires choisis via `@` étaient bien ajoutés sous forme de puces, mais le **vault
|
||
n'était pas transmis** : en mode Général (`_vault` nul), la requête partait sans `vault` et le
|
||
backend ignorait le contexte ad-hoc. La sélection capture maintenant le `vault` renvoyé par
|
||
`/api/tree-search`, `_contextVault()` le propage aux requêtes `/context` et `/chat`, et les
|
||
recherches suivantes restent dans ce vault. Tests JSDOM (`tests/frontend/ai.test.mjs`).
|
||
|
||
- **BUG-009 — Assistant IA : liste de modèles corrompue et clés i18n brutes** — deux causes :
|
||
(1) les fichiers de locale n'étant pas *content-hashed*, un `fr.json` en cache HTTP affichait
|
||
les clés brutes (`ai.model_search`, `mobile_editor.*`, …) ; le chargement i18n utilise désormais
|
||
`cache: 'no-store'` et `SW_VERSION` est incrémenté pour purger les anciens caches du service
|
||
worker. (2) la liste de modèles (OpenRouter = plusieurs centaines d'entrées) pouvait se retrouver
|
||
non stylée si la feuille de style était en cache ; le picker applique maintenant les styles
|
||
critiques **en ligne** (popover, liste en colonne, options `display:block`), plafonne le rendu à
|
||
200 entrées avec un indicateur « … N autres — affinez la recherche », et la recherche filtre le
|
||
reste. Tests JSDOM (`tests/frontend/ai.test.mjs` +1).
|
||
|
||
- **BUG-007 — Assistant IA : menus `/` et `@` (navigation ↑/↓ et filtrage accentué)** — la
|
||
détection des commandes/mentions et le filtrage des skills utilisaient des motifs ASCII
|
||
(`[a-z0-9-]`, `\w`) : dès qu'un caractère accentué était saisi (`/résumé`, `@café`), le menu se
|
||
fermait. Les motifs sont désormais **Unicode** (`\p{L}`) et la recherche est **insensible aux
|
||
accents** (normalisation NFD). La navigation clavier est fiabilisée par un **jeton de séquence**
|
||
qui ignore les rendus asynchrones obsolètes (frappe rapide) et fait défiler l'élément actif dans
|
||
la vue (`scrollIntoView`). Tests JSDOM (`tests/frontend/ai.test.mjs` +3).
|
||
|
||
- **BUG-008 — Assistant IA : commande `@` et contexte ad-hoc en mode Général** — deux causes :
|
||
(1) le backend ignorait les fichiers/répertoires ad-hoc en mode Général car `_resolve_system_prompt`
|
||
ne résolvait pas de vault (`backend/bookslm_routes.py`) ; le vault optionnel est maintenant résolu
|
||
dès que du contexte `@` est présent. (2) sans vault courant, la recherche de mention échouait ;
|
||
elle bascule désormais sur `vault=all`. Tests backend (`tests/test_bookslm.py` +2) et frontend.
|
||
|
||
- **#77 Desktop — bannière de premier lancement réaffichée à chaque démarrage** —
|
||
l'état du wizard « Choisissez votre vault » n'était mémorisé que dans le
|
||
`localStorage` de la webview et le paramètre `hasVaultPath` n'était jamais
|
||
renseigné. Ajout d'un booléen persistant `wizard_done` dans la config desktop
|
||
(`desktop/src/main.rs`, commandes `get_wizard_state` / `complete_wizard`,
|
||
rétro-compatible via `#[serde(default)]`) : la bannière ne réapparaît plus après
|
||
un choix de dossier ou un clic « Plus tard », même si le stockage webview est
|
||
vidé. Tests Rust (`desktop/src/main.rs`) et JSDOM
|
||
(`tests/frontend/desktop.test.mjs`) ajoutés.
|
||
|
||
- **Build Docker — « No space left » lors de `apt-get install`** — le stage *builder*
|
||
installait inutilement `libpango-1.0-0`, `libpangocairo-1.0-0` et `shared-mime-info`
|
||
(libs runtime de WeasyPrint, sans usage à la compilation), dupliquant les téléchargements
|
||
apt. Ces paquets sont retirés du builder et `apt-get clean` est ajouté dans les deux
|
||
stages pour purger les `.deb` conservés par défaut sous Debian trixie, réduisant
|
||
l'empreinte disque et le temps de build. En complément, purge du cache de build
|
||
(`docker builder prune`) ayant libéré l'espace nécessaire.
|
||
|
||
- **BUG-005 — Chargement mobile incomplet derrière Cloudflare (`og.dracodev.net`)** —
|
||
le service worker utilisait une stratégie **cache-first avec un nom de cache fixe**
|
||
(`obsigate-v1`) et un précache de chemins erronés (`/frontend/js/…`) : le Cache Storage
|
||
du SW (distinct du cache navigateur/Cloudflare) servait un ancien build indéfiniment,
|
||
même après purge. Le middleware renvoyait en plus `Cache-Control: public, max-age=31536000,
|
||
immutable` sur des assets **non fingerprintés**. Correctifs : `frontend/sw.js` réécrit
|
||
(**network-first** pour HTML/JS/CSS, caches versionnés `SW_VERSION`, précache corrigé
|
||
`/static/js/…`, `skipWaiting`/`clients.claim`) ; migration ponctuelle `localStorage`
|
||
(suppression des anciens caches) en remplacement du kill-switch de session ; en-têtes
|
||
`no-cache` sur `/static`, `index.html`, `manifest.json` et pages HTML ; rechargement unique
|
||
sur `controllerchange`. Tests : `tests/frontend/sw.test.mjs` + `TestStaticCaching`.
|
||
Guide Cloudflare : [docs/PWA_GUIDE.md](./docs/PWA_GUIDE.md).
|
||
|
||
- **Typage backend (mypy) — 33 erreurs corrigées** (`backend/main.py`, `indexer.py`,
|
||
`auth/router.py`, `pdf_reader.py`, `export.py`, `bookslm_routes.py`) : annotations de types,
|
||
gardes `None` sur `get_user()`, `PdfReader: Any` et import `PROVIDERS` manquant dans `main.py`
|
||
(bug latent : le modèle par défaut n'était jamais prépendé à la liste des modèles live).
|
||
L'étape `mypy` du CI devient **bloquante** (elle était en mode advisory).
|
||
|
||
- **README** — lien « Contributing » corrigé vers `docs/CONTRIBUTING.md` (était cassé vers la
|
||
racine) ; arbre du projet mis à jour.
|
||
|
||
- **#79 façade `backend/tools/api.py`** — gestion des namespace packages et du `__init__` ignoré
|
||
lors du chargement des modules d'outils.
|
||
|
||
### Documentation
|
||
|
||
- **Guide d'architecture IA** — `docs/AI_ARCHITECTURE_GUIDE.md` (architecture, catalogue d'outils,
|
||
sécurité, phases).
|
||
- **Refonte de la documentation** — la [Roadmap](./docs/ROADMAP.md) ne contient plus que le travail
|
||
à venir + un index compact ; les fonctionnalités livrées sont archivées dans
|
||
`docs/archive/COMPLETED_v1-v2.md` et documentées par feature dans `docs/features/`.
|
||
|
||
- **Méthode de livraison unifiée** — nouveau [`docs/DELIVERY_WORKFLOW.md`](./docs/DELIVERY_WORKFLOW.md)
|
||
(Definition of Done : tests, documentation, commit, push, CI) et [`AGENTS.md`](./AGENTS.md)
|
||
(instructions obligatoires lues à chaque session). Référencés depuis la Roadmap, CONTRIBUTING
|
||
et ISSUES_TODOLIST.
|
||
|
||
---
|
||
|
||
## [2.2.1] — 2026-09-11
|
||
|
||
### Ajouté
|
||
|
||
- **Mobile — assistant AI central** — bouton assistant dans la barre du bas (commit 50b823e).
|
||
|
||
### Corrigé
|
||
|
||
- **Version affichée dans l'UI** — affichait `2.1.0` au lieu de `2.2.0` (commit 84bda90).
|
||
- **Mobile** — boîte d'édition de l'assistant relevée au-dessus de la barre du bas (commit f307ecb).
|
||
|
||
---
|
||
|
||
## [2.2.0] — 2026-09-11
|
||
|
||
### Ajouté
|
||
|
||
- **Assistant AI contextuel (sidebar)** — l'assistant s'adapte désormais au contexte d'ouverture :
|
||
- **Répertoire** (`directory`) : ouvert depuis le menu contextuel d'un dossier — le contexte est
|
||
le dossier et son contenu (mode historique BooksLM).
|
||
- **Documents** (`documents`) : ouvert via le bouton flottant quand un ou plusieurs documents
|
||
sont ouverts — le contexte est la liste des fichiers ouverts (tous onglets/panneaux).
|
||
- **Général** (`general`) : ouvert via le bouton flottant quand aucun document n'est ouvert —
|
||
l'assistant répond sur l'application et peut proposer des actions (créer un fichier/dossier)
|
||
via un bloc `obsigate-action` rendu en carte avec bouton « Appliquer » (aucune exécution
|
||
automatique).
|
||
- Le contexte est affiché dans le header de la sidebar (icône, titre, sous-titre) et les
|
||
suggestions de questions s'adaptent au mode.
|
||
- Backend : `/api/ai/bookslm/context` et `/chat` acceptent `mode` (`directory`/`documents`/
|
||
`general`) et `context_files` ; `collect_files_context()`, `empty_context()` et
|
||
`build_general_system_prompt()` dans `backend/bookslm.py` ; le mode documents dégrade
|
||
proprement vers le mode général si aucun fichier n'est lisible.
|
||
- Tests : `tests/test_bookslm.py` (+13 tests modes/documents/général) et
|
||
`tests/frontend/ai.test.mjs` (+8 tests détection de contexte, clavier, actions, header).
|
||
|
||
- **#72 API publique documentée — OpenAPI 3.1 enrichie** — documentation interactive complète
|
||
de l'API REST, générée automatiquement et enrichie.
|
||
- Backend `backend/openapi_docs.py` : métadonnées de tags (18 catégories : System, Auth, Files,
|
||
PDF, Vaults, Search, Bookmarks, Backups, Export, AI, BooksLM, Sharing, Webhooks, Conflicts,
|
||
Admin, Plugins, Push, Frontend), assignation automatique des tags par préfixe de route
|
||
(normalisation des tags des routeurs), schémas de sécurité (`bearerAuth`, `cookieAuth`),
|
||
exemples de requête/réponse sur les endpoints clés, réponses d'erreur documentées
|
||
(401/403/404/422/500), serveur et `externalDocs`.
|
||
- `backend/schemas.py` : nouveaux `response_model` Pydantic pour les endpoints qui n'en avaient
|
||
pas (recent, bookmarks, saved searches, backups, diff/restore/backlinks, pdf/info, replace,
|
||
vaults, attachments, settings, config, AI keys/models, diagnostics, dashboard, webhooks,
|
||
shares, conflicts, BooksLM context, AI status).
|
||
- `backend/main.py` : `FastAPI(...)` enrichi (description Markdown, contact, licence, tags) et
|
||
override `app.openapi` pour post-traiter le schéma ; page de documentation `/api` (HTML
|
||
autonome listant les endpoints groupés par catégorie, liens vers `/docs`, `/redoc`,
|
||
`/openapi.json`).
|
||
- Frontend : entrée « API » dans le menu d'options (i18n FR/EN) ouvrant Swagger UI.
|
||
- Tests : `tests/test_openapi.py` (58 tests — version 3.1, tags, sécurité, erreurs, exemples,
|
||
schémas de réponse, pages `/api`, `/docs`, `/redoc`, `/openapi.json`).
|
||
|
||
- **#61 Plugins système au complet** — système de plugins permettant d'étendre ObsiGate
|
||
(renderers personnalisés, filtres de recherche, actions d'éditeur), sandboxé pour la sécurité.
|
||
- Backend `backend/plugins.py` : validation du manifest `plugin.json` (name regex lowercase,
|
||
semver, hooks/permissions autorisés), stockage par vault `<vault>/.obsigate-plugins/`, lifecycle
|
||
complet (install/uninstall/enable/disable via marker `.disabled`), validation ZIP à l'upload
|
||
(anti path-traversal, max 100 fichiers, 500KB/fichier, 5MB upload), 9 endpoints `/api/plugins/*`
|
||
(list/get/hooks/code/template + install/uninstall/enable/disable admin-gated), template API,
|
||
scan au démarrage par vault (`get_plugin_registry().scan_vault`).
|
||
- Frontend `frontend/js/plugins.js` : PluginManager (install/uninstall/enable/disable/view-code),
|
||
sandbox d'exécution via Web Worker (code chargé par blob URL, protocole `postMessage` structuré,
|
||
isolation DOM/localStorage/network selon permissions), hooks dispatch
|
||
(`executeHook`, `onFileRender`, `onSearchFilter`, `onEditorAction`, `onSidebarItem`,
|
||
`onFileCreate`, `onFileDelete`, `onVaultMount`), UI Settings > Plugins.
|
||
- Sécurité : manifest de permissions (`read_files`, `write_files`, `network_request`, …
|
||
restreint), CSP stricte sans `importScripts`, limites de taille.
|
||
- Tests : `tests/test_plugins.py` (44 tests — validation manifest, lifecycle manager,
|
||
validation ZIP/directory, démarrage scan) + `tests/frontend/plugins.test.mjs`
|
||
(21 tests JSDOM — protocole sandbox Worker, isolation DOM, lifecycle mirror).
|
||
- CI : job lint ajoute `node plugins.test.mjs` aux tests JSDOM.
|
||
- Docs : `docs/PLUGINS.md` (manifest, hooks, permissions, modèle de sécurité, API, guide).
|
||
|
||
- **#78 Excalidraw — finitions** : décompression lz-string du format plugin Obsidian,
|
||
création depuis la modale et le menu contextuel, extraction du texte pour la recherche
|
||
(B5), support `.excalidraw.md` (commit ac16fc1 + correctifs associés).
|
||
|
||
- **#67 Notifications web (Push API)** : `backend/push.py`, `POST /api/push/subscribe`,
|
||
clés VAPID dans `config.json`, toggle par vault, payload (fichier/vault/action) et
|
||
ouverture du fichier au clic (commit ac16fc1).
|
||
|
||
- **#68 Health check enrichi** : `GET /api/health/detailed` (admin-gated) exposant index,
|
||
mémoire (RSS/heap), uptime, connexions SSE, backups et espace disque (commit ac16fc1).
|
||
|
||
- **#77 Desktop — jumplist vaults récents** dans le menu Démarrer (commit ac16fc1).
|
||
|
||
- **#75 Split View — matrice E2E complète (37 tests)** : 16 tests `split-view.spec.js`
|
||
(raccourcis, drag & drop, persistance, navigation clavier) + 21 tests
|
||
`split-view-matrix.spec.js` couvrant 100% des cas d'ouverture/fermeture.
|
||
|
||
### Documentation
|
||
|
||
- **#78 Excalidraw — doc utilisateur finalisée** : `.excalidraw` / `.excalidraw.md` ajoutés aux
|
||
formats supportés (README FR/EN), nouvelle section « Diagrammes Excalidraw » dans le guide
|
||
intégré (i18n FR/EN) et note de compatibilité avec le plugin Obsidian Excalidraw.
|
||
- **Roadmap** : #78 marqué terminé (B5 extraction texte, C8 menu contextuel, F3 E2E
|
||
`tests/e2e/excalidraw.spec.js`, H1-H3 docs) ; F2 non retenu. Points optionnels #61
|
||
(dépôt communautaire de plugins) et #74 (D2/E4/H2/I2) explicitement marqués non retenus.
|
||
|
||
### Corrigé
|
||
|
||
- **Assistant AI — sidebar qui ne s'ouvrait plus & erreur de contexte** :
|
||
- Le bouton flottant passait le **chemin d'un fichier** comme répertoire de contexte, d'où
|
||
l'erreur « Aucun fichier markdown trouvé dans ce dossier » à l'ouverture sur un document.
|
||
Le contexte est maintenant détecté automatiquement (documents ouverts → mode documents,
|
||
sinon mode général).
|
||
- Un panneau précédemment masqué (`obsigate-bookslm-hidden=true` persisté en localStorage)
|
||
restait caché lors d'une ouverture explicite → l'ouverture force désormais l'affichage.
|
||
- **Ergonomie du header** : le sélecteur fournisseur/modèle était sur la même ligne que les
|
||
actions et masquait ces dernières ; il est déplacé sur une seconde ligne dédiée (toolbar)
|
||
pour que « nouvelle conversation / export / plein écran / fermer » restent toujours visibles.
|
||
- **Clavier de la boîte de chat** : `Entrée` envoie la requête, `Ctrl+Entrée` insère un saut
|
||
de ligne (au lieu de l'inverse), avec un texte d'aide sous le champ.
|
||
|
||
- **Outil AI de l'UI — fiabilisation** :
|
||
- **BooksLM (chat IA par répertoire)** : les requêtes `context`/`chat` n'envoyaient pas le
|
||
jeton d'authentification (échec 401 quand l'auth est activée) et la réponse SSE était
|
||
mal parsée (le backend émet `{token: ...}`, le front lisait `data.content`) → les réponses
|
||
n'apparaissaient jamais. Le message utilisateur envoyé était le placeholder assistant vide
|
||
au lieu du texte saisi. Corrigé : requêtes authentifiées via `AuthManager` (retry 401),
|
||
parsing SSE `event:`/`data:` avec support `token`/`error`, historique construit avant
|
||
l'ajout du message courant, barre de progression basée sur `max_total_chars`.
|
||
- **AI Editor** : le raccourci `Ctrl/Cmd+J` (complétion inline) était re-lié à chaque
|
||
ouverture de l'éditeur (N listeners → N requêtes) ; un seul listener global est désormais
|
||
posé. Les libellés de la barre d'outils AI étaient codés en dur (FR/EN mélangés) → i18n
|
||
complet. La réécriture personnalisée utilisait `window.prompt()` → remplacée par une modale
|
||
accessible (Échap annule, Ctrl/Cmd+Entrée valide).
|
||
|
||
- **Recherche cassée (régression plugins)** : `onSearchFilter()` était appelée avec 2 arguments
|
||
au lieu de 3 (`frontend/js/search.js`), renvoyait `undefined`, faisait échouer le rendu des
|
||
résultats et basculait silencieusement sur la recherche hors-ligne (0 résultat). Corrigé →
|
||
la recherche full-text et l'autocomplétion refonctionnent (20 tests E2E).
|
||
- **`.excalidraw.md` corrompu à l'ouverture** : Excalidraw émet `onChange` au montage, ce qui
|
||
déclenchait un auto-save 2 s plus tard réécrivant le fichier au format JSON brut et détruisant
|
||
le format plugin Obsidian (`frontend/excalidraw-editor.html` + `frontend/js/excalidraw-viewer.js`).
|
||
Les changements initiaux sont désormais ignorés et le format `frontmatter + compressed-json`
|
||
est préservé à la sauvegarde.
|
||
- **Splash / tests E2E** : `window.__OBSIGATE_BOOTED` était posé avant la fin de `init()` — le
|
||
splash disparaissait trop tôt et les tests E2E interagissaient avant que les handlers soient
|
||
liés. Le flag est maintenant posé après résolution de `init()` (`frontend/js/app.js`), et
|
||
`goHome()`/`login()` attendent ce signal.
|
||
- **Tests E2E Excalidraw** : réécriture de `tests/e2e/excalidraw.spec.js` avec les sélecteurs
|
||
réels (modale `.obsigate-modal` + `#file-ext-select`/`#file-name-input`, menu contextuel,
|
||
`canvas.first()` pour les deux couches canvas).
|
||
|
||
---
|
||
|
||
## [2.1.0] — 2026-09-08
|
||
|
||
### Ajouté
|
||
|
||
- **#74 Support PDF au complet** — `GET /api/file/{vault}/pdf/info` (métadonnées sans
|
||
contenu), streaming avec HTTP Range / 206 Partial Content (rendu progressif des gros PDF),
|
||
config `OBSIGATE_PDF_MAX_SIZE_MB` (50) + `OBSIGATE_PDF_EXTRACT_TIMEOUT` (30s).
|
||
16 tests supplémentaires (26 au total dans `test_pdf.py`).
|
||
- **#64 MFA — WebAuthn** (second facteur en plus du TOTP) : enregistrement de clés de
|
||
sécurité / biométrie (Windows Hello, Touch ID), assertion au login, gestion des clés dans
|
||
« Sécurité du compte », codes de récupération émis à l'activation. Nouveau module
|
||
`backend/auth/webauthn_mfa.py` (lib `webauthn==2.6.0`, challenges in-memory TTL 180s à
|
||
usage unique). 10 tests avec authentificateur virtuel (CBOR réel, ECDSA P-256).
|
||
i18n FR/EN (13 clés). Config : `OBSIGATE_WEBAUTHN_RP_ID` / `_RP_NAME` / `_ORIGINS`.
|
||
- **#77 Desktop — port auto-increment** : `pick_free_port()` scanne 17890..17899 si le port
|
||
est occupé (2 instances côte à côte possibles) + 3 tests Rust (19 au total côté desktop).
|
||
- Docs : sections PDF README FR/EN (Range, /pdf/info), variables env, guide WebAuthn.
|
||
- **#75 Split View — matrice E2E complète (37 tests)** : 16 tests `split-view.spec.js` (raccourcis,
|
||
drag & drop, persistance, navigation clavier) + 21 tests `split-view-matrix.spec.js` couvrant
|
||
100% des cas d'ouverture/fermeture : boutons ⊞→/⊞↓, menu contextuel (diviser bas, fermer, fermer
|
||
les autres/à droite/tout, fermer le panneau, flyout « Déplacer vers… »), palette (diviser, focus
|
||
suivant/précédent, reset), fermeture par X/double-clic/molette/Ctrl+W, auto-collapse d'un panneau
|
||
vidé, plafond 4 panneaux, drag-to-split bas, pas de doublon à la réouverture.
|
||
- Fix `scripts/run-e2e-local.sh` : chemins Windows via `cygpath` (les env vars MSYS n'étaient pas
|
||
converties → vaults vides, les 16 tests split-view échouaient en local alors qu'ils passaient
|
||
en CI).
|
||
|
||
### Corrigé
|
||
|
||
- **PDF stream 500** : `api_pdf_stream` plantait systématiquement (`NameError: current_user`
|
||
non injecté — endpoint jamais couvert par un test). Désormais authentifié + testé.
|
||
- **Indexation incrémentale des PDF** : le chemin watcher (`_index_single_file_sync`) lisait
|
||
les PDFs en `read_text()` → contenu garbage indexé. Utilise maintenant `extract_pdf_text()`
|
||
comme le scan complet.
|
||
|
||
---
|
||
|
||
## [2.0.0] — 2026-08-25
|
||
|
||
> ObsiGate passe à **2.0.0** avec sa **version bureau native** et de nombreuses fonctionnalités
|
||
> de productivité (branch main, 341 commits après le tag v1.8.0).
|
||
|
||
### Ajouté
|
||
|
||
- **Application bureau native (Tauri 2)** — Porte d'entrée desktop pour vaults Obsidian (`desktop/`)
|
||
- **Dashboard administrateur (#71, backend)** — 4 endpoints admin-gated pour monitoring serveur
|
||
- `GET /api/admin/stats` — CPU/RAM/Disk/Uptime via psutil
|
||
- `GET /api/admin/audit` — 500 dernières entrées d'audit avec filtres `user`/`action`/`limit`/`offset`
|
||
- `GET /api/admin/backup-stats` — compte + taille + age par vault
|
||
- `GET /api/admin/stream` — Server-Sent Events qui push les stats toutes les 5s
|
||
- Nouveau module `backend/admin.py` + 13 tests pytest
|
||
- **Tests JSDOM PaneManager (#75, sous-tâche I2)** — 9 tests d'intégration frontend via JSDOM 30
|
||
- Couvre : factory, init, open/activate/close, isolation entre panes, drag/drop smoke
|
||
- Wired dans le CI Gitea (`.gitea/workflows/ci.yml`)
|
||
- Shell Rust + Tauri 2 (tray icon, notifications OS, auto-update depuis Gitea)
|
||
- Backend Python embarqué (python-embed) avec health check, démarrage ~2s
|
||
- Sélecteur de dossiers natif, config persistante des vaults (type VAULT vs DIR)
|
||
- Fenêtre console masquée, arrêt propre via tray, associations de fichiers `.md`
|
||
- Packages : Windows MSI + NSIS, Linux .deb + AppImage
|
||
- Pipeline CI/CD Desktop (`.gitea/workflows/desktop-build.yml`)
|
||
- Thème système auto (clair/sombre) + RAM réduite (~80 MB au repos)
|
||
- Écran de chargement inline (staging backend/frontend pour le bundle desktop)
|
||
- **Internationalisation FR/EN complète** — 1357 clés i18n, préférence serveur, guide entièrement traduit
|
||
- **Vue multi-panneaux (Split View #75)** — PaneManager + TabManager par panneau
|
||
- Split droite/bas, drag & drop cross-pane, drag-to-split (bord droit/bas)
|
||
- Boutons de split, navigation clavier, fermeture auto des panneaux vides
|
||
- **Mermaid.js** — Rendu de diagrammes (22 templates, thème dark synchronisé)
|
||
- Header bar Code/Preview, zoom, export SVG + PNG, plein écran / focus 480px
|
||
- Pré-processeur Obsidian (`[[liens]]`, `![[img]]`, `==highlight==`)
|
||
- **Gestionnaire de Backups complet** — Page, filtres, purge, restauration
|
||
- Diff viewer (unifié + côte à côte), preview 100 Ko, compression gzip
|
||
- Backup automatique, auto-nettoyage (max_backups_per_file)
|
||
- **Support Excalidraw (#78)** — Fichiers `.excalidraw` / `.excalidraw.md`
|
||
- Décompression lz-string, création depuis modale/menu contextuel
|
||
- **Éditeur Forge + autocomplétion IA** — Auto-height, Mermaid QI, ghost text
|
||
- Autocomplétion Ollama (qwen2.5-coder), Alt+/, auto-continuation listes/checkboxes
|
||
- **Support PDF + multi-format** — PDF avec TOC, images/CSV/JSON/TXT
|
||
- **15 thèmes clair/sombre (#65)** — Système de thèmes configurable
|
||
- **Mode hors-ligne PWA (#59)** — Badge hors-ligne + gestion des conflits
|
||
- **Tests E2E Playwright (#58)** — Suite desktop (44 tests) + CI
|
||
|
||
### Modifié
|
||
|
||
- `desktop/` — Nouveau : application Tauri (Cargo.toml, build.rs, `src/main.rs`, scripts build)
|
||
- `frontend/` — i18n, split view, Mermaid, Excalidraw, Forge, thèmes
|
||
- `backend/` — Endpoints backups, Excalidraw, multi-format, versioning git
|
||
- `docs/ROADMAP.md` — Feuille de route passée à 2.0.0-dev, items #75/#78 complétés
|
||
|
||
---
|
||
|
||
## [1.8.0] — 2026-06-04
|
||
|
||
### Ajouté
|
||
|
||
- **Palette de commandes** — Navigation rapide fichiers + commandes
|
||
- Raccourcis : `Ctrl+P` fichiers, `Ctrl+Alt+Espace` commandes, `Ctrl+Shift+Espace`
|
||
- Navigateur de dossiers : créer/supprimer fichiers/dossiers par sélection
|
||
- Opérateurs `+include` / `-exclude` dans la recherche globale
|
||
- 6 nouvelles commandes : créer/supprimer fichiers/dossiers, éditer, pop-out
|
||
- **Barre d'outils mobile de bas de page** — Type Obsidian 📱
|
||
- Explorateur, recherche, palette, changement d'onglet
|
||
- Indicateur de vault contextuel sous le header, pull-to-refresh
|
||
- **Diff viewer des backups** — Comparaison unifiée + côte à côte, restauration
|
||
- **Indicateur AI Actif** — Badge/statut IA dans le header (lecture runtime des clés)
|
||
- **Page d'accueil de vault** — Liste récursive des fichiers par date
|
||
- **Drag & drop de fichiers** dans l'arborescence
|
||
- **Guide d'aide enrichi** — Recherche, scroll spy, slide-over mobile, section webhooks
|
||
- **Indexation inversée non-bloquante** (`run_in_executor`)
|
||
- **Infrastructure de tests** — Couverture pytest portée à 70% (+109 tests)
|
||
|
||
### Modifié
|
||
|
||
- `frontend/` — Palette, mobile toolbar, aide, AI indicator, vault home
|
||
- `backend/` — Indexation non-bloquante, statut IA, diff/restauration backups
|
||
- `docs/` — Guide d'utilisation enrichi (navigation clavier), CHANGELOG/README/ROADMAP
|
||
|
||
### Corrigé
|
||
|
||
- Correctifs UI mobile, palette, aide et AI toolbar (thème clair, menu clipping)
|
||
|
||
---
|
||
|
||
## [1.7.0] — 2026-05-30
|
||
|
||
### Ajouté
|
||
|
||
- **AI Editor Toolbar** — Barre d'outils IA intégrée à l'éditeur CodeMirror
|
||
- Menus dropdown : Edit (improve, fix spelling, shorter, longer, simplify), Tone (professional, casual), Translate (multi-langue), Generate (explain, summarize, continue), Custom Rewrite, Toolbox (to list, to table, frontmatter, to canvas)
|
||
- Multi-provider : DeepSeek / OpenRouter / Gemini, configurable via `.env`
|
||
- 16 endpoints REST : `POST /api/ai/{edit|tone|translate|generate|rewrite|toolbox}`
|
||
- Auto-save silencieux (2s debounce) avec feedback visuel toast
|
||
- Cache toolbar si pas de clé API configurée
|
||
- Messages d'erreur clairs (401→clé invalide, etc.)
|
||
- **Graph view — Améliorations majeures**
|
||
- Header flat design 2 lignes responsives (titre flexible + recherche dédiée + barre statut)
|
||
- Navigation historique ← → + ↑ Parent
|
||
- Sticky panels : tuile info (top-left/right) avec métadonnées, preview pleine hauteur (droite)
|
||
- Ctrl+survol → aperçu contenu formaté (via `/raw`) dans tooltip
|
||
- Filtre par tag dans la vue graphe
|
||
- Boutons close ✕ sur les panneaux
|
||
- Fond hover foncé unifié
|
||
|
||
### Modifié
|
||
|
||
- **backends/ai.py** — Nouveau module IA backend
|
||
- **backends/ai_routes.py** — Routes API pour l'éditeur IA
|
||
- **frontend/js/ai.js** — Module frontend de la toolbar IA (404 lignes)
|
||
- **frontend/js/graph.js** — Refonte complète : sticky panels, nav historique, aperçu markdown
|
||
|
||
---
|
||
|
||
## [1.6.0] — 2026-05-29
|
||
|
||
### Ajouté
|
||
|
||
- **Vue graphe des wikilinks** — Canvas force-directed
|
||
- Phase 1 : Full-vault view, filtre par tag, backlinks entrants, métriques de nœud
|
||
- Phase 2 : Recherche visuelle, tooltips survol, couleurs adaptatives, slider profondeur (0-3)
|
||
- Phase 3 : Filtre par type (dossier/fichier/.md/autre), mode focus, plein écran, export PNG
|
||
- Phase 4 : Barnes-Hut O(n log n), cache graphe
|
||
- **sortedcontainers** → O(log n) insert/remove dans l'index inversé
|
||
- **CI/CD Pipeline complet** — Gitea Actions
|
||
- Ruff linting (0 erreur)
|
||
- Mypy type checking (0 erreur)
|
||
- Pytest — 175 tests, 49% coverage
|
||
- Bandit SAST — scan de sécurité
|
||
- Pip-audit — vulnérabilités dépendances
|
||
- Docker build — vérification image
|
||
- Coverage artifact — uploadé via `actions/upload-artifact@v3`
|
||
- Runner Gitea auto-hébergé (`gitea/act_runner:0.2.11` sur Alpine/Proxmox)
|
||
|
||
### Modifié
|
||
|
||
- `backend/search.py` — Remplacement bisect → SortedList pour le vocabulaire
|
||
- `.gitea/workflows/ci.yml` — Pipeline CI/CD complet
|
||
|
||
### Corrigé
|
||
|
||
- Résolution de 28 erreurs mypy pré-existantes
|
||
- Fix lint ruff + faux positifs bandit + pip-audit non-bloquant
|
||
|
||
---
|
||
|
||
## [1.5.1] — 2026-05-28
|
||
|
||
### Ajouté
|
||
|
||
- **Split `app.js` (8 875 lignes) en 16 modules ES**
|
||
- Modules : `state.js`, `utils.js`, `auth.js`, `ui.js` (76KB), `viewer.js` (47KB), `sidebar.js`, `search.js` (45KB), `config.js`, `dashboard.js`, `graph.js` (33KB), `sync.js`, `legacy.js`, `ai.js`
|
||
- Import/export validator CI (`tests/frontend/validate-imports.mjs`)
|
||
- Tests unitaires frontend (`tests/frontend/unit.test.mjs`)
|
||
- **Stemming français** — `snowballstemmer` intégré au tokenizer
|
||
- "manger" trouve "mangé", "mangeons", "mangeait"
|
||
- Performance O(T) au lieu de O(S×T) — fix freeze 15min sur gros vaults
|
||
- Crash guard : try/except snowballstemmer IndexError sur tokens exotiques
|
||
|
||
### Modifié
|
||
|
||
- `frontend/js/app.js` → entrypoint ES module important les 16 modules
|
||
- `backend/search.py` — tokenizer avec FrenchStemmer
|
||
|
||
### Corrigé
|
||
|
||
- Nombreuses régressions post-split : imports manquants, exports oubliés, shadowing de variables
|
||
- Réécriture state.js → mutable object (`export const state = {...}`) pour éviter les erreurs `assignment to constant`
|
||
- Plus de 60 correctifs d'imports/exports validés par le validator CI
|
||
- Tags de template `{{...}}` exclus du tag cloud via filtre configurable
|
||
|
||
---
|
||
|
||
## [1.5.0] — 2026-05-26
|
||
|
||
### Ajouté
|
||
|
||
- **Publication publique** — Génération de lien partageable avec token unique (64-char hex)
|
||
- Expiration configurable, lecture seule, sans authentification
|
||
- `backend/share.py` + endpoints CRUD + vue publique `/s/{token}`
|
||
- Export PDF via WeasyPrint (lazy import) dans la vue publique
|
||
- Support fichiers non-Markdown dans la vue publique
|
||
- **Webhooks** — Notifications HTTP POST vers services externes
|
||
- Signature HMAC-SHA256 optionnelle
|
||
- `backend/webhooks.py` + CRUD endpoints + UI dans Configuration
|
||
- **Dashboard statistiques** — Métriques agrégées par vault
|
||
- Widget `DashboardStatsWidget` avec 4 cartes (fichiers, tags, taille, vaults)
|
||
- Widget "Derniers fichiers ouverts" avec timestamps
|
||
- **Documentation OpenAPI enrichie** — Tous les modèles Pydantic documentés (`Field(description=...)`)
|
||
- Visible dans `/docs` (Swagger UI) et `/redoc`
|
||
- **Documentation complète** — `ANALYSE_REVIEW.md`, `AUDIT_TECHNIQUE.md`, `ROADMAP.md`
|
||
|
||
### Modifié
|
||
|
||
- `frontend/js/app.js` — Nouveau système d'onglets (TabManager), dashboard
|
||
- `frontend/style.css` — Dashboard, share view, webhooks UI
|
||
- `backend/main.py` — Nouveaux endpoints share/webhooks/dashboard
|
||
- `backend/search.py` — Index inversé incrémental (hook pattern)
|
||
|
||
---
|
||
|
||
## [1.4.0] — 2026-05-25
|
||
|
||
### Ajouté
|
||
|
||
- **Rate limiting** — IP-based (10 tentatives/15min) + lockout par compte (5 tentatives)
|
||
- `backend/ratelimit.py` — RateLimiter thread-safe avec nettoyage périodique
|
||
- Intégré à `backend/auth/router.py`
|
||
- **Secret redactor** — Masquage automatique des secrets dans les aperçus
|
||
- `backend/secret_redactor.py` — JWT, API keys, tokens GitHub, clés privées, connection strings
|
||
- **Audit log** — Traçage des écritures/suppressions/changements de config
|
||
- `backend/audit.py` — JSON lines dans `data/audit.log`, rotation 10MB
|
||
- **Backup automatique avant écriture**
|
||
- Sauvegarde du contenu original dans `.obsigate-backup/` avant PUT/DELETE
|
||
- **Backlinks panel** — Fichiers avec wikilinks pointant vers le fichier courant
|
||
- `GET /api/file/{vault}/backlinks` + index inversé dans `indexer.py`
|
||
- **Gestion des conflits Syncthing**
|
||
- Détection automatique des fichiers `.sync-conflict-*`
|
||
- Résolution : garder local, garder conflit
|
||
- `GET /api/conflicts`, `POST /api/conflicts/resolve`
|
||
- **Syncthing conflicts dashboard** — Vue dédiée dans l'UI
|
||
- **IGNORED_DIRS configurable** — `OBSIGATE_IGNORED_DIRS` (liste séparée par virgules)
|
||
- **Timeout de session configurable** — `OBSIGATE_ACCESS_TOKEN_TTL` / `OBSIGATE_REFRESH_TOKEN_TTL`
|
||
|
||
### Modifié
|
||
|
||
- `backend/main.py` — +audit, +backup, +redaction, +backlinks endpoint, +conflicts endpoint
|
||
- `backend/indexer.py` — +backlink index, +IGNORED_DIRS
|
||
- `backend/auth/router.py` — +IP rate limiting
|
||
- `backend/auth/jwt_handler.py` — +configurable TTL
|
||
- `backend/watcher.py` — +configurable IGNORED_DIRS
|
||
|
||
---
|
||
|
||
## [1.3.0] — 2026-05-23
|
||
|
||
### Ajouté
|
||
|
||
- **Authentification complète** — JWT + Argon2id
|
||
- Login/logout, refresh tokens, cookies httpOnly
|
||
- Contrôle d'accès par vault
|
||
- Interface d'administration : création/modification/suppression d'utilisateurs
|
||
- "Se souvenir de moi", sessions persistantes
|
||
- `backend/auth/` — 5 modules (~600 lignes)
|
||
- **CodeMirror 6** — Éditeur de fichiers intégré
|
||
- Syntax highlighting multi-langage
|
||
- Sauvegarde, annulation, fallback textarea si CM6 échoue
|
||
- Auto-sync frontmatter YAML
|
||
- Find-in-page (Ctrl+F) avec regex, barre de navigation
|
||
- **PWA complet** — `manifest.json`, `sw.js`, icônes multi-tailles
|
||
- Installation via bouton "Installer l'application"
|
||
- Thème synchronisé entre fenêtres popout
|
||
- Service Worker avec mise en cache
|
||
- **Synchronisation temps réel** — Watchdog + SSE
|
||
- Surveillance automatique des fichiers
|
||
- Mise à jour incrémentale de l'index
|
||
- SSE Manager avec reconnexion automatique
|
||
- `backend/watcher.py` — watchdog observer avec debounce 2s
|
||
- **Drag & drop / rename** — Menu contextuel arborescence
|
||
- Création fichier/dossier, rename inline, suppression
|
||
- Boutons d'action toujours visibles, support mobile long-press
|
||
|
||
### Modifié
|
||
|
||
- `frontend/app.js` — Refonte majeure : authentication flows, code editor, PWA, sync
|
||
- `frontend/style.css` — CodeMirror themes, auth forms, PWA UI, responsive
|
||
- `docker-compose.yml` — auth env vars, data volume, non-root user
|
||
- `backend/main.py` — auth middleware, file CRUD, code editor API, SSE, PWA
|
||
- `requirements.txt` — argon2-cffi, python-jose, python-multipart
|
||
|
||
---
|
||
|
||
## [1.2.0] — 2026-05-18
|
||
|
||
### Ajouté
|
||
|
||
- **Rendu d'images Obsidian** — Support complet de toutes les syntaxes
|
||
- Standard Markdown avec attributs HTML
|
||
- Wiki-link embed (`![[path/to/image.png]]`)
|
||
- Markdown standard (``)
|
||
- Résolution multi-stratégies (7 niveaux)
|
||
- Indexation des attachements au démarrage
|
||
- Cache de résolution pour performance
|
||
- **Système de fichiers cachés** — Configuration par vault
|
||
- `includeHidden`, `hiddenWhitelist` — UI + env vars
|
||
- Filtrage côté client (hideHiddenFiles)
|
||
|
||
### Modifié
|
||
|
||
- `backend/attachment_indexer.py` — Scan et indexation d'images
|
||
- `backend/image_processor.py` — Prétraitement Markdown pour les syntaxes d'images
|
||
- `GET /api/image/{vault}?path=` — Serve images avec MIME types
|
||
- `POST /api/attachments/rescan/{vault}` — Rescan manuel
|
||
- `HIDDEN_FILES_GUIDE.md`, `IMAGE_RENDERING_GUIDE.md`
|
||
|
||
---
|
||
|
||
## [1.1.0] — 2026-05-15
|
||
|
||
### Ajouté
|
||
|
||
- **Recherche TF-IDF avancée** — Moteur complet avec index inversé
|
||
- Opérateurs : `tag:`, `vault:`, `title:`, `path:`, `ext:`
|
||
- Autocomplétion intelligente (fichiers, tags, historique)
|
||
- Facettes, pagination, tri par pertinence
|
||
- Snippets surlignés `<mark>`, accent-insensitive
|
||
- Search history (localStorage, max 50, LIFO, dédupliqué)
|
||
- **Recherche regex** — `extractRegexSnippet()` avec surlignage
|
||
- **Recherches sauvegardées** — CRUD API + sidebar UI
|
||
- Sauvegarde/chargement/suppression de requêtes
|
||
- **Filtres de recherche** — toggles (case, mot entier, regex), chemins
|
||
- **Onglets sidebar** — vaults, tags, récents, saved searches
|
||
- **Auto-expand vault** dans le filtre sidebar
|
||
- **Tree search** — Filtrage temps réel de l'arborescence avec surlignage
|
||
|
||
### Modifié
|
||
|
||
- `backend/search.py` — Nouveau : InvertedIndex, TF-IDF, autocomplete
|
||
- `frontend/app.js` — Refonte recherche : nouveau système de requêtes, facettes, pagination, autocomplete
|
||
- `frontend/style.css` — Search results cards, autocomplete dropdown, tags
|
||
|
||
---
|
||
|
||
## [1.0.0] — 2026-05-10
|
||
|
||
### Ajouté
|
||
|
||
- **Première version stable** — Porte d'entrée web pour vaults Obsidian
|
||
- **Multi-vault** — Visualisation de plusieurs vaults simultanément
|
||
- **Arborescence** — Navigation hiérarchique avec lazy-loading
|
||
- **Rendu Markdown** — Conversion HTML via mistune (tables, task lists, footnotes, strikethrough)
|
||
- **Extraction YAML frontmatter** — Tous les champs parsés avec carte pliable, badges, tags
|
||
- **Vue Source (raw)** — Toggle markdown brut + frontmatter
|
||
- **Édition** — PUT/DELETE fichiers via API
|
||
- **Breadcrumbs** — Navigation avec auto-expand et highlight
|
||
- **TOC** — Table des matières avec scroll spy et barre de progression
|
||
- **Thème clair/sombre** — Toggle localStorage + synchronisé fenêtres popout
|
||
- **Popout** — Fenêtre détachée pour affichage standalone
|
||
- **Configuration UI** — Paramètres persistants par vault
|
||
- **Docker multi-stage** — Image ~180MB, linux/amd64 + arm64 + arm/v7 + i386
|
||
- **Healthcheck** — Endpoint `/api/health`
|
||
- **Headers sécurité** — CSP, X-Frame-Options, XSS-Protection, Referrer-Policy
|
||
- **Path traversal protection** — `_resolve_safe_path()` symlink-aware
|
||
- **Security hardening** — Utilisateur non-root (UID 1000)
|
||
- **Compression GZip** (SSE-safe), **Cache-Control immutable**
|
||
- **build.sh** — Script de build automatisé
|
||
|
||
### Architecture
|
||
|
||
- **Backend** : FastAPI 0.110.3, uvicorn 0.30.0, Python 3.11+
|
||
- **Frontend** : Vanilla JS SPA (0 dépendances npm), CSS custom properties
|
||
- **Indexation** : In-memory, mise à jour incrémentale, watcher watchdog
|
||
- **Recherche** : TF-IDF inversé, sans I/O disque
|