Files
rpa_vision_v3/tests/unit/test_log_safe.py
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

74 lines
2.3 KiB
Python

"""Tests unitaires des helpers de logging PII-safe du client Léa (agent_v1).
Assainissement des logs à la source : on ne logge jamais le contenu brut
(titres de fenêtre, noms de workflow, chemins, métadonnées sensibles). On le
remplace par un hash court stable, une longueur, ou un dict filtré.
Branche feat/push-log-dgx — DETTE-020 (assainissement PII des logs, brique 4).
"""
from __future__ import annotations
import re
import sys
from pathlib import Path
_ROOT = str(Path(__file__).resolve().parents[2])
if _ROOT not in sys.path:
sys.path.insert(0, _ROOT)
_HEX8 = re.compile(r"^[0-9a-f]{8}$")
def test_title_hash_is_short_stable_hex():
from agent_v0.agent_v1.core.log_safe import _title_hash
h = _title_hash("Dossier MOREL Catherine")
assert _HEX8.match(h), f"attendu 8 hex, obtenu {h!r}"
assert h == _title_hash("Dossier MOREL Catherine") # déterministe
def test_title_hash_never_reveals_raw_title():
"""Propriété PII centrale : le hash ne contient jamais le contenu brut."""
from agent_v0.agent_v1.core.log_safe import _title_hash
title = "Dossier MOREL Catherine"
h = _title_hash(title)
assert title not in h
assert "MOREL" not in h
def test_title_hash_distinguishes_different_titles():
from agent_v0.agent_v1.core.log_safe import _title_hash
assert _title_hash("popup A") != _title_hash("popup B")
def test_title_hash_handles_empty_and_non_ascii():
from agent_v0.agent_v1.core.log_safe import _title_hash
assert _HEX8.match(_title_hash(""))
assert _HEX8.match(_title_hash("Éléonore — café ☕"))
def test_sanitize_metadata_drops_pii_keys_keeps_technical():
from agent_v0.agent_v1.core.log_safe import _sanitize_metadata
meta = {
"resolution": "1920x1080", "dpi": 96, "theme": "dark",
"title": "Dossier Dupont", "active_window": "Medicare", "window_title": "x",
}
safe = _sanitize_metadata(meta)
assert safe == {"resolution": "1920x1080", "dpi": 96, "theme": "dark"}
assert meta.get("title") == "Dossier Dupont" # original non muté
def test_path_ext_returns_extension_only():
from agent_v0.agent_v1.core.log_safe import _path_ext
assert _path_ext("/home/tim/Dossier Dupont 1980.png") == ".png"
assert "Dupont" not in _path_ext("/x/Dupont.png")
assert _path_ext("") == ""
assert _path_ext("/no/ext/here") == ""