RedactionOperator
Masks text matching a word or regex pattern with a configurable character. Short name: redaction · Category: Quality
Overview
The RedactionOperator scans each document's content column for text matching a given regular expression and replaces every matched character with a masking character. Use it to redact PII, sensitive keywords, or any structured pattern (emails, phone numbers, SSNs) before storing or embedding documents. Chain multiple instances for different patterns.
Key Features
- Regex and literal-word matching
- Configurable masking character (
*,#,X, etc.) - Tracks the number of redactions per document in an output column
- Chain multiple redaction operators for different PII types
- Works on any text content column
Operator Configuration
{
"name": "redact_emails",
"type": "redaction",
"depends_on": ["extract"],
"config": {
"redaction_regex": "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}",
"redaction_masking_character": "*" // optional, default "*"
}
}
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
redaction_regex |
string |
Yes | — | Regex pattern or literal word to match for redaction. Double-escape backslashes in JSON (e.g. \\d). |
redaction_masking_character |
string |
No | "*" |
Single character used to replace each matched character. |
Output Columns
| Column | Type | Description |
|---|---|---|
redaction_stats |
int |
Count of matches found and redacted in the document. Column name is the value of stats_column parameter (default: redaction_stats). |
The operator also modifies the content column in-place, replacing matched text with the masking character.
Examples
Example 1: Redact email addresses
{
"name": "redact_emails",
"type": "redaction",
"depends_on": ["extract"],
"config": {
"redaction_regex": "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}",
"redaction_masking_character": "*"
}
}
Example 2: Chain two redaction operators for email and phone
{
"flow": [
{
"name": "redact_emails",
"type": "redaction",
"depends_on": ["extract"],
"config": {
"redaction_regex": "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}",
"redaction_masking_character": "*"
}
},
{
"name": "redact_phones",
"type": "redaction",
"depends_on": ["redact_emails"],
"config": {
"redaction_regex": "\\b\\d{3}-\\d{3}-\\d{4}\\b",
"redaction_masking_character": "#"
}
}
]
}
Common patterns
| Target | Pattern |
|---|---|
| Email address | [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,} |
| US phone (dashes) | \\b\\d{3}-\\d{3}-\\d{4}\\b |
| SSN | \\b\\d{3}-\\d{2}-\\d{4}\\b |
| 16-digit credit card | \\b\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}\\b |
| IPv4 address | \\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b |
| Keyword (case-insensitive) | (?i)\\b(confidential\|secret\|private)\\b |
DocLang XML Considerations & Limitations
When doc_format == "doclang", RedactionOperator performs DOM-aware redaction:
- Text content is parsed into an XML element tree, and redaction is applied individually to element.text and element.tail nodes.
- XML tags, attributes, and element hierarchies are preserved intact.
Known limitation (Cross-node PII):
Redaction is scoped to individual DOM text nodes. Target patterns or words split across separate XML tags (for example, <text>John </text><bold>Doe</bold>) cannot be matched across the tag boundary.
Troubleshooting
Pattern matches nothing — verify the regex in a tool like regex101.com with a sample document. Remember to double-escape backslashes in JSON (\\d not \d).
Too many false positives — use word boundary anchors (\\b) to avoid partial matches.
redaction_masking_character longer than one character — only single characters are accepted. Using a multi-character string will raise a validation error.
Sample Flow
See sample_flows/operators/pii_hap_detection.json for a complete example using PII detection with redaction.