No-PHI exception taxonomy¶
OpenMed privacy gates sometimes need a deliberate, local exception—for example, a reviewed false positive or a narrowly bounded compatibility allowance. This taxonomy makes those exceptions reviewable without carrying a reason string, patient value, source path, or other arbitrary payload into telemetry or audit artifacts.
The implementation is openmed/risk/exception_taxonomy.py. It is versioned independently of application configuration:
| Field | Value |
|---|---|
| Schema version | 1 |
| Taxonomy version | 1.0 |
| Report type | no_phi_exception_taxonomy |
Closed record schema¶
Every telemetry or audit exception record must contain exactly these fields. The validator accepts at most 16 input fields while reporting unknown fields, then emits only the eight-field canonical schema:
| Field | Allowed value |
|---|---|
schema_version | Integer 1 |
taxonomy_version | String 1.0 |
category | One of the four categories below |
reason_code | A category-specific code below |
scope | telemetry or audit; it must match the validator used |
evidence | One to eight typed references with a sha256: digest |
expires_at | Explicit UTC ISO-8601 timestamp |
approval | Status, role, digest, and explicit UTC approval timestamp |
Evidence references contain only an allow-listed kind (test, review, policy, fixture, or incident) and a lowercase SHA-256 digest. Evidence kinds may occur only once. Approval metadata has no owner, name, email, ticket body, notes, or other free-form field; its role is one of privacy_reviewer, release_reviewer, maintainer, or test_reviewer.
The canonical shape is therefore bounded and content-free:
{
"schema_version": 1,
"taxonomy_version": "1.0",
"category": "local_suppression",
"reason_code": "false_positive_reviewed",
"scope": "telemetry",
"evidence": [
{"kind": "test", "digest": "sha256:0000000000000000000000000000000000000000000000000000000000000000"},
{"kind": "review", "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111"}
],
"expires_at": "2026-09-01T00:00:00Z",
"approval": {
"status": "approved",
"role": "privacy_reviewer",
"approval_digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222",
"approved_at": "2026-08-09T00:00:00Z"
}
}
Version 1 categories¶
| Category | Reason codes | Required evidence | Maximum lifetime |
|---|---|---|---|
local_suppression | false_positive_reviewed, policy_exclusion | test and review | 90 days |
local_allowance | false_positive_reviewed, compatibility_boundary | test and review | 90 days |
synthetic_fixture | synthetic_only | fixture and test | 30 days |
operational_fallback | bounded_degradation | incident and test | 7 days |
An expiry is measured from approval.approved_at and must not exceed the category bound. Timestamp strings and datetime values must carry a zero UTC offset; local offsets and date-only values fail closed. Callers that need time-aware validation pass an explicit as_of value; omitting it performs structural validation without reading the system clock. This keeps repeated validation deterministic and offline.
Validation API¶
from datetime import datetime, timezone
from openmed.risk import validate_audit_record, validate_telemetry_record
as_of = datetime(2026, 8, 9, 12, 0, tzinfo=timezone.utc)
telemetry_result = validate_telemetry_record(record, as_of=as_of)
audit_result = validate_audit_record(audit_record, as_of=as_of)
if not telemetry_result.valid:
safe_report = telemetry_result.to_dict()
validate_exception_record is the shared entry point, and the validate_telemetry_record and validate_audit_record wrappers make the surface explicit. A valid result exposes only the canonical typed record and a stable record digest. An invalid result exposes fixed finding codes, structural paths, and fixed messages; it never includes rejected values. Unknown fields, free-form reasons, owner fields, raw payloads, duplicate evidence, unsupported versions, missing evidence, invalid digests, and expired records fail closed. Mappings are copied into bounded plain dictionaries before inspection, and oversized evidence is rejected before its entries are traversed. Public typed records, rules, approvals, findings, and results enforce the same closed invariants when constructed directly.
This is an operational review aid, not a compliance certification or clinical decision guarantee. The validator performs no mandatory network call and does not provide a release approval decision.
Focused tests: