Implement multi-stage Docker build with security hardening, add health check endpoint, optimize in-memory search with O(1) wikilink lookup, extract inline tags from markdown content, and enhance documentation with architecture diagrams and performance metrics
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.
|
||||
|
||||
[]()
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://www.docker.com/)
|
||||
[](https://www.python.org/)
|
||||
@@ -25,6 +26,7 @@
|
||||
## 📋 Table des matières
|
||||
|
||||
- [Fonctionnalités](#-fonctionnalités)
|
||||
- [Architecture](#-architecture)
|
||||
- [Prérequis](#-prérequis)
|
||||
- [Installation rapide](#-installation-rapide)
|
||||
- [Configuration détaillée](#-configuration-détaillée)
|
||||
@@ -33,8 +35,10 @@
|
||||
- [Build multi-platform](#-build-multi-platform)
|
||||
- [Utilisation](#-utilisation)
|
||||
- [API](#-api)
|
||||
- [Performance](#-performance)
|
||||
- [Dépannage](#-dépannage)
|
||||
- [Stack technique](#-stack-technique)
|
||||
- [Changelog](#-changelog)
|
||||
|
||||
---
|
||||
|
||||
@@ -48,7 +52,8 @@
|
||||
- **🎨 Syntax highlight** : Coloration syntaxique des blocs de code
|
||||
- **🌓 Thème clair/sombre** : Toggle persisté en localStorage
|
||||
- **🐳 Docker multi-platform** : linux/amd64, linux/arm64, linux/arm/v7, linux/386
|
||||
- **🔒 Lecture seule** : Aucune écriture sur vos vaults (sécurité maximale)
|
||||
- **🔒 Sécurité** : Protection contre le path traversal, utilisateur non-root dans Docker
|
||||
- **❤️ Healthcheck** : Endpoint `/api/health` intégré pour Docker et monitoring
|
||||
|
||||
---
|
||||
|
||||
@@ -270,15 +275,25 @@ ObsiGate expose une API REST complète :
|
||||
|
||||
| Endpoint | Description | Méthode |
|
||||
|----------|-------------|---------|
|
||||
| `/api/health` | Health check (status, version, stats) | GET |
|
||||
| `/api/vaults` | Liste des vaults configurées | GET |
|
||||
| `/api/browse/{vault}?path=` | Navigation dans les dossiers | GET |
|
||||
| `/api/file/{vault}?path=` | Contenu rendu d'un fichier .md | GET |
|
||||
| `/api/file/{vault}?path=` | Contenu rendu d'un fichier | GET |
|
||||
| `/api/file/{vault}/raw?path=` | Contenu brut d'un fichier | GET |
|
||||
| `/api/file/{vault}/download?path=` | Téléchargement d'un fichier | GET |
|
||||
| `/api/file/{vault}/save?path=` | Sauvegarder un fichier | PUT |
|
||||
| `/api/file/{vault}?path=` | Supprimer un fichier | DELETE |
|
||||
| `/api/search?q=&vault=&tag=` | Recherche fulltext | GET |
|
||||
| `/api/tags?vault=` | Tags uniques avec compteurs | GET |
|
||||
| `/api/index/reload` | Force un re-scan des vaults | GET |
|
||||
|
||||
> Tous les endpoints exposent des schémas Pydantic documentés. La doc interactive est disponible sur `/docs` (Swagger UI).
|
||||
|
||||
**Exemple d'utilisation :**
|
||||
```bash
|
||||
# Health check
|
||||
curl http://localhost:2020/api/health
|
||||
|
||||
# Lister les vaults
|
||||
curl http://localhost:2020/api/vaults
|
||||
|
||||
@@ -327,51 +342,106 @@ docker-compose logs -f obsigate
|
||||
docker-compose logs --tail=100 obsigate
|
||||
```
|
||||
|
||||
### Performance
|
||||
---
|
||||
|
||||
- **Indexation** : Première utilisation peut prendre quelques secondes
|
||||
- **Mémoire** : ~50-100MB par 1000 fichiers (index en mémoire)
|
||||
- **CPU** : Minimal, sauf lors des recherches fulltext
|
||||
## ⚡ Performance
|
||||
|
||||
| Métrique | Estimation |
|
||||
|----------|------------|
|
||||
| **Indexation** | ~1–2s pour 1 000 fichiers markdown |
|
||||
| **Recherche fulltext** | < 50ms (index en mémoire, zéro I/O disque) |
|
||||
| **Résolution wikilinks** | O(1) via table de lookup |
|
||||
| **Mémoire** | ~80–150MB par 1 000 fichiers (contenu capé à 100 KB/fichier) |
|
||||
| **Image Docker** | ~180MB (multi-stage, sans outils de build) |
|
||||
| **CPU** | Minimal ; pas de polling, pas de watchers |
|
||||
|
||||
### Optimisations clés (v1.1.0)
|
||||
|
||||
- **Recherche sans I/O** : le contenu des fichiers est mis en cache dans l'index mémoire
|
||||
- **Scoring multi-facteurs** : titre exact (+20), titre partiel (+10), chemin (+5), tag (+3), fréquence contenu (x1 par occurrence, capé à 10)
|
||||
- **Rendu Markdown singleton** : le renderer mistune est instancié une seule fois
|
||||
- **AbortController** : les requêtes de recherche obsolètes sont annulées côté client
|
||||
- **Debounced icon rendering** : `lucide.createIcons()` est batché via `requestAnimationFrame`
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ Sécurité
|
||||
|
||||
- **Path traversal** : tous les endpoints fichier valident que le chemin résolu reste dans la vault
|
||||
- **Utilisateur non-root** : le conteneur Docker tourne sous l'utilisateur `obsigate`
|
||||
- **Volumes read-only** : les vaults sont montées en `:ro` par défaut dans docker-compose
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Stack technique
|
||||
|
||||
- **Backend** : Python 3.11 + FastAPI + Uvicorn
|
||||
- **Backend** : Python 3.11 + FastAPI 0.110 + Uvicorn
|
||||
- **Frontend** : Vanilla JS + HTML + CSS (zéro framework, zéro build)
|
||||
- **Rendu Markdown** : mistune 3.x
|
||||
- **Image Docker** : python:3.11-slim
|
||||
- **Image Docker** : python:3.11-slim (multi-stage)
|
||||
- **Base de données** : Aucune (index en mémoire uniquement)
|
||||
- **Architecture** : SPA + API REST
|
||||
|
||||
---
|
||||
|
||||
## 🏠 Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────────────────────────────┐
|
||||
│ Navigateur │◄───►│ FastAPI (backend/main.py) │
|
||||
│ (SPA) │ REST │ │
|
||||
│ │ │ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ app.js │ │ │ indexer.py │ │ search.py │ │
|
||||
│ style.css │ │ │ (scan+cache)│ │ (in-memory) │ │
|
||||
│ index.html │ │ └───────┬──────┘ └──────┬───────┘ │
|
||||
└─────────────────┘ │ │ │ │
|
||||
│ └──────┬───────┘ │
|
||||
│ │ │
|
||||
│ ┌────────┴─────────┐ │
|
||||
│ │ Index en mémoire │ │
|
||||
│ │ (fichiers, tags, │ │
|
||||
│ │ contenu, lookup)│ │
|
||||
│ └──────────────────┘ │
|
||||
└─────────────────────────────────────────┘
|
||||
┌───────────────────────────────┐
|
||||
│ Filesystem (vaults montées) │
|
||||
│ /vaults/Recettes (ro) │
|
||||
│ /vaults/IT (ro) │
|
||||
└───────────────────────────────┘
|
||||
```
|
||||
|
||||
**Flux de données :**
|
||||
1. Au démarrage, `indexer.py` scanne tous les vaults en parallèle (thread pool)
|
||||
2. Le contenu, les tags (YAML + inline) et les métadonnées sont mis en cache en mémoire
|
||||
3. Une table de lookup O(1) est construite pour la résolution des wikilinks
|
||||
4. Les requêtes de recherche utilisent l'index en mémoire (zéro I/O disque)
|
||||
5. Le frontend SPA communique via REST et gère l'état côté client
|
||||
|
||||
---
|
||||
|
||||
## 📝 Développement
|
||||
|
||||
### Structure du projet
|
||||
```
|
||||
ObsiGate/
|
||||
├── backend/ # API FastAPI
|
||||
│ ├── main.py # Point d'entrée
|
||||
│ ├── indexer.py # Indexation des vaults
|
||||
│ ├── search.py # Moteur de recherche
|
||||
├── backend/ # API FastAPI
|
||||
│ ├── main.py # Endpoints, Pydantic models, rendu markdown
|
||||
│ ├── indexer.py # Scan des vaults, index en mémoire, lookup table
|
||||
│ ├── search.py # Moteur de recherche fulltext avec scoring
|
||||
│ └── requirements.txt
|
||||
├── frontend/ # Interface web
|
||||
│ ├── index.html # Page principale
|
||||
│ ├── app.js # Logique SPA
|
||||
│ └── style.css # Styles
|
||||
├── Dockerfile # Configuration Docker
|
||||
├── docker-compose.yml # Déploiement
|
||||
└── build.sh # Build multi-platform
|
||||
├── frontend/ # Interface web (Vanilla JS, zéro framework)
|
||||
│ ├── index.html # Page SPA + modales (aide, config, éditeur)
|
||||
│ ├── app.js # Logique SPA, gestion d'état, API client
|
||||
│ └── style.css # Styles (CSS variables, thèmes, responsive)
|
||||
├── Dockerfile # Multi-stage, healthcheck, non-root
|
||||
├── docker-compose.yml # Déploiement avec healthcheck
|
||||
├── build.sh # Build multi-platform (amd64/arm64/arm/v7/i386)
|
||||
└── CONTRIBUTING.md # Guide de contribution
|
||||
```
|
||||
|
||||
### Contribuer
|
||||
|
||||
1. Fork le projet
|
||||
2. Créer une branche `feature/nouvelle-fonctionnalite`
|
||||
3. Commit vos changements
|
||||
4. Push vers la branche
|
||||
5. Créer une Pull Request
|
||||
Voir [CONTRIBUTING.md](CONTRIBUTING.md) pour les détails.
|
||||
|
||||
---
|
||||
|
||||
@@ -389,4 +459,45 @@ Ce projet est sous licence **MIT** - voir le fichier [LICENSE](LICENSE) pour les
|
||||
|
||||
---
|
||||
|
||||
*Projet : ObsiGate | Version : 1.0.0 | Dernière mise à jour : 2025*
|
||||
## 📝 Changelog
|
||||
|
||||
### v1.1.0 (2025)
|
||||
|
||||
**Sécurité**
|
||||
- Protection path traversal sur tous les endpoints fichier
|
||||
- Utilisateur non-root dans le conteneur Docker
|
||||
- Dockerfile multi-stage (élimination des outils de build)
|
||||
|
||||
**Performance**
|
||||
- Recherche fulltext en mémoire (zéro I/O disque par requête)
|
||||
- Table de lookup O(1) pour la résolution des wikilinks
|
||||
- Renderer mistune mis en cache (singleton)
|
||||
- Scoring multi-facteurs (titre, chemin, tags, fréquence)
|
||||
- `lucide.createIcons()` batché via `requestAnimationFrame`
|
||||
- `AbortController` sur les requêtes de recherche
|
||||
|
||||
**Robustesse**
|
||||
- Swap atomique de l'index (thread-safe) pendant le reload
|
||||
- Extraction des tags inline (#tag) depuis le contenu markdown
|
||||
- Modèles Pydantic sur tous les endpoints API
|
||||
- Gestion d'erreurs avec toasts utilisateur (frontend)
|
||||
- États de chargement pour la sidebar et le contenu
|
||||
- Remplacement de `on_event` déprécié par `lifespan`
|
||||
|
||||
**Infrastructure**
|
||||
- Endpoint `/api/health` pour monitoring
|
||||
- Healthcheck Docker (Dockerfile + docker-compose)
|
||||
- `build.sh` amélioré (variable version, checks, couleurs)
|
||||
|
||||
**Documentation**
|
||||
- Docstrings complètes sur toutes les fonctions Python
|
||||
- Schémas Pydantic documentés (Swagger UI auto-générée)
|
||||
- README : sections Architecture, Performance, Sécurité, Changelog
|
||||
- CONTRIBUTING.md ajouté
|
||||
|
||||
### v1.0.0 (2025)
|
||||
- Version initiale
|
||||
|
||||
---
|
||||
|
||||
*Projet : ObsiGate | Version : 1.1.0 | Dernière mise à jour : 2025*
|
||||
|
||||
Reference in New Issue
Block a user