Skip to main content
Version: v0.0.8

Known Limitations & Honesty

@cosyte/deid transforms a healthcare document per a configured de-identification policy (Safe Harbor by default) and emits a value-free manifest of what it acted on. It never labels output "de-identified," and it never certifies HIPAA de-identification. Safe Harbor is implemented mechanically; Expert Determination is supported, never rendered. The structured-field core is the guarantee; free text is blocked by default; DICOM is metadata-only (burned-in pixels are flagged, not cleaned). The library fails closed - on any ambiguity it blocks or removes, never passes a value through as "probably safe."

Read this page before you rely on the library for anything that leaves your control.

What it does

  • Locates PHI structurally at each parser's loci (never by regex over raw bytes) and applies the configured policy transform per Safe Harbor category.
  • Returns an immutable transformed document plus a value-free manifest (category + transform + locus + count + disposition - never the value removed, never the key, never the date-shift offset).
  • Fails closed: an unrecognized structure, an un-locatable identifier, an unknown segment/extension, or a free-text blob is blocked or removed, never emitted as safe.
  • Preserves clinical/financial values (codes, units, results, statuses, amounts) - the over-scrub guard - so it does not degenerate into a "safe but useless" blanket scrubber.
  • Ships two named policy profiles and a defineDeidProfile() that can only ever tighten (widen safety), never loosen, a base standard.

What it does NOT do

It does notBecause…
Certify HIPAA de-identificationThe library transforms and evidences; it never certifies. Output is "Safe-Harbor-transformed per the configured policy," never "de-identified."
Discharge the §164.514(b)(2)(ii) actual-knowledge clauseThat is an organizational judgment about what a recipient knows - the library surfaces the residual (kept year, safe-3-digit ZIP) so a human can apply it, but cannot make it.
Render or certify Expert Determination (§164.514(b)(1))"The risk is very small" is a qualified statistician's contextual judgment about a dataset and its recipient. The ED support report emits value-free facts as input; determination is always null and it computes no risk score.
De-identify free text / narrativeFree-text loci (HL7 OBX-5/NTE, C-CDA narrative <text>, FHIR notes/div, X12 MSG/NTE, NCPDP free text) are blocked by default. A BYO redactor is consumer-asserted, never the library's guarantee; a naive built-in regex scrub is deliberately refused as a false-safety hazard.
Clean DICOM burned-in pixels or full-face images (category Q)v1 is metadata-only (delegated PS3.15 Annex E). Burned-in annotation raises DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED and burnedInAnnotationHazard; pixel decode is a future @cosyte/dicom-pixel. Do not release an image on metadata alone.
Handle NCPDP SCRIPT ePrescribingDeferred. The current parser surface (lossy serialize + an address-less Patient model) cannot support a faithful structural de-id, so SCRIPT is not silently half-handled. NCPDP Telecom is supported.
Handle loci/formats absent from the parser modelsA locus the parser does not model, or a format not in the suite, fails closed - never silently passed. Vendor-proprietary loci absent from public specs are deferred, not invented.
Guarantee against a determined re-identification attackDe-identification reduces risk to the regulatory bar; it is not a cryptographic guarantee. Key custody is the consumer's - a leaked HMAC key or date-shift offset re-identifies.
Do anything the manifest does not recordIf it is not in the manifest, the library did not do it. The manifest is the complete, value-free audit.

Fail-closed posture

Uniquely, harm here runs in two directions and both are guarded:

  • Under-scrub (a leak): a missed PHI element leaves a patient identifiable. The reflex is the inverse of a parser's Postel's-Law liberality - when in doubt, block/remove.
  • Over-scrub (destroyed meaning): a clinical value wrongly treated as an identifier destroys data a clinician relies on. Clinical-kind loci are retained untouched.

A keyed transform with no key is a fatal DEID_NO_KEY - never a silent unkeyed fallback (an unkeyed hash of an identifier is re-identifiable). A context configured with maxShiftDays: 0 is a fatal DEID_CONTEXT_INVALID - a zero-bound shift is a guaranteed no-op, i.e. the original real dates.

Policy profiles - and the Limited Data Set caveat

  • SAFE_HARBOR_PROFILE - the fail-closed default: dates generalized to year, the (R) catch-all blocked.
  • LIMITED_DATA_SET_PROFILE - a research / longitudinal preset that date-shifts dates (interval-preserving) rather than generalizing them. It is deliberately less protective than Safe Harbor for dates: a shifted-but-real date is still "an element of a date." Therefore it is not labelled safe-harbor, it requires a keyed per-patient context, and it produces an Expert-Determination-supporting dataset - not a certified de-identification, and not, on its own, a HIPAA §164.514(e) Limited Data Set. Disclosing an actual Limited Data Set additionally requires a Data Use Agreement, which is the consumer's responsibility.

defineDeidProfile() derives a per-site profile under a widen-never-narrow contract: a site may move a category to an equal-or-stronger transform (more removal), but never re-weaken a category - a weakening override is a fatal DEID_PROFILE_INVALID. A site preset can only tighten the base.

Free text is the consumer's responsibility

The library bundles no NLP/PHI detector. With no redactor, free-text loci are blocked. With a FreeTextRedactor, its output is recorded as consumer-asserted (DEID_FREETEXT_CONSUMER_REDACTED) and is not re-verified by the library - "no findings" from a redactor is not an attestation. The structural PHI the adapters remove is unaffected either way.

The Expert-Determination report makes no determination

The report is descriptive input a determiner consumes and documents - it reaches no conclusion:

import { OUTPUT_LABEL, SAFE_HARBOR_PROFILE, LIMITED_DATA_SET_PROFILE } from "@cosyte/deid";

// The output is never labelled "de-identified".
OUTPUT_LABEL; // => "Safe-Harbor-transformed per the configured policy"
OUTPUT_LABEL.includes("de-identified"); // => false

// Safe Harbor is the fail-closed default; the LDS preset is honestly not Safe Harbor.
SAFE_HARBOR_PROFILE.standard; // => "safe-harbor"
LIMITED_DATA_SET_PROFILE.standard; // => "limited-data-set"
LIMITED_DATA_SET_PROFILE.requiresContext; // => true
import { buildExpertDeterminationSupportReport } from "@cosyte/deid";

const report = buildExpertDeterminationSupportReport([], { policy: "safe-harbor" });
report.determination; // => null
report.disclaimer.includes("NOT a determination"); // => true

The library's promise is narrow and honest: structured-field, fail-closed, policy-driven Safe-Harbor transformation with a value-free manifest - never a leaked patient, never a destroyed clinical value, and never a claim of "de-identified."