Skip to main content

Registration Service — Application Logic

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

1. Commands (write use cases)

Use CaseCommand DTOPorts touchedEmits event
RegisterPatientUseCaseRegisterPatientCommandPatientRepository, MpiPort, EventPublisher, AuditClient, IdempotencyStorepatient.created
UpdatePatientUseCaseUpdatePatientCommandPatientRepository, EventPublisher, AuditClientpatient.updated
RecordVitalStatusUseCaseRecordVitalStatusCommandPatientRepository, EventPublisher, AuditClientpatient.vital-status-changed, patient.updated
MergePatientUseCaseMergePatientCommandPatientRepository, EventPublisher, AuditClientpatient.merged
UnmergePatientUseCaseUnmergePatientCommandPatientRepository, EventPublisher, AuditClientpatient.unmerged
RegisterEncounterUseCaseRegisterEncounterCommandEncounterRepository, PatientRepository, EventPublisher, AuditClientencounter.registered
TransitionEncounterStatusUseCaseTransitionEncounterStatusCommandEncounterRepository, EventPublisher, AuditClientencounter.status-changed
UploadPortraitUseCaseUploadPortraitCommandPatientRepository, PortraitStore, AuditClient
SaveExtensionInstanceUseCaseSaveExtensionInstanceCommandPatientRepository, ExtensionSchemaRegistry, AuditClient

2. Queries (read use cases)

Use CaseQuery DTONotes
SearchPatientsUseCaseSearchPatientsQueryMinimum-necessary criteria enforced; break-glass header audited
GetPatientByIdUseCaseGetPatientQueryOptional includeIncomingRelatedLinks
GetUnidentifiedReconciliationQueueUseCaseUnidentifiedQueueQueryOptional SLA breach filter
GetPatientForecastUseCaseDelegated to immunization-service; not owned here
GetEncounterUseCaseGetEncounterQuery
ListEncountersUseCaseListEncountersQueryFilter by patientId, status
GetPortraitUseCaseGetPortraitQueryReturns raw bytes; consent/retention check
GetPortraitHistoryUseCaseMetadata list newest-first
GetExtensionInstancesUseCaseGetExtensionsQueryPrivacy masking applied by role
GetKinRelationshipCodesUseCaseCatalog read

3. Orchestration Flows

3.1 Patient Registration Flow

3.2 Merge Flow

3.3 Encounter Status Transition Flow

4. Ports (Interfaces)

PortDirectionDescription
PatientRepositoryOutboundCRUD + search + MRN generation for patients
EncounterRepositoryOutboundCRUD for encounters
MpiPortOutboundProbabilistic duplicate scoring
EventPublisherOutboundNATS JetStream CloudEvents publication
AuditClientOutboundEmit structured audit events
IdempotencyStoreOutboundCache idempotency key → response (Redis TTL 24h)
PortraitStoreOutboundBinary media storage (object store)
ExtensionSchemaRegistryOutboundRetrieve and validate active JSON Schemas for bundles
KinRelationshipCatalogOutboundRead relationship codes from kin_relationship_types

5. Outbox / Saga Patterns

PatternWhere usedDetails
OutboxAll event-emitting use casesEvents written to outbox table in same DB transaction; relay publishes to NATS
Idempotent createRegisterPatientUseCaseIdempotency-Key / clientMutationId cached for 24h in Redis
Optimistic lockPatient + Encounter mutationsversion field incremented on save; 409 on mismatch
Fail-open CDSNot applicable (CDS owned by orders-service)

6. Error Handling

Error codeHTTPWhen
DUPLICATE_DETECTED409MPI ≥ 85 on normal create
IDENTIFIER_ALREADY_ASSIGNED409Same (system, value) exists on another patient
DUPLICATE_IDENTIFIER_IN_REQUEST400Duplicate (system, value) within one payload
INVALID_NATIONAL_IDENTIFIER400National ID fails digit-length validation
MISSING_MANDATORY_FIELD400Tenant required field list not satisfied
PATIENT_NOT_FOUND404Patient missing or cross-tenant
ENCOUNTER_NOT_FOUND404Encounter missing or cross-tenant
OPTIMISTIC_LOCK_CONFLICT409version mismatch
INVALID_STATUS_TRANSITION409Encounter transition not in allowed graph
MERGE_SELF409Survivor equals source
UNMERGE_DISABLED_BY_POLICY403REGISTRATION_UNMERGE_ENABLED not true
UNMERGE_INVALID_STATE400Source not recorded as merged into this survivor
PORTRAIT_CONSENT_REQUIRED400Policy requires consent; consentGiven false
EXTENSION_PAYLOAD_INVALID400JSON Schema validation failure
PATIENT_SEARCH_INSUFFICIENT_CRITERIA400Minimum-necessary criteria not met
RELATIONSHIP_CODE_INVALID400NOK relationship code not in catalog