PII Guards
Four guards from Provider.PII provide a complete two-layer PII protection pipeline: detect and block in Pre, redact and anonymize in Post. PiiNodeGuard wires both layers into a single integration point.
BizFirst.Ai.GuardRails.Provider.PII — Register with services.AddGuardRailsPiiGuards() or via the full-stack services.AddGuardRailsExecution().
PiiDetectionGuard (v1.0.0). Provider.PII contains the full implementation (v2.0.0) backed by RegexPiiDetector with 10 compiled patterns.
RegexPiiDetector
The detection engine used by all PII guards. Patterns are compiled at construction time with RegexOptions.Compiled | RegexOptions.IgnoreCase for maximum performance.
The 10 Detection Patterns
| PiiType | Example | Sensitivity | Notes |
|---|---|---|---|
SSN | 123-45-6789 | low | Hyphenated format |
SSN_NoHyphen | 123456789 | medium | 9-digit number — context-dependent |
CreditCard | 4111-1111-1111-1111 | low | Groups with optional spaces/hyphens |
Email | user@domain.com | high | Standard RFC email pattern |
Phone | +1-555-123-4567 | high | US phone number with various separators |
Passport | AB1234567 | medium | 1-2 letters + 6-9 digits |
DriverLicense | A12345678 | medium | 1-2 letters + 5-8 digits |
IPAddress | 192.168.1.1 | high | Standard IPv4 pattern |
CVV | 123 | low | 3-4 digit number — context-dependent |
BankAccount | 12345678901 | medium | 8-17 digit number |
Two detection methods
public interface IPiiDetector
{
IReadOnlyList<PatternDefinition> DetectionRules { get; }
// Returns {piiType → count} — fast check for Pre-phase blocking
Dictionary<string, int> DetectPii(string text);
// Returns full match details — used by Post-phase redaction
List<PiiMatch> DetectPiiDetailed(string text);
}
public class PiiMatch
{
public string PiiType { get; set; } // e.g. "SSN", "Email"
public string MatchedText { get; set; } // the actual matched string
public int StartPosition { get; set; }
public int EndPosition { get; set; }
public string Pattern { get; set; } // the regex pattern that matched
public double ConfidenceLevel { get; set; } // always 0.95
}
PiiDetectionGuard v2
| Property | Value |
|---|---|
| Name | "PiiDetectionGuard" |
| Version | 2.0.0 Production |
| Supported Phases | Pre |
| IsSecurityCritical | true → fail-secure |
How it works
Converts context.Input to string via .ToString(), calls IPiiDetector.DetectPii(inputStr). If any PII is found, returns Blocked with detected types and counts in metadata.
Configuration
{
"name": "PiiDetectionGuard",
"enabled": true,
"config": {
"sensitivityLevel": "medium", // required; "low" | "medium" | "high"
"detection_rules": [] // optional; custom rules (currently all 10 patterns always run)
}
}
Block result
{
"IsAllowed": false,
"ErrorMessage": "PII detected in input: SSN, Email",
"Metadata": {
"detected_pii_types": ["SSN", "Email"],
"pii_counts": { "SSN": 1, "Email": 2 },
"sensitivity_level": "medium"
}
}
PiiRedactionGuard
| Property | Value |
|---|---|
| Name | "PiiRedactionGuard" |
| Version | 1.0.0 |
| Supported Phases | Post |
| IsSecurityCritical | true → fail-secure |
How it works
Converts context.Output to string, calls IPiiDetector.DetectPiiDetailed() to get exact positions of all PII matches. Applies redaction in reverse positional order (to preserve string offsets). Directly sets context.Output to the redacted string and returns Success(outputModified: true).
Three redaction methods
| Method | How | Example input → output |
|---|---|---|
"mask" | Replace all characters with * (same length) | john@example.com → **************** |
"hash" | SHA256 → hex → first 16 characters (irreversible, consistent) | john@example.com → a3f9b2c1d4e5f678 |
"partial" | Keep first + last character, mask middle | john@example.com → j**************m |
Configuration
{
"name": "PiiRedactionGuard",
"enabled": true,
"config": {
"redaction_method": "mask", // required; "mask" | "hash" | "partial"
"fields": [] // optional; target specific field names (empty = all output)
}
}
Success result
{
"IsAllowed": true,
"OutputModified": true,
"Metadata": {
"redacted_pii_count": 3,
"redaction_method": "mask"
}
}
PiiAnonymizationGuard
| Property | Value |
|---|---|
| Name | "PiiAnonymizationGuard" |
| Version | 1.0.0 |
| Supported Phases | Post |
| IsSecurityCritical | true |
Less destructive than redaction — preserves structure but replaces PII values with anonymized equivalents. Use when downstream systems need data in a recognizable format but without real personal data.
Configuration
{
"name": "PiiAnonymizationGuard",
"enabled": true,
"config": {
"anonymization_method": "pseudonymize", // required
"preserve_format": true // optional; keep same data type/format
}
}
PiiNodeGuard (Composite)
A composite INodeGuardExecutor that wires PiiDetectionGuard (Pre) and PiiRedactionGuard (Post) into a single integration point. Use this when you want full two-layer PII protection without configuring each guard separately.
// PiiNodeGuard implements INodeGuardExecutor
ExecutePreAsync() → runs PiiDetectionGuard (blocks if PII found)
ExecutePostAsync() → runs PiiRedactionGuard (redacts PII from output)
ExecuteOnErrorAsync() → no-op (returns Success)
Registering PiiNodeGuard
// In DI setup, for nodes that need full PII protection:
services.AddSingleton<INodeGuardExecutor, PiiNodeGuard>();
// Or use the standard full-stack registration which includes PiiNodeGuard:
services.AddGuardRailsExecution();
Full PII Workflow
Pre — PiiDetectionGuard
Scans context.Input for all 10 PII patterns. If any found: returns Blocked. Node never runs. Email never sent. API never called.
Node executes
Input was clean. Node performs its operation (e.g., calls AI model, queries database, sends email).
Post — PiiRedactionGuard
Scans context.Output (the node's result). Redacts any PII found. Sets OutputModified=true. Caller receives clean, redacted output.