PriorAuthdocs

Tenancy and isolation

Each practice is a separate covered entity. Two practices seeing each other's authorizations is a reportable breach, not a configuration nuisance.

#Row-level security

Every row that belongs to a practice carries practice_id, and a read that does not name a practice is refused rather than returning everything. The filter is not something a caller remembers to apply; it is something the store will not proceed without.

javascript
store.listTasks();
// TenantScopeError: Read of "tasks" attempted with no tenant scope. Every row in this
// collection belongs to a practice, and an unscoped read is how one practice sees another.

store.forPractice('p_north').listTasks();   // fine

// the escape hatch: platform work sometimes genuinely needs to see across tenants
store.crossTenant('scheduler dispatch: per-practice fairness requires every queue')
     .listJobs();                            // audited, with the reason
The dangerous failure mode
An earlier version computed the practice id for the write guard and then stored the un-augmented row, so every scoped read filtered to nothing. An isolation control that silently returns zero rows looks exactly like isolation working - which is the most dangerous way for one to fail.

#A practice-less principal is a real case

Platform roles have no practice. Routes that read tenant data must handle that explicitly, because the stores refuse an untenanted read rather than returning everything. Two console routes got this wrong and returned 500s, and one returned every tenant's job queue to a superadmin - the list looked exactly like a correct list, only longer.

#Channels are not tenants

A channel partner - an EHR vendor, for example - is a route through which many practices arrive. It is never itself the tenant.

diagram
100%
The channel is a route. The isolation boundary is the practice, and it does not move.
  • Each practice authorises the channel separately, naming the scopes it grants.
  • A practice can revoke without the channel agreeing, and without leaving the platform.
  • Suspending a channel stops every practice on it at once, checked per call rather than at connection time.
  • Terminating a channel does not delete its practices. They are separate covered entities that happened to arrive by a shared route.

#Offboarding

A purge is followed by a canary that reads the tenant back. It has to come back empty. The audit record of the offboarding is retained, because a deletion nobody can evidence is not a deletion.