- Shipped
- August 25, 2026 at 7:15 PM UTC
- Author
- Kamo
- Commit
- 7035a29
The access rule is the part worth reading. Being logged in is not a reason to see a chart. The overwhelming majority of real HIPAA enforcement is not outside attackers, it is workforce members looking up a neighbour, a relative, a celebrity, an ex-partner — and in every one of those cases the ROLE is legitimate, the person genuinely is a nurse. What separates a permitted access from a snoop is whether they have a RELATIONSHIP with that patient, which is a question about data rather than about roles. So ClinicalAccessService answers care team, or panel, or an explicit break-the-glass grant, and anything else is refused and recorded as refused, because a refused reach at a chart is a stronger detection signal than a permitted one. Break-the-glass is a bargain, not an escape hatch: the access is allowed because it is unmistakably recorded and because someone reviews it. The grant needs a stated reason (it is what the reviewer reads), expires in an hour (the emergency that justifies it is measured in minutes), and is written BEFORE the read it authorises, so an access taken under it can never be one the record cannot explain. The care-team check runs first, so ordinary care is never filed as an emergency and the review queue stays reviewable. purpose is a required parameter with no default. §164.528 excludes treatment, payment and operations while 42 CFR §2.25 includes them, so a wrong purpose produces a wrong legal document handed to a patient — and it cannot be reconstructed later from a request path. Auditing is per RECORD, not per request. "Someone opened a chart" is true and useless; per-record rows are what let a §164.402 assessment answer whether a named individual's medication list was seen. Search audits every match, because a name-and-birth-date search returns the names, birth dates and MRNs of everyone who matched. Forbidden and not-found collapse to the same 404 at the HTTP boundary. Internally they differ — a denial is audited against a named record — but a caller who can tell them apart can walk the id space and learn which patients a practice has, which is a disclosure in itself. The compliance boundary is the one explicit refusal, at 403, because that fix is a contract rather than a permission and "not found" would send a practice hunting for a bug. Free slots are computed from rules, never stored: materialising a year for forty providers is tens of millions of rows that go stale the moment somebody changes their Tuesday. Booking checks conflicts in the DATABASE, because two schedulers taking the same slot at once is ordinary and an in-memory check has a window the second booking fits through. Overbooking is modelled rather than refused, since clinics deliberately double-book against no-shows and an unmodelled policy moves the workaround somewhere unauditable. EhrEndpointGuardTest is stricter than the platform ratchet on purpose. This service is anyRequest().permitAll() with no method security, so public is the default; the platform ratchet catches a handler that mentions no session helper, but cannot catch one that resolves a session and ignores the answer. For lead data that is a gap — for a chart it is an unauthenticated read of medical records. So it requires BOTH halves in every mapped handler under ehr/, plus that no handler takes a tenant from the caller. Mutation-proven by deleting one isResolved() check. 1211 tests green.