- Add .dockerignore to exclude .git, __pycache__, docs, etc. from Docker context - Create .env.example template with documented env vars - Move OBSIGATE_ADMIN_PASSWORD from docker-compose.yml to env_file: .env - Add .env.* to .gitignore (excluding .env.example) - Enable GZipMiddleware for ~70% bandwidth reduction on text responses - Add Cache-Control: immutable for /static/ assets - Update ROADMAP: mark all 4 quick wins as done, add audit findings - Add comprehensive technical audit report (AUDIT_TECHNIQUE_2026-05-27.md)
12 KiB
ObsiGate — Roadmap
Date : 2026-05-27 | Version : 1.4.0 / 1.5.0
Dernier audit : AUDIT_TECHNIQUE_2026-05-27.md — Note globale 7.5/10
Légende
- ✅ Complété
- 🟡 En cours / Partiel / À investiguer
- ⬜ À faire
- 🔴 Critique
Quick Wins (15-30 min cumulées) — Implémenter immédiatement
Ces 4 actions prennent moins de 30 minutes au total et ont un impact élevé.
✅ .dockerignore — Réduire le contexte de build Docker
Impact : Sécurité (pas de fuite de .git), performance (build plus rapide)
✅ .env pour les secrets — Ne jamais commiter de mots de passe
Impact : Sécurité (pas de secret dans le repo)
✅ Compression GZip — Réduire la bande passante de ~70%
Impact : Performance (pages plus rapides, moins de data transférée)
✅ Cache-Control pour assets statiques — Éviter les re-téléchargements
Impact : Performance (cache navigateur sur CSS/JS/icons)
Nouvelles fonctionnalités (historique TODO.md)
- ✅ Indexation incrémentale automatique — Le watcher détecte les nouveaux fichiers et met à jour l'index sans réindexation complète. Utilise
_on_vault_change→update_single_file/remove_single_file/handle_file_move. - ✅ Copier le chemin — Option "Copier le chemin" dans le menu contextuel (clic droit) de l'arborescence pour tout élément (vault, dossier, fichier).
- ✅ Panneau À propos — Section "À propos" dans le modal Configurations affichant la version, la version API, les stats de santé.
- ✅ Vue Graphique — Canvas force-directed accessible via menu contextuel sur les vaults et dossiers. Affiche nœuds (fichiers/dossiers) et arêtes (parent + wikilinks). Zoom/pan interactif.
- ✅ Mode onglets (Tabs) — Barre d'onglets multi-fichiers permettant de visualiser plusieurs fichiers simultanément, avec fermeture et navigation.
- ✅ Login Popout — La fenêtre popout affiche un formulaire de connexion quand l'authentification est requise, puis recharge la page après login.
Corrections (historique TODO.md)
- ✅ Login popout avec redirection — Quand un fichier est ouvert via l'URL popout et que l'authentification est requise, un formulaire de login est proposé. Après connexion réussie, la page recharge automatiquement.
- ✅ Correction TOC — scroll avec caractères accentués — Les fonctions slugify (frontend et backend) utilisent maintenant
unicodedata.category()pour une classification Unicode-aware identique (catégories L* et N* au lieu de.isalpha()ASCII-only).
Améliorations complétées (voir ANALYSE_REVIEW.md §4 et AUDIT_TECHNIQUE)
🔴 Sécurité — P0
- ✅ Rate limiting sur le login — IP-based rate limiting (10 tentatives/15 min par IP) + lockout par compte (5 tentatives). Implémenté dans
backend/ratelimit.py+backend/auth/router.py. - ✅ Masquage automatique des secrets —
SecretRedactordansbackend/secret_redactor.pymasque JWT, clés API, tokens GitHub, clés privées et connection strings dans les aperçus de contenu.
🟠 Robustesse — P1
- ✅ Log d'audit —
backend/audit.pytrace les écritures, suppressions et changements de config dansdata/audit.log(format JSON lines). - ✅ Backup automatique avant écriture — Sauvegarde du contenu original dans
.obsigate-backup/avant chaque PUT ou DELETE, avec timestamp.
🟡 UX — P2
- ✅ Clic simple / double clic dans l'arborescence — Simple clic = onglet preview (italique, temporaire). Double clic = onglet persistant (normal, cumulable). Implémenté dans
TabManager.openPreview()/TabManager.openPersistent(). - ✅ Backlinks panel — Panneau affichant les fichiers avec wikilinks pointant vers le fichier courant. Backend :
GET /api/file/{vault}/backlinks+ index inversé dansindexer.py. Frontend : panneaurenderBacklinksPanel(). - ✅ Gestion des conflits Syncthing — Dashboard « Conflits » avec détection automatique des fichiers
.sync-conflict-*et résolution (garder local, garder conflit). Backend :GET /api/conflicts,POST /api/conflicts/resolve. - ✅ Liste IGNORED_DIRS configurable — Configurable via
OBSIGATE_IGNORED_DIRS(liste séparée par virgules). Appliqué au watcher et à l'indexer. - ✅ Timeout de session configurable — JWT TTL configurable via
OBSIGATE_ACCESS_TOKEN_TTLetOBSIGATE_REFRESH_TOKEN_TTL.
🟢 Fonctionnel — P3/P4
- ✅ Publication publique de documents — Génération de lien partageable avec token unique (64-char hex), expiration configurable, lecture seule, sans authentification. Backend :
backend/share.py+POST /api/share/{vault},GET /api/shares,DELETE /api/share/{id},GET /s/{token}(vue publique). Frontend : bouton « Partager » dans les actions de fichier + dialogue de copie de lien. - ✅ Dashboard statistiques — Métriques agrégées par vault : fichiers totaux, taille, tags uniques. Backend :
GET /api/dashboard. Frontend : widgetDashboardStatsWidgetavec 4 cartes (fichiers, tags, taille, vaults). - ✅ Webhooks — Notifications HTTP POST vers des services externes lors de changements (création, modification, suppression, renommage de fichiers et dossiers). Signature HMAC-SHA256 optionnelle. Backend :
backend/webhooks.py+ CRUD endpoints. Frontend : gestion dans le modal Configurations. - ✅ Documentation OpenAPI enrichie — Tous les modèles Pydantic (
FileContentResponse,SearchResponse,AdvancedSearchResponse, etc.) ont maintenant desField(description=...)documentés visibles dans/docs(Swagger UI) et/redoc. - ✅ Gestion fichiers non-supportés — Message explicite avec nom du fichier, taille et bouton de téléchargement pour les fichiers binaires. Backend : réponse structurée avec
unsupported: true. Frontend : interfaceunsupported-file.
🔴 Problèmes identifiés par l'audit (P1) — Priorité immédiate
⬜ Tests unitaires backend (pytest) — Risque N°1
Impact : Sans tests, chaque changement = risque de régression. 20k lignes sans filet.
Comment :
# 1. Installer pytest
pip install pytest pytest-cov pytest-asyncio httpx
# 2. Créer tests/conftest.py avec fixtures (TestClient, vaults de test)
# 3. Tests à créer en priorité :
# - backend/tests/test_search.py : tokenizer, TF-IDF scoring, snippets, regex
# - backend/tests/test_indexer.py : parsing frontmatter, extraction tags, wikilinks
# - backend/tests/test_auth.py : JWT flow, login, permissions, rate limiting
# - backend/tests/test_api.py : health, vaults, browse, search (intégration)
# 4. Lancer avec couverture
pytest --cov=backend --cov-report=term --cov-report=html
⬜ CI/CD pipeline (GitHub/Gitea Actions)
Impact : Automatiser lint, test, security scan et build Docker à chaque push.
Comment :
# Créer .github/workflows/ci.yml (ou .gitea/workflows/ci.yml)
name: CI
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/ruff-action@v1
- run: pip install mypy && mypy backend/ --ignore-missing-imports
test:
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install -r backend/requirements.txt pytest pytest-cov pytest-asyncio httpx
- run: pytest --cov=backend --cov-report=xml
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install pip-audit bandit && pip-audit && bandit -r backend/
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker build -t obsigate:ci .
✅ Mot de passe admin hors de docker-compose.yml
Impact : Secret dans le fichier de config = risque si le repo est partagé.
Fait : Mot de passe retiré de docker-compose.yml, remplacé par env_file: .env.
🟠 Problèmes modérés (P2) — Cette semaine
⬜ Splitter app.js en modules ES (8,869 lignes → ~8 modules)
Impact : Maintenabilité, onboarding développeur, réduction de la dette technique.
Comment : Voir la section Architecture dans AUDIT_TECHNIQUE_2026-05-27.md §4.3.8.
Approche : extraction progressive module par module, en commençant par ui.js (helpers).
⬜ Remplacer bisect par sortedcontainers.SortedList dans l'InvertedIndex
Impact : O(log n) insert/remove au lieu de O(n) pour le vocabulaire de tokens.
Comment :
pip install sortedcontainers
# backend/search.py — dans InvertedIndex.__init__ :
from sortedcontainers import SortedList
self._sorted_tokens = SortedList()
# add_document : remplacer bisect.insort par self._sorted_tokens.add(token)
# _remove_doc_internals : remplacer bisect.bisect_left + pop par self._sorted_tokens.discard(token)
⬜ Stemming français pour la recherche TF-IDF
Impact : "manger" trouve "mangé", "mangeons", "mangeait". Qualité de recherche ×2.
Comment :
pip install snowballstemmer
# backend/search.py — dans tokenize() :
from snowballstemmer import FrenchStemmer
_stemmer = FrenchStemmer()
def tokenize(text: str) -> List[str]:
words = _WORD_RE.findall(normalize_text(text))
return _stemmer.stemWords(words) # stemming français
🟡 Améliorations UX (P2/P3) — Ce mois-ci
- ⬜ Palette de commandes (
Ctrl+P) — Navigation rapide style VS Code - ⬜ Drag & drop de fichiers dans l'arborescence pour déplacer/réorganiser
- ⬜ Diff viewer pour comparer les versions backupées (
.obsigate-backup/) - ⬜ Fichiers récents par vault dans le dashboard (filtrage par vault actif)
- ⬜ Finaliser la vue Graphique — Le backend a déjà
GraphNode/GraphEdge/GraphResponse, finaliser l'UI
🟢 Fonctionnalités next-level (P3/P4) — Long terme
- ⬜ Mode hors-ligne PWA complet — IndexedDB pour recherche offline + synchro au retour en ligne
- ⬜ OAuth2/OIDC — Google, GitHub, authentification SSO en plus du JWT local
- ⬜ Plugin système — Extensions utilisateur (custom renderers, search operators, widgets)
- ⬜ Collaboration temps réel — WebSocket + CRDT (Yjs) pour édition simultanée
- ⬜ i18n — Support anglais + français avec système de traduction
- ⬜ Authentification multi-facteurs — TOTP/WebAuthn
- ⬜ Health check enrichi — État de l'index, mémoire, uptime, clients SSE
Qualité & Polish (P5+) — Fondations
- ⬜ Tests unitaires (pytest) — remonté en P1
- ⬜ Tests E2E (Playwright)
- ⬜ CI/CD pipeline (GitHub Actions) — remonté en P1
- ⬜ CHANGELOG.md
- ⬜ Documentation utilisateur enrichie
- ⬜ Déduplication de
IGNORED_DIRS— indexer.py et watcher.py ont des définitions séparées - ⬜ Rotation des logs Python —
RotatingFileHandlerpour éviter les logs infinis
Chronologie suggérée
| Semaine | Actions |
|---|---|
| S27 (cette semaine) | Quick Wins ✅ (.dockerignore, .env, GZip, Cache-Control) |
| S27-S28 | Tests unitaires backend — objectif 70% coverage |
| S28 | CI/CD pipeline |
| S29 | Split app.js en modules (commencer par ui.js, puis search.js) |
| S30 | Stemming français + sortedcontainers |
| S31+ | Fonctionnalités P3/P4 au fil de l'eau |
Document généré le 2026-05-27 — Intègre les recommandations de l'audit technique.
Voir aussi : AUDIT_TECHNIQUE_2026-05-27.md pour le rapport complet.