Skip to main content

Tenant Service — Security Model

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 13 Security · 14 Compliance

1. RBAC matrix

RoleTenant lifecycleHierarchyUser profilesMembershipRole assignmentsConfig
SUPER_ADMINFull CRUDRead + create rootRead allReadReadRead + write
TENANT_ADMINRead own + update profileFull CRUD (own tenant)Full CRUD (own)Full CRUD (own)Full CRUD (own)Read + write (own)
CLINICIANRead own tenantReadRead ownRead ownRead ownRead own
NURSERead own tenantReadRead ownRead ownRead ownRead own
PATIENTRead ownRead own
Internal serviceRead (via /internal/*)Ancestors query

2. ABAC (S2+)

ABAC policies (S2 / M2) extend RBAC with attribute conditions:

Policy typeExample
Node-scoped resource accessCLINICIAN may read patient_chart WHERE node_id IN user_membership_nodes
Specialty-gated actionprescribe_medication REQUIRES clinician.specialty IN ['GP','Internal Medicine']
Time-bounded accessemergency_access ALLOWED DURING shift.active_window

Evaluate endpoint: POST /api/v1/tenants/:id/access/evaluate — returns { decision, reasons }.

3. Encryption classes

DataClassificationAt-rest encryptionIn-transit
Tenant legal/commercial dataConfidentialPostgreSQL TDE (AWS RDS AES-256)TLS 1.3
Tenant configuration (branding, MFA policy)InternalPostgreSQL TDETLS 1.3
User profiles (name, specialty)ConfidentialPostgreSQL TDETLS 1.3
Org membership / role dataInternalPostgreSQL TDETLS 1.3
Event payloads (NATS)InternalTLS in transit; at-rest encrypted per NATS JetStream storageTLS 1.3

4. Audit events (emitted to audit-service)

EventTrigger
tenant.tenant.activated.v1Activation (irrevocable step)
tenant.tenant.suspended.v1Suspension
tenant.tenant.terminated.v1Termination
tenant.role_assignment.created.v1Role granted
tenant.role_assignment.removed.v1Role revoked
tenant.config.changed.v1Config key mutation
tenant.org_membership.removed.v1Membership removed

All audit events include actorId, tenantId, timestamp, requestId.

5. GDPR participation

ActionMechanism
User erasureConsumes identity.user.deactivated.v1; anonymizes user_profiles (first_name, last_name → "ANONYMIZED"); removes org_memberships
Data export/api/v1/tenants/:id/users/:userId/export returns user profile + membership + role data
Lawful basisHealthcare treatment (Article 9 GDPR); tenant signs DPA

6. Data residency

Tenant rows include country_code. Data residency enforcement:

  • Afghan tenants (AF): data stored in AF/UAE cluster region only.
  • UAE tenants (AE): data stored in UAE cluster region only.
  • Cross-region replication prohibited for tenant PII.
  • Module catalogue (no PII) replicated cross-region for availability.

7. Tenant isolation controls

ControlImplementation
Row-level securityRLS on all tenant-scoped tables; SET app.tenant_id per transaction
Guard layerTenantContextGuard validates JWT tid matches URL :tenantId
Internal API/internal/tenant/* IP-restricted to cluster CIDR; no JWT required
Cross-tenant read preventionRLS policy; test enforced by tenant-isolation.spec.ts (mandatory)