PIIGuard: mask PII before it
ever reaches the server
"Did you know cachly can stop sensitive data — emails, PINs, IBANs, API keys — from ever leaving your machine in the first place?" Meet PIIGuard (a.k.a. DataShield): a small, local-only utility that masks sensitive values into deterministic tokens before any request goes out — and puts you, not us, in control of what gets sent.
Did you know? Your data can be masked before it ever leaves your machine
Most "privacy" features in dev tools work on data afterit has already arrived on a server — redacting it in logs, encrypting it at rest, restricting who can query it. That's better than nothing, but it still means the raw value crossed the wire at some point.
PIIGuard takes a different approach: masking happens locally, in your process, before the SDK ever calls cache.set(). The cachly server never sees the raw email, phone number, IBAN, PIN, or secret — only a short, deterministic token like [MASKED_a8f3c2]. The original-to-masked mapping lives only in memory, on your machine, for as long as you keep it.
What it masks
PIIGuard ships with built-in detectors for the PII categories that most commonly leak into logs, lessons, and cached context:
- Email addresses — enabled by default
- Phone numbers — enabled by default
- IBANs — enabled by default
- IPv4 addresses — opt-in via
fields: ["ipv4"] - Names — opt-in heuristic match on capitalized word pairs
- Anything else — PINs, API keys, order IDs, internal account numbers — via your own
customPatternsregexes
That last one is the important part. You are never limited to the built-in categories — if your team stores 4-digit support PINs, internal ticket IDs, or vendor secrets in a recognizable format, you write one regex and PIIGuard masks it the same way it masks an email.
How the masking actually works
Each detected value is hashed with SHA-256, and the first six hex characters become the token: [MASKED_a8f3c2]. Two important properties fall out of this design:
- Deterministic — the same input always produces the same token within an instance, so masked values stay consistent and comparable across a session (collisions are disambiguated automatically).
- Reversible, locally — call
unmask()to restore the original text from the in-memory mapping. The mapping never leaves your process and is never transmitted — you decide if and when to clear it withclearMapping().
A simple example
Here's the entire flow — mask on the way in, store the masked version, restore locally whenever you need the original:
import { createClient } from '@cachly-dev/sdk'
import { PIIGuard } from '@cachly-dev/sdk/pii'
// One guard per request/session — keeps the local mapping bounded
const guard = new PIIGuard({
fields: ['email', 'phone', 'iban'],
customPatterns: [/\bPIN\s?\d{4}\b/gi], // your own format, e.g. support PINs
})
const cache = createClient({ url: process.env.CACHLY_URL! })
const note =
"Customer [email protected] called from +49 171 1234567, " +
"verified with PIN 4471."
// Masking happens here — locally, before anything is sent
const masked = guard.mask(note)
// → "Customer [MASKED_a8f3c2] called from [MASKED_b9d4e1], verified with [MASKED_7c12d0]."
await cache.set('support:ticket:8841', masked)
// The cachly server only ever stores the masked string above.
// Need the original later? Restore it locally — the mapping never left your machine.
const restored = guard.unmask(masked)
// Done with this request? Bound memory usage and drop the mapping.
guard.clearMapping()Notice what never happens here: the raw email, phone number, or PIN is never part of any network request. If you inspect traffic between your process and cachly, you will only ever see [MASKED_xxxxxx] tokens.
You decide — that's the whole point
PIIGuard is deliberately not wired into the SDK automatically as a hidden middleware step. There is no silent beforeSend hook rewriting your data behind your back. You import it explicitly, configure exactly which categories and patterns matter for your team, and call mask() / maskObject() at the exact point where it makes sense for your workflow.
That is a deliberate trade-off: a tiny bit more setup, in exchange for full transparency over what is being masked, when, and how. For teams in regulated environments — healthcare, fintech, anything GDPR-sensitive — that explicitness is the feature, not friction.
Where this fits in the bigger picture
cachly already runs on EU (Hetzner, Germany) infrastructure and is GDPR-aligned by default. PIIGuard pushes the privacy boundary one layer further out — to before the request is even formed. Combine the two and the result is a memory layer where:
- Sensitive values never cross the network in plain text
- You hold the only copy of the original-to-masked mapping
- The server stores and recalls masked, useful context
- You can restore the originals locally whenever you actually need them
It's a small utility — about 170 lines — but it changes the default answer to "what does the server see?" from "everything you send it" to "exactly what you chose to let through."
cachly is a persistent AI Brain for developers — memory shared across Claude Code, Cursor, GitHub Copilot & Windsurf simultaneously. Auto-detects every editor. Bootstraps from your git history. 115 MCP tools. Free tier, EU servers, no credit card.
Your AI is forgetting everything right now.
Every session starts blank. Every bug re-discovered. Every deploy procedure re-explained. cachly fixes that in 30 seconds — your AI remembers every lesson, every fix, every teammate's hard-won knowledge. Forever.