Ghasi e-Prescribing Gateway Service — Domain Model
Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 03 platform-services · 02 DDD
Aggregates
PrescriptionRecord (Root Aggregate)
Represents the gateway's authoritative interop copy of a MedicationRequest. The EHR is the clinical author; the gateway mediates and persists the interop copy.
Invariants:
tenantIdis extracted from JWT — never client-supplied.prescriberIdmust be a valid EHR actor (enforced byehr-backendpersona scope).- Status transitions strictly follow the FHIR MedicationRequest state machine.
- ETag is issued on create and required on update (
If-Match); stale writes return412. - Idempotent create: same
Idempotency-Key+ payload fingerprint → same resource ID, no duplicate. - A
MedicationDispensecannot reference aprescriptionIdunknown to this tenant (BR-RX-001).
FHIR resource: MedicationRequest
Status state machine:
DispenseRecord (Root Aggregate)
Represents the gateway's interop copy of a MedicationDispense. The Pharmacy is the author.
Invariants:
- Must reference a known
PrescriptionRecordfor the same tenant (BR-RX-001). - Only
pharmacy-backendpersona may create. - ETag issued;
If-Matchrequired on update. - Partial fills allowed when tenant policy permits;
quantity.value < prescribed.quantity.value.
FHIR resource: MedicationDispense
SubscriptionChannel (Aggregate)
Represents a registered HTTPS notification channel for a consumer (EHR or Pharmacy per tenant).
Invariants:
- Must have a valid
endpointUrl(HTTPS, verified on registration). - Signing key pair rotates per tenant policy.
- Cursor tracks last delivered event sequence; replay from cursor on reconnect.
FHIR resource: Subscription
WorkflowTask (Aggregate)
Represents a renewal or clarification task (P1+).
FHIR resource: Task
Invariants:
requesteris the pharmacy or patient proxy.owneris the prescriber queue (EHR).- Terminal states:
completed,rejected,cancelled.
Domain Events
| Event type (NATS subject) | Version | Trigger |
|---|---|---|
eprescribing.medication_request.created.v1 | v1 | MR successfully persisted and routed |
eprescribing.medication_request.updated.v1 | v1 | MR status changed or revised |
eprescribing.medication_request.cancelled.v1 | v1 | MR cancelled by EHR actor |
eprescribing.medication_dispense.created.v1 | v1 | MD accepted by gateway |
eprescribing.medication_dispense.updated.v1 | v1 | MD status/quantity updated |
eprescribing.task.status_changed.v1 | v1 | Renewal/clarification task state change (P1) |
eprescribing.subscription.delivery_failed.v1 | v1 | After retry exhaustion → DLQ |
eprescribing.subscription.replayed.v1 | v1 | Manual replay triggered |
Value Objects
| Value object | Description |
|---|---|
PrescriptionBusinessId | Platform-issued correlation ID spanning EHR–Gateway–Pharmacy; format prx_<ULID> |
ETag | Opaque version token; format W/"<sha256-of-resource>" |
IdempotencyKey | Client-supplied string + payload fingerprint hash |
TenantId | Branded string Branded<string, 'TenantId'> |
PrescriptionRecordId | ULID with prefix mr_ |
DispenseRecordId | ULID with prefix md_ |
SubscriptionId | ULID with prefix sub_ |
WorkflowTaskId | ULID with prefix wtk_ |
RoutingEnvelope | { targetOrgId, targetEndpointId, region, fallbackEndpointId? } |
ValidationOutcome | { valid: boolean, issues: OperationOutcomeIssue[] } |
PersonaType | enum { ehr_backend, pharmacy_backend, b2b_external } |
Ubiquitous Language
| Term | Definition |
|---|---|
| Gateway | The ghasi-eprescribing-gateway-service as a platform component |
| PrescriptionRecord | Gateway's authoritative interop copy of a MedicationRequest |
| DispenseRecord | Gateway's interop copy of a MedicationDispense |
| Prescription business ID | Platform-level correlation identifier (prx_) spanning all systems |
| ETag | Opaque concurrency token issued per resource version; required on updates |
| Idempotency-Key | Client-supplied header to deduplicate creates on retry |
| IG package | FHIR Implementation Guide package (StructureDefinition + ValueSets) pinned per tenant |
| Subscription | FHIR R4 Subscription: durable HTTPS notification channel |
| DLQ | Dead-letter queue for failed notification deliveries |
| Persona type | ehr_backend, pharmacy_backend, or b2b_external — dictates which resources the actor may write |
| Routing envelope | Resolved pharmacy target (Organization + Endpoint) for a prescription |
| Store-and-forward | Offline-tolerant mode: gateway accepts and queues prescriptions when pharmacy endpoint is unreachable |