ObsiGate/README.md

28 KiB
Raw Blame History

ObsiGate

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.

Version License: MIT Docker Python

┌─────────────────────────────────────────────────────────┐
│  [🔍 Recherche...]          [☀/🌙 Thème]   ObsiGate    │
├──────────────┬──────────────────────────────────────────┤
│  SIDEBAR     │           CONTENT AREA                   │
│  ▼ Recettes  │   📄 Titre du fichier                    │
│    📁 Soupes │   Tags: #recette #rapide                 │
│    📄 Pizza  │   [Contenu Markdown rendu]               │
│  ▼ IT        │                                          │
│    📁 Docker │                                          │
│  Tags Cloud  │                                          │
└──────────────┴──────────────────────────────────────────┘

📋 Table des matières


Fonctionnalités

  • 🗂️ Multi-vault : Visualisez plusieurs vaults Obsidian simultanément
  • 🌳 Navigation arborescente : Parcourez vos dossiers et fichiers dans la sidebar
  • 🔍 Recherche avancée : Moteur TF-IDF avec normalisation des accents, snippets surlignés, facettes, pagination et tri
  • 💡 Autocomplétion intelligente : Suggestions de fichiers, tags et historique avec navigation clavier
  • 🧩 Syntaxe de requête : Opérateurs tag:, #, vault:, title:, path: avec chips visuels
  • 📜 Historique de recherche : Persisté en localStorage (max 50 entrées, LIFO, dédupliqué)
  • 🏷️ Tag cloud : Filtrage par tags extraits des frontmatters YAML
  • 🔗 Wikilinks : Les [[liens internes]] Obsidian sont cliquables
  • 🖼️ Images Obsidian : Support complet des syntaxes d'images Obsidian avec résolution intelligente
  • 🎨 Syntax highlight : Coloration syntaxique des blocs de code
  • 🌓 Thème clair/sombre : Toggle persisté en localStorage
  • <EFBFBD> Synchronisation temps réel : Surveillance automatique des fichiers via watchdog avec mise à jour incrémentale de l'index
  • 📡 Server-Sent Events : Notifications SSE pour les changements d'index avec reconnexion automatique
  • Gestion dynamique des vaults : Ajout/suppression de vaults via API sans redémarrage
  • <EFBFBD>🐳 Docker multi-platform : linux/amd64, linux/arm64, linux/arm/v7, linux/386
  • 🔒 Sécurité : Protection contre le path traversal, utilisateur non-root dans Docker
  • ❤️ Healthcheck : Endpoint /api/health intégré pour Docker et monitoring

🚀 Prérequis

Système requis

  • Docker >= 20.10
  • docker-compose >= 2.0
  • Espace disque : ~200MB pour l'image Docker

Systèmes supportés

  • Linux (Ubuntu, Debian, CentOS, etc.)
  • macOS (Intel et Apple Silicon)
  • Windows (avec Docker Desktop)
  • NAS compatibles Docker (Synology, QNAP, etc.)

Installation rapide

1. Cloner le dépôt

git clone https://git.dracodev.net/Projets/ObsiGate.git
cd ObsiGate

2. Configurer vos vaults

Éditez le fichier docker-compose.yml pour ajouter vos vaults Obsidian :

volumes:
  - /chemin/absolu/vers/votre/vault:/vaults/NomDeVotreVault:ro

Important

: Le chemin doit être absolu et le volume en lecture seule (:ro)

3. Lancer l'application

# Build local de l'image + démarrage
docker-compose up -d --build

# Vérifier les logs
docker-compose logs -f obsigate

Note

: ObsiGate est construit localement depuis le Dockerfile du projet. Sans build local, Docker essaiera de télécharger une image distante obsigate:latest qui n'existe pas forcément.

4. Accéder à l'interface

Ouvrez votre navigateur sur : http://localhost:2020


⚙️ Configuration détaillée

Étape 1 : Préparation des vaults

  1. Localisez vos vaults Obsidian sur votre système
  2. Notez les chemins absolus vers chaque dossier .obsidian
  3. Vérifiez les permissions : Docker doit pouvoir lire ces dossiers

Étape 2 : Configuration docker-compose.yml

Voici un exemple complet :

services:
  obsigate:
    build:
      context: .
    image: obsigate:latest
    container_name: obsigate
    restart: unless-stopped
    ports:
      - "2020:8080"  # Port local 2020 → Port conteneur 8080
    volumes:
      # Exemples de vaults (adaptez à vos chemins)
      - /home/user/Documents/Obsidian-Recettes:/vaults/Recettes:ro
      - /home/user/Documents/Obsidian-IT:/vaults/IT:ro
      - /home/user/Documents/Obsidian-Perso:/vaults/Perso:ro
    environment:
      # Configuration des vaults
      - VAULT_1_NAME=Recettes
      - VAULT_1_PATH=/vaults/Recettes
      - VAULT_2_NAME=IT
      - VAULT_2_PATH=/vaults/IT
      - VAULT_3_NAME=Perso
      - VAULT_3_PATH=/vaults/Perso

Étape 3 : Construction de l'image

# Build l'image Docker
docker build -t obsigate:latest .
 
# Puis démarrer le service
docker-compose up -d --build
 
# Ou utilisez le script de build multi-platform
chmod +x build.sh
./build.sh

Compatibilité Docker : l'image utilise la variante minimale de uvicorn et une version de fastapi compatible (0.110.3) afin d'éviter certaines dépendances optionnelles natives (watchfiles, uvloop, httptools, fastapi-cli, etc.) qui peuvent échouer au build sur certaines plateformes comme Alpine, ARM ou i386.


🌍 Variables d'environnement

Les vaults sont configurées par paires de variables VAULT_N_NAME / VAULT_N_PATH (N = 1, 2, 3…) :

Variable Description Exemple
VAULT_1_NAME Nom affiché de la vault Recettes
VAULT_1_PATH Chemin dans le conteneur /vaults/Obsidian-RECETTES
VAULT_1_ATTACHMENTS_PATH Chemin relatif vers le dossier d'attachements (optionnel) 06_Boite_a_Outils/6.2_Attachments
VAULT_1_SCAN_ATTACHMENTS Activer le scan d'images au démarrage (optionnel, défaut: true) true
VAULT_2_NAME Nom affiché de la vault IT
VAULT_2_PATH Chemin dans le conteneur /vaults/Obsidian_IT

Règles de nommage :

  • Utilisez uniquement des lettres, chiffres et tirets
  • Pas d'espaces ou caractères spéciaux
  • Le nom doit correspondre au chemin dans le conteneur

Ajouter une nouvelle vault

Méthode 1 : Édition directe

  1. Arrêtez le conteneur :

    docker-compose down
    
  2. Ajoutez un volume dans docker-compose.yml :

    volumes:
      - /nouveau/chemin/vault:/vaults/NouvelleVault:ro
    
  3. Ajoutez les variables d'environnement :

    environment:
      - VAULT_4_NAME=NouvelleVault
      - VAULT_4_PATH=/vaults/NouvelleVault
    
  4. Redémarrez :

    docker-compose up -d --build
    

Méthode 2 : Hot-reload (recommandé)

  1. Ajoutez le volume et les variables comme ci-dessus
  2. Appliquez les changements :
    docker-compose up -d --build
    
  3. Rechargez l'index via l'interface ou l'API :
    curl http://localhost:2020/api/index/reload
    

Méthode 3 : API dynamique (sans redémarrage)

Ajoutez une vault à chaud via l'API (le volume doit déjà être monté) :

curl -X POST http://localhost:2020/api/vaults/add \
  -H "Content-Type: application/json" \
  -d '{"name": "NouvelleVault", "path": "/vaults/NouvelleVault"}'

Supprimez une vault :

curl -X DELETE http://localhost:2020/api/vaults/NouvelleVault

🔨 Build multi-platform

Pour les architectures multiples (Raspberry Pi, NAS, etc.) :

# Rendre le script exécutable
chmod +x build.sh

# Lancer le build multi-platform
./build.sh

Architectures supportées :

  • linux/amd64 (PC, serveurs standards)
  • linux/arm64 (Raspberry Pi 4, Apple Silicon, NAS modernes)
  • linux/arm/v7 (Raspberry Pi 3, anciens NAS)
  • linux/386 (Systèmes 32-bit legacy)

Pour un build local uniquement :

docker buildx build --platform linux/amd64 --load -t obsigate:latest .

<EFBFBD> Rendu d'images Obsidian

ObsiGate supporte toutes les syntaxes d'images Obsidian avec un système de résolution intelligent multi-stratégies.

Syntaxes supportées

  1. Standard Markdown avec attributs HTML (compatible Obsidian) :

    [<img width="180" height="60" src="path/to/image.svg"/>](https://example.com)
    
  2. Wiki-link embed avec chemin complet :

    ![[06_Boite_a_Outils/6.2_Attachments/image.svg]]
    
  3. Wiki-link embed avec nom de fichier uniquement :

    ![[image.svg]]
    
  4. Markdown standard :

    ![alt text](path/to/image.png)
    

Résolution intelligente des chemins

ObsiGate utilise 7 stratégies de résolution par ordre de priorité :

  1. Chemin absolu : Si le chemin est absolu et existe
  2. Dossier d'attachements configuré : Via VAULT_N_ATTACHMENTS_PATH
  3. Index de démarrage (match unique) : Recherche par nom de fichier dans l'index
  4. Même répertoire : Relatif au fichier markdown courant
  5. Racine du vault : Relatif à la racine du vault
  6. Index de démarrage (match le plus proche) : Si plusieurs fichiers portent le même nom
  7. Fallback : Affiche un placeholder stylisé [image not found: filename.ext]

Configuration

Pour optimiser la résolution, configurez le dossier d'attachements de chaque vault :

environment:
  - VAULT_1_NAME=MonVault
  - VAULT_1_PATH=/vaults/MonVault
  - VAULT_1_ATTACHMENTS_PATH=Assets/Images  # Chemin relatif
  - VAULT_1_SCAN_ATTACHMENTS=true           # Activer le scan (défaut)

Rescan manuel

Pour rescanner les images d'un vault après ajout/suppression :

curl -X POST http://localhost:2020/api/attachments/rescan/MonVault

<EFBFBD>📖 Utilisation

Interface web

  1. Navigation : Cliquez sur les vaults dans la sidebar pour les développer
  2. Recherche : Utilisez la barre de recherche pour chercher dans toutes les vaults
  3. Tags : Cliquez sur les tags pour filtrer les contenus
  4. Wikilinks : Les liens [[page]] sont cliquables et navigables
  5. Images : Toutes les syntaxes d'images Obsidian sont rendues automatiquement
  6. Thème : Basculez entre thème clair/sombre avec l'icône 🌙/☀️

Raccourcis clavier

Action Raccourci
Recherche Ctrl + K ou /
Toggle thème Ctrl + T
Focus recherche Esc

🔌 API

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 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 (legacy) GET
/api/search/advanced?q=&vault=&tag=&limit=&offset=&sort= Recherche avancée TF-IDF avec facettes et pagination GET
/api/suggest?q=&vault=&limit= Suggestions de titres de fichiers (autocomplétion) GET
/api/tags/suggest?q=&vault=&limit= Suggestions de tags (autocomplétion) GET
/api/tags?vault= Tags uniques avec compteurs GET
/api/index/reload Force un re-scan des vaults GET
/api/events Flux SSE temps réel (index updates, vault changes) GET
/api/vaults/add Ajouter une vault dynamiquement POST
/api/vaults/{name} Supprimer une vault DELETE
/api/vaults/status Statut détaillé des vaults (fichiers, watching) GET
/api/image/{vault}?path= Servir une image avec MIME type approprié GET
/api/attachments/rescan/{vault} Rescanner les images d'un vault POST
/api/attachments/stats?vault= Statistiques d'images indexées GET
/api/config Lire la configuration GET
/api/config Mettre à jour la configuration POST
/api/diagnostics Statistiques index, mémoire, moteur de recherche GET

Tous les endpoints exposent des schémas Pydantic documentés. La doc interactive est disponible sur /docs (Swagger UI).

Exemple d'utilisation :

# Health check
curl http://localhost:2020/api/health

# Lister les vaults
curl http://localhost:2020/api/vaults

# Recherche simple (legacy)
curl "http://localhost:2020/api/search?q=recette&vault=all"

# Recherche avancée avec TF-IDF, facettes et pagination
curl "http://localhost:2020/api/search/advanced?q=recette%20tag:cuisine&vault=all&limit=20&offset=0&sort=relevance"

# Autocomplétion de titres
curl "http://localhost:2020/api/suggest?q=piz&vault=all"

# Autocomplétion de tags
curl "http://localhost:2020/api/tags/suggest?q=rec&vault=all"

# Obtenir un fichier
curl "http://localhost:2020/api/file/Recettes?path=pizza.md"

🔍 Recherche avancée

Syntaxe de requête

Opérateur Description Exemple
tag:<nom> Filtrer par tag tag:recette docker
#<nom> Raccourci tag #linux serveur
vault:<nom> Filtrer par vault vault:IT kubernetes
title:<texte> Filtrer par titre title:pizza
path:<texte> Filtrer par chemin path:recettes/soupes
"phrase exacte" Recherche de phrase tag:"multi mots"

Les opérateurs sont combinables : tag:linux vault:IT serveur web recherche "serveur web" dans le vault IT avec le tag linux.

Raccourcis clavier

Raccourci Action
Ctrl+K / Cmd+K Focaliser la barre de recherche
/ Focaliser la recherche (hors champ texte)
/ Naviguer dans les suggestions
Enter Sélectionner la suggestion active ou lancer la recherche
Escape Fermer les suggestions / quitter la recherche

Fonctionnalités

  • TF-IDF : Scoring basé sur la fréquence des termes pondérée par l'inverse de la fréquence documentaire
  • Boost titre : Les correspondances dans le titre reçoivent un score 3× supérieur
  • Normalisation des accents : resume trouve résumé, elephant trouve éléphant
  • Snippets surlignés : Les termes trouvés sont encadrés par <mark> dans les extraits
  • Facettes : Compteurs par vault et par tag dans les résultats
  • Pagination : Navigation par pages de 50 résultats
  • Tri : Par pertinence (TF-IDF) ou par date de modification
  • Chips visuels : Les filtres actifs sont affichés comme des chips colorés supprimables
  • Historique : Les 50 dernières recherches sont mémorisées en localStorage

🔧 Dépannage

Problèmes courants

Port déjà utilisé :

# Vérifier qui utilise le port
sudo netstat -tulpn | grep 2020
# Changer le port dans docker-compose.yml
ports:
  - "2021:8080"

Vault non trouvée :

  • Vérifiez que les chemins sont absolus
  • Assurez-vous que les permissions permettent la lecture
  • Redémarrez le conteneur après modification

Build échoue :

# Nettoyer et rebuild
docker system prune -f
docker-compose down
docker build --no-cache -t obsigate:latest .
docker-compose up -d

Logs pour debugging :

# Logs en temps réel
docker-compose logs -f obsigate

# Logs détaillés
docker-compose logs --tail=100 obsigate

Performance

Métrique Estimation
Indexation ~12s pour 1 000 fichiers markdown
Recherche avancée < 10ms pour la plupart des requêtes (index inversé + TF-IDF)
Résolution wikilinks O(1) via table de lookup
Mémoire ~80150MB par 1 000 fichiers (contenu capé à 100 KB/fichier)
Image Docker ~180MB (multi-stage, sans outils de build)
CPU Non-bloquant ; recherche offloadée sur thread pool dédié

Paramètres recommandés par taille de vault

Taille Fichiers search_workers prefix_max_expansions max_content_size
Petit < 500 1 50 100 000
Moyen 5005 000 2 50 100 000
Grand 5 000+ 4 30 50 000

Ces paramètres sont configurables via l'interface (Settings) ou l'API /api/config.

Optimisations clés (v1.2.0)

  • Index inversé avec set-intersection : la recherche utilise les posting lists pour un retrieval O(k × postings) au lieu de O(N) scan complet
  • Prefix matching par recherche binaire : O(log V + k) au lieu de O(V) scan linéaire du vocabulaire
  • ThreadPoolExecutor : les fonctions de recherche CPU-bound sont offloadées du event loop asyncio
  • Race condition guard : currentSearchId + AbortController empêchent le rendu de résultats obsolètes
  • Progress bar : barre de progression animée pendant la recherche
  • Search timeout : abandon automatique après 30s (configurable)
  • Query time display : temps serveur affiché dans les résultats (query_time_ms)
  • Staleness detection fix : utilisation d'un compteur de génération au lieu de id(index) pour détecter les changements d'index

Optimisations 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 0.110 + Uvicorn
  • File Watcher : watchdog 4.x (inotify natif + fallback polling)
  • Frontend : Vanilla JS + HTML + CSS (zéro framework, zéro build)
  • Rendu Markdown : mistune 3.x
  • Image Docker : python:3.11-slim (multi-stage)
  • Base de données : Aucune (index en mémoire uniquement)
  • Architecture : SPA + API REST + SSE

🏠 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. watcher.py démarre la surveillance des fichiers (watchdog natif ou polling)
  5. Les modifications détectées déclenchent une mise à jour incrémentale de l'index
  6. Les changements sont notifiés au frontend via Server-Sent Events (SSE)
  7. Les requêtes de recherche utilisent l'index en mémoire (zéro I/O disque)
  8. Le frontend SPA communique via REST + SSE et gère l'état côté client

📝 Développement

Structure du projet

ObsiGate/
├── 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
│   ├── watcher.py       # Surveillance fichiers (watchdog + debounce)
│   └── requirements.txt
├── 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

Voir CONTRIBUTING.md pour les détails.


📄 Licence

Ce projet est sous licence MIT - voir le fichier LICENSE pour les détails.


🤝 Support


📝 Changelog

v1.3.0 (2025)

Synchronisation temps réel

  • Surveillance automatique des fichiers via watchdog avec fallback polling automatique
  • Mise à jour incrémentale de l'index : ajout, modification, suppression et déplacement de fichiers sans rebuild complet
  • Server-Sent Events (SSE) : endpoint /api/events pour notifications temps réel vers le frontend
  • Badge de synchronisation dans le header avec indicateur visuel (connecté/déconnecté/syncing)
  • Panel d'événements récents accessible en cliquant sur le badge
  • Reconnexion SSE automatique avec backoff exponentiel
  • Toast informatif à chaque mise à jour détectée
  • Rafraîchissement automatique de la sidebar et du fichier courant si affecté

Gestion dynamique des vaults

  • POST /api/vaults/add : ajouter une vault à chaud sans redémarrage
  • DELETE /api/vaults/{name} : supprimer une vault de l'index
  • GET /api/vaults/status : statut détaillé (fichiers, tags, état de surveillance)
  • Les vaults ajoutées sont automatiquement surveillées par le watcher

Configuration watcher

  • Nouveaux paramètres dans config.json : watcher_enabled, watcher_use_polling, watcher_polling_interval, watcher_debounce
  • Section « Synchronisation automatique » dans la modal de configuration frontend
  • Toggles pour activer/désactiver la surveillance et le mode polling

v1.2.0 (2025)

Performance (critique)

  • Réécriture du moteur advanced_search() : retrieval par set-intersection sur l'index inversé (O(k × postings) au lieu de O(N))
  • Prefix matching par recherche binaire sur liste triée de tokens (O(log V + k) au lieu de O(V))
  • Offload des fonctions de recherche CPU-bound via ThreadPoolExecutor (2 workers par défaut)
  • Pré-calcul des expansions de préfixe pour éviter les recherches binaires répétées
  • Fix du bug de staleness : is_stale() utilise un compteur de génération au lieu de id(index)

Frontend

  • Guard contre les race conditions : currentSearchId vérifié après chaque fetch avant rendu
  • Barre de progression animée pendant la recherche
  • Timeout de recherche configurable (30s par défaut)
  • Longueur minimale de requête configurable (2 caractères par défaut)
  • Affichage du temps de requête serveur (query_time_ms) dans les résultats
  • Pagination ajoutée sur l'endpoint legacy /api/search (params limit/offset)

Configuration & Diagnostics

  • Nouveaux endpoints GET/POST /api/config pour la configuration persistante (config.json)
  • Nouveau endpoint GET /api/diagnostics (stats index, mémoire, moteur de recherche)
  • Page de configuration étendue : paramètres frontend (debounce, résultats/page, timeout) et backend (workers, boosts, expansions)
  • Panel de diagnostics intégré dans la modal de configuration
  • Boutons « Forcer réindexation » et « Réinitialiser » dans les paramètres

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.2.0 | Dernière mise à jour : 2025