Before user text goes to a third-party model or into your logs, strip out personal data. Implement redact(text) returning (redacted_text, counts):
[CARD]: runs of 13–19 digits, optionally separated by single spaces or dashes, that pass the Luhn checksum. Digit runs that fail Luhn are left alone.[EMAIL]: something@domain.tld.[PHONE]: an optional leading +, then digits with optional spaces, dashes, dots or parentheses, containing 10 to 15 digits in total.Redact cards first, then emails, then phones. counts is a dict like {"CARD": 1, "EMAIL": 2, "PHONE": 0} and always has all three keys.
Luhn check: starting from the rightmost digit, double every second digit (subtracting 9 if the result exceeds 9), sum everything, and the total must be divisible by 10.