Current state. Live on npm as v0.2.0-alpha.4 with provenance attestation. One interface, two analyzers: the RemotePresidioAdapter over a deployed Presidio container (spaCy NER + per-request Indian recognizers) and a zero-dependency deterministic engine that doubles as the outage fallback. Extension path: recognizer pass-through (#25). Remaining P2 hardening in #19.
Context
The package owns the integration; the deployment owns the intelligence. mastra-pii is an adapter over a Presidio deployment — not a detector — and its story is compatibility and ease of use, not engine accuracy.
Problem
An agent loop touches sensitive text at many surfaces — prompts, tool inputs and outputs, traces, logs, memory — and every one of them needs redaction coverage. The consumer is an agent application whose users write Hinglish and share Indian identifiers (Aadhaar, PAN, UPI, IFSC, bank accounts); Western redaction libraries optimize for English prose and US formats, so off-the-shelf coverage was never the answer. The hard problem that remains is integration: wiring a redaction layer into a Mastra agent normally means custom code at every boundary. The adapter exists so that wiring is zero.
Approach
- One interface, two analyzers.
RemotePresidioAdaptertalks to a deployed Presidio container (spaCy NER by default, plus per-request Indian recognizers);LocalFallbackAdapteris the zero-dependency deterministic engine that takes over on outage. Swap deployments without changing app code. - The deterministic layer ships with the package.
INDIAN_DEFAULTS— Indian regex recognizers with client-side Verhoeff (Aadhaar) and Luhn (cards) checksums, a curated entity allowlist, and shape post-filters — sent as per-requestad_hoc_recognizers, and runnable standalone with no deployment at all. - Drop-in Mastra integration.
pii.processorimplements Mastra’sProcessorinterface —inputProcessors: [pii.processor]plusoutputProcessorsis the whole integration, with a third hook (processLLMRequest) covering every model call including tool continuations. Placeholders stay type-tagged ([PAN_1]); custom regexes run in time-bounded worker sandboxes. - Fail-closed by default. Outages degrade to the local engine (or
[REDACTION_FAILED]in strict mode); raw PII never leaks. - Layer boundaries explicit. The package accepts only the deterministic layer;
nerandmodelrequests are rejected. Adding a model layer or custom recognizers is a deployment-side decision.
Roadmap
Built-in recognizer expansion (#9–#13) and obfuscation canonicalization (#8) are closed as out of scope (2026-08-14) — detection extensions flow through recognizer pass-through, not new built-ins. The remaining P2 hardening is tracked in the master issue #19, ordered for implementation — pick the first open one, top to bottom:
- #14 — Presidio adapter: retries with jitter + timeout config
- #25 — Recognizer pass-through: user recognizers (Presidio shape) replace the adapter’s recognizer set; custom patterns (local shape) run in both modes — the documented way to add detection
- #16 — Observability: per-entity redaction counters
- #15 — Agent-callable redactPII Mastra tool
- #17 — Structured-document inspection (redact inside JSON/objects)
- #18 — Mastra compatibility matrix (1.57 → latest 1.x) — final guard
Evidence
The package is live on npm (provenance-attested), the README documents the full contract, and the repo is public — src/ for the adapter internals, deploy/ for the Presidio recipe. Comparison harnesses live in docs/evaluation/ for internal use; accuracy is the deployed analyzer’s property, not this package’s headline. Portfolio examples are synthetic fixtures only.
Decisions
The published ADR records the starting decision: deterministic local redaction with fail-closed behavior before broader model-backed promises. The pivot to a remote Presidio analyzer was gated on an internal spike before any package work.
Outcome / current state
The package is live on npm (0.2.0-alpha.4, provenance-attested) with 67 passing tests and a clean-consumer verification gate. What it does not do is documented as loudly as what it does:
- Obfuscated formats still defeat every engine — a stated permanent limit, not a backlog item.
- Names and addresses are NER-only, deployment-side.
- International identifiers have no built-in recognizers; pass-through is the extension path.
- The model layer is explicitly out of scope.
Those limits are scope, not surprises.
Next
The hardening backlog (#19) is the ordered plan: retries with jitter, recognizer pass-through, observability, the agent-callable tool, structured-document inspection, and finally the Mastra compatibility matrix. Release cadence bundles pairs per alpha — alpha.5 = #14 + #25, alpha.6 = #16 + #15, alpha.7 = #17 + #18, then stable 0.2.0 once the matrix is green. Every alpha ships through the existing release workflow (trusted publishing, provenance attestation) — no token publishes.