Facility Service — Service Overview
Status: populated
Owner: TBD
Last updated: 2026-04-17
Companion: Service Template · 03 platform-services · 02 DDD
1. Purpose
The facility-service is the authoritative registry of physical and organisational structure within the Ghasi-eHealth platform. It owns the organisation hierarchy graph (HierarchyNode + HierarchyEdge + HierarchyProfile) and the facility operational overlay (Location, Bed, ResourceCatalogItem, LocationHours) that every clinical, scheduling, licensing, billing, and access-policy service depends on.
2. Bounded Context
Facility & Hierarchy — classified as Supporting. It is not a clinical domain itself, but it is a shared-kernel prerequisite for Licensing, Access Policy, Registration, Scheduling, Orders, Billing, and Population Health. The context consolidates two legacy modules — facility-management and hierarchy — into a single bounded context with one aggregate model, one API surface, and one event stream.
3. Responsibilities
| Area | What facility-service Owns |
|---|
| Hierarchy graph | HierarchyNode (moph, region, district, hospital, clinic, department, ward, virtual-clinic), HierarchyEdge (contains/manages/refers-to), DAG invariants |
| Hierarchy profiles | Per-tenant configurable schema (allowed node types, depth, required children); seeded profiles for AFG_MOPH, UAE_DOH, PRIVATE_HOSPITAL, CLINIC_SIMPLE, TELEMEDICINE |
| Facility locations | Location rows anchored to exactly one HierarchyNode; operational hours; time zone + locale defaults |
| Bed management | Bed aggregate with bed class, status, isolation capability, housekeeping status; single-active-encounter invariant |
| Resource catalog | Rooms and equipment consumable by scheduling-service |
| Traversal APIs | Sub-tree, ancestors, context-by-provider, inheritance chain (for Licensing/Access Policy) |
| Provider node membership | ProviderNodeMembership — linkage from provider → node with effective-from/to; consumed by access-policy |
| Facility definition import/export | Snapshot artefact for multi-site deployments |
| FHIR canonical projection | Organization, Location, HealthcareService |
4. Non-Responsibilities
| Area | Owner | Why Not facility-service |
|---|
| Clinician identity & credentials | provider-directory-service | Providers are an identity concern; facility only stores node-membership edges |
| License/entitlement policy | Licensing Service (inside platform-admin) | Facility publishes node context; Licensing resolves entitlement at that node |
| RBAC/ABAC evaluation | tenant-service + access-policy | Facility publishes scope context only |
| Patient identity | registration-service | Encounters link location → patient, not the other way |
| Appointment booking | scheduling-service | Scheduling consumes the resource catalog and slot hours |
5. Dependencies
5.1 Upstream
| Dependency | Pattern | Purpose |
|---|
| tenant-service | Shared kernel (TenantId) | Tenant isolation; tenant.created event seeds default hierarchy profile |
| identity-service | CF (JWT validation) | Admin APIs validate JWTs issued by identity-service |
| Access Policy (platform-admin) | RPC | Every write authorised via POST /internal/access/evaluate |
5.2 Downstream Consumers
| Consumer | Pattern | What They Consume |
|---|
| Licensing (platform-admin) | Event + RPC | Hierarchy ancestor chain for resolveEffectiveLicenses(nodeId) |
| Access Policy (platform-admin) | Event + RPC | Node subtree + provider memberships for scope decisions |
| scheduling-service | Event + RPC | Location, hours, resource catalog; bed / resource availability seeds |
| registration-service | Event + RPC | Location reference on Encounter.location |
| orders/laboratory/radiology | Event + RPC | Performing-location resolution |
| billing-service | Event | Service-line + bed-class reporting dimensions |
| interop-service (FHIR) | Event | Organization, Location publication to FHIR gateway |
| population-health-service | Event | Hierarchy dimensions for HMIS aggregation |
5.3 Events Consumed
| Event | Producer | Purpose |
|---|
tenant.tenant.created.v1 | tenant-service | Seed default hierarchy profile + root org node for new tenant |
tenant.tenant.archived.v1 | tenant-service | Cascade-deactivate facility nodes; preserve historical data |
provider_directory.practitioner.created.v1 | provider-directory-service | Allow subsequent ProviderNodeMembership writes |
6. Slice Involvement
| Slice | Scope | Milestone |
|---|
| S0 — Foundation | Hierarchy graph CRUD, profiles, Location + Bed CRUD, ancestor/subtree APIs, FHIR Location | M0 |
| S1 — Operational | Resource catalog, location hours, holiday calendars, bed status stream, provider memberships | M1 |
| S2 — Interop | FHIR Organization/HealthcareService; HL7 v2 PV1 location alignment | M2 |
| S4 — Enterprise | Facility definition import/export, cross-site federation, accreditation registry bridges | M3 |
7. Architectural Freeze Points
| Freeze | What Is Frozen | By |
|---|
| F03 | HierarchyNodeId, LocationId, BedId, ResourceId, ProfileId branded types | End of M0 |
| F01 | EventEnvelope conformance for all facility.* events | End of M0 |
| F04 | Hierarchy DAG invariant: contains edges may not form cycles | End of M0 |
8. Readiness Levels
| Level | Target Milestone | Capabilities |
|---|
| L2 | M0 | Hierarchy graph + Location + Bed operational, basic monitoring |
| L3 | M1 | Provider membership live, cached context lookups p99 ≤ 20ms, contract tests green |
| L4 | M3 | Federated registries, import/export at scale, chaos-tested |
9. Architecture Diagram
10. Key Design Decisions
- One service owns both the structural graph and the operational overlay. Legacy
hierarchy and facility-management merged. Locations always anchor to exactly one HierarchyNode (no orphan locations).
- Graph is a DAG, not a strict tree. A node may have multiple parents (
refers-to, manages). contains edges are the primary ownership edge and must not form cycles.
- HierarchyProfile drives validation, not code. Country / deployment variations (AFG MoPH vs UAE DoH vs private clinic) are configuration.
- Redis-cached context lookup is the hot path. Every downstream service calls
GET /internal/nodes/:id/context; p99 must stay ≤ 20ms. Event-driven invalidation within 30s.
- License + access checks are delegated, not local. facility-service never evaluates entitlement; it publishes node context and ancestors for Licensing/Access Policy to resolve.
- FHIR is a projection, not the store. Internal domain uses the DAG; FHIR Organization/Location is generated from it.
11. Source Reconciliation
The two legacy modules are merged per the following rules:
| Concern | Legacy module | Post-merge owner |
|---|
| HierarchyNode / Edge / Profile CRUD | hierarchy | facility-service — Hierarchy aggregate |
| Location + Bed + Hours operational metadata | facility-management | facility-service — Location and Bed aggregates anchored to HierarchyNode |
| Resource catalog | facility-management | facility-service — Resource aggregate |
| Provider node membership | hierarchy | facility-service — shared-kernel read model for access-policy |
| FHIR Organization/Location | facility-management | facility-service infrastructure projection |
Legacy FR prefixes (FR-FAC-*, FR-HIER-*) are preserved in EPICS.md / USER_STORIES.md under the "Legacy ref" column.
12. Open Questions
- Are national accreditation registries (AFG HMIS facility codes) a first-class field or
metadata JSON? TBD.
- Cross-tenant hierarchy federation (shared regional nodes) — defer to M3+.