Privacy & PII Masking
ContextRouter includes a built-in privacy subsystem (cortex.privacy) that runs entirely in-process — no external service, no gRPC hop. PII masking is applied transparently at the SecureNode level before any LLM call and reversed after.
Architecture
User prompt → SecureNode → PiiSession.hide() → LLM Provider → PiiSession.reveal() → Response │ │ └── AES-256-GCM ephemeral key (RAM only) ────────────┘Privacy sits inside the Router process. There is no external “ContextZero” service — all masking, encryption, and persona logic is a direct function call.
PII Masking Pipeline
How It Works
- Detection —
PIIMaskerscans text using configurable entity rules (regex + NER) - Tokenization — detected entities are replaced with reversible tokens (
<PII_EMAIL_a1b2c3>) - Encryption — original values are encrypted with ephemeral AES-256-GCM keys (RAM-only, CSPRNG)
- Storage — encrypted mappings live in an in-memory SQLite
MappingStore(per-session) - Reversal — after LLM response,
PIIUnmaskerdecrypts and restores original values - Destruction —
PiiSession.destroy()wipes all mappings and encryption keys from RAM
Supported Entity Types
| Entity | Pattern | Example |
|---|---|---|
| Regex | user@example.com → <PII_EMAIL_x> | |
| Phone | Regex | +380 67 123 4567 → <PII_PHONE_x> |
| Credit Card | Regex + Luhn | 4111-1111-1111-1111 → <PII_CC_x> |
| Name | NER (spaCy) | John Smith → <PII_NAME_x> |
| Address | NER (spaCy) | 123 Main St → <PII_ADDRESS_x> |
| Custom | Configurable | Project-specific patterns via EntityRule |
Token Scope Requirements
PII masking activates when the node’s ContextToken carries both:
privacy:anonymizeprivacy:deanonymize
These scopes are derived automatically from the project manifest when pii_masking: true is set on a graph node.
PiiSession API
PiiSession is the infrastructure-level wrapper created per-node by secure_node.py:
from contextunity.router.cortex.utils.pii import PiiSession
session = PiiSession(session_id="abc-123")
# Hide various data types before LLM callmasked_messages = session.hide_messages(messages)masked_dict = session.hide_dict(state_data)masked_text = session.hide_text("Call me at +380 67 123 4567")masked_request = session.hide_model_request(model_request)
# Reveal after LLM responserevealed_dict = session.reveal_dict(response_data)revealed_text = session.reveal_text(masked_response)
# Destroy session — wipe all keys from RAMsession.destroy()Encryption
Each PiiSession creates its own EphemeralAES256Backend:
- Key generation:
os.urandom(32)— CSPRNG, never persisted - Algorithm: AES-256-GCM (authenticated encryption)
- TTL: Configurable via
privacy.pii_encryption_ttl_seconds(default: 60s) - Destruction:
destroy()zeroes all keys in RAM — no recovery possible
If the cryptography package is not installed, falls back to PlaintextBackend with a warning.
Persona Engine
The PersonaEngine injects synthetic identity and behavioral guidelines into LLM conversations:
from contextunity.router.cortex.privacy import PersonaEngine, PersonaTemplate
engine = PersonaEngine()
# Use a built-in personapersona = engine.create_persona("professional", session_id="session-123")enriched = persona.inject_into_prompt("What is the best approach?")
# Register a custom personaengine.register_template(PersonaTemplate( name="medical_ua", display_name="Медичний аналітик", system_prompt="Ти — медичний аналітик. Відповідай українською.", traits={"tone": "professional", "domain": "medical"}, restrictions=["Не ставити діагнози"], language="uk",))Built-in Personas
| Name | Purpose | Tone |
|---|---|---|
contextunity-harmless-agent | Default safe agent (default) | Neutral, strict safety |
neutral | Minimal assistant | Neutral, concise |
professional | Formal advisor | Formal, detailed |
creative | Creative writing helper | Warm, moderate |
Configuration
Privacy settings are part of the Router config (router.yml):
privacy: pii_encryption_ttl_seconds: 60 # AES key TTL default_persona: "contextunity-harmless-agent"Module Layout
cortex/privacy/├── __init__.py # Public API exports├── anonymizer.py # Anonymizer — orchestrates mask/unmask├── persona.py # PersonaEngine, PersonaTemplate, Persona└── masking/ ├── config.py # MaskingConfig, EntityRule ├── contracts.py # Abstract protocols (PandasSeriesLike, PresidioResultLike) ├── defaults.py # DEFAULT_MASKING_CONFIG ├── encryption.py # EphemeralAES256Backend, PlaintextBackend ├── masker.py # PIIMasker ├── scanner.py # Entity detection (regex + NER) ├── store.py # MappingStore (SQLite in-memory) ├── tokens.py # PII token format ├── unmasker.py # PIIUnmasker └── rules/ └── defaults.yaml # Default entity masking rules
cortex/utils/pii.py # PiiSession — infrastructure wrapper for SecureNode