import re from typing import Dict, Any, Tuple, List # PII / PHI Redaction Patterns for HIPAA, ABDM, GDPR Compliance PII_PATTERNS = [ # 1. India Aadhaar 12-Digit Number (r"\b[2-9]\d{3}[-\s]?\d{4}[-\s]?\d{4}\b", "[REDACTED_AADHAAR]"), # 2. India ABHA Health ID 14-Digit Number (r"\b\d{2}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b", "[REDACTED_ABHA_ID]"), # 3. Phone Numbers (Indian +91, 10-digit, US/Intl) (r"\b(?:\+?91[-\s]?)?[6-9]\d{9}\b", "[REDACTED_PHONE]"), (r"\b(?:\+?1[-\s]?)?\(?\d{3}\)?[-\s]?\d{3}[-\s]?\d{4}\b", "[REDACTED_PHONE]"), # 4. Email Addresses (r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b", "[REDACTED_EMAIL]"), # 5. Social Security Number (US SSN) (r"\b\d{3}[-\s]?\d{2}[-\s]?\d{4}\b", "[REDACTED_SSN]"), # 6. Credit Card / Debit Card Numbers (16 digits) (r"\b(?:\d{4}[-\s]?){3}\d{4}\b", "[REDACTED_PAYMENT]") ] def anonymize_phi_text(text: str) -> Tuple[str, List[str]]: """ Scrubs sensitive PII/PHI identifiers from text before cloud storage or public broadcast. Returns (anonymized_text, list_of_redacted_types). """ if not text or not text.strip(): return text, [] scrubbed_text = text redacted_categories: List[str] = [] for pattern, replacement in PII_PATTERNS: matches = re.findall(pattern, scrubbed_text, re.IGNORECASE) if matches: category_name = replacement.replace("[", "").replace("]", "").replace("REDACTED_", "") if category_name not in redacted_categories: redacted_categories.append(category_name) scrubbed_text = re.sub(pattern, replacement, scrubbed_text, flags=re.IGNORECASE) return scrubbed_text, redacted_categories