deidgate
Prove your PHI de-identification actually works — before the cloud LLM sees the data.
You told the security review "we de-identify PHI before it hits the model." deidgate is the test that proves it — on every deploy.
It runs a labeled, 100% synthetic HIPAA Safe Harbor corpus through your de-identification function and fails the build if any of the 18 identifiers survive. It runs entirely in your CI and never touches real PHI — so running it does not make you a Business Associate, and there's no BAA and nothing to procure.
pip install deidgate
# tests/test_deid.py
from deidgate import check_all
from myapp.deid import scrub # <-- your de-identification, whatever it is
def test_deid_strips_all_phi():
result = check_all(scrub)
assert result.passed, result.summary()
or gate CI directly:
deidgate check --deid myapp.deid:scrub --md evidence.md # exit 1 if anything leaks
Why this exists
Every guide says "de-identify first, then call the LLM." Almost nobody independently verifies the de-id works — they trust the vendor's accuracy number. But NLP de-id tops out around 90–99% recall and falls apart on real clinical text: dates written in prose, an MRN embedded mid-word, a reformatted SSN, an age over 89, a hyphenated surname, a nickname. One leak across the BAA boundary is a reportable event.
deidgate is a QA oracle, not another de-id model. Because the corpus is synthetic and labeled, it never has to detect PHI in unknown text (the hard problem everyone loses at). It only checks that each known planted identifier is gone — so the verdict is precise, deterministic, and auditable. It catches a leak three ways:
- exact — the value survives verbatim
- digits — a numeric identifier is reformatted but the digit run survives (
123-45-6789→123456789) - split — a multi-token name/address survives with its distinctive tokens intact
What it covers
All 18 Safe Harbor identifiers (deidgate corpus lists them), including the adversarial cases naive pipelines miss:
| Edge case | Sample |
|---|---|
| Identifier in prose | "admitted on the third of July… filed under mrn 2280" |
| Reformatted digits | "SSN as written: 402 19 8877" (spaces, not dashes) |
| Age > 89 | "a 94-year-old woman" |
| Embedded identifier | "seen in clinic (chartMRN04857211)" |
| Hyphenated / misspelled name | "Reyes-Villalobos, also charted as Reyes Villalobos" |
| Nickname | "prefers to be called 'Sunny'" |
| City/county geo (no street) | "resides in Tulare County near Visalia" |
Try it against the deliberately-imperfect example de-id and watch it fail:
deidgate check --deid examples.naive_deid:naive_scrub
# FAIL — leaks across Safe Harbor categories: date, geo, mrn, ssn, ...
Audit evidence
--md evidence.md / --json evidence.json emits a per-element Safe Harbor pass/fail table you can drop into a validation record:
# deidgate Safe Harbor evidence — ✅ PASS
| # | Safe Harbor identifier | Tested | Result |
| 1 | Names | 3 | ✅ pass |
| 3 | Dates (except year); ages > 89 | 4 | ✅ pass |
| 8 | Medical record numbers | 3 | ✅ pass |
...
pytest integration
# pyproject.toml
[tool.pytest.ini_options]
deidgate_deid = "myapp.deid:scrub"
from deidgate import check_sample
def test_deid_leaves_no_phi(deidgate_deid, deid_sample): # one test per corpus sample
leaks = [l for l in check_sample(deidgate_deid, deid_sample) if not l.warning]
assert not leaks, "; ".join(f"{l.cat.value}:{l.value!r}" for l in leaks)
Roadmap / commercial packs
The bundled corpus is a free starter set. Maintained adversarial edge-case packs (oncology notes, pediatric dates, i18n names, new LLM-jailbreak-style leaks), drift/canary monitoring, and one-click audit-evidence export are the paid tier — same --pack file.jsonl interface. Interested? → (landing page / waitlist link)
FAQ
- Does it touch real PHI? No. The corpus is entirely synthetic — invented names, fake numbers. That's the point.
- Is this legal or compliance advice? No. It's a testing tool; it gives you evidence, not an attestation.
- What counts as "my de-id"? Any
str -> strcallable — a regex, a spaCy/Presidio pipeline, a call to a de-id API, whatever you run before the model.
MIT licensed.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file deidgate-0.1.0.tar.gz.
File metadata
- Download URL: deidgate-0.1.0.tar.gz
- Upload date:
- Size: 17.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d9117f7a4e8d750eec534caf1fa9818308f7f70df4d9cbddd2da46d7754b80bf
|
|
| MD5 |
f5a3499d8692d22a8f4b34456280fb38
|
|
| BLAKE2b-256 |
6360d06b4f5d851030f6ad7e10b2fe6dc84df88eef6b79e03e31418747b5cbcb
|
File details
Details for the file deidgate-0.1.0-py3-none-any.whl.
File metadata
- Download URL: deidgate-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79e21c2dd9483560f7d3a0473c16a19a18f4b3b084f26dc6dc5b445f991ce39e
|
|
| MD5 |
f0b8083ceba184f13329a253950a20cb
|
|
| BLAKE2b-256 |
b2f97c5065dced00f1533d28fce8fe04ac6aba8edad403f2db8e578af342a169
|