Caveman.PrivacyGuard 1.4.0

dotnet add package Caveman.PrivacyGuard --version 1.4.0
                    
NuGet\Install-Package Caveman.PrivacyGuard -Version 1.4.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Caveman.PrivacyGuard" Version="1.4.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Caveman.PrivacyGuard" Version="1.4.0" />
                    
Directory.Packages.props
<PackageReference Include="Caveman.PrivacyGuard" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Caveman.PrivacyGuard --version 1.4.0
                    
#r "nuget: Caveman.PrivacyGuard, 1.4.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Caveman.PrivacyGuard@1.4.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Caveman.PrivacyGuard&version=1.4.0
                    
Install as a Cake Addin
#tool nuget:?package=Caveman.PrivacyGuard&version=1.4.0
                    
Install as a Cake Tool

Caveman.PrivacyGuard ๐Ÿ›ก๏ธ๐Ÿ‡ช๐Ÿ‡บ

<img width="638" height="408" alt="Gemini_Generated_Image_tnxoi9tnxoi9tnxo" src="https://github.com/user-attachments/assets/5a8e3193-b7d3-4a41-90e6-e672467ce6cb" />

NuGet Downloads License .NET 8 .NET Standard 2.0 GDPR Ready

Enterprise-grade PII & Privacy Analyzer for AI/LLM workflows Detects, scores, and automatically masks sensitive data across 32 countries (27 EU + UK, Switzerland, China, Russia, Ukraine), with risk scoring, GDPR/AI Act/NIS2/PCI-DSS/NIST compliance mapping, and seamless integration with any AI pipeline โ€” including multi-session scenarios (multiple chatbots/conversations running in parallel).


โœจ Features

Feature Description
๐ŸŒ 32 Countries Native patterns for all 27 EU countries (IT, DE, FR, ES, PL, NL, SE, FI, DK, AT, BE, PT, IE, GR, CZ, RO, HU, BG, HR, SK, SI, LT, LV, EE, CY, MT, LU) + generic EU rules, plus UK, Switzerland, China, Russia, Ukraine
๐Ÿ” Heuristic Detection Precompiled regex + algorithmic validators (Luhn, IBAN MOD97, national checksums) + Shannon entropy analysis
๐Ÿ“Š Privacy Score 0-100 score with levels: Safe โ†’ Low โ†’ Medium โ†’ High โ†’ Critical
๐ŸŽญ Auto-Masking Dynamic replacement with contextual placeholders ([EMAIL], [IBAN], [CF_IT], etc.)
โš™๏ธ YAML-Driven Configurable rules in an embedded rules.yaml, extensible at runtime
๐Ÿ” Compliance Flags Automatic mapping to GDPR, EU AI Act, NIS2, PCI-DSS, NIST 800-53, national authorities (CNIL, BfDI, AEPD, etc.)
๐Ÿงต Thread-Safe Ready for high-throughput microservices with ReaderWriterLockSlim and a regex cache
๐Ÿ”„ Session Restore Unique [PG_N] placeholders per occurrence, client-side restoration of original data in AI responses, zero sensitive data sent to the LLM
โœ‚๏ธ Dynamic Rules Load/unload/inspect rules at runtime: LoadCustomYaml, RemoveRule(), GetRule(), GetLoadedCategories()
๐Ÿงน Whitelist Lifecycle AddToWhitelist, RemoveFromWhitelist, ClearWhitelist, GetWhitelist, IsWhitelisted
๐Ÿ”Œ Extensible Validators Register, remove, or reset custom validators via ValidatorRegistry.Register / Unregister / Reset
โšก Async API AnalyzeAsync with 4 overloads + CancellationToken for UI/web
๐Ÿ”Œ JSON Config LoadCustomJson / LoadCustomJsonFromString with hot-reload (WatchConfig / ConfigReloaded)
๐Ÿ’พ Session Export ToJson / FromJson / ImportFromJson for placeholder persistence
๐Ÿ” IReadOnlySession Read-only interface for public APIs that must not mutate the session
โœ… ValidateRules Public method to validate all loaded rules
๐Ÿ›ก๏ธ Safe Dispose ThrowIfDisposed() on all public methods, graceful catch(SynchronizationLockException)
๐Ÿชต ILogger Integration with Microsoft.Extensions.Logging.Abstractions for diagnostics
๐Ÿ“‹ CHANGELOG Version history shipped inside the NuGet package
๐ŸŒ .NET Standard 2.0 Compatible with legacy .NET frameworks
๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘ Multi-Session PrivacySessionManager isolates sessions per conversation/user/tenant โ€” built for backends running multiple chatbots or an AI provider handling many concurrent conversations
๐Ÿ’ฌ AI Transparency Notice AiTransparencyNotice โ€” a configurable, localized (EN/IT/DE/FR/ES) message informing users they're talking to an AI system and that sensitive data is masked
๐Ÿงญ Chat Intent Router ChatIntentRouter โ€” routes bot commands (e.g. /reset, /help) before the text reaches the analyzer
๐Ÿš€ Performance RegexOptions.NonBacktracking (.NET 8), precompilation, O(1) cache, zero redundant allocations, 3s anti-ReDoS timeout

๐Ÿ“ฆ Installation

dotnet add package Caveman.PrivacyGuard

๐Ÿš€ Quick Start

Warning Mode (Default)

var analyzer = new PrivacyAnalyzer { EnableAutoMasking = true };

// ๐Ÿ”น Default: English
var resEn = analyzer.Analyze("CF: RSSMRA80A01H501U, email: test@x.com");
Console.WriteLine($"[EN] Risk: {resEn.RiskLevel}\n{resEn.WarningMessage}");

// ๐Ÿ”น Overload: Italian
var resIt = analyzer.Analyze("CF: RSSMRA80A01H501U, email: test@x.com", "it");
Console.WriteLine($"[IT] Risk: {resIt.RiskLevel}\n{resIt.WarningMessage}");

// ๐Ÿ”น Overload: German
var resDe = analyzer.Analyze("Steuer-ID: 12345678901, IBAN: DE89370400440532013000", "de");
Console.WriteLine($"[DE] Risk: {resDe.RiskLevel}\n{resDe.WarningMessage}");

Output:

๐Ÿ”’ Score: 26/100
โš ๏ธ  Warning: โ›” Data detected: Italian Tax Code (CF), Email. Pseudonymization mandatory.
โœ… Safe for AI: False
var analyzer = new PrivacyAnalyzer { EnableAutoMasking = true };

var text = "Customer: Mario Rossi, email mario@company.it, IBAN: IT60X0542811101000000123456";
var result = analyzer.Analyze(text);

Console.WriteLine($"๐Ÿ›ก๏ธ  Text safe for LLM:\n{result.MaskedText}");

Output:

๐Ÿ›ก๏ธ  Text safe for LLM:
Customer: Mario Rossi, email [EMAIL], IBAN: [IBAN]

๐Ÿช„ Session Restore โ€” Zero Sensitive Data to the LLM

The core value proposition: sensitive data never leaves the client. The flow is:

  1. Mask โ€” PrivacyAnalyzer detects PII and replaces it with unique placeholders [PG_1], [PG_2], etc.
  2. Send โ€” The masked text (no real data) is sent to the LLM
  3. Restore โ€” The LLM's response is processed by PrivacySession.Restore(), which restores the original values client-side
var session = new PrivacySession();
var analyzer = new PrivacyAnalyzer { EnableAutoMasking = true };

// 1. Analyze and mask (the real data only lives in the session)
var result = analyzer.Analyze(
    "Mario Rossi, email mario@company.it, IBAN: IT60X0542811101000000123456",
    "en", session);

Console.WriteLine(result.MaskedText);
// Output: Mario Rossi, email [PG_1], IBAN: [PG_2]

// 2. Send result.MaskedText to the LLM...
var aiResponse = "Contact the customer via [PG_1] regarding the charge on [PG_2]";

// 3. Restore client-side (no sensitive data ever left the client)
var safeResponse = session.Restore(aiResponse);
Console.WriteLine(safeResponse);
// Output: Contact the customer via mario@company.it regarding the charge on IT60X0542811101000000123456

API Reference

// Create a new session
var session = new PrivacySession();

// Analyze with a session (unique [PG_N] placeholders)
var result = analyzer.Analyze(input, "en", session);

// Or via the CurrentSession property
analyzer.CurrentSession = new PrivacySession();
var result = analyzer.Analyze(input);

// Restore an AI response
string restored = session.Restore(aiResponseText);

// Inspect the generated placeholders
foreach (var entry in session.GetAll())
    Console.WriteLine($"{entry.Key} โ†’ {entry.Value.OriginalValue} ({entry.Value.Category})");

// Get a single mapping
var entry = session.GetEntry("[PG_1]");

// Manually add a placeholder (public)
session.AddOrGet("Email", "manual@test.com");

// Merge another session (skips duplicates by value)
session.MergeFrom(anotherSession);

// Reset the session
session.Clear();

// Static method on PrivacyAnalyzer
string restored = PrivacyAnalyzer.RestoreText(aiResponse, session);

// Instance method (uses CurrentSession)
analyzer.CurrentSession = session;
string restored2 = analyzer.RestoreText(aiResponse);

Note: Without a session (Analyze(input) or Analyze(input, lang)), masking uses the textual placeholders [EMAIL], [IBAN], etc. as before.

Countries Covered

Code Country Main Identifiers Reference Authority
๐Ÿ‡ฎ๐Ÿ‡น IT Italy Tax Code (CF), VAT Number Garante Privacy, Revenue Agency
๐Ÿ‡ฉ๐Ÿ‡ช DE Germany Tax ID, ID Card BfDI, GDPR
๐Ÿ‡ซ๐Ÿ‡ท FR France NIR/SSN, SIREN/SIRET CNIL, GDPR
๐Ÿ‡ช๐Ÿ‡ธ ES Spain NIF/NIE AEPD, GDPR
๐Ÿ‡ต๐Ÿ‡ฑ PL Poland PESEL, NIP UODO, GDPR
๐Ÿ‡ณ๐Ÿ‡ฑ NL Netherlands BSN AP, GDPR
๐Ÿ‡ธ๐Ÿ‡ช SE Sweden Personnummer IMY
๐Ÿ‡ซ๐Ÿ‡ฎ FI Finland Henkilรถtunnus (HETU) Data Protection Ombudsman
๐Ÿ‡ฉ๐Ÿ‡ฐ DK Denmark CPR Datatilsynet
๐Ÿ‡ฆ๐Ÿ‡น AT Austria Social Insurance No., VAT ID DSB
๐Ÿ‡ง๐Ÿ‡ช BE Belgium National Registry Number APD
๐Ÿ‡ต๐Ÿ‡น PT Portugal NIF CNPD
๐Ÿ‡ฎ๐Ÿ‡ช IE Ireland PPSN DPC
๐Ÿ‡ฌ๐Ÿ‡ท GR Greece AFM, AMKA HDPA
๐Ÿ‡จ๐Ÿ‡ฟ CZ Czechia Birth Number รšOOรš
๐Ÿ‡ท๐Ÿ‡ด RO Romania CNP ANSPDCP
๐Ÿ‡ญ๐Ÿ‡บ HU Hungary Tax ID NAIH
๐Ÿ‡ง๐Ÿ‡ฌ BG Bulgaria EGN CPDP
๐Ÿ‡ญ๐Ÿ‡ท HR Croatia OIB AZOP
๐Ÿ‡ธ๐Ÿ‡ฐ SK Slovakia Birth Number รšOOรš
๐Ÿ‡ธ๐Ÿ‡ฎ SI Slovenia EMล O IP
๐Ÿ‡ฑ๐Ÿ‡น LT Lithuania Personal Code VDAI
๐Ÿ‡ฑ๐Ÿ‡ป LV Latvia Personal Code DVI
๐Ÿ‡ช๐Ÿ‡ช EE Estonia Isikukood AKI
๐Ÿ‡จ๐Ÿ‡พ CY Cyprus ID Number CIPD
๐Ÿ‡ฒ๐Ÿ‡น MT Malta ID Number IDPC
๐Ÿ‡ฑ๐Ÿ‡บ LU Luxembourg National ID Number CNPD
๐Ÿ‡ฌ๐Ÿ‡ง GB United Kingdom National Insurance Number (NINO) ICO
๐Ÿ‡จ๐Ÿ‡ญ CH Switzerland AHV/AVS Number FDPIC
๐Ÿ‡จ๐Ÿ‡ณ CN China Resident ID Number CAC (PIPL)
๐Ÿ‡ท๐Ÿ‡บ RU Russia Taxpayer ID (INN) Roskomnadzor
๐Ÿ‡บ๐Ÿ‡ฆ UA Ukraine Taxpayer Number (RNOKPP) State Data Protection Service

๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘ Multi-Session: Multiple Chatbots / AI Providers

If your service juggles many concurrent conversations โ€” several chatbot instances, or an AI-provider-facing gateway serving many users โ€” PrivacySessionManager keeps each conversation's placeholder mapping isolated, so one conversation can never leak another's data.

var sessions = new PrivacySessionManager();
var analyzer = new PrivacyAnalyzer { EnableAutoMasking = true };

// Each conversation gets (and reuses) its own isolated session
var chat1 = sessions.GetOrCreate("conversation-123");
var chat2 = sessions.GetOrCreate("conversation-456");

var r1 = analyzer.Analyze("email alice@example.com", "en", chat1);
var r2 = analyzer.Analyze("email bob@example.com", "en", chat2);

// chat1 can only restore its own placeholders โ€” chat2's data never crosses over
var restored = chat1.Restore(r1.MaskedText);

// Periodically bound memory usage in long-running services:
int removed = sessions.PruneIdleSessions(TimeSpan.FromMinutes(30));

๐Ÿ’ฌ AI Transparency Notice & ๐Ÿงญ Chat Intent Router

For chatbot/assistant use cases, AiTransparencyNotice gives you a ready-to-display, configurable disclosure that the user is talking to an AI system and that their data is screened/masked โ€” a technical aid toward the transparency expectations of EU AI Act Art.50 for limited-risk AI systems (whether it fully satisfies your specific obligations depends on your use case and should be confirmed with legal counsel).

var notice = new AiTransparencyNotice { Language = "en" }; // or "it", "de", "fr", "es"
Console.WriteLine(notice.GetMessage());
// "You are interacting with an AI system. Your messages are screened locally and any
//  personal or sensitive data is masked before being sent to the AI model (EU AI Act
//  Art.50 transparency notice)."

// Disable it, or supply your own wording:
notice.Enabled = false;
notice.CustomMessage = "Custom disclosure text for your organization.";

ChatIntentRouter lets you register bot commands (e.g. /reset, /help) and route them before the text ever reaches the analyzer:

var router = new ChatIntentRouter();
router.RegisterCommand("/reset", _ => session.Clear());
router.RegisterCommand("/help", _ => ShowHelp());

var matchedIntent = router.TryRoute(userInput);
if (matchedIntent is null)
{
    // No command matched: treat userInput as regular content to analyze/mask.
    var result = analyzer.Analyze(userInput, "en", session);
}

Streaming & Document Masking (v1.3.0)

Boundary-Safe Stream Masking

PrivacyStreamMasker masks PII in incrementally-arriving text (a chunked file read, or a live LLM stream) without loading the whole input. It keeps a tail buffer of overlapChars (default 512) so a match that spans a chunk boundary is still analyzed whole.

var masker = new PrivacyStreamMasker(session: session, language: "en", overlapChars: 512);
foreach (var chunk in ReadInChunks(path))
    Console.Write(masker.Feed(chunk));   // masked-safe prefix as it becomes safe
Console.Write(masker.Flush());           // final remainder

// Or, for an in-memory iterable:
var masked = string.Concat(PrivacyStreamMasker.MaskStream(chunks, session));

Redacted Session Summary

PrivacySession.Summary() returns placeholder + category only โ€” never the original value โ€” so it is safe to log, display, or return from an API/CLI response. GetAll() / ToJson() carry the cleartext PII; keep them server-side only.

foreach (var item in session.Summary())   // SessionSummaryItem { Placeholder, Category }
    Console.WriteLine($"{item.Placeholder}: {item.Category}");

Document Masking (txt / Markdown / CSV)

DocumentMasker.MaskFile streams a file in chunks and writes a masked copy to name.masked.ext next to the source โ€” the original file is never overwritten. CSV rows are read with a minimal RFC-4180-aware reader so quoted multi-line cells survive.

var result = DocumentMasker.MaskFile("contacts.csv", session: session);
// result.OutputPath โ†’ "contacts.masked.csv", result.MaskedMatchCount โ†’ total PII matches

Fewer false positives, and an optional ML tier (v1.3.1 / v1.4.0)

A bare number in prose is not PII. Since 1.3.1 a match only counts when it is confirmed: a value that fails its checksum is never detected or masked, and a rule marked requires_context (every bare numeric format: phone, PESEL, BSN, OIB, CNP, ...) additionally needs one of its context_keywords within 25 characters - short keywords match as whole words, so tel is not confirmed by "hotel". A +-prefixed number is E.164 by definition and needs no keyword. Structurally anchored rules (e-mail, IBAN, codice fiscale, NINO, ...) are unaffected.

Optional learned confirmation (1.4.0). PrivacyAnalyzer.MlDetector accepts any IMlEntityDetector; the CavemanML package ships PrivacyGuardML, a small offline model that recognises PII by shape and context:

using var analyzer = new PrivacyAnalyzer { MlDetector = await PrivacyGuardMLDetector.LoadAsync() };
var r = analyzer.Analyze("ssn 123-45-6789 lo trovi nel file");   // r.MlAssistedCount == 1

The model is only a confirmation signal: it can recover a bare value the context gate rejected (when an overlapping span has the right label), it can never override a failed checksum, and without a detector nothing changes.

โš™๏ธ Advanced Configuration

Whitelist (Safe Exclusions)

analyzer.AddToWhitelist(
    "test@company.eu",      // Test email
    "127.0.0.1",             // Localhost IP
    "IT00000000000"         // Dummy VAT number
);

// Removal and reset
analyzer.RemoveFromWhitelist("test@company.eu");
analyzer.ClearWhitelist();  // removes all exclusions

// Inspection
var all = analyzer.GetWhitelist();     // IReadOnlySet<string>
if (analyzer.IsWhitelisted("127.0.0.1"))
    Console.WriteLine("IP is whitelisted");

Custom Validators

// Register a new validator for a custom national format
ValidatorRegistry.Register("MY_CUSTOM_ID", value =>
    value.Length == 10 && value.StartsWith("XYZ") && value.All(char.IsDigit));

// Remove an existing validator
ValidatorRegistry.Unregister("MY_CUSTOM_ID");

// Reset all validators to the built-in defaults (removes custom ones)
ValidatorRegistry.Reset();

Runtime Rule Inspection & Management

// List all currently loaded rule categories
var categories = analyzer.GetLoadedCategories();

// Inspect a specific rule (regex, weight, validator, etc.)
var emailRule = analyzer.GetRule("Email");
Console.WriteLine(emailRule.Pattern);   // compiled regex
Console.WriteLine(emailRule.BaseWeight); // weight

// Remove all rules for a category
analyzer.RemoveRule("Email");

// Clear ALL rules (embedded + custom)
analyzer.ClearRules();

Resource Disposal

PrivacyAnalyzer implements IDisposable to release its ReaderWriterLockSlim. All public methods throw ObjectDisposedException if called after disposal:

using var analyzer = new PrivacyAnalyzer { EnableAutoMasking = true };
var result = analyzer.Analyze("test@example.com");
// analyzer.Dispose() is called automatically on exiting the using block

Async Analysis

For UI or web applications, AnalyzeAsync runs the analysis on the thread pool and supports CancellationToken:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

try
{
    var result = await analyzer.AnalyzeAsync(
        "Email: test@example.com, IBAN: IT60X0542811101000000123456",
        cts.Token);

    Console.WriteLine($"Score: {result.Score}");
}
catch (OperationCanceledException)
{
    Console.WriteLine("Analysis cancelled due to timeout.");
}

Available overloads: AnalyzeAsync(input), AnalyzeAsync(input, session, ct), AnalyzeAsync(input, language, ct), AnalyzeAsync(input, language, session, ct).

External and Dynamic YAML

// Load rules from a file (added to the embedded ones)
analyzer.LoadCustomYaml("path/to/custom-rules.yaml");

// Load rules from a YAML string (useful for DB/remote config)
var yaml = @"
version: ""2.0""
countries:
  - code: ""XX""
    rules:
      - category: ""CustomPII""
        pattern: '\bSENSITIVE_\w+\b'
        base_weight: 20
        compliance_tags: [""GDPR Art.4(1)""]";
analyzer.LoadCustomYamlFromString(yaml);

Compliance Tags from YAML

Compliance flags (compliance_tags in the YAML) are automatically collected and merged with the hardcoded ones. You can add custom tags per rule:

- category: "MyCustomID"
  pattern: '\bMY_\d{6}\b'
  base_weight: 15
  compliance_tags: ["GDPR Art.4(1)", "Internal Policy #42"]

JSON Config and Hot-Reload

Besides YAML, JSON configuration with automatic hot-reload is also supported:

// Load rules from a JSON file
analyzer.LoadCustomJson("path/to/custom-rules.json");

// Load from a string
var json = @"{
  ""version"": ""2.0"",
  ""countries"": [
    { ""code"": ""XX"", ""rules"": [
      { ""category"": ""CustomPII"", ""pattern"": ""\\bSENSITIVE_\\w+\\b"", ""base_weight"": 20 }
    ]}
  ]
}";
analyzer.LoadCustomJsonFromString(json);

// Hot-reload: watch the file and reload automatically
analyzer.WatchConfig("path/to/custom-rules.json");

// Event fired after every reload
analyzer.ConfigReloaded += (s, e) => Console.WriteLine("โšก Config reloaded!");

// Stop the watcher
analyzer.StopWatching();

Rule Validation

Check that all loaded rules are valid (no exceptions during matching):

if (analyzer.ValidateRules())
    Console.WriteLine("โœ… All rules are valid");
else
    Console.WriteLine("โŒ Invalid rules found");

ILogger Integration

Attach a logger for diagnostics during analysis and configuration:

analyzer.Logger = myLogger;  // ILogger<PrivacyAnalyzer>
// Logged events: detected categories, high scores, configuration loads

Session Export and Persistence

Export and import sessions as JSON to save/restore state across requests:

var session = new PrivacySession();
session.AddEntry("Email", "test@example.com");

// Export
string json = session.ToJson();

// Reconstruct
var restored = PrivacySession.FromJson(json);

// Import into an existing session
existingSession.ImportFromJson(json);

IReadOnlySession

A safe read-only API for public exposure:

IReadOnlySession readOnly = session;
int count = readOnly.Count;
var entry = readOnly.GetEntry("[PG_1]");
string text = readOnly.Restore(aiResponse);

๐Ÿ” Compliance & GDPR

PrivacyAnalysisResult.ComplianceFlags automatically combines:

  • YAML โ€” compliance_tags defined for each rule in rules.yaml
  • Hardcoded โ€” automatic mapping for known categories (GDPR, EU AI Act, NIS2, PCI-DSS, NIST 800-53)
if (result.ComplianceFlags.Contains("GDPR Art.4(1)"))
{
    // Logic for legal basis, DPIA, minimization
}
if (result.ComplianceFlags.Contains("PCI-DSS"))
{
    // Encryption, network segmentation, audit
}

Score Components

Component Description Notes
BaseScore Sum of matched-rule weights ร— validation ร— confidence
CorrelationMultiplier 1.0 + (distinct categories ร— 0.12) capped at 2.2
ContextBoost +0.12 for each PII near a trigger word ("password:", "confidential", etc.)
DensityBonus Penalizes short texts containing many PII (data-leak risk)

Risk Thresholds:

Score Level Recommended Action
0-15 โœ… Safe (AI Ready) Direct submission to the LLM
16-35 โš ๏ธ Low Logging + monitoring
36-60 โ›” Medium Anonymization mandatory
61-85 ๐Ÿšจ High Isolated sandbox or synthetic data
86-100 ๐Ÿ›‘ Critical Absolute block, on-premise processing

๐Ÿงช Testing & Performance

// Quick benchmark
var analyzer = new PrivacyAnalyzer();
var sw = System.Diagnostics.Stopwatch.StartNew();

for (int i = 0; i < 10_000; i++)
{
    analyzer.Analyze("Text with email test@example.com and IBAN DE89370400440532013000");
}

sw.Stop();
Console.WriteLine($"โšก 10k analyses in {sw.ElapsedMilliseconds}ms ({10_000.0 / sw.ElapsedMilliseconds:F1} req/sec)");

๐Ÿค Contributing

Fork the repo Create a branch for your feature (git checkout -b feature/new-country) Add rules in rules.yaml + validators in ValidatorRegistry.cs Add tests in tests/ (xUnit) Submit a PR with a clear description and examples ๐ŸŒ To add a new country: follow the existing YAML schema, implement a validator (if needed), and add an entry to the README table.

๐Ÿ“„ License

Distributed under the MIT license. See LICENSE for details.

๐Ÿ†˜ Support & Roadmap

Version Feature Status
1.0 27 EU countries, masking, embedded YAML โœ… Released
1.1 Session Restore, unique placeholders, client-side restoration โœ… Released
1.2 JSON config, hot-reload, async API, batch analyze, session export, ILogger, netstandard2.0, whitelist lifecycle, dynamic validators, regex cache, ValidateRules, IReadOnlySession, CHANGELOG โœ… Released
1.2.2 5 new countries (UK, CH, CN, RU, UA), AI Act/NIS2 compliance flags, PrivacySessionManager, AiTransparencyNotice, ChatIntentRouter, Demo dashboard โœ… Released
1.3 Remote YAML configuration, session streaming ๐Ÿ”„ Planned

Technology Partnership

<img src="https://www.digitalsolutions.it/img/partners/novaroutelogo.png" alt="NovaRouteAI" height="180" style="max-width: 100%; height: auto; min-height: 180px; max-height: 190px;">

NovaRouteAI โ€” Build with Chinese AI models through one simple API.

NovaRouteAI helps developers and AI SaaS teams test, compare, and run models like DeepSeek, Qwen, Doubao, Kimi, and GLM without managing multiple provider accounts. Start with test credits and optimize your cost per successful task.

Click here to know NovaRouteAI


๐Ÿ›ก๏ธ Protect data, enable AI. Compliance by design.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Caveman.PrivacyGuard:

Package Downloads
Caveman.PrivacyGuard.Mcp

MCP (Model Context Protocol) server for Caveman.PrivacyGuard โ€” exposes PII detection/masking, session-based restore, AI-transparency notices, and prompt-injection screening as MCP tools for Claude Code, OpenCode, Cursor, and any MCP-compatible agent.

CavemanML

The optional ML tier of the Caveman family, in pure C# (no torch, no onnxruntime, no native code): SynthelionML, a learned per-token prompt compressor (39 languages, 70% target), and PrivacyGuardML, a learned PII confirmation model for Caveman.PrivacyGuard. Models from Hugging Face (digitalsolutionsai), fully offline at inference.

Caveman.Compliance

AI compliance engine for LLM gateways: one rule registry (risk, action, scope) over PII, secrets, prompt-injection, agent-policy, toxicity, PHI, data-residency and code-vulnerability controls; a traceability matrix to EU AI Act / GDPR / NIS 2 / ISO 42001 articles; a hash-chained audit trail (Art. 12); and technical file, DPIA, FRIA and executive report generated as JSON and as PDF through Stilo.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.4.0 89 10/11/2026
1.3.1 105 10/11/2026
1.3.0 159 8/13/2026
1.2.2 160 7/19/2026
1.2.1 179 6/2/2026
1.0.1 166 5/4/2026
1.0.0 121 5/4/2026

1.4.0: optional ML confirmation tier - IMlEntityDetector / PrivacyAnalyzer.MlDetector / MlSpan (the learned PrivacyGuardML model ships in the CavemanML package); a failed checksum still vetoes. 1.3.1: False-positive hardening ported from Synthelion 1.2.5 - a failed checksum is never detected or masked, bare numeric formats are gated by requires_context + nearby keyword, short keywords match as whole words, Maltese ID tightened, spaced phone/card numbers. 1.3.0: Streaming & document masking (ported from Synthelion 1.2.5 privacy_stream.py / document_extractor.py). PrivacyStreamMasker: boundary-safe chunked/streaming PII masking with a configurable overlap window (default 512 chars) so patterns spanning a chunk boundary are caught; Feed()/Flush() API for incremental streams and a MaskStream() convenience helper for chunked iterables. PrivacySession.Summary(): redacted placeholder+category view (never the original value) safe to log/display/return over APIs, unlike GetAll()/ToJson() which carry cleartext PII (their XML docs now warn about this). DocumentMasker: streaming masking of plain text, Markdown and CSV files into a "name.masked.ext" copy next to the source (the original is never overwritten) โ€” files are processed in chunks, never loaded whole; CSV rows are read with a minimal RFC-4180-aware reader so quoted multi-line cells survive. Added 12 new regression tests. 1.2.2: NuGet icon restored (caveman-icon.png now packed and referenced via PackageIcon).