specs/pm/specs/PM-01-EN-01-patient-merge-workflow.md
Companion (UI): specs/pm/specs/PM-01-EN-03-patient-merge-ui-workflow.md
Status: 📋 Specification — implementation pending
Last Updated: 2026-05-03
1. Purpose
PM-01-EN-01 introduces the canonical mechanism by which twopm_patients rows belonging to the same organization are consolidated into a single survivor record. This document captures the cross-core integration contract for that workflow:
- The same-transaction cross-core write into
cl_patient_charts.patient_id(CL). - The
pm_patient_mergeddomain event consumed by CL, PM-08, CE-29, and platform identity boundaries. - The PF-44 audit hook.
- Idempotency, retry, and ordering expectations for downstream consumers.
2. Pattern Selection
No other core directly imports PM code. All consumers use
@/platform/clinical, @/platform/scheduling, event subscriptions, or the published RPC.
3. Cross-Core Write Inventory (ADR-002 Exception)
The SECURITY DEFINER functionpm_merge_patients() performs the following CL-owned write inside the same transaction as the PM updates:
No other CL, FA, GR, RH, HR, or FW table is written by
pm_merge_patients(). Downstream side-effects (cache invalidation, claim re-grouping, lead reconciliation) are event-driven.
Drift detection: The migration MUST query information_schema.key_column_usage for every column whose foreign key target is pm_patients(id) and assert the resulting set equals the documented re-point list (PM tables) plus the documented CL exception. Any drift fails the migration. See specs/pm/specs/PM-01-EN-01-patient-merge-workflow.md § Re-pointed columns.
4. Event Contract — pm_patient_merged
- Channel:
pm_events - Schema version: 1
- Publisher:
pm_merge_patients()(SECURITY DEFINER) on successful commit path. - Subscribers (planned):
- CL — invalidate cached chart-by-patient lookups for
merged_patient_id. - PM-08 (Claims) — invalidate any in-memory grouping that keys on
merged_patient_id. - CE-29 (Lead Conversion) — re-point lead↔patient mapping where applicable.
- PF-71 (Patient Identity Boundary) — refresh identity caches.
- CL — invalidate cached chart-by-patient lookups for
- Idempotency key:
merge_log_id(UUID). - Delivery semantics: at-least-once.
- Ordering: per
survivor_patient_id. - PHI safety: payload contains UUIDs and
occurred_atonly — no demographics, nomerge_reason, no chart data. - No undo event in v1. Consumers MUST treat
pm_patient_mergedas best-effort and reconcile frompm_patient_merge_logwhenrolled_back_at IS NOT NULL. A futurepm_patient_merge_undoneevent may be added; until then, consumers that materialise long-lived projections SHOULD pollpm_patient_merge_logon a low-frequency cadence (≤ once perpatient_merge_undo_window_hours).
EVENT_CONTRACTS.md under PM-01-EN-01 — Patient Merge Events.
5. Audit Contract (PF-44)
Every successfulpm_merge_patients() call writes exactly one pf_audit_logs row with:
entity = 'pm_patients'action = 'merge'actor_id = p_actor_idmetadata = { survivor_patient_id, merged_patient_id, merge_log_id, organization_id }(no PHI; nomerge_reasonbody)
pm_undo_patient_merge() writes one additional row with action = 'merge_undo' and the same metadata shape plus rolled_back_by.
Both writes occur inside the same transaction as the data mutation.
6. Consumer Obligations
Subscribers ofpm_patient_merged MUST:
- Validate
organization_idagainst their own tenant context before applying any side effect. - Treat the event as idempotent — multiple deliveries for the same
merge_log_idMUST be no-ops after the first. - Reconcile against
pm_patient_merge_log(filtering byrolled_back_at IS NULL) when in doubt. - NOT cache
merge_reasonor any derived demographic data. - NOT block patient operations on event delivery — the source-of-truth is the PM database state at commit.
7. Failure Modes
8. Open Items
- 42 CFR Part 2 acknowledgement step for SUD-bearing merges — deferred to a future EN; tracked in CL-11 follow-ups.
pm_patient_merge_undoneevent — deferred. Consumer reconciliation guidance is documented above.- Bulk merge / auto-merge — explicitly out of scope (safety).
9. References
- Spec:
specs/pm/specs/PM-01-EN-01-patient-merge-workflow.md - Plan:
specs/pm/plans/PM-01-EN-01-patient-merge-workflow-PLAN.md - Tasks:
specs/pm/tasks/PM-01-EN-01-TASKS.md - Context:
specs/pm/specs/PM-01-EN-01-CONTEXT.md - Companion (UI):
specs/pm/specs/PM-01-EN-03-patient-merge-ui-workflow.md - ADR-002:
docs/architecture/decisions/ADR-002-cl-pm-cross-core-foreign-keys.md - Event contracts:
EVENT_CONTRACTS.md— PM-01-EN-01 Patient Merge Events - Cross-core overview:
CROSS_CORE_INTEGRATIONS.md