- Shipped
- August 25, 2026 at 2:19 PM UTC
- Author
- Kamo
- Commit
- c1bdbd7
Four fields the clinical read paths cannot work without, and none of which can be backfilled — each records something only knowable at the moment of access. purposeOfUse is the one that matters most, because TWO different legal reports are built from the same rows and they disagree. §164.528 — HIPAA, six-year lookback — EXCLUDES treatment, payment and operations. 42 CFR §2.25 — Part 2, three-year lookback through an EHR, live since 16 February 2026 — INCLUDES them. A row with no purpose belongs in neither and cannot be assigned to one later; deriving it from the request path afterwards is guesswork, and the output is a legal document handed to a patient. Over-reporting alarms them about disclosures that never happened, under-reporting is a violation, and neither raises an exception. patientCompartmentId is NOT resourceId. The sensitive record is usually an Observation or a note whose id says nothing about whose chart it is, so without it the literal §164.528 question — everything ever seen about this patient — has no predicate and becomes a full scan of the largest table on the platform. It gets an index, and that is a stated trade rather than a free win: on Yugabyte each secondary index is a separate distributed table, so an audit insert becomes five distributed writes rather than four. The batched writer absorbs it; a full scan against a 60-day legal clock does not absorb anything. accessBasis records on what AUTHORITY the caller reached the record, as distinct from why they wanted it. "Opened this chart for treatment" is unremarkable; "opened this chart for treatment and is not on the care team" is the finding an insider-threat review exists to surface. Whether someone was on a care team six months ago is not answerable from today's care team table, so it is stamped now or it is gone. Nineteen clinical resource types appended, named after their FHIR resource types so an audit row, an AuditEvent projection and a TEFCA disclosure record all say the same word. Safe to append with no migration: the column is VARCHAR(40) with no CHECK — and a test pins that every name still fits, because an oversized name fails at insert, which for a fail-closed kind means refusing the read itself. Every field is nullable, so all existing rows and every non-clinical caller are unaffected. 1636 tests green.