# Plan d'action — Dashboard Web RPA Vision V3 _Date : 2026-04-15 — périmètre : `web_dashboard/` (port 5001). Auteur : audit technique (lecture seule, aucune modif de code)._ Objectifs : 1. faire le ménage dans un dashboard qui a grossi par sédimentation, 2. préparer l'onglet **Audit & Traçabilité** attendu par les clients (AI Act / RGPD), 3. donner à Dom une roadmap actionnable et priorisée. --- ## Section A — Inventaire Le dashboard a aujourd'hui **14 onglets** déclarés dans `web_dashboard/templates/index.html` (3 455 lignes) plus des pages auxiliaires (`chat.html`, `gestures.html`, `extractions.html`, `streaming.html`). Le backend Flask (`web_dashboard/app.py`, 2 665 lignes) expose **~65 routes HTTP** + 4 events SocketIO. | # | Onglet (label UI) | Routes backend principales | État | MAJ estimée | Utile ? | |---|---|---|---|---|---| | 1 | 🎛️ Services | `/api/services*`, `/api/version*` | **OK** — fonctionne, utilisé quotidiennement | avril 2026 | **oui, cœur** | | 2 | 📊 Vue d'ensemble | `/api/system/status`, SocketIO | **OK partiel** — `statTests` et `statExecution` remplis par legacy | mars 2026 | doublonne avec Services | | 3 | ⚡ Exécution | `/api/automation/*`, SocketIO `subscribe_execution` | **Douteux** — branché sur le moteur v1 core, pas sur Agent V1 streaming (5005). Le replay réel passe par VWB ou `/api/v1/traces/stream/replay*` | janv. 2026 | **non en l'état** — obsolète face au flux replay actuel | | 4 | 🔄 Workflows | `/api/workflows*`, `/api/chains*`, `/api/triggers*` | **OK liste**, exécution via `/api/workflows//execute` redondante avec VWB et Agent V1 | janv.-mars 2026 | partiel — la liste oui, l'exécution non | | 5 | 📦 Sessions | `/api/agent/sessions*` | **OK** — affiche bien les sessions dans `data/training/sessions/` | avril 2026 | **oui** mais se recoupe avec le cleaner (5006) | | 6 | 📈 Performance | `/api/system/performance`, `/api/system/faiss/test`, `/metrics` | **OK** — FAISS + Prometheus + cache hit | mars 2026 | **oui, utile debug/benchmark** | | 7 | 📡 Streaming | proxy vers `http://localhost:5005/api/v1/traces/stream/*` | **OK** — lecture seule, bonne visibilité live sessions | mars 2026 | **oui, cœur Agent V1** | | 8 | 📄 Logs | `/api/logs`, `/api/logs/download` | **OK minimaliste** — lit `logs/*.log`, pas de filtre/tail | nov. 2025 | utile ponctuel, pourrait disparaître si Audit bien fait | | 9 | 🧪 Tests | `/api/tests*` (subprocess `pytest`) | **Cassé en prod** — pytest non dispo sur cible packagée, timeout 120s bloque l'UI, **aucun droit d'exécuter pytest depuis une UI exposée sur Internet** | mars 2026 | **NON — à retirer** | | 10 | 💾 Sauvegardes | `/api/backup/*` | **OK** — exports fonctionnels | janv. 2026 | **oui**, valeur clairement réglementaire | | 11 | 🔧 Corrections (packs) | routes ailleurs (VWB / API core) — onglet affiche des stats | **Cassé** — `refreshCorrectionPacks` appelle une route qui n'existe plus côté dashboard, données via VWB | févr. 2026 | à supprimer côté dashboard, garder côté VWB | | 12 | 🧠 Apprentissage | idem : placeholders `statCorpusSize`, charts Chart.js non alimentés | **Cassé/placeholder** — aucune route backend ne nourrit les 4 stat-cards ni les 2 canvas | janv. 2026 | **NON — à retirer ou refaire sérieusement** | | 13 | 🔧 Configuration | `/api/config*`, `/api/config/ollama-models`, `/api/config/test-connection` | **OK** — édition ports/modèles/DB/sécurité/logs | avril 2026 | **oui** (utile admin) | | 14 | 🧹 Nettoyage | iframe → `http://localhost:5006` | **OK** — ajouté hier, dépend du service session_cleaner | avril 2026 | **oui** | Pages auxiliaires (templates séparés, non liées aux onglets) : | Page | Route | État | Verdict | |---|---|---|---| | `/chat` | `chat.html` + `/api/chat/*` | **OK expérimental** — utilisé en dev | doublonne Agent Chat (5004), à supprimer ici | | `/gestures` | `gestures.html` + `/api/gestures` | **Mort** — aucune donnée, concept abandonné | **à supprimer** | | `/extractions` | `extractions.html` + `/api/extractions*` | **Douteux** — fonctionnalité concurrente au plan Data Extraction prévu via VWB | à geler/archiver | | `/streaming` | `streaming.html` | **Doublon** — remplacé par l'onglet Streaming intégré dans `index.html` | **à supprimer** | SocketIO : 4 events (`connect`, `disconnect`, `subscribe_execution`, `get_performance`). Seul `connect/disconnect` sert aujourd'hui — le reste alimente l'onglet Exécution qui va disparaître. --- ## Section B — À virer (cleanup) Dans cet ordre, à faire en un seul coup (effort total estimé : **2 à 3 heures**). 1. **Onglet 🧪 Tests** (lignes 67, 499-517 de `index.html` ; routes 1006-1094 de `app.py`) - Pourquoi : exécuter `pytest` depuis une UI auth Basic exposée sur Internet est une RCE déguisée. Et ça plante en prod. Les tests se lancent en CLI. - Effort : 20 min. 2. **Onglet 🧠 Apprentissage** (lignes 70, 665-720) - Pourquoi : placeholders, aucune route backend, induit le client en erreur. - Alternative : soit on le refait proprement dans l'onglet **Audit & Traçabilité** (stats globales sur trace d'exécution), soit on l'enlève. - Effort : 10 min (retrait). 3. **Onglet 🔧 Corrections** (lignes 69, 603-664) - Pourquoi : les correction packs sont gérés dans VWB, pas ici. L'onglet affiche des cartes qui ne se remplissent plus. Ajouter un simple bouton "Ouvrir VWB" dans l'onglet Services suffit. - Effort : 10 min. 4. **Onglet ⚡ Exécution** (lignes 61, 197-233) - Pourquoi : branché sur l'ancien moteur core via SocketIO `subscribe_execution`. Aujourd'hui le replay passe par l'Agent V1 et VWB. L'onglet Streaming couvre déjà le live. - Effort : 15 min (retrait + supprimer les 4 routes `/api/automation/*`). 5. **Onglet 📊 Vue d'ensemble** (lignes 60, 162-194) - Pourquoi : 4 stat-cards dupliquées depuis Services + Sessions + Workflows. Un `perfChart` qui duplique ce qui est dans Performance. - Alternative : fusionner un mini-résumé (4 KPIs) en tête de l'onglet Services, ce qui fait gagner un clic. Puis supprimer l'onglet. - Effort : 30 min. 6. **Pages auxiliaires `/chat`, `/gestures`, `/streaming`, `/extractions`** - Pourquoi : concurrence avec services dédiés (Agent Chat 5004, VWB, plan Data Extraction) ou fonctionnalités mortes (gestures). - Effort : 15 min (supprimer templates + routes Flask). 7. **Code mort résiduel** - `execution_state`, `performance_metrics` (globales module) : utiles uniquement si Exécution / Overview subsistent. - `chain_manager`, `trigger_manager`, `automation_scheduler` : à évaluer, probablement à garder côté moteur mais retirer l'UI. - Effort : 30 min. **Résultat visé** : de 14 onglets à **8 onglets** (Services, Sessions, Performance, Streaming, Logs, Sauvegardes, Config, Nettoyage) **+ 1 nouveau** (Audit). Soit **9 onglets utiles et alimentés**. --- ## Section C — À garder mais améliorer Par priorité. 1. **🎛️ Services** — ajouter un bandeau "santé globale" (somme du statut des 6 services critiques + streaming server + session cleaner) et rapatrier les 4 stat-cards de "Vue d'ensemble" en tête. Effort : **1 h**. 2. **📦 Sessions** — ajouter un filtre par statut (pending/processing/completed/failed — la donnée existe déjà dans `PROCESSING_STATUS_FILE`). Ajouter un bouton "Voir dans le cleaner" qui ouvre l'onglet Nettoyage pré-filtré sur la session. Effort : **1 h**. 3. **📄 Logs** — passer en lecture "tail -f" WebSocket plutôt que polling d'un fichier entier. Filtrer par niveau (INFO/WARN/ERROR) côté serveur. Effort : **2 h**. Faible priorité : une fois l'onglet Audit en place, 90 % de l'usage métier disparaît. 4. **📈 Performance** — la section FAISS est bonne. Retirer les deux graphiques Chart.js `cacheChart` et `faissChart` : ils se redessinent toutes les 5s avec un tableau vide au reload, c'est du bruit visuel. Effort : **20 min**. 5. **🔧 Configuration** — documenter dans un tooltip chaque champ (DASHBOARD_PASSWORD, RPA_API_TOKEN, etc.) et signaler clairement les secrets. Ajouter un bouton "Recharger les modèles Ollama" déjà présent mais discret. Effort : **1 h**. Aucune amélioration pour Streaming, Sauvegardes, Nettoyage : ils sont récents et suffisants. --- ## Section D — Nouvel onglet "⚖️ Audit & Traçabilité" ### Ce que l'utilisateur voit Une table paginée des actions Léa, précédée de filtres, avec export CSV. **Bandeau haut** — 4 KPIs aujourd'hui : - Actions totales (24 h) - Taux de succès global - Nombre de TIMs actifs - Applications cibles touchées **Zone de filtres** (ligne horizontale) : - Période (preset : Aujourd'hui / 7j / 30j / personnalisée via deux date pickers) - Collaborateur (dropdown peuplé via `/api/v1/audit/summary` → `by_user`) - Application métier (dropdown, peuplé via le champ `target_app` des entrées) - Type d'action (click, type, key_combo, wait) - Résultat (success / failed / recovered / skipped) - Mode d'exécution (autonomous / assisted / shadow) - Workflow (dropdown si < 50, sinon champ texte) - Recherche libre (matche `action_detail`) **Boutons d'action** (à droite du bandeau) : - 📥 Exporter CSV (respecte les filtres courants) - 📄 Rapport PDF pour DSI (génération simple, voir ci-dessous) - 🔄 Actualiser **Tableau principal** (colonnes dans cet ordre) : | Colonne | Source `AuditEntry` | Remarque | |---|---|---| | Horodatage | `timestamp` | affichage local `HH:mm:ss · JJ/MM` | | Collaborateur | `user_name` ou fallback `user_id` | | | Poste | `machine_id` | utile multi-sites | | Application | `target_app` | DPI, Orbis, DxCare, navigateur… | | Action | `action_type` + badge | icône par type | | Détail | `action_detail` | tronqué à 80 car., tooltip complet | | Mode | `execution_mode` | badge coloré | | Résultat | `result` | vert/rouge/orange | | Récup. | `recovery_action` | uniquement si `result != success` | | Durée | `duration_ms` | ms → s si > 1 s | | Workflow | `workflow_name` ou `workflow_id` tronqué | lien vers détail workflow | Ligne cliquable → panneau latéral avec le JSON complet (+ `critic_result`, `resolution_method`, session_id, action_id). Ce panneau sert aux audits techniques. **Pagination** serveur (limit 100, offset) — le backend `/api/v1/audit/history` gère déjà. **Widgets complémentaires** (en dessous du tableau) : - Camembert "répartition par application" (utile DSI pour visualiser le périmètre Léa) - Courbe "taux d'échec sur 7 j" (seuil d'alerte ajustable) - Liste "Top 10 échecs récents" — pour qu'un TIM/RSSI identifie vite les workflows à retoucher ### Sources de données — ce qui existe déjà Tout le backend est **déjà là** côté streaming server (port 5005) : - Module `agent_v0/server_v1/audit_trail.py` — `AuditTrail` avec `record()`, `query()`, `get_summary()`, `export_csv()`. - Endpoints FastAPI déjà en place : - `GET /api/v1/audit/history` — historique filtrable paginé - `GET /api/v1/audit/summary?date=YYYY-MM-DD` — résumé du jour - `GET /api/v1/audit/export` — export CSV - Données réelles présentes dans `data/audit/audit_YYYY-MM-DD.jsonl` (7 fichiers, ~500 ko sur les 10 derniers jours, ~1 800 entrées aujourd'hui). ### Ce qu'il manque 1. **Proxy Flask côté dashboard (5001 → 5005)** — sur le modèle de `/api/streaming/` qui existe déjà (`app.py:2505`). Coût : ~30 lignes. 2. **Template HTML + JS** — nouvel onglet dans `index.html`, ~300 lignes. Pas de framework : réutiliser le style et Chart.js existant. 3. **Champ patient pseudonymisé** : actuellement **pas présent** dans `AuditEntry`. Décision nécessaire : - Option A (recommandée) : ajouter un champ optionnel `patient_ref_hash` (SHA-256 tronqué du n° patient), alimenté quand Léa extrait ou saisit un identifiant patient. Coût : ajout d'un champ dataclass + propagation dans 2-3 endroits au niveau exécuteur. - Option B : n'en pas mettre pour le POC Anouste, préciser dans la doc DSI. 4. **Rapport PDF DSI** — simple template ReportLab ou WeasyPrint, une page A4 avec en-tête (client, période, nombre d'actions, signature hash des logs source pour intégrité), puis le tableau filtré. Coût : ~150 lignes + 1 dép. ### Effort estimé | Lot | Jours·homme | |---|---| | Proxy Flask + nouvel onglet (MVP : tableau + filtres + export CSV) | **0.5** | | Widgets graphiques (camembert + courbe 7j) | 0.25 | | Rapport PDF DSI | 0.5 | | Champ `patient_ref_hash` (option A) | 0.5 | | Alerting (si > N échecs consécutifs sur 1 h → badge rouge + email optionnel) | 0.5 | | **Total MVP (sans PDF ni patient)** | **0.75 j** | | **Total version "complète DSI-ready"** | **~2.25 j** | ### Réglementaire — ce qui est adressé - **AI Act, article 12 — "Record-keeping"** : les systèmes d'IA à haut risque doivent **automatiquement enregistrer** les événements pertinents. L'onglet rend visibles et exportables les logs qui existent déjà côté serveur. Respect du critère _traçabilité permanente_. - **AI Act, article 14 — "Human oversight"** : le champ `execution_mode` (`shadow/assisted/autonomous`) documente le niveau de supervision humaine pour chaque action. - **RGPD, article 30 — registre des traitements** : champ `target_app` + `domain` permettent de produire un inventaire des traitements par application métier. - **RGPD, article 32 — intégrité** : ajouter un hash SHA-256 du fichier JSONL signé à la clôture journalière (coût marginal, 20 lignes) garantit la non-falsification. - **RGPD, article 33 — notification de violation** : l'alerting (> N échecs sur fenêtre glissante) est la brique technique qui permet à un RSSI d'être notifié. ### Exemple concret — "un DSI hospitalier demande un audit" **Scénario** : le DSI du CH d'Auch veut montrer à son directeur que Léa n'a jamais validé seule une codification CIM-10 sur le patient X pendant la semaine 15. 1. Il ouvre le dashboard → onglet Audit. 2. Filtre : période = 2026-04-06 → 2026-04-12, application = `DxCare`, action = `click`. 3. Il saisit dans la recherche libre le hash pseudo du patient (fourni par le TIM responsable). 4. Il voit 3 lignes, toutes en mode `assisted`, toutes avec `user_name = "Marie Dupont"`. 5. Il clique sur "📄 Rapport PDF DSI" → reçoit un PDF d'une page avec les 3 lignes, la signature d'intégrité, le tampon Léa, la période. 6. Il remonte ça à sa direction. Dossier clos en 4 minutes. C'est exactement le cas d'usage qui manque aujourd'hui et qui fera la différence en appel d'offres CHU. --- ## Section E — Non-décisions (ce qu'on ne fait pas) - **Dashboard mobile / responsive** : le dashboard est un outil admin, pas un produit grand public. Les TIMs n'en ont pas besoin sur téléphone. **Non.** - **Multi-thème (clair/sombre)** : sombre tout le temps. **Non.** - **Internationalisation du dashboard** : tout est en français, cible FR. i18n prévu côté produit Léa, pas côté dashboard admin. **Non pour 2026.** - **Refonte complète en framework (React/Vue)** : le HTML vanilla + Chart.js tient la route. Une refonte coûterait 2 semaines pour zéro gain utilisateur. **Non.** - **Authentification OAuth / SSO** : HTTP Basic suffit sur usage interne. SSO hôpital = chantier en soi, ne pas le mélanger avec ce cleanup. **Pas maintenant.** - **Temps réel sur l'onglet Audit** : le polling toutes les 30 s est largement suffisant. WebSocket = complexité inutile ici. **Non.** --- ## Section F — Roadmap recommandée Ordre **non négociable** : on fait le ménage **avant** d'ajouter du neuf. Un onglet Audit brillant au milieu d'un dashboard bruité envoie un signal d'amateurisme. ### Sprint 1 — Cleanup (0.5 jour) - Section B points 1 à 7 (retirer Tests, Apprentissage, Corrections, Exécution, Vue d'ensemble, pages mortes, code orphelin). - **Livrable** : dashboard à 8 onglets fonctionnels, zéro placeholder, zéro 404 silencieuse. - **Critère de sortie** : un client invité voit l'interface sans jamais tomber sur une page vide ou une erreur JS. ### Sprint 2 — Onglet Audit MVP (0.75 jour) - Proxy Flask `/api/audit/*` → `http://localhost:5005/api/v1/audit/*` (réutilise le pattern `/api/streaming/`). - Nouvel onglet "⚖️ Audit & Traçabilité" : bandeau 4 KPIs + filtres + tableau paginé + export CSV. - **Livrable** : un DSI peut filtrer, visualiser, exporter. - **Critère de sortie** : scénario CH Auch (voir Section D) exécutable en < 5 min par un utilisateur non technique. ### Sprint 3 — Audit complet DSI-ready (1.5 jour, à chaud si appel d'offres) - Rapport PDF DSI. - Champ `patient_ref_hash` dans `AuditEntry` + propagation executor. - Signature d'intégrité journalière (hash du JSONL en clôture). - Widgets graphiques (camembert + courbe 7 j). - Alerting seuil d'échecs. - **Livrable** : conformité démontrable AI Act art. 12 + 14 + RGPD art. 30 + 32. ### Sprint 4 — Améliorations ciblées (1 à 2 jours, au fil de l'eau) - Section C (santé globale Services, filtres Sessions, tail logs WebSocket, retrait graphiques vides Performance, tooltips Config). - À faire **seulement** quand un TIM ou un DSI remonte un manque précis, pas en préventif. --- ## Annexe — Justification du cleanup Pourquoi on supprime plutôt qu'on "met en veille" ? 1. Chaque onglet coûte en maintenance (CSS, JS, tests manuels, support client). 2. Chaque route Flask morte est une surface d'attaque (surtout `/api/tests/run` qui exécute `pytest` en subprocess). 3. Chaque placeholder visuel dégrade la perception client : "pourquoi il y a un onglet 🧠 Apprentissage qui n'affiche rien ?" 4. Git garde tout. Aucune donnée n'est perdue. Revert possible. Principe général : **moins de surface, plus de valeur**. Un dashboard de 9 onglets pleins bat un dashboard de 14 onglets dont 5 creux, tous les jours.