Skip to main content

Tenant Service — Service Overview

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 03 platform-services · 02 DDD

1. Purpose

The tenant-service is the authoritative owner of the legal entity (tenant) on the Ghasi-eHealth platform. It governs tenant onboarding and lifecycle (pending → active → suspended → terminated), subscription management, RBAC/ABAC policy (authorization), user profiles and org membership, org hierarchy governance, and data-residency configuration. It is the platform's authorization hub: downstream services resolve roles, memberships, and permission grants against tenant-service.

2. Bounded context

Tenant, Authorization & Membership — classified as Generic / Supporting. Runs in-house because:

  • Multi-tenant data isolation enforced at DB level via tenant_id column + RLS.
  • Authorization policy (RBAC/ABAC evaluate) is tenant-sensitive and must be evaluated in-cluster.
  • Org hierarchy is tenant-owned; structure varies by country profile (AFG MoPH, UAE DOH, private hospital).
  • SCIM-driven provisioning requires tight integration with identity-service events.

3. Responsibilities

AreaWhat tenant-service owns
Tenant lifecycleCreate (PENDING), activate, suspend, reactivate, terminate; orchestrates root hierarchy node + admin user + always-on license seeding on activation
Subscription managementTier (STARTER / PROFESSIONAL / ENTERPRISE), contract dates, expiry events
Tenant configurationConfig KV store with allow-listed keys; branding, MFA policy, session timeouts
Org hierarchyHierarchyNode tree (organization → facility → department → ward → bed); country-profile-based structure
RBAC/ABACRole definitions, role assignments to users at nodes, permission grants, evaluate() decision endpoint
User profilesProvider profiles (name, specialty, credentials) for clinical users; links to UserId in identity-service
Org membershipUser ↔ node membership; multi-node assignments; status transitions
FHIR OrganizationTenant is modelled as FHIR Organization resource via interop-service bridge

4. Non-responsibilities

AreaOwner
Authentication / credentials / sessionsidentity-service
Module licensingidentity-service
Notification deliverycommunication-service
Audit log storageaudit-service
Platform operator console (cross-tenant oversight)platform-admin-service
Billing transactionsbilling-service

5. Upstream & downstream dependencies

5.1 Upstream (services tenant-service calls or consumes events from)

DependencyPatternPurpose
identity-serviceEvent consumer (identity.user.registered.v1)Provision user profile; link UserId to org membership
identity-serviceInternal HTTP (GET /internal/identity/providers/:id/identity)Identity package for evaluate() context
facility-serviceInternal HTTPHierarchy cross-reference for facility-level node creation
config-servicePullPlatform runtime config (hierarchy profile defaults)

5.2 Downstream consumers

ConsumerPatternWhat they consume
identity-serviceEvent consumertenant.activated, tenant.suspended, tenant.terminated for session management and user seeding
All servicesInternal HTTP (GET /internal/tenant/tenants/:id)Tenant status / active check
All servicesJWT claim tidTrust tenant-scoped requests
platform-admin-serviceInternal HTTP + eventsCross-tenant health / oversight
communication-serviceEvent consumertenant.activated, tenant.user.invited for onboarding emails
audit-serviceEvent consumerAll tenant lifecycle events

6. Slice involvement

SliceScopeMilestone
S0 — FoundationTenant lifecycle, basic config, hierarchy root, simple RBAC, user profilesM0
S1 — Hierarchy & membershipFull hierarchy tree, multi-node membership, permission grants, SCIMM1
S2 — ABAC & federatedABAC policy engine, context-aware evaluate(), external IdP membership syncM2
S4 — EnterpriseAdvanced ABAC (attribute policies), freeze mode, idempotency hardeningM3

7. Architecture diagram

8. Key design decisions

  1. AuthN vs AuthZ split. identity-service owns who you are; tenant-service owns what you can do within a tenant. Prevents circular dependencies.
  2. Activation is orchestrated. POST /admin/tenants/:id/activate is a saga: create root HierarchyNode → seed Tenant Admin user in identity-service → seed always-on licenses. Bounded retries with backoff; tenant stays PENDING on failure.
  3. Hierarchy nodes. All org structure (facility, dept, ward) lives in tenant-service as HierarchyNode aggregates, not in a separate service. This reduces fan-out for authorization path.
  4. RBAC first, ABAC later. S0 delivers role-based access (TENANT_ADMIN, CLINICIAN, NURSE, PATIENT). ABAC attribute policies are S2.
  5. FHIR Organization. Tenant is exposed as FHIR Organization via interop-service bridge. Tenant-service owns the source record; FHIR representation is derived.

9. Source reconciliation

ConcernDecision
Legacy tenant moduleCore tenant lifecycle + config retained; schema updated to ULID IDs and RLS
Legacy hierarchy moduleMerged into tenant-service — HierarchyNode is a tenant aggregate
Legacy access-policy moduleMoved from identity-service into tenant-service — RBAC/ABAC is a tenant concern
FHIR OrganizationExposed via interop-service bridge; tenant-service owns source record
Legacy FR prefixesFR-TEN-*FR-TENANT-*; FR-ACPOL-*FR-TENANT-ACC-*