feat: pipeline complet MACRO/MÉSO/MICRO — Critic, Observer, Policy, Recovery, Learning, Audit Trail, TaskPlanner

Architecture 3 niveaux implémentée et testée (137 tests unitaires + 21 visuels) :

MÉSO (acteur intelligent) :
- P0 Critic : vérification sémantique post-action via gemma4 (replay_verifier.py)
- P1 Observer : pré-analyse écran avant chaque action (api_stream.py /pre_analyze)
- P2 Grounding/Policy : séparation localisation (grounding.py) et décision (policy.py)
- P3 Recovery : rollback automatique Ctrl+Z/Escape/Alt+F4 (recovery.py)
- P4 Learning : apprentissage runtime avec boucle de consolidation (replay_learner.py)

MACRO (planificateur) :
- TaskPlanner : comprend les ordres en langage naturel via gemma4 (task_planner.py)
- Contexte métier TIM/CIM-10 pour les hôpitaux (domain_context.py)
- Endpoint POST /api/v1/task pour l'exécution par instruction

Traçabilité :
- Audit trail complet avec 18 champs par action (audit_trail.py)
- Endpoints GET /audit/history, /audit/summary, /audit/export (CSV)

Grounding :
- Fix parsing bbox_2d qwen2.5vl (pixels relatifs, pas grille 1000x1000)
- Benchmarks visuels sur captures réelles (3 approches : baseline, zoom, Citrix)
- Reproductibilité validée : variance < 0.008 sur 10 itérations

Sécurité :
- Tokens de production retirés du code source → .env.local
- Secret key aléatoire si non configuré
- Suppression logs qui leakent les tokens

Résultats : 80% de replay (vs 12.5% avant), 100% détection visuelle Citrix JPEG Q20

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-04-09 21:03:25 +02:00
parent 72a9651b94
commit 99041f0117
21 changed files with 7810 additions and 110 deletions

View File

@@ -68,12 +68,19 @@ class TokenManager:
logger.info(f"Loading token config. RPA_TOKEN_ADMIN present: {bool(admin_token)}")
logger.info(f"Loading token config. RPA_TOKEN_READONLY present: {bool(readonly_token)}")
if admin_token:
logger.info(f"RPA_TOKEN_ADMIN value: {admin_token[:8]}...")
logger.info("RPA_TOKEN_ADMIN configuré")
if readonly_token:
logger.info(f"RPA_TOKEN_READONLY value: {readonly_token[:8]}...")
logger.info("RPA_TOKEN_READONLY configuré")
# Clé secrète pour signer les tokens
self.secret_key = os.getenv("TOKEN_SECRET_KEY", "dev-token-secret-change-in-production")
# Clé secrète pour signer les tokens — OBLIGATOIRE en production
self.secret_key = os.getenv("TOKEN_SECRET_KEY", "")
if not self.secret_key:
logger.warning(
"TOKEN_SECRET_KEY non défini — utilisation d'une clé aléatoire. "
"Définir TOKEN_SECRET_KEY dans .env.local pour la production."
)
import secrets
self.secret_key = secrets.token_hex(32)
# Tokens statiques pour rétrocompatibilité
self.admin_tokens = set()
@@ -89,24 +96,26 @@ class TokenManager:
self.admin_tokens.add(admin_token)
logger.info(f"Added RPA_TOKEN_ADMIN to admin_tokens")
# Temporary fix: Add production tokens directly
prod_admin_token = "73cf0db73f9a5064e79afebba96c85338be65cc2060b9c1d42c3ea5dd7d4e490"
prod_readonly_token = "7eea1de415cc69c02381ce09ff63aeebf3e1d9b476d54aa6730ba9de849e3dc6"
self.admin_tokens.add(prod_admin_token)
logger.info(f"Added hardcoded production admin token")
# Tokens de production : lus EXCLUSIVEMENT depuis les variables d'environnement.
# Ne JAMAIS hardcoder de tokens dans le code source.
prod_admin_token = os.getenv("RPA_PROD_ADMIN_TOKEN", "")
prod_readonly_token = os.getenv("RPA_PROD_READONLY_TOKEN", "")
if prod_admin_token:
self.admin_tokens.add(prod_admin_token)
logger.info("Added RPA_PROD_ADMIN_TOKEN to admin_tokens")
self.read_only_tokens = set()
if os.getenv("READ_ONLY_TOKENS"):
self.read_only_tokens = set(os.getenv("READ_ONLY_TOKENS").split(","))
# Support tokens RPA Vision V3 (Fiche #23)
if readonly_token:
self.read_only_tokens.add(readonly_token)
logger.info(f"Added RPA_TOKEN_READONLY to read_only_tokens")
# Temporary fix: Add production tokens directly
self.read_only_tokens.add(prod_readonly_token)
logger.info(f"Added hardcoded production readonly token")
logger.info("Added RPA_TOKEN_READONLY to read_only_tokens")
if prod_readonly_token:
self.read_only_tokens.add(prod_readonly_token)
logger.info("Added RPA_PROD_READONLY_TOKEN to read_only_tokens")
# Configuration expiration
self.default_expiry_hours = int(os.getenv("TOKEN_EXPIRY_HOURS", "24"))