Skip to main content

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

RuleDetail
Tenant isolationEvery persisted entity carries tenant_id. Cross-tenant queries are forbidden.
Hierarchy scopingOrg-unit scoping uses HierarchyNode (DAG) via the Hierarchy Service — not a flat Facility/Location model.
Request contextEvery request MUST carry tenantId (from JWT) and, where applicable, nodeId.

3. FHIR-First Canonical Model

Per FHIR_FIRST_STANDARD.md:

  • 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:

  1. Its domain entities and aggregates (database schema)
  2. Its REST + FHIR API surface
  3. Its domain events (published to NATS JetStream)
  4. Its business rules and invariants

Context map (repository baseline)

Convention: The current main branch 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 ContextServiceModule Code
Identity & Accessiamplatform.iam
Access Policy (RBAC/ABAC)access-policyplatform.access-policy
Tenant Managementtenantplatform.tenant
Org Hierarchyhierarchyplatform.hierarchy
Licensinglicensingplatform.licensing
Auditauditplatform.audit
Terminologyterminologyplatform.terminology
Platform Adminplatform-adminplatform.admin
Patient Registrationregistrationehr.registration
Schedulingschedulingehr.scheduling
Provider Directoryprovider-directoryehr.providers
Facility Managementfacilityehr.facility
Patient Chartpatient-chart-serviceehr.chart
Clinical Notesclinical-notesehr.notes
Orders / CPOEordersehr.orders
Resultsresultsehr.results
Medication Managementmedicationehr.medications
Allergiesallergiesehr.allergies
Vitalsvitalsehr.vitals
Problem Listproblem-listehr.problems
FHIR Gatewayfhir-gatewayehr.core
HL7 v2 Interophl7v2-interopehr.core
AI Orchestrationai-orchestratorplatform.ai (licensed)
Immunizationsimmunizationsclinical.immunizations
Care Planscare-plans-serviceclinical.care-plans
Messagingmessagingengage.messaging
Patient Portalpatient-portal-apiengage.patient-portal
Laboratory / LISlaboratory-lisdiag.laboratory
Radiology / PACSradiology-pacsdiag.radiology
Billingbillingbilling.rcm
Insuranceinsurancebilling.insurance
Claimsclaimsbilling.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

AspectStandard
TransportNATS JetStream (durable, replay, DLQ)
EnvelopeCloudEvents via CloudEventsBuilder (@ghasi/nats-client)
Mandatory fieldsid, time, source, type, tenantid, actorid, correlationid, data
Subject naming{domain}.{entity}.{action} — lowercase, dot-delimited
DeliveryAt-least-once; all consumers MUST be idempotent
DLQMandatory 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-Key header
  • 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

ConcernStandard
AuthNKeycloak OIDC; JWT validated at gateway (Kong) AND at service (zero-trust)
AuthZ — RBACKeycloak roles + service-level guards
AuthZ — ABACDelegated to Access Policy Service via POST /internal/access/evaluate; services MUST NOT embed role-checking logic
EncryptionTLS in transit; encryption at rest
SecretsManaged secret store; rotate per policy
AuditTamper-evident append-only audit log for PHI access, modifications, exports, break-glass
Consent/disclosurePolicy-driven; evaluated server-side; minimum-necessary and segmentation where configured
Rate limitingApplied 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: true in 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-on on 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_ACTIVE per service OpenAPI — some flows use HTTP 422 where documented (e.g. licensing assignment APIs).
  • HTTP module gating on REST/FHIR controllers uses ModuleEntitlementGuard in @ghasi/nestjs-common: unlicensed module → HTTP 403 with body code MODULE_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 (RTL fa-AF), Arabic (RTL ar-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

TargetValue
Page load< 2s p95
Search results< 1s
API response< 500ms p95
ScalingHorizontal for stateless services
AsyncIntegration ingestion, notifications, PDF/exports
RetryExponential backoff for adapters; graceful degradation
DRConfigurable 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.