Commit Graph

183 Commits

Author SHA1 Message Date
Dom
f9a0531325 feat(navigation): brique login visuel OCR-ancre + action navigate au replay
Some checks failed
tests / Lint (ruff + black) (push) Failing after 1m52s
tests / Tests unitaires (sans GPU) (push) Failing after 1m58s
tests / Tests sécurité (critique) (push) Has been skipped
- core/navigation/ : visual_verifier (presence=OCR, role=VLM ancre sur tokens),
  grounding (OCR-anchor first, VLM fallback, cache coords valide par la vue),
  visual_login (verify_before/after, DETTE-023), action_resolver (pont runtime)
- api_stream/replay_engine : dispatch action navigate server-side,
  never-fail -> needs_review, import depuis core.navigation (boot 5005 garanti)
- 131 tests verts (wiring boot, e2e handler, unit modules)

Chantier Qwen 01-02/07/2026, revue croisee Claude (plan deploy v2).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 10:31:44 +02:00
Dom
ab78ae390a chore(version): bump 1.0.1 -> 1.0.2 (fixes client + installeur upgrade-safe)
Nouvelle politique : versionner chaque livrable. 1.0.2 = httpx embed +
capture JPEG + watchdog RDP + MAJ silencieuse (OFF) + installeur voie 1
(preserve identite, tue Lea, backup, purge). Source de verite = config.py
(AGENT_VERSION) + Lea.iss (MyAppVersion).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 00:06:39 +02:00
Dom
a210e5ee32 feat(update): swap atomique + rollback (Lea.bat) + confirmation boot (main.py)
Implémente le SWAP réel de la MAJ silencieuse (DETTE-022), remplace les stubs :
- updater.apply_update : ARME le swap (extrait le ZIP -> agent_v1_new/ +
  marqueur UPDATE_READY, garde-fou zip-slip). N'écrase JAMAIS le vivant.
- updater.write_boot_ok_marker : désarme le rollback (retire PENDING_BOOT).
- Lea.bat (template + embed généré par configure_embed.ps1) : swap ATOMIQUE
  par renames (agent_v1 -> agent_v1_prev backup ; agent_v1_new -> agent_v1)
  + rollback auto si PENDING_BOOT persiste (boot précédent non confirmé).
- main.py : confirme le boot après 90 s de liveness locale OU quit propre
  (évite un faux rollback ; RPA_BOOT_CONFIRM_DELAY_S surchargeable pour les tests).

Testable (Python) : 45 tests verts. Le swap OS (renames Lea.bat) + le câblage
main.py seront validés par le test Win 11 (step 0 pré-canary, dont le rollback).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 14:10:34 +02:00
Dom
5d235e49f1 merge: MAJ silencieuse scaffold 2026-07-01 12:37:21 +02:00
Dom
e679804cfd merge: disparition Lea (watchdog) 2026-07-01 12:37:21 +02:00
Dom
e57b54a100 merge: capture JPEG+chemin 2026-07-01 12:37:21 +02:00
Dom
61664c9a36 feat(update): scaffold MAJ silencieuse + canary par machine (DETTE-022, gated OFF, swap encore stub)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 12:36:48 +02:00
Dom
9ab5ed4671 fix(agent): resilience disparition Lea en RDP/Citrix (watchdog session interactive re-affiche le tray)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 12:36:47 +02:00
Dom
144a5c288a fix(agent): capture JPEG+downscale (allege CPU/disque, frequence intacte) + robustesse chemin _background/shots
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 12:36:47 +02:00
Dom
e3f61de4ad fix(agent): embarquer httpx>=0.27 dans le build embed (orchestrateur Lea muet en clinique)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 12:36:47 +02:00
Dom
2a1b1ed80e feat(stream): dispatch extract_dossier -> handler serveur
Some checks failed
tests / Lint (ruff + black) (push) Failing after 2m3s
tests / Tests unitaires (sans GPU) (push) Failing after 1m51s
tests / Tests sécurité (critique) (push) Has been skipped
Câble le type d'action 'extract_dossier' dans get_next_action (api_stream)
vers _handle_extract_dossier_action (replay_engine). La brique 3 (OCR ->
gate -> persist dossier VWB) était committée mais non atteignable au runtime
faute de dispatch. Import + elif dédié, timeout 180s, exécuteur non bloquant.

Note: le handler utilise encore l'ancienne chaîne (extract_grid + gate maison).
Le remplacement par l'extraction ancrée (map_roles/vlm_client) est une modif
séparée côté replay_engine (ma zone).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:05:22 +02:00
Dom
813b33b47e feat(update): DETTE-022 — noyau MAJ silencieuse client Léa (gated, swap en stub)
Logique PURE testée : parse_version semver (R3), decide_update code-only/full (R2),
should_update client (double garde anti-downgrade), download_update (staging only +
SHA256, downloader injectable). Endpoint GET /api/v1/agents/update/check gated
(RPA_AUTO_UPDATE_SERVER_ENABLED). Flags client+serveur OFF par défaut.
Swap fichiers / Lea.bat / restart = STUBS no-op réservés révision humaine.
34 tests TDD. refs DETTE-022

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 16:21:35 +02:00
Dom
3ed9798f06 feat(agent_v1): log shipper — remontee auto des logs vers le serveur (gated OFF)
Some checks failed
tests / Lint (ruff + black) (push) Failing after 1m43s
tests / Tests unitaires (sans GPU) (push) Failing after 1m51s
tests / Tests sécurité (critique) (push) Has been skipped
LogShipperHandler + LogShipper : buffer borne, flush par batch <= max, resilience
0-perte (rejeu sur echec), sender injectable. Flag RPA_LOG_SHIP_ENABLED (defaut
off, activable par config.txt sans rebuild). Sanitizer client = identite (rempart
PII = serveur, cf commit precedent). Wiring gated dans main.py. 8 tests TDD.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 13:30:08 +02:00
Dom
b65710ae43 feat(server): assainissement PII des logs clients à la réception
sanitize_log_entries (réutilise anonymize_text, mapping partagé = tokens cohérents),
branché dans POST /api/v1/agents/logs avant le store : message + logger tokenisés,
ts/level préservés. 7 tests TDD. Rempart PII central du push-log (couvre les postes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 13:30:08 +02:00
Dom
c82829f2bb feat(server): R1 — import auto du workflow appris vers la DB VWB (gated)
Some checks failed
tests / Lint (ruff + black) (push) Failing after 1m44s
tests / Tests unitaires (sans GPU) (push) Failing after 1m49s
tests / Tests sécurité (critique) (push) Has been skipped
finalize_session appelle _maybe_import_to_vwb : si RPA_R1_AUTO_IMPORT (OFF par
défaut), le workflow appris est assaini (sanitize_workflow_dict) puis importé en
DB VWB rejouable via le pont idempotent (import_core_workflow_to_db), dans un
app-context VWB lazy mutualisé (vwb_db). NON bloquant : un échec n'interrompt
jamais la finalisation. Rend l'appris rejouable sans geste manuel (R1).
Tests : câblage du seam + gating du flag + non-régression.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 17:44:24 +02:00
Dom
6075717353 feat(server): durcissement sanitizer PII (chevauchements + GXD5 + workflow_dict)
- Résolution des chevauchements par priorité de détecteur + longueur : corrige le
  FN où, sur 'Dossier/Patient NOM (NAISSANCE) Prénom', le nom de naissance fuyait. (Qwen)
- RE_GXD5_DIAG : tokenise le numéro de dossier ([DOSSIER_n]) ET le nom ([NOM_n]) dans
  'GXD5 Diagnostics - <num> - NOM PRENOM' — 3 patients fuyaient en prod clinique, 0 FP. (Qwen)
- sanitize_workflow_dict : assainit les champs texte d'un workflow appris (by_text, noms)
  avant import en DB VWB (canal apprentissage). Utilisé par R1. (Claude)
14 tests verts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 17:44:24 +02:00
Dom
13f760a3b9 feat(extraction): handler extract_dossier + pont worker→DB VWB mutualisé (brique 3)
vwb_db.py : couplage worker→DB VWB lazy (app Flask sur instance/workflows.db)
mutualisé (R1 + extraction), + persist_extracted_dossier (grille → Job/Table/Field).
replay_engine.py : handler _handle_extract_dossier_action — lit le screenshot,
extrait une grille structurée, gate qualité conservatrice (complete|needs_review),
persiste avec preuve (screenshot_ref/bbox/confidence). N'échoue JAMAIS le replay.
Données patient EN CLAIR (canal extraction, non anonymisé).

Réserve : dispatch runtime (api_stream.py) non encore branché — étape suivante,
à coordonner. Brique 3/4 de la verticale extraction dossier patient.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 14:18:08 +02:00
Dom
fccc06e4a2 feat(server): floute aussi les focus_* (blind spot PII)
Les screenshots focus_* (plein écran, ~1440 fichiers/350 Mo) contenaient des
titres PII non floutés. La condition de blur serveur les inclut désormais,
au même titre que shot_*_full et heartbeat_*. Brut conservé, version _blurred
produite en parallèle. (blind spot relevé par Qwen, revue 28/06)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 11:05:10 +02:00
Dom
6461f0a21b feat(server): câble sanitize_event au chokepoint stream_event (PII)
Assainissement PII appliqué une seule fois à l'entrée de stream_event(),
avec un mapping de tokens par session (cohérence intra-session). Les chemins
de persistance et de traitement (jsonl, worker.process_event_direct,
shadow_observe_event, enrichissement SOM) consomment tous la copie assainie
au lieu de l'event brut — plus aucune PII patient en clair côté serveur.

Test de non-régression du câblage: stream_event ne doit jamais écrire de PII
brute (IPP/contenu saisi) dans live_events.jsonl ni la propager au worker/shadow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 10:39:27 +02:00
Dom
e84cdee393 fix(server): durcissement sanitizer PII suite revue adversariale Qwen
- FN-1/2/3 : ajout RE_PRENOM_NOM (« Prénom NOM » inversé sans parens/crochets,
  ex. « Alix DATTIN ») ; 2e mot tout-majuscules -> 0 FP sur « Mozilla Firefox ».
- FN-4 (majeur, 228 events) : sanitize_event scanne désormais les titres
  RÉCURSIVEMENT (vision_info.window_capture.window_title et tout titre imbriqué),
  au lieu de 3 clés top-level hardcodées.
2 correctifs issus de la revue croisée Qwen. 11 tests verts, 0 FP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 20:24:52 +02:00
Dom
30d8f65e9a feat(server): sanitize_event — assainissement PII au niveau event
sanitize_event(event, mapping) applique le principe « Léa apprend l'interface,
pas la donnée » (décision Dom 28/06) avant persistance :
- text_input -> contenu (text + raw_keys) remplacé par [SAISIE] (option b) :
  résout la fuite la plus grave (contenu médical) SANS NER ni détection ;
- titres de fenêtre (active_window_title + window/to/from.title) : identité
  patient tokenisée (anonymize_text), app/écran gardés ; cohérence par mapping.
Copie défensive (ne mute pas l'event d'origine). 4 tests (9 au total) verts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 19:53:09 +02:00
Dom
8e4d09594c feat(server): assainissement PII couche regex+structurelle (tokens typés cohérents)
pii_sanitizer.anonymize_text() remplace la PII par des tokens typés et
cohérents ([IPP_1], [AGE_1], [NOM_1]) : protège la donnée ET garde la structure
(type de champ) utile à l'apprentissage des variables. Sans modèle, déployable
partout. Filet regex (IPP/NIR/TEL/EMAIL/AGE, repris de anonymisation) + règles
structurelles cliniques (NOM (NAISSANCE) Prénom ; [Nom Prénom] PACS) + blacklist
logiciels anti-FP. 5 tests verts. Couche NER (noms libres) en complément ensuite.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 19:08:43 +02:00
Dom
46ad5973d1 fix(agent_v1): assainissement PII des logs client a la source (push-log-DGX, brique 4)
Remplace dans les logs/print le contenu utilisateur brut par un equivalent
PII-safe via core/log_safe : titres de fenetre -> _title_hash, reponses VLM ->
[len,has_target], metadonnees -> _sanitize_metadata, chemins -> _path_ext,
workflow_name -> _title_hash. 8 fichiers (executor, recovery, captor, streamer,
main, capture_server, activity_panel, window_info_crossplatform).

Audit Qwen complete : ~17 fuites de titre multi-lignes + 2e fuite VLM (print)
non listees ont ete traitees ; localisation par contenu (refs Qwen derivees).

Preserve volontairement : prompts de grounding VLM (vlm_description) ou le titre
est load-bearing (resolution 100% vision) -> ne PAS hasher.
Differe : window_focus_change (verdict apprentissage).
En attente arbitrage Dom : button_text (~11 captions), patterns, champs detail.

py_compile 8/8 OK, imports OK, helper 6/6 vert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 11:42:40 +02:00
Dom
4a38000e74 feat(agent_v1): helpers logging PII-safe (push-log-DGX, brique 4)
Module agent_v1/core/log_safe.py — 3 helpers purs pour assainir les logs
client à la source : _title_hash (SHA1[:8], corrélation sans révéler),
_sanitize_metadata (drop title/active_window/window_title), _path_ext
(extension seule). 6 tests unitaires verts. Module inerte (non encore wired) ;
le branchement dans le code runtime suit en étape supervisée.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 11:24:54 +02:00
Dom
2597ca9110 feat(server): endpoint GET /api/v1/agents/logs/{machine_id} (push-log-DGX, brique 3)
Route de diagnostic dashboard (read-only) : restitue les logs poussés par un
poste, rangés par machine_id. Bearer global ; volontairement sans garde fleet
(consultation d'un poste révoqué/en panne). limit=tail pour borner la réponse.
4 tests d'intégration verts ; store inchangé (briques 1-2 figées).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 10:47:08 +02:00
Dom
bbe897e614 feat(server): endpoint POST /api/v1/agents/logs (push-log-DGX, brique 2)
Reçoit un batch de logs client, range via AgentLogsStore par machine_id.
Garde-fous : auth Bearer (401), agent actif via _guard_agent_registry_access
(403 si révoqué/inconnu, + touch_last_seen), cap anti-flood 413 (G3 Qwen,
RPA_AGENT_LOGS_MAX_BATCH=1000). TDD 4/4 ; non-régression enroll 16/16.

refs DETTE-020 DETTE-021

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 16:25:14 +02:00
Dom
a29b7a2f21 feat(server): store de logs clients par machine_id (push-log-DGX, brique 1)
AgentLogsStore : append/read JSONL rangés par machine_id (fichier par jour),
anti path-traversal sur machine_id (entrée réseau), purge_old rétention 30j
(garde-fou G4 Qwen). TDD 3/3 vert. Pas encore wired (endpoint = brique 2).

refs DETTE-020 DETTE-021

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 16:14:28 +02:00
Dom
105ade959d chore(agent_v1): AGENT_VERSION configurable via RPA_AGENT_VERSION (amorce DETTE-022)
Permet d'identifier la version déployée par poste (préparation MAJ auto).
Inoffensif pour DETTE-021 ; nettoie le working tree avant déploiement Émilie.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 09:50:58 +02:00
Dom
29cb466595 fix(lea): journalisation client vers fichier (DETTE-021)
setup_logging() branche un TimedRotatingFileHandler vers LOG_FILE (rotation
quotidienne + rétention 180j, Règlement IA Art.12) + console. Sous pythonw
(sans console), basicConfig->stderr était perdu => diagnostic terrain aveugle.
main.py appelle setup_logging au démarrage, avec fallback console si le fichier
est indisponible (ne jamais empêcher Léa de démarrer).

TDD: tests/unit/test_agent_v1_logging.py (3 tests RED->GREEN ; module chargé par
chemin pour éviter les imports lourds DETTE-011/013). py_compile main.py OK.

refs DETTE-021

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 16:44:31 +02:00
Dom
ec1fb81054 fix(dashboard,worker): vérité produit P0 — dashboard+worker+VWB export
Some checks failed
tests / Lint (ruff + black) (push) Failing after 1m46s
tests / Tests unitaires (sans GPU) (push) Failing after 2m0s
tests / Tests sécurité (critique) (push) Has been skipped
War-room clôture DGX 2026-06-18 (recadrage Dom : graphe/apprentissage/mémoire/dashboard = surface produit P0).
Le dashboard et le statut worker affichaient des états faux ; corrige pour refléter la vérité du produit.

- dashboard FAISS: distingue index brut / metadata HMAC invalide / runtime / absent (plus de faux "inactif")
- dashboard process-mining: 503 explicite missing_dependency (plus de message trompeur)
- dashboard /api/workflows + system/status: lecture DB VWB v3 canonique (total réel = 24, plus de 0)
- worker /processing/status: véridique (lit _worker_health.json) + statut "idle/armé (lazy)" distinct de "dégradé (échec)"
- VWB export: N steps -> N actions/edges (dernière action n'est plus perdue)
- tests: dashboard routes, worker status truthfulness, export VWB

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 17:50:12 +02:00
Dom
667575c3ad feat(installer): make Lea autonomous for POC 2026-06-17 17:53:46 +02:00
Dom
2b1743c206 fix(poc-agent): ouvrir le chat Lea DGX si Tk est indisponible
Some checks failed
tests / Lint (ruff + black) (push) Failing after 1m43s
tests / Tests unitaires (sans GPU) (push) Failing after 1m46s
tests / Tests sécurité (critique) (push) Has been skipped
2026-06-15 21:32:54 +02:00
Dom
33c1e2e0d1 fix(grounding): confiance grounding dérivée sémantique (DETTE-019)
Some checks failed
tests / Lint (ruff + black) (push) Failing after 1m48s
tests / Tests unitaires (sans GPU) (push) Failing after 1m50s
tests / Tests sécurité (critique) (push) Has been skipped
Le score/confidence figés à 0.85 dans _resolve_by_grounding rendaient le
garde-seuil (_RESOLUTION_MIN_SCORES["grounding"]=0.60) inopérant (0.85>0.60
toujours accepté). Le grounding VLM n'a pas de confiance modèle native (prompt
{"x","y"}, pas de logprob de localisation — confirmé QG Qwen 2026-06-15). On
dérive une confiance SÉMANTIQUE : le texte cible est-il à la position trouvée ?
(_validate_text_at_position). Confirmé→0.90, absent→0.45 (<seuil→rejet),
non vérifiable→0.70. Confiance contextuelle documentée, PAS une proba modèle.

TDD : 5 tests (score varie / présent accepté / absent rejeté / score==confidence
/ sans by_text neutre), RED→GREEN. Non-régression : 24 tests resolve_engine +
câblage qwen3vl + legacy bbox verts. E2E panel inchangé (15/15). Pré-check OCR
non impacté. DETTE-018 (legacy non gardé) reste séparée.

refs DETTE-019

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 09:17:46 +02:00
Dom
5c5ce747b0 feat(grounding): câblage Qwen3-VL-4B/vLLM (RPA_GROUNDING_ENGINE, défaut off)
Active via RPA_GROUNDING_ENGINE=qwen3vl_vllm (défaut OFF = legacy Qwen2.5-VL
inchangé, byte-identique). Mode qwen3vl : port 8001/Qwen3-VL-4B, prompt point
0-1, think=false, parse /1000 (dissout DETTE-006), method "grounding" gardée
(seuil 0.60), pas de fallback Ollama (abstention si vLLM down). Grounder validé
au bench Easily réel (0.933, ~1s/cas). TDD : 4 tests (normalisation 0-1000,
think=false, prompt fractions 0-1, gating score bas).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 08:39:29 +02:00
Dom
b20d17882e feat(wp-c): méthode verify_token côté registre (patch 3, inerte)
Ajoute AgentRegistry.verify_token(token) -> machine_id|None : compare le
SHA-256 du token aux token_hash des agents 'active' via hmac.compare_digest
(temps constant). Agent désinstallé/révoqué refusé ; rotation à l'enroll
invalide l'ancien token.

Inerte au runtime : méthode non branchée sur l'auth HTTP (le branchement
derrière flag RPA_FLEET_PER_AGENT_TOKEN sera le Patch 4). api_stream.py
intouché. TDD : 6 tests + non-régression WP-C/WP-B (53 verts). Voir
PLAN-WPC-TDD-EXECUTABLE.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 14:21:04 +02:00
Dom
9fb2c7bfee feat(wp-c): génération token par poste à l'enroll (patch 2, inerte runtime)
Génère un token unique (secrets.token_hex(32)) à chaque (ré)enrôlement,
persiste uniquement son empreinte SHA-256 dans token_hash, renseigne
token_issued_at, retourne le clair une seule fois dans le résultat de
enroll. Le clair n'est jamais journalisé ni persisté.

Inerte au runtime : api_stream.py intouché, l'endpoint /agents/enroll ne
propage ni le clair ni le hash (api_token global inchangé). Auth runtime
non modifiée. Aucun branchement _verify_token. TDD : 8 tests + non-régression
WP-B/WP-C (47 verts). Voir PLAN-WPC-TDD-EXECUTABLE / DETTE-015.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 11:36:44 +02:00
Dom
f7f6926410 feat(wp-c): migration colonnes token par poste (patch 1, inerte)
Ajoute token_hash + token_issued_at à enrolled_agents via ALTER TABLE
idempotent (_init_db). Colonnes inertes : aucun branchement auth, runtime
inchangé (tests WP-B verts). Base du token par poste (WP-C, cf DETTE-015).

TDD: tests/unit/test_wpc_migration.py (présence, idempotence, préservation
des données d'une base existante). 3 tests + non-régression WP-B = 9 passed.

refs DETTE-015

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 21:04:18 +02:00
Dom
09f65cecbe fix(security): bind 127.0.0.1 par défaut via RPA_BIND_HOST (plus de host=0.0.0.0 en dur)
Some checks failed
tests / Lint (ruff + black) (push) Failing after 1m44s
tests / Tests unitaires (sans GPU) (push) Failing after 1m48s
tests / Tests sécurité (critique) (push) Has been skipped
Les 4 entrypoints HTTP (api_stream 5005, api_upload 8000, VWB backend 5002,
dashboard 5001) bindaient host=0.0.0.0 en dur -> exposés sur tout le réseau.
Désormais host=os.environ.get('RPA_BIND_HOST','127.0.0.1') : local-only par
défaut, configurable. Découvert à la mise en service DGX local-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 17:49:58 +02:00
Dom
6d34b3cb68 chore(dgx): snapshot consolidation WIP pour transfert poc DGX
Some checks failed
tests / Lint (ruff + black) (push) Failing after 1m44s
tests / Tests unitaires (sans GPU) (push) Failing after 1m49s
tests / Tests sécurité (critique) (push) Has been skipped
Regroupe le WIP non committé requis pour le clone/runtime DGX (Option A) :
- api_stream.py : préflight replay + smoke santé modèles + handler 403 WP-B
- de-hardcode VLM : vlm_config, gpu/*, vram_orchestrator, ollama_manager
- stream_processor, semantic_matcher, agent_chat (app/planner/intent)
- workflows.db (acquis ; le transfert artifacts le mettra à jour + rewrite chemins)
- docs : plans DGX, benchmarks VLM/grounders, recherche SOTA, coordination 8 juin

Snapshot destiné à la branche poc-dgx poussée sur Gitea pour cloner le DGX.
Scan anti-secret : clean. graphify (repo embarqué) exclu.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 16:33:58 +02:00
Dom
f18de016d7 fix(wp-b): verrou d'enrôlement du parc (RPA_FLEET_ENROLL_LOCKED)
Ferme le contournement "poste révoqué + nouveau machine_id + token global" :
quand RPA_FLEET_ENROLL_LOCKED=true, l'enrôlement d'un machine_id INCONNU est refusé
(FleetEnrollLockedError). Les machines déjà connues conservent leur comportement :
active -> AlreadyEnrolled, désinstallé non-revoke -> réactivable, admin_revoke -> Revoked.

- agent_registry.py : _fleet_enroll_locked() + FleetEnrollLockedError + gate avant INSERT
- tests/unit/test_fleet_enroll_lock_wpb.py : 6 tests (verts)

NB : le handler HTTP 403 (api_stream.py /api/v1/agents/enroll) reste dans le WIP de la
branche (api_stream déjà modifié par le préflight non committé) — sera embarqué au commit
de consolidation api_stream. La logique de sécurité (gate) est dans agent_registry, committée.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 15:43:04 +02:00
Dom
0e215da842 feat(p1g): device policy GPU/CPU paramétrable pour la cascade vision
resolve_device(auto/cuda/cpu) avec garde-fou VRAM et fallback CPU propre.
Bascule EasyOCR/SoM/docTR sur GPU si VRAM libre, rollback env sans toucher au code.

- core/gpu/device_policy.py (nouveau) : resolve_device + garde-fou VRAM (max_total_gb)
- core/detection/som_engine.py, core/llm/ocr_extractor.py,
  agent_v0/server_v1/resolve_engine.py : câblage device auto (35 lignes)
- tests/unit/test_device_policy.py : 15 tests (verts venv réel)

Rollback sans toucher au code : RPA_VISION_DEVICE=cpu (force CPU global) / RPA_EASYOCR_GPU=0.
Bench GPU réel (latence) + activation large après verdict Qwen. QG Qwen deja valide sur le patch.
Mergé depuis worktree agent-a4f390f410e00ad7c (base 5b2afa362), 3 fichiers cibles non modifiés
dans le principal (zéro écrasement), dry-run apply propre.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 15:20:52 +02:00
Dom
4dc7d840d6 feat(p1x): de-hardcode VLM models/endpoints to vlm_config (DGX-ready)
Migre les call-sites VLM serveur vers la configuration centrale pour
fonctionner sur DGX (tunnel Ollama 11434), où gemma4:* est absent et le
port Docker 11435 est mort.

- task_planner, replay_verifier, domain_context, ir_builder, resolve_engine
  (popup): modele -> vlm_config.get_vlm_model(), defaut 11435 -> 11434
  (override GEMMA4_PORT legacy conserve)
- resolve_engine (grounding bbox x2): nouvel helper
  vlm_config.get_bbox_grounding_model() (var dediee RPA_BBOX_GROUNDING_MODEL,
  fallback RPA_GROUNDING_MODEL puis qwen2.5vl:7b-rpa) -> desambiguise le
  conflit D5-v3b, bbox_2d + num_ctx 4096 preserves
- safety_checks_provider: defaut -> get_vlm_model(), override
  RPA_SAFETY_CHECKS_LLM_MODEL preserve
- ui_detector: default_factory + resolution lazy (corrige aussi un gel a
  l'import), pas d'appel reseau a l'import
- field_extractor: property lazy via vlm_config

TDD strict (RED->GREEN), 305 tests verts, tests mockes HTTP (zero dependance
DGX reel), aucun alias Ollama.

Hors perimetre (arbitrage Dom): client Lea agent_v1/executor.py (gele),
chemin V4 observe_reason_act (RPA_REASONING_MODEL), core/config.py defaults.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:06:03 +02:00
Dom
5289f3de48 feat(p11): learn from offline cross-session matches 2026-06-02 17:46:15 +02:00
Dom
d38f0b0f2f feat(agent): add learn action flow and grounding guards 2026-06-02 16:24:10 +02:00
Dom
86b3c8f7e7 feat(p1): persist workflows and semantic learning artifacts 2026-06-02 16:20:38 +02:00
Dom
7a1a5cb6fd fix(p0): secure agent revocation and R6 worker queue 2026-06-02 15:52:35 +02:00
Dom
7ef98d8089 feat(lea): expose competence replay api 2026-05-29 13:40:15 +02:00
Dom
4ba426c205 fix(replay): guard single in-flight dispatch
Add a private in-flight helper for replay dispatch, block machine retargeting while an action is still pending on the previous session, and warn on duplicate in-flight entries for the same replay triplet.

Freeze the Notepad runtime dialog success path and add integration coverage for single in-flight dispatch, watchdog late-report documentation, and the known concurrent-poll race as an xfail.
2026-05-25 11:00:59 +02:00
Dom
10136f0ee0 feat(agent): add standalone anchor-relative resolver 2026-05-24 21:54:39 +02:00
Dom
345762330b fix(agent): respect server visual reject before text fallback 2026-05-24 21:10:42 +02:00