FHIR multi-tenancy
Multi-Tenant FHIR Server Access Control
Tenant boundaries belong in the same model that describes the clinical and organisational domain. Fire Arrow expresses tenant isolation through FHIR Organizations, PractitionerRole codes, LegitimateInterest, and CareTeam, then enforces it at request time.
Who this is for
Architects building B2B digital health products for clinics, providers, research networks, or multi-organization care programs.
Clinical applicability
Clinic A and Clinic B share one server. Each clinic's clinicians can search and read only their own patients via LegitimateInterest. A specialist can be added to a patient's CareTeam in Clinic A and gain access to that patient only, without seeing the rest of Clinic A's panel.
Tenancy as data, not topology
Tenants are FHIR Organizations. Practitioners belong to an Organization through PractitionerRole, which also encodes the role code (physician, nurse, IT staff, support). Patients are managed by an Organization through `Patient.managingOrganization`. The same FHIR resources that describe the clinical domain describe the tenant boundary.
This avoids the failure mode where some tenant rules live in the database, some in REST handlers, and some in GraphQL resolvers. The boundary is defined once and enforced at request time across all access paths.
Within-organisation isolation with LegitimateInterest
The `LegitimateInterest` validator grants access when the caller's Organization matches the target resource's relevant organisation reference (typically `managingOrganization` for Patient, or the patient's managing org for related resources like Observation and CarePlan). Rules can layer multiple LegitimateInterest entries with different inclusion parameters; results are additive.
PractitionerRole codes feed into role-aware rules through identity filters. A nurse role and a physician role within the same Organization can share most rules but differ on operations like `MedicationRequest:create` or property filters on sensitive fields.
Cross-organisation access with CareTeam
A specialist who needs to consult on a single patient is not a member of that patient's Organization. Adding them to the patient's CareTeam grants scoped access through the `CareTeam` validator: read access to that patient and related resources, no access to the rest of the organisation's data.
When the consultation ends, removing the CareTeam entry revokes access. The audit trail shows membership changes alongside the data accesses they enabled.
Deny by default and search narrowing
`default-validator: Forbidden` ensures that an organisation added without explicit rules sees nothing. Rules that grant access also drive search narrowing: a clinician searching Patient under LegitimateInterest gets a query that filters by their organisation at the database layer. There is no client-side filter step that could be bypassed.
FAQ
Do I need a separate database per tenant?
No. Fire Arrow enforces tenant boundaries through FHIR identities and validators on a shared database. Per-tenant database isolation is an option for stricter physical separation, at higher operational cost.
How does cross-tenant patient transfer work?
Update the patient's `managingOrganization` reference. Subsequent requests evaluate against the new Organization through the same rules. CareTeam entries can be added to maintain access during a handover period.
Can support staff get temporary cross-tenant access?
Yes, through a dedicated support role with rules scoped via identity filters and time-bounded CareTeam membership where appropriate. The rule set is explicit, so audit reviews can show what support access existed and when.
Does GraphQL respect the same tenant boundaries?
Yes, but the rules must be declared on `graphql-read` and `graphql-search` operations alongside REST `read` and `search`. The validator and search narrowing logic is shared.