Architecture Baseline — Ghasi EHR Platform
Scope: System-level architectural constraints that ALL modules and services MUST respect.
Authority: This document is normative. Module specs may narrow but never contradict these rules.
1. Architecture Style
- Microservices architecture — each bounded context is an independently deployable service owning its schema, APIs, and event contracts.
- No shared databases between services. Inter-service communication uses REST calls or NATS JetStream events.
- A single API Gateway (Kong, DB-less) fronts all HTTP traffic.
2. Multi-Tenancy
| Rule | Detail |
|---|---|
| Tenant isolation | Every persisted entity carries tenant_id. Cross-tenant queries are forbidden. |
| Hierarchy scoping | Org-unit scoping uses HierarchyNode (DAG) via the Hierarchy Service — not a flat Facility/Location model. |
| Request context | Every request MUST carry tenantId (from JWT) and, where applicable, nodeId. |
3. FHIR-First Canonical Model
- FHIR R4+ resources are the system of record for clinical meaning.
- Local tables are permitted ONLY for: performance indices, workflow orchestration state, adapter payload references, and non-clinical config.
- Each module MUST declare its canonical FHIR resources and required search parameters.
- Non-FHIR standards (HL7 v2, CDA, DICOM, X12) are supported only via adapters that map to canonical FHIR.
4. Bounded Contexts (Domain-Driven Design)
Each service is a bounded context that owns:
- Its domain entities and aggregates (database schema)
- Its REST + FHIR API surface
- Its domain events (published to NATS JetStream)
- Its business rules and invariants
Context map (repository baseline)
Convention: The current
mainbranch is the product baseline (historically referred to as “MVP0”). There is no separate phased roadmap in this repository; maturity is tracked via module specs, traceability matrices, and_generation/SERVICE_BASELINE_AUDIT_TRACKER.md.
| Bounded Context | Service | Module Code |
|---|---|---|
| Identity & Access | iam | platform.iam |
| Access Policy (RBAC/ABAC) | access-policy | platform.access-policy |
| Tenant Management | tenant | platform.tenant |
| Org Hierarchy | hierarchy | platform.hierarchy |
| Licensing | licensing | platform.licensing |
| Audit | audit | platform.audit |
| Terminology | terminology | platform.terminology |
| Platform Admin | platform-admin | platform.admin |
| Patient Registration | registration | ehr.registration |
| Scheduling | scheduling | ehr.scheduling |
| Provider Directory | provider-directory | ehr.providers |
| Facility Management | facility | ehr.facility |
| Patient Chart | patient-chart-service | ehr.chart |
| Clinical Notes | clinical-notes | ehr.notes |
| Orders / CPOE | orders | ehr.orders |
| Results | results | ehr.results |
| Medication Management | medication | ehr.medications |
| Allergies | allergies | ehr.allergies |
| Vitals | vitals | ehr.vitals |
| Problem List | problem-list | ehr.problems |
| FHIR Gateway | fhir-gateway | ehr.core |
| HL7 v2 Interop | hl7v2-interop | ehr.core |
| AI Orchestration | ai-orchestrator | platform.ai (licensed) |
| Immunizations | immunizations | clinical.immunizations |
| Care Plans | care-plans-service | clinical.care-plans |
| Messaging | messaging | engage.messaging |
| Patient Portal | patient-portal-api | engage.patient-portal |
| Laboratory / LIS | laboratory-lis | diag.laboratory |
| Radiology / PACS | radiology-pacs | diag.radiology |
| Billing | billing | billing.rcm |
| Insurance | insurance | billing.insurance |
| Claims | claims | billing.claims |
Anti-Corruption Layers
- Services consume other contexts through published interfaces (REST or events) — never by querying another service's DB directly.
- Integration with external systems (PACS, national registries, payer clearinghouses) goes through dedicated adapter services that translate between external formats and the internal canonical model.
5. Event-Driven Architecture
| Aspect | Standard |
|---|---|
| Transport | NATS JetStream (durable, replay, DLQ) |
| Envelope | CloudEvents via CloudEventsBuilder (@ghasi/nats-client) |
| Mandatory fields | id, time, source, type, tenantid, actorid, correlationid, data |
| Subject naming | {domain}.{entity}.{action} — lowercase, dot-delimited |
| Delivery | At-least-once; all consumers MUST be idempotent |
| DLQ | Mandatory for integration pipelines; subject: dlq.{originalSubject} |
6. API Contract Rules
6.1 Internal REST
- Base path:
/v1/{service-path}for clinical module APIs; platform surfaces MAY use/api/...and/internal/...as documented in API_PATH_CONVENTIONS.md. - Documented via OpenAPI
- Versioned; no breaking changes without compatibility plan
- Consistent error envelope:
{ error: { code, message, details }, correlationId, timestamp } - Stable error codes:
MODULE_NOT_ACTIVE,FORBIDDEN,VALIDATION_FAILED,CONFLICT,RATE_LIMITED
6.2 FHIR R4
- Base path:
/fhir/R4/{ResourceType} - Exposed through
fhir-gateway - Errors return
OperationOutcome - Minimum interactions per owned resource:
read,search-type,create,update(where mutable)
6.3 Idempotency
- REST writes: support
Idempotency-Keyheader - HL7 v2: deduplicate by message control ID + sending app/facility
6.4 Public HTTP edge (Kong)
- Kong is the only internet-facing HTTP entry for browser clients and external integrations; they MUST NOT call NestJS upstream URLs directly in production.
- Automated contract tests for externally visible APIs SHOULD exercise the same route and host clients use (through Kong), not only direct upstream tests. Direct upstream tests MAY supplement isolation debugging.
- Service-to-service HTTP on private networks MAY bypass Kong per deployment policy.
7. Security Baseline
| Concern | Standard |
|---|---|
| AuthN | Keycloak OIDC; JWT validated at gateway (Kong) AND at service (zero-trust) |
| AuthZ — RBAC | Keycloak roles + service-level guards |
| AuthZ — ABAC | Delegated to Access Policy Service via POST /internal/access/evaluate; services MUST NOT embed role-checking logic |
| Encryption | TLS in transit; encryption at rest |
| Secrets | Managed secret store; rotate per policy |
| Audit | Tamper-evident append-only audit log for PHI access, modifications, exports, break-glass |
| Consent/disclosure | Policy-driven; evaluated server-side; minimum-necessary and segmentation where configured |
| Rate limiting | Applied at gateway; anomaly detection for patient-facing and integration endpoints |
8. Data Model Invariants
- Every table:
tenant_id,created_at,updated_at,version(optimistic locking). - Use migrations; never
synchronize: truein production. - Opaque UUIDs for external identifiers — never expose sequential DB IDs.
- Multiple identifiers with
system/ assigning authority. - Immutable clinical artifacts: corrections create new versions; provenance preserved.
9. Licensing Enforcement
- Managed by Licensing Service; licenses assigned to HierarchyNodes.
- Core EHR modules seeded as
always-onon root node at tenant activation. - Add-on modules require explicit license assignment.
- Hierarchy-scoped effective license checks (where services call Licensing APIs per node) SHOULD return stable error codes such as
MODULE_NOT_ACTIVEper service OpenAPI — some flows use HTTP 422 where documented (e.g. licensing assignment APIs). - HTTP module gating on REST/FHIR controllers uses
ModuleEntitlementGuardin@ghasi/nestjs-common: unlicensed module → HTTP 403 with body codeMODULE_NOT_LICENSED(tenant-scoped resolve via Licensing Service). Do not conflate with licensing assignment API validation responses. - UI hides disabled module nav entries.
10. Localization & Regional Baseline
Per REGIONAL_PROFILE_AFG_UAE.md:
- Languages: English (LTR), Pashto (RTL
ps-AF), Dari (RTLfa-AF), Arabic (RTLar-AE) - Bidirectional/mixed-direction rendering in UI AND print/PDF
- Dates: ISO 8601 storage; locale-aware display; Gregorian + Hijri + Solar Hijri calendars
- Time zones:
Asia/Kabul(UTC+04:30),Asia/Dubai(UTC+04:00) — configurable per facility - Currencies: AFN, AED minimum; multi-currency; configurable tax/VAT
- Language fallback: user preference → facility default → tenant default
11. Observability
- Structured logs with correlation IDs
- Metrics: throughput, latency (p95), error rates, queue depth, adapter health
- Distributed tracing (OpenTelemetry) across gateway → services → NATS
- Separate audit logs from application logs
12. Performance & Resilience
| Target | Value |
|---|---|
| Page load | < 2s p95 |
| Search results | < 1s |
| API response | < 500ms p95 |
| Scaling | Horizontal for stateless services |
| Async | Integration ingestion, notifications, PDF/exports |
| Retry | Exponential backoff for adapters; graceful degradation |
| DR | Configurable RTO/RPO per deployment |
13. Offline-First Clients and Synchronization
Where a module declares offline-capable workflows, clients MAY use local-first storage and sync per OFFLINE_FIRST_AND_CLIENT_SYNC.md. The server remains authoritative for tenant-wide invariants, licensing, and safety rules. Domain-specific sync and conflict rules belong in the module SPEC.md and TECHNICAL_REQUIREMENTS.md.
14. AI and Assisted Workflows
Optional AI-assisted features (documentation, speech, imaging helpers) MUST be license-gated, audited, and privacy-reviewed. They MUST NOT bypass ABAC, consent, or minimum-necessary rules. All model access from clients flows through ai-orchestrator (or successor) behind Kong; see AI_PLATFORM.md and FR-AI-### in specs/core/EHR_FUNCTIONAL_REQUIREMENTS.md. Module specs define which actors may invoke which AI-backed actions and how drafts become finalized records.