Patient
Patient migrations own organization-scoped profile storage, MRN counters and retry records. The shared patient domain in pkg/types owns demographics, validation, contact normalization and profile changes. Doctor owns portal HTTP routes and implements the shared PatientService port in its internal/services package, using its own persistence adapters.
The four implemented endpoints are POST /api/v1/doctors/patients, GET /api/v1/doctors/patients, GET /api/v1/doctors/patients/{patientId} and PATCH /api/v1/doctors/patients/{patientId}. The former /api/v1/patients CRUD routes and /api/patients aliases are unregistered. See the Doctor patient workflow for requests, affiliation scoping and service wiring.
Each registration belongs to one organization, with a distinct patient UUID and organization-local MRN. Email/phone are non-unique, including within an organization. Separate organizations may register the same person and may each assign P-000001. Contacts never create an Identity account or establish patient access.
The Patient module retains PatientCreator, PatientLister, PatientReader and PatientPatcher for existing internal consumers and aliases its public data models to the shared patient domain. Doctor endpoints use the shared PatientService directly and do not call these legacy capabilities. Doctor patient operations require the exact active professional affiliation, with no role or permission checks.
Apply the append-only Patient migration through go run ./tools/cli database migrate --service patient after Organization migrations, or migrate all services. Patient uses its own goose_patient_version table. Profiles, MRN counters and retry records are included in development cleanup. Writes append patient.created or patient.updated in the same transaction. No event bus or notification delivery is required.
A profile requires name, free-text age and sex (male, female, other, unknown). Age accepts arbitrary nonblank text without parsing numbers or units; the server tracks age_recorded_at. Email, phone, blood group and a single address string are optional. Address supports multiple lines and up to 1,000 Unicode characters. Birth date, allergies and chronic conditions are removed from the profile contract. Email comparison follows Identity's trimmed full-address lowercase policy; display spelling is retained. Phone validation uses nyaruka/phonenumbers, with default region BD and E.164 canonical storage. Verification and patient self-account connections remain Phase 2 work and have no registered routes.
Migration 00002_simplify_patient_profiles.sql requires an empty patient table, matching the confirmed absence of existing patients. Both upgrade and downgrade stop if profiles exist, before removing columns. No patient data is deleted automatically. Apply through the normal CLI migration workflow before running the updated API.
See the search measurement for representative query plans and their limits.