Portal Community
Project: BizFirst.Ai.GuardRails.Provider.PII — Register with services.AddGuardRailsPiiGuards() or via the full-stack services.AddGuardRailsExecution().
Use Provider.PII, not Provider.Core, for PII detection in production. Provider.Core contains a placeholder 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

PiiTypeExampleSensitivityNotes
SSN123-45-6789lowHyphenated format
SSN_NoHyphen123456789medium9-digit number — context-dependent
CreditCard4111-1111-1111-1111lowGroups with optional spaces/hyphens
Emailuser@domain.comhighStandard RFC email pattern
Phone+1-555-123-4567highUS phone number with various separators
PassportAB1234567medium1-2 letters + 6-9 digits
DriverLicenseA12345678medium1-2 letters + 5-8 digits
IPAddress192.168.1.1highStandard IPv4 pattern
CVV123low3-4 digit number — context-dependent
BankAccount12345678901medium8-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

PropertyValue
Name"PiiDetectionGuard"
Version2.0.0 Production
Supported PhasesPre
IsSecurityCriticaltrue → 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

PropertyValue
Name"PiiRedactionGuard"
Version1.0.0
Supported PhasesPost
IsSecurityCriticaltrue → 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

MethodHowExample input → output
"mask"Replace all characters with * (same length)john@example.com****************
"hash"SHA256 → hex → first 16 characters (irreversible, consistent)john@example.coma3f9b2c1d4e5f678
"partial"Keep first + last character, mask middlejohn@example.comj**************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

PropertyValue
Name"PiiAnonymizationGuard"
Version1.0.0
Supported PhasesPost
IsSecurityCriticaltrue

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

1

Pre — PiiDetectionGuard

Scans context.Input for all 10 PII patterns. If any found: returns Blocked. Node never runs. Email never sent. API never called.

N

Node executes

Input was clean. Node performs its operation (e.g., calls AI model, queries database, sends email).

2

Post — PiiRedactionGuard

Scans context.Output (the node's result). Redacts any PII found. Sets OutputModified=true. Caller receives clean, redacted output.