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>
74 lines
2.3 KiB
Python
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") == ""
|