Skip to course content
Free generative AI app course

Generative AI Application Development with Python

Unit 12.01: Redaction on the way in

Redact on the way in. A log that captures raw content and promises to clean it later is personal data with a plan attached.

Structured identifiers, caught by pattern

Account numbers, emails and card numbers replaced before writing.

The code redacts a realistic string.

import re

PATTERNS = [
    (re.compile(r"\bACC-\d+\b"), "[ACCOUNT]"),
    (re.compile(r"[\w.+-]+@[\w-]+\.[\w.]+"), "[EMAIL]"),
    (re.compile(r"\b\d{4}[ -]?\d{4}[ -]?\d{4}[ -]?\d{4}\b"), "[CARD]"),
]


def redact(text):
    for pattern, replacement in PATTERNS:
        text = pattern.sub(replacement, text)
    return text


RAW = "[email protected] on ACC-1187, card 4111 1111 1111 1111"
print("raw     :", RAW)
print("redacted:", redact(RAW))

print("""
Redact on the way in, not on the way out. A log that captures raw content and
promises to clean it later is personal data with a plan attached.

What this catches is structured identifiers. A customer writing their own name
and address in free text matches no pattern, which is why retention and access
control do the rest.
""")

All three structured identifiers are caught. What is not caught is a customer writing their own name and address in free text, which matches no pattern and is just as much personal data.

So redaction reduces exposure and does not remove it - which is why the next unit's retention limits are not optional.

The mistake this prevents

The mistake is treating redaction as sufficient and skipping retention. A log store with good redaction and no limit accumulates years of partially-redacted personal data in a system reviewed less carefully than the primary one.

Takeaway

Redact structured identifiers before writing, and treat it as reduction rather than removal. Free-text personal data matches no pattern.