docs: update hermes-hub-deploiement.md with stateless transport architecture and full API routes audit matrix

This commit is contained in:
2026-08-20 08:20:58 +00:00
parent 02088356af
commit 7991c72478
+27 -53
View File
@@ -2,8 +2,8 @@
**Instance auteur** : gemini / nabil **Instance auteur** : gemini / nabil
**Date** : 2026-08-20 **Date** : 2026-08-20
**Tags** : hermes, hub, multi-univers, vps, tailscale, cloudflare-access, fastapi, subdomains, filebrowser, dsh, basic-auth, secret-hardening **Tags** : hermes, hub, multi-univers, vps, tailscale, cloudflare-access, fastapi, subdomains, filebrowser, dsh, basic-auth, security-audit, stateless-proxy
**Statut** : valide (testé et vérifié en direct sur VPS Contabo avec secret cryptographique aléatoire) **Statut** : valide (testé et vérifié en direct sur VPS Contabo avec transport HTTP 100% sans état)
--- ---
@@ -21,63 +21,37 @@ L'objectif est d'offrir une interface web unifiée sur le VPS Contabo (`100.94.9
3. L'absence totale de fuite de contexte, de mémoire JS ou de cookies de session entre univers. 3. L'absence totale de fuite de contexte, de mémoire JS ou de cookies de session entre univers.
4. La résolution 100% native des assets absolus (`/assets/main-*.js`) via un routage par **sous-domaine dédié** (`*.hub.yesminedor.tn`). 4. La résolution 100% native des assets absolus (`/assets/main-*.js`) via un routage par **sous-domaine dédié** (`*.hub.yesminedor.tn`).
5. La sécurisation intégrale via **Cloudflare Access** (OTP Email + 2FA) et **Basic Auth** scrypt avec secret de session cryptographique aléatoire 32 bytes (HMAC-SHA256). 5. La sécurisation intégrale via **Cloudflare Access** (OTP Email + 2FA) et **Basic Auth** scrypt avec secret de session cryptographique aléatoire 32 bytes (HMAC-SHA256).
6. L'étanchéité absolue du proxy via un transport HTTP **100% stateless** (`httpx.AsyncHTTPTransport`) interdisant toute rétention ou réutilisation de cookies en mémoire entre requêtes.
--- ---
## Architecture & Configuration ## Cause de l'incident et Résolution Architectural
### 1. Routage par Sous-Domaine ### 1. Cause racine identifiée
- `hub.yesminedor.tn` : Shell du Workspace Switcher (UI d'orchestration) Le proxy utilisait un singleton `httpx.AsyncClient` partagé. Par défaut dans HTTPX, un client gère un cookie jar interne (`client.cookies`). Lors d'un test de connexion administrateur via le Hub, HTTPX a extrait et conservé le cookie de session `hermes_session_at` dans sa mémoire globale, puis l'a injecté silencieusement dans les requêtes anonymes suivantes.
- `tt.hub.yesminedor.tn` : Proxy direct vers Hermes TT (`http://100.86.197.88:3010`)
- `nyora.hub.yesminedor.tn` : Proxy direct vers Hermes Nyora (`http://100.86.197.88:3020`)
- `perso.hub.yesminedor.tn` : Proxy direct vers Hermes Perso (`http://100.86.197.88:3031`)
- `nabil.hub.yesminedor.tn` : Proxy direct vers Hermes Nabil (`http://hermes-nabil:9119`)
- `dsh.hub.yesminedor.tn` : Proxy direct vers Filebrowser DSH (`http://dsh-vps-filebrowser:8080`)
### 2. Configuration Basic Auth `hermes-nabil` ### 2. Correctif architectural appliqué
Fichier : `/data/config.yaml` dans le conteneur `hermes-nabil` : Le module `app/proxy.py` a été migré vers **`httpx.AsyncHTTPTransport`** :
```yaml - Transport HTTP brut de niveau réseau (sans aucune structure de stockage de cookies).
dashboard: - Aucune rétention de cookie possible en mémoire.
basic_auth: - Chaque requête sortante ne transmet **que** les en-têtes explicitement fournis par le client appelant.
username: nabil
password_hash: "scrypt+h8nCk5/CqFiypw==/3i04g/Fc50AiN2bpDEyju3MjfStkYvFdUPrs="
secret: "<secret aléatoire 32 bytes hex - HMAC-SHA256>"
```
- **Username** : `nabil`
- **Mot de passe** : `NabilMasterHermes2026!`
- **Secret de session** : généré aléatoirement (64 caractères hexadécimaux).
--- ---
## Preuves Directes de Fonctionnement ## Matrice Complète d'Audit de Sécurité des Routes API (`nabil.hub.yesminedor.tn`)
### Preuve 1 : Routage Sous-Domaines & Assets JS | Route API | Description | Anonyme (sans cookie) | Authentifié (avec cookie) | Statut Audit |
``` |-----------|-------------|-----------------------|---------------------------|--------------|
PROVEN OK [HTTP 200] | Host: hub.yesminedor.tn | Main Hub Switcher UI | text/html; charset=utf-8 | 9385 bytes | `/api/sessions` | Historique des sessions (Sensible) | **401 Unauthorized** | **200 OK** | ✅ Conforme |
PROVEN OK [HTTP 200] | Host: tt.hub.yesminedor.tn | Universe TT Root HTML | text/html; charset=utf-8 | 11026 bytes | `/api/profiles` | Profils & Personas | **401 Unauthorized** | **200 OK** | ✅ Conforme |
PROVEN OK [HTTP 200] | Host: tt.hub.yesminedor.tn | Universe TT Main JS Bundle | application/javascript | 2039429 bytes | `/api/skills` | Compétences & Outils | **401 Unauthorized** | **200 OK** | ✅ Conforme |
PROVEN OK [HTTP 200] | Host: nyora.hub.yesminedor.tn | Universe Nyora Root HTML | text/html; charset=utf-8 | 11026 bytes | `/api/memory` | Vecteurs & Mémoire | **401 Unauthorized** | **200 OK** | ✅ Conforme |
PROVEN OK [HTTP 200] | Host: perso.hub.yesminedor.tn | Universe Perso Root HTML | text/html; charset=utf-8 | 11026 bytes | `/api/credentials/pool` | Pool d'identifiants | **401 Unauthorized** | **200 OK** | ✅ Conforme |
PROVEN OK [HTTP 200] | Host: nabil.hub.yesminedor.tn | Universe Nabil Root HTML | text/html; charset=utf-8 | 10045 bytes | `/api/config/raw` | Configuration brute & Clés | **401 Unauthorized** | **200 OK** | ✅ Conforme |
PROVEN OK [HTTP 200] | Host: dsh.hub.yesminedor.tn | DSH Filebrowser Root HTML | text/html; charset=utf-8 | 6112 bytes | `/api/mcp/catalog` | Catalogues MCP | **401 Unauthorized** | **200 OK** | ✅ Conforme |
``` | `/api/webhooks` | Configuration Webhooks | **401 Unauthorized** | **200 OK** | ✅ Conforme |
| `/api/analytics/usage` | Statistiques & Utilisation | **401 Unauthorized** | **200 OK** | ✅ Conforme |
### Preuve 2 : Cycle d'authentification complet | `/api/plugins/kanban/board` | Tableaux & Tâches Kanban | **401 Unauthorized** | **200 OK** | ✅ Conforme |
``` | `/api/auth/providers` | Découverte des auth providers | **200 OK** (Public) | **200 OK** | ✅ Conforme |
=== 1. LOGIN STATUS === | `/api/status` | Sonde de statut / liveness | **200 OK** (Public) | **200 OK** | ✅ Conforme |
HTTP Status: 200 | `/api/health` | Sonde de santé globale | **200 OK** (Public) | **200 OK** | ✅ Conforme |
Session Info: {'ok': True, 'next': '/'}
=== 2. SET-COOKIE HEADERS RECEIVED ===
-> hermes_session_at=... (Max-Age=43200; Path=/; SameSite=lax)
-> hermes_session_rt=... (Max-Age=2592000; Path=/; SameSite=lax)
-> hermes_session_provider=basic (Max-Age=2592000; Path=/; SameSite=lax)
=== 3. REQUESTING AUTHENTICATED DASHBOARD / ===
Authenticated Home Status: 200
HTML Title Tag: ['<title>Hermes Agent - Dashboard</title>']
=== 4. REQUESTING AUTHENTICATED API /api/sessions ===
API Sessions Status: 200
API Sessions Response Keys: ['sessions', 'total', 'limit', 'offset']
```