Security

For the Data Protection Officer (DPO) or security reviewer deciding whether to run the SDK on real patient data. The full reviewer document is SECURITY.md in the package; this page is its summary. It is not a legal opinion.

The trust boundary

The SDK runs inside your infrastructure. The real transcript, the audio, names, dates, health and record numbers, phone numbers, addresses, occupations, family identity, and your case identifier never leave. The one value that crosses by default is the BoundaryArtifact (the tokenized transcript crosses too only when you turn send_tokenized_transcript on), and the boundary is enforced by what that contract can hold, not by network configuration: every model in it is strict, and there is no field for a transcript, a name, or a case id.

The LLM seam

The judge and the extractor send the surrogate-cleaned transcript to a large language model (LLM). There, and only there, the model’s input is the transcript. Two consequences:
  1. The model must be yours and in-boundary. model in tacit_deid.yaml must resolve to an endpoint inside your tenancy: your Bedrock account, your Azure deployment, a local model.
  2. The endpoint gate is fail-closed. The client is constructed only if the resolved host is on allowed_endpoint_hosts; otherwise EndpointNotAllowedError is raised before any PHI is sent. The resolved host is recorded in the artifact’s audit log.
The transcript and the beats are wrapped by harden_untrusted before they reach a model: a note marks the content as data, not instructions, inside a labelled delimiter, and the system prompt says the same. The engine’s own tests plant instruction-shaped text and assert it is ignored.

Files on your side

Every file below is created owner-only (mode 0600) by write_private_text, and a looser mode is tightened on overwrite. Run folders are named by a hash of the source, not its filename, so the one thing the SDK prints about an input is not its name. Retention, deletion, encryption at rest, and access control are yours: keep the ledger only as long as your audit needs it (it is the complete key from surrogate back to real value), delete run folders with the tooling you use for other PHI, and run the SDK from an encrypted volume under a dedicated service account. ledger_crossing.json is counts only and safe to share with a DPO; ledger_local.json is not. Exceptions name their cause without quoting the transcript: a size error reports the length and the cap, a truncation error the model and response type, an endpoint error the host, an input error the file and the byte offset. The one place raw text can surface is your own model provider’s error message, which the SDK re-raises unchanged; route those logs where PHI is allowed.

Regulatory framing

Designed against the three residual risks regulators use (Article 29 Working Party Opinion 05/2014, carried forward by the European Data Protection Board): singling out (the constrained schema plus the population-uniqueness check), linkability (regeneration breaks any one-to-one mapping to a real record), and inference (generalization plus l-diversity). The adversary is the UK ICO motivated intruder, including one with generative tools. For US contexts the HIPAA Safe Harbor identifiers are the floor (Stage 0) and the population-uniqueness layer is the Expert-Determination-style argument; equivalence-class definitions follow NIST SP 800-188. For Australia and New Zealand the design sits under the Australian Privacy Principles and the NZ Privacy Act 2020 with the Health Information Privacy Code; the NZ NHI is targeted explicitly. Confirm the applicable regimes with your DPO.

What is claimed, and what is not

Claimed: no direct identifiers in the artifact, and a bounded, measurable, layered reduction in re-identification risk. Not claimed: “zero PII” or “impossible to leak”; absolute claims do not survive an audit. The limits, stated plainly:
  • Audio is a biometric identifier; the SDK handles text only. Source audio is on your side.
  • Clinical joint distributions are not public; the singling-out engine has demographic joints and clinical marginals only. A hard ceiling, mitigated, not eliminated.
  • The binding contextual-leak control is an LLM judge whose recall is not perfect; measure it against a labelled leak set for your domain.
  • Population-uniqueness estimators assume representative sampling; a single clinic is not a national sample. The SDK bounds conservatively, and the bound shifts as public data changes.
  • The canary and simulation results are lower bounds from planted truth, never proof about un-planted data. A refusal passes them trivially, because nothing crossed.
  • The bundled base-rate tables carry their own source licenses; see Data licenses.
Report a vulnerability to the maintainers by email, never in a public issue.