Skip to main content

Registration Service — User Stories

Service: registration-service Story prefix: REG-US Last updated: 2026-04-17

Stories

REG-US-001 — Register patient with demographics and identifiers

FieldValue
Issue typeStory
SummaryRegister patient with mandatory demographics and multiple identifiers
Epic linkREG-EPIC-01
StatusTo Do
PriorityMust
Story points5
Labelsservice:registration, type:backend, type:api, slice:S0
Componentspatients, identifiers
FR referencesFR-REG-001, FR-REG-002
Legacy FR refsFR-REG-001, FR-REG-002 (ADMIN-REG v2.1)
Dependencies

User story: As a front-desk registrar, when a new patient presents, I want to create a patient record with required demographics and multiple identifiers so that a unique, searchable identity exists in the system.

Acceptance criteria (Gherkin):

  • Given tenant required fields are configured, when a create request omits a required field, then the API returns 400 MISSING_MANDATORY_FIELD with the field name.
  • Given a valid demographic payload with two identifiers (NID and MRN), when the patient is created, then all identifiers are persisted and returned with correct system values.
  • Given a duplicate system+value identifier already exists on another patient, when a create is attempted, then 409 IDENTIFIER_ALREADY_ASSIGNED is returned.

Technical notes:

  • POST /api/v1/patients with identifiers[]
  • Identifier uniqueness enforced at DB level via unique index ix_patient_identifiers_tenant_system_value
  • MRN generated server-side PAT-{tenantCode}-{timestamp}

Definition of Done:

  • Unit + integration tests added; coverage ≥ thresholds in DEFINITION_OF_DONE.md.
  • OpenAPI contract updated; Pact consumer tests green.
  • Event schema registered; schema conformance test green.
  • Telemetry spans/metrics added.
  • Documentation updated in relevant 17 docs.

REG-US-002 — Create and transition encounter registration

FieldValue
Issue typeStory
SummaryRegister encounter and transition status through visit lifecycle
Epic linkREG-EPIC-01
StatusTo Do
PriorityMust
Story points3
Labelsservice:registration, type:backend, type:api, slice:S0
Componentsencounters
FR referencesFR-REG-008
Legacy FR refsFR-REG-008 (ADMIN-REG v2.1)
DependenciesREG-US-001

User story: As a front-desk registrar, when a patient arrives, I want to create an encounter and transition its status so that clinical staff have accurate visit context.

Acceptance criteria (Gherkin):

  • Given a valid patient and facility, when an encounter is created, then status is planned and encounter.registered event is emitted.
  • Given a planned encounter, when PATCH /status is called with arrived, then status updates and encounter.status-changed is emitted.
  • Given an encounter in finished state, when a status transition is attempted, then 409 INVALID_STATUS_TRANSITION is returned.

Technical notes:

  • POST /api/v1/encounters, PATCH /api/v1/encounters/:id/status
  • Optimistic lock version required on PATCH

Definition of Done:

  • Unit + integration tests added; coverage ≥ thresholds.
  • OpenAPI contract updated.
  • Event schema conformance test green.
  • Telemetry spans added.

REG-US-010 — Duplicate detection feedback on patient create

FieldValue
Issue typeStory
SummarySurface MPI duplicate score and block likely duplicates on create
Epic linkREG-EPIC-02
StatusTo Do
PriorityMust
Story points5
Labelsservice:registration, type:backend, slice:S0
ComponentsMPI
FR referencesFR-REG-004
Legacy FR refsFR-REG-004 (ADMIN-REG v2.1)
DependenciesREG-US-001

User story: As a registrar, when creating a new patient, I want the system to detect probable duplicates so that I avoid creating split-identity records.

Acceptance criteria (Gherkin):

  • Given a patient with same name + DOB already exists, when a create is attempted, then MPI scores the candidate and if score ≥ 85, returns 409 DUPLICATE_DETECTED with match list.
  • Given the create is blocked, when the event is published, then REGISTRATION.patient.duplicate-detected includes matches[] with id, mrn, score.
  • Given isUnidentified=true, when MPI score ≥ 85, then the patient is still created and patient.unidentified-duplicate-review is published instead of a 409.

Technical notes:

  • MPI scoring configurable thresholds; default probable = 85
  • pg_trgm + birth-date narrowing for candidate set

Definition of Done:

  • Unit tests for MPI scoring logic; integration test for 409 path.
  • Contract test for patient.duplicate-detected schema.
  • Coverage ≥ 90% on MPI module.

REG-US-011 — Governed patient merge with survivorship rules

FieldValue
Issue typeStory
SummaryMerge duplicate patients with survivorship rules and audit trail
Epic linkREG-EPIC-02
StatusTo Do
PriorityMust
Story points8
Labelsservice:registration, type:backend, slice:S0
Componentsmerge, audit
FR referencesFR-REG-005, FR-REG-021
Legacy FR refsFR-REG-005, FR-REG-021 (ADMIN-REG v2.1)
DependenciesREG-US-010

User story: As a supervisor, when duplicate patients are confirmed, I want to merge them with documented survivorship rules so that a single authoritative identity is maintained.

Acceptance criteria (Gherkin):

  • Given a supervisor role, when merge is requested, then source is deactivated, identifiers transferred to survivor, NOK relatedPatientId repointed, and patient.merged event emitted.
  • Given merge action is completed, then audit record includes actorId, survivorId, sourceId, and mergeReason.
  • Given REGISTRATION_UNMERGE_ENABLED=false, when unmerge is requested, then 403 UNMERGE_DISABLED_BY_POLICY is returned.

Technical notes:

  • POST /api/v1/patients/:survivorId/merge
  • POST /api/v1/patients/:survivorId/unmerge (if enabled)
  • BR-REG-005/006: provisional/unidentified confirmations required

Definition of Done:

  • Integration test covers merge + source deactivation + identifier transfer.
  • Mandatory: test/integration/outbox.integration.spec.ts includes merge event.
  • Audit event verified in audit-service contract test.

REG-US-020 — Minimum-necessary patient search with break-glass

FieldValue
Issue typeStory
SummaryEnforce minimum-necessary criteria on patient search with audited break-glass
Epic linkREG-EPIC-03
StatusTo Do
PriorityMust
Story points3
Labelsservice:registration, type:backend, type:api, slice:S0
Componentssearch, audit
FR referencesFR-REG-003, FR-REG-022
Legacy FR refsFR-REG-003, FR-REG-022 (ADMIN-REG v2.1)
DependenciesREG-US-001

User story: As a registration clerk, when searching for patients, I want minimum-necessary criteria enforced so that broad identity disclosure is prevented.

Acceptance criteria (Gherkin):

  • Given only a single-character name query, when search is called without other criteria, then 400 PATIENT_SEARCH_INSUFFICIENT_CRITERIA is returned.
  • Given a valid MRN, when search is called, then results are returned without additional criteria required.
  • Given X-Ghasi-Break-Glass-Reason header present, when search executes, then audit event includes detail.breakGlass.reason.

Technical notes:

  • GET /api/v1/patients?q=&birthDate=&...
  • Strong criterion (patientId, mrn, identifier) bypasses weak-factor check

Definition of Done:

  • Unit tests for all criteria combinations.
  • Break-glass audit verified in integration test.

REG-US-030 — Multi-script names and preferred language capture

FieldValue
Issue typeStory
SummaryCapture multi-script names and locale-aware preferred language
Epic linkREG-EPIC-04
StatusTo Do
PriorityMust
Story points3
Labelsservice:registration, type:backend, slice:S0
Componentsnames, i18n
FR referencesFR-REG-009, FR-REG-013, FR-REG-014
Legacy FR refsFR-REG-009, FR-REG-013, FR-REG-014 (ADMIN-REG v2.1)
DependenciesREG-US-001

User story: As a registrar, when capturing a patient's name and language preference, I want multi-script support and RTL text direction hints so that records match local usage.

Acceptance criteria (Gherkin):

  • Given a patient with both fa-af and latn name rows, when retrieved, then both are returned with correct textDirection (rtl / ltr).
  • Given preferredLang: "fa-af", when set and retrieved, then value is stored and returned.
  • Given an invalid preferredLang value, when submitted, then 400 is returned.

Technical notes:

  • names[].scripttextDirection derived server-side
  • preferredLang validated against allowed language set

Definition of Done:

  • Unit tests for direction derivation, language validation.
  • OpenAPI schema updated with script + textDirection examples.

REG-US-040 — Record and correct deceased vital status

FieldValue
Issue typeStory
SummaryRecord patient deceased status with RBAC, correction, and audit
Epic linkREG-EPIC-05
StatusTo Do
PriorityMust
Story points5
Labelsservice:registration, type:backend, slice:S1
Componentsvital-status
FR referencesFR-REG-016
Legacy FR refsFR-REG-016 (ADMIN-REG v2.1)
DependenciesREG-US-001

User story: As an authorized clinician, when recording a patient's death, I want controlled deceased status recording and correction so that the legal identity status is accurate and auditable.

Acceptance criteria (Gherkin):

  • Given a physician role with patient_record:record_vital_status, when deceased is set to true with deceasedDateTime, then both fields are persisted and vital-status-changed event is emitted.
  • Given a front-desk role (no vital status permission), when the endpoint is called, then 403 is returned.
  • Given an existing deceased record is corrected, when PATCH /vital-status is called again, then isCorrection: true in the event and prior state is stored in patient_vital_status_corrections.

Technical notes:

  • PATCH /api/v1/patients/:id/vital-status
  • Requires patient_record:record_vital_status catalog key

Definition of Done:

  • Unit tests for authorization check, state change, and correction path.
  • Integration test verifies audit record and correction table entry.

REG-US-041 — Provisional and newborn registration workflows

FieldValue
Issue typeStory
SummaryRegister provisional (emergency) and newborn patients with reconciliation paths
Epic linkREG-EPIC-05
StatusTo Do
PriorityMust
Story points8
Labelsservice:registration, type:backend, slice:S1
Componentsprovisional, newborn, reconciliation
FR referencesFR-REG-017, FR-REG-018
Legacy FR refsFR-REG-017, FR-REG-018 (ADMIN-REG v2.1)
DependenciesREG-US-001, REG-US-011

User story: As an emergency or maternity registrar, when identity is incomplete, I want provisional and newborn workflows so that care can begin safely before full identity is confirmed.

Acceptance criteria (Gherkin):

  • Given isProvisional: true, when patient is created, then provisional record is created and isProvisional flag is returned.
  • Given a provisional patient, when merge is called with confirmProvisionalMerge: true, then provisional flag is cleared on survivor.
  • Given isNewborn: true with newbornLinkedPatientId pointing to mother, then linkage is persisted and returned in patient response.

Technical notes:

  • POST /api/v1/patients with isProvisional / isNewborn flags
  • Reconciliation via POST /v1/patients/:survivorId/merge with appropriate confirm flags

Definition of Done:

  • Integration tests cover provisional create + reconciliation merge + newborn linkage.
  • Unit tests for flag mutual-exclusivity invariant.

REG-US-050 — Unidentified patient intake and reconciliation queue

FieldValue
Issue typeStory
SummaryRegister unidentified patients with enterprise key and SLA reminders
Epic linkREG-EPIC-06
StatusTo Do
PriorityMust
Story points8
Labelsservice:registration, type:backend, slice:S3
Componentsunidentified, reconciliation-queue
FR referencesFR-REG-023
Legacy FR refsREG-NAT-US-010, REG-NAT-US-011
DependenciesREG-US-041

User story: As an emergency registrar, when an unconscious or unidentified patient arrives, I want to create a minimal record immediately so that care can proceed while a reconciliation queue reminds staff to confirm identity.

Acceptance criteria (Gherkin):

  • Given isUnidentified: true with intakeContext, when created, then temporaryEnterpriseKey is returned and patient.created includes it.
  • Given REGISTRATION_UNIDENTIFIED_SLA_DAYS=7, when record created, then unidentifiedSlaDueAt is set 7 days in future.
  • Given GET /v1/patients/unidentified-reconciliation?slaBreachedOnly=true, then only records past unidentifiedSlaDueAt are returned.

Technical notes:

  • Temporary enterprise key format: UNK-{tenantCode}-{timestamp}-{random8}
  • MPI score ≥ 85 does NOT block unidentified create — emits unidentified-duplicate-review instead

Definition of Done:

  • Unit tests for enterprise key generation, SLA calculation.
  • Integration test for reconciliation queue endpoint.
  • Contract test for unidentified-duplicate-review schema.

REG-US-060 — Idempotent patient create for offline-first retries

FieldValue
Issue typeStory
SummarySupport idempotent patient create for safe offline-first retries
Epic linkREG-EPIC-07
StatusTo Do
PriorityMust
Story points3
Labelsservice:registration, type:backend, slice:S0
Componentsidempotency
FR referencesNFR-REG-004
Legacy FR refsNFR-REG-004 (ADMIN-REG v2.1)
DependenciesREG-US-001

User story: As a platform engineer, when a mobile client retries a patient create after a network failure, I want idempotent create semantics so that duplicate records are not created.

Acceptance criteria (Gherkin):

  • Given a request with Idempotency-Key: abc123, when the same key is submitted twice within 24h, then the second call returns the same 201 body without creating a duplicate patient.
  • Given a different Idempotency-Key, when submitted, then a new patient is created normally.

Technical notes:

  • Idempotency key stored in Redis with 24h TTL
  • Key scoped by (tenantId, key)

Definition of Done:

  • Integration test for key replay path.
  • Integration test for cache expiry (mock time).
  • Coverage ≥ 80%.