fix: labels DPI masqués (Date, Note, Type, Heure) + whitelist désactivée
- Whitelist post-masquage désactivée : injectait des phrases au mauvais endroit dans le texte anonymisé (bug critique) - Labels DPI "Date", "Note", "Heure", "Type", "Saint", "Page" ajoutés à _NEVER_MASK_AS_NAME et _DPI_LABELS_BLACKLIST pour empêcher leur propagation globale comme noms de personnes - Corrige "Date d'admission → [NOM] d'admission", "Note d'évolution → [NOM] d'évolution", etc. Score évaluation : 99.3/100 (fuites pré-existantes Sie/GRAND inchangées) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2381,7 +2381,16 @@ def _apply_extracted_names(text: str, names: set, audit: List[PiiHit], force_nam
|
|||||||
"""Remplace globalement chaque nom extrait dans le texte."""
|
"""Remplace globalement chaque nom extrait dans le texte."""
|
||||||
placeholder = PLACEHOLDERS["NOM"]
|
placeholder = PLACEHOLDERS["NOM"]
|
||||||
_force = force_names or set()
|
_force = force_names or set()
|
||||||
safe_names = {n for n in names if len(n) >= 4 and (n in _force or n.lower() not in _MEDICAL_STOP_WORDS_SET)}
|
# Labels DPI structurels à ne jamais masquer comme noms
|
||||||
|
_NEVER_MASK_AS_NAME = {
|
||||||
|
"Date", "DATE", "Note", "NOTE", "Heure", "HEURE", "Type", "TYPE",
|
||||||
|
"Soin", "SOIN", "Soins", "SOINS", "Surv", "SURV",
|
||||||
|
"Saint", "SAINT", "Sainte", "SAINTE",
|
||||||
|
"Page", "PAGE", "Presc", "PRESC",
|
||||||
|
}
|
||||||
|
safe_names = {n for n in names if len(n) >= 4
|
||||||
|
and n not in _NEVER_MASK_AS_NAME
|
||||||
|
and (n in _force or n.lower() not in _MEDICAL_STOP_WORDS_SET)}
|
||||||
# Ajouter un hit global (page=-1) par nom pour la redaction PDF raster
|
# Ajouter un hit global (page=-1) par nom pour la redaction PDF raster
|
||||||
# (un seul hit suffit — redact_pdf_raster cherche le token sur chaque page)
|
# (un seul hit suffit — redact_pdf_raster cherche le token sur chaque page)
|
||||||
# Les noms forcés (contexte Dr/Mme) utilisent NOM_FORCE pour bypasser
|
# Les noms forcés (contexte Dr/Mme) utilisent NOM_FORCE pour bypasser
|
||||||
@@ -4225,6 +4234,13 @@ def process_pdf(
|
|||||||
|
|
||||||
# 4a) Noms : extraire les tokens individuels
|
# 4a) Noms : extraire les tokens individuels
|
||||||
_nom_kinds = {"NOM", "NOM_EXTRACTED", "NER_PER", "EDS_NOM"}
|
_nom_kinds = {"NOM", "NOM_EXTRACTED", "NER_PER", "EDS_NOM"}
|
||||||
|
# Labels DPI / mots structurels à ne JAMAIS propager comme noms
|
||||||
|
_DPI_LABELS_BLACKLIST = {
|
||||||
|
"Date", "DATE", "Note", "NOTE", "Heure", "HEURE", "Type", "TYPE",
|
||||||
|
"Soin", "SOIN", "Soins", "SOINS", "Surv", "SURV",
|
||||||
|
"Saint", "SAINT", "Sainte", "SAINTE",
|
||||||
|
"Page", "PAGE", "Presc", "PRESC",
|
||||||
|
}
|
||||||
_global_name_tokens: set = set()
|
_global_name_tokens: set = set()
|
||||||
for h in anon.audit:
|
for h in anon.audit:
|
||||||
if h.kind not in _nom_kinds:
|
if h.kind not in _nom_kinds:
|
||||||
@@ -4235,6 +4251,8 @@ def process_pdf(
|
|||||||
continue
|
continue
|
||||||
if word.lower() in _MEDICAL_STOP_WORDS_SET:
|
if word.lower() in _MEDICAL_STOP_WORDS_SET:
|
||||||
continue
|
continue
|
||||||
|
if word in _DPI_LABELS_BLACKLIST:
|
||||||
|
continue
|
||||||
if not word[0].isupper():
|
if not word[0].isupper():
|
||||||
continue
|
continue
|
||||||
_global_name_tokens.add(word)
|
_global_name_tokens.add(word)
|
||||||
@@ -4483,10 +4501,9 @@ def process_pdf(
|
|||||||
)
|
)
|
||||||
final_text = _RE_BRACKET_CLEAN.sub(r"\1", final_text)
|
final_text = _RE_BRACKET_CLEAN.sub(r"\1", final_text)
|
||||||
|
|
||||||
# 6) Whitelist : restaurer les phrases qui ne doivent jamais être anonymisées
|
# 6) Whitelist : DÉSACTIVÉ — l'approche post-masquage est défectueuse
|
||||||
whitelist_phrases = cfg.get("whitelist_phrases", [])
|
# (injecte des phrases whitelist au mauvais endroit quand [NOM] masque un vrai nom)
|
||||||
if whitelist_phrases:
|
# TODO: implémenter en pré-masquage (protéger les spans avant anonymisation)
|
||||||
final_text = _apply_whitelist(final_text, whitelist_phrases, anon.audit)
|
|
||||||
|
|
||||||
# Sauvegardes
|
# Sauvegardes
|
||||||
base = pdf_path.stem
|
base = pdf_path.stem
|
||||||
|
|||||||
Reference in New Issue
Block a user