The question behind the term
A tenant selector in a URL or interface is not an authorization boundary. Every query, object, job, cache key and derived projection can become a cross-tenant path when scope is accepted from untrusted input.
A reviewable approach
Resolve membership and active tenant context on the server, carry it through narrow repositories and enforce it again with forced row-level policy in non-bypass runtime roles. Return uniform denials that do not leak another tenant’s record existence.
- Never trust tenant IDs from request data
- Use transaction-local trusted scope
- Test cross-tenant reads, writes and side channels
- Separate platform operations from clinical browsing
The boundary to keep visible
Row-level security is one layer, not a complete privacy program. Operator privileges, backup access, object storage, search indexes, analytics and incident procedures need their own isolation evidence.
Trace scope from authentication to storage
Resolve the acting user, current organization and facility membership on the server. A tenant identifier in a URL can choose a requested context, but it cannot grant access to that context. Carry the verified scope into a short database transaction and apply row policy there; avoid connection-level state that can leak between pooled requests.
Test both read and write paths with two tenants and the same record shape. A denial should not reveal whether another tenant’s record exists through a different status code, count or timing pattern. Repeat the review for background jobs, cache keys, attachment stores and search indexes: database row policy does not automatically cover those copies.
References and further reading
Frequently asked questions
Is a tenant ID in the URL an authorization check?
No. The server must establish the actor’s membership and permitted facility context, and the storage layer must enforce the same scope independently.
