Skip to content
Docs for briefcase-ai v3.3.0see what’s new.

PII Sanitization

PII sanitization is data minimization for your records: detect sensitive data and redact it before a decision is recorded or stored.

sanitize For: governance & audit

The principle is minimize before you store: a record you never wrote sensitive data into is one you never have to scrub later.

Install

Terminal window
pip install briefcase-ai[sanitize]

Sanitize before capture

  1. Detect — scan the incoming ticket text for known patterns (email, phone, and any custom patterns you register).

  2. Redact — replace matches with a [REDACTED_<TYPE>] marker so the meaning survives but the sensitive value doesn’t.

  3. Capture — record the decision on the sanitized text, so the stored record never held raw PII.

from briefcase.sanitize import Sanitizer
sanitizer = Sanitizer()
result = sanitizer.sanitize("Email me at jane.doe@example.com please")
print(result.sanitized) # Email me at [REDACTED_EMAIL] please
print(result.redaction_count) # 1
print(result.has_redactions) # True
# feed result.sanitized into classify_ticket() so the captured record is clean

sanitize() returns a SanitizationResult with .sanitized, .redactions, .redaction_count, and .has_redactions.

Redaction markers

Each match is replaced with a [REDACTED_<TYPE>] marker. The built-in PII types and their markers:

PII typeMarker
email[REDACTED_EMAIL]
phone[REDACTED_PHONE]
credit_card[REDACTED_CREDIT_CARD]
ssn[REDACTED_SSN]
ip_address[REDACTED_IP]
api_key[REDACTED_API_KEY]

Inspect redactions

Each entry in result.redactions is a Redaction with .pii_type, .start_position, .end_position, and .original_length (positions index into the original text).

from briefcase.sanitize import Sanitizer
sanitizer = Sanitizer()
result = sanitizer.sanitize("Call 555-123-4567 or email jane.doe@example.com")
for redaction in result.redactions:
print(redaction.pii_type, redaction.start_position, redaction.end_position)
# phone 5 21
# email 27 43

Sanitize JSON

sanitize_json() walks a dict and redacts string values, returning a SanitizationJsonResult with .sanitized and .redaction_count. Useful for sanitizing a structured ticket payload before you record it.

from briefcase.sanitize import Sanitizer
sanitizer = Sanitizer()
record = {
"ticket_id": "TKT-4821",
"contact_email": "jane.doe@example.com",
"priority": 2,
}
result = sanitizer.sanitize_json(record)
print(result.sanitized)
# {'contact_email': '[REDACTED_EMAIL]', 'priority': 2, 'ticket_id': 'TKT-4821'}
print(result.redaction_count) # 1

Reject sensitive data in a guardrail

Sometimes you don’t want to redact and continue — you want to stop. Use contains_pii (a fast boolean) or analyze_pii (a summary that doesn’t modify the text) to refuse a payload before it’s ever recorded.

from briefcase.sanitize import Sanitizer
sanitizer = Sanitizer()
def guard(text: str) -> None:
if sanitizer.contains_pii(text):
report = sanitizer.analyze_pii(text) # summary for logging the reason
raise ValueError(f"refusing to store record: PII detected ({report})")
guard("Email jane.doe@example.com") # raises before classify_ticket is recorded
report = sanitizer.analyze_pii("Email jane.doe@example.com and call 555-123-4567")
print(report)
# {'has_pii': True, 'total_matches': 2, 'unique_types': 2,
# 'detected_types': ['phone', 'email']}
MethodReturnsUse it to…
sanitize(text)SanitizationResultStrip PII and keep going
sanitize_json(data)SanitizationJsonResultStrip PII from a structured payload
contains_pii(text)boolCheaply gate a guardrail — proceed or reject
analyze_pii(text)summary dictGet the details (types, counts) for logging or decisions

This pairs naturally with Guardrails, where you can run this check inside an evaluate() and return DENY when PII is still present.

Custom patterns

Register your own patterns for identifiers specific to your domain — a ticket number scheme, an internal account ID format — with add_pattern(name, regex). The marker uppercases the name, so ticket_id redacts to [REDACTED_TICKET_ID]. Registered patterns are picked up by sanitize, contains_pii, and analyze_pii.

from briefcase.sanitize import Sanitizer
sanitizer = Sanitizer()
sanitizer.add_pattern("ticket_id", r"\bTKT-\d{4}\b")
result = sanitizer.sanitize("Ticket TKT-4821 was escalated")
print(result.sanitized) # Ticket [REDACTED_TICKET_ID] was escalated
ArgumentTypeDescription
namestrA label for the pattern; uppercased into the [REDACTED_<NAME>] marker and reported by analyze_pii
patternstrThe regex to match and redact

remove_pattern(pattern_name) removes a registered pattern again.

Key classes

  • Sanitizer — detects and redacts PII; sanitize, sanitize_json, add_pattern, remove_pattern, contains_pii, analyze_pii.
  • SanitizationResult.sanitized, .redactions, .redaction_count, .has_redactions.
  • Redaction.pii_type, .start_position, .end_position, .original_length.
  • SanitizationJsonResult.sanitized, .redaction_count.

Where this fits