> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# ↔ PM-07: Problem List → Encounter Diagnosis Pre-population — Integration

> CL-46 owns the longitudinal patient problem list (ICD-10-CM coded, status-managed: active, resolved, inactive, entered_in_error). Two downstream consumers depe…

**Feature ID:** CL-46 (publisher) ↔ PM-07 (subscriber)
**Status:** 📝 Planned (pending CL-46 Phase 1 + compliance review)
**Spec Reference:** [CL-46-problem-list-management-icd10.md](https://github.com/Encore-OS/encoreos/blob/development/specs/cl/specs/CL-46-problem-list-management-icd10.md)
**Last Updated:** 2026-05-12

***

## Table of Contents

* [Overview](#overview)
* [Quick Reference](#quick-reference)
* [Integration Points](#integration-points)
* [Event Contract: `cl_problem_list_updated`](#event-contract-cl_problem_list_updated)
* [Cross-Core Read API](#cross-core-read-api)
* [Security and RLS](#security-and-rls)
* [Idempotency, Retry, and Ordering](#idempotency-retry-and-ordering)
* [Failure Modes](#failure-modes)
* [Related Docs](#related-docs)

***

## Overview

CL-46 owns the longitudinal patient **problem list** (ICD-10-CM coded, status-managed: `active`, `resolved`, `inactive`, `entered_in_error`). Two downstream consumers depend on problem-list state:

1. **CL-08 (Clinical Decision Support)** — re-evaluates rules (drug-disease interactions, monitoring, quality-measure gaps) when active problems change.
2. **PM-07 (Encounter Diagnosis Capture / Charge Entry)** — pre-populates encounter diagnoses from the patient's active problem list at encounter creation/check-in, so coders/clinicians do not re-enter chronic conditions.

Integration is event-driven (Pattern 2) for write notifications and read-API (Pattern 1, via `@/platform/clinical`) for synchronous lookups. No direct core-to-core imports.

***

## Quick Reference

| Category            | Value                                                                                                                        |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Publisher**       | CL-46 (`cl_problems`)                                                                                                        |
| **Subscribers**     | CL-08 (CDS re-evaluation), PM-07 (encounter diagnosis pre-population)                                                        |
| **Event name**      | `cl_problem_list_updated`                                                                                                    |
| **Channel**         | `domain_events` (pg\_notify) + `fw_workflow_events` registry (PF-70/FW-16)                                                   |
| **Read API**        | `usePatientActiveProblems(patientId)` from `@/platform/clinical`                                                             |
| **Server helper**   | `cl_get_patient_active_problems(p_organization_id, p_patient_id)` (SECURITY DEFINER, `SET search_path = public, pg_catalog`) |
| **Idempotency key** | `problem_id + action + changed_at`                                                                                           |
| **PHI in payload**  | None — IDs and ICD-10 code only                                                                                              |
| **Cross-core FK**   | None (UUID-only reference; ADR-002 exception does not apply here)                                                            |

***

## Integration Points

| Dependency                | Pattern     | Purpose                                                                                            |
| ------------------------- | ----------- | -------------------------------------------------------------------------------------------------- |
| PF-70 (Code Libraries)    | API         | ICD-10-CM canonical lookup (`pf_icd10_codes`) for `icd10_display` resolution                       |
| PF-30 (Permissions)       | API         | `cl.problems.read` gate on `usePatientActiveProblems`                                              |
| CL-08 (CDS)               | Event       | Re-evaluates active rules on `cl_problem_list_updated`                                             |
| PM-07 (Encounter Charges) | Event + API | Subscribes to event for cache invalidation; calls read API on encounter create/check-in            |
| FW-16 (Workflow Events)   | API         | Event registered in `fw_workflow_events` so workflow designers can trigger on problem-list changes |

***

## Event Contract: `cl_problem_list_updated`

### Trigger

`AFTER INSERT OR UPDATE OF status, icd10_code, resolved_date OR DELETE` on `cl_problems`.

### Payload (JSONB)

```json theme={null}
{
  "event_type": "cl_problem_list_updated",
  "event_version": "1.0.0",
  "occurred_at": "2026-05-12T18:42:11.123Z",
  "organization_id": "uuid",
  "payload": {
    "patient_id": "uuid",
    "problem_id": "uuid",
    "icd10_code": "F33.1",
    "action": "added | status_changed | resolved | reactivated | corrected | removed",
    "previous_status": "active | resolved | inactive | entered_in_error | null",
    "new_status": "active | resolved | inactive | entered_in_error | null",
    "changed_by": "uuid",
    "changed_at": "2026-05-12T18:42:11.000Z"
  }
}
```

**No PHI in payload.** Patient name, DOB, narrative description are deliberately excluded; subscribers fetch via the read API under their own RLS context.

### Action mapping

| DB change                                                          | `action`                         |
| ------------------------------------------------------------------ | -------------------------------- |
| INSERT                                                             | `added`                          |
| UPDATE `status` active → resolved                                  | `resolved`                       |
| UPDATE `status` resolved/inactive → active                         | `reactivated`                    |
| UPDATE `status` \* → entered\_in\_error                            | `corrected`                      |
| UPDATE `icd10_code` (status unchanged)                             | `status_changed` (code revision) |
| DELETE (hard delete; rare — soft via `entered_in_error` preferred) | `removed`                        |

### Subscribers

| Subscriber | Action                                                                                                                                    |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| **CL-08**  | Invalidate `['cds-alerts', patient_id]`; re-run drug-disease and quality-measure rules                                                    |
| **PM-07**  | Invalidate `['encounter-diagnoses-suggestions', patient_id]`; if an in-progress encounter exists, surface a "problem list updated" banner |

***

## Cross-Core Read API

PM-07 (and any other consumer) MUST use the platform integration layer rather than querying `cl_problems` directly.

```ts theme={null}
// src/platform/clinical/index.ts (re-export)
export { usePatientActiveProblems } from '@/platform/clinical/hooks/usePatientActiveProblems';

// Consumer (PM-07 charge capture)
import { usePatientActiveProblems } from '@/platform/clinical';

const { data: problems, isLoading } = usePatientActiveProblems(patientId);
// problems: Array<{ problem_id, icd10_code, icd10_display, onset_date, priority }>
```

**Server-side / edge functions** call the SECURITY DEFINER helper:

```sql theme={null}
SELECT * FROM cl_get_patient_active_problems(p_organization_id := $1, p_patient_id := $2);
```

The helper enforces `pf_has_org_access(organization_id)` and the `cl.problems.read` permission, returns only `status = 'active'` rows, and orders by `priority ASC NULLS LAST, onset_date DESC`.

***

## Security and RLS

* `cl_problems` has RLS enabled with `FORCE ROW LEVEL SECURITY`; all CRUD policies scope by `organization_id` via `cl_user_has_problem_permission(action)`.
* Cross-core reads from PM-07 execute under the **calling user's** auth context — RLS still applies. The SECURITY DEFINER helper does not bypass tenant scoping; it only avoids the need for PM code to know CL table internals.
* Event payload contains no PHI; consumers MUST re-fetch via the read API to obtain ICD-10 display text or clinician description.
* Status state-machine enforcement (e.g., `entered_in_error` is terminal) is implemented in a `BEFORE UPDATE` trigger on `cl_problems`, not in the RLS `WITH CHECK` clause (which has no access to `OLD`).

***

## Idempotency, Retry, and Ordering

* **Idempotency key:** `problem_id || ':' || action || ':' || changed_at` (ISO-8601, millisecond precision). Subscribers MUST de-duplicate using this key for at least 24 h.
* **Ordering:** Not strictly guaranteed across the `domain_events` channel. Subscribers MUST treat events as state notifications (re-fetch on receipt) rather than authoritative deltas.
* **Retry:** PF event dispatcher retries with exponential backoff (per PF-70 event publishing standards). Failed deliveries land in the dead-letter queue after 5 attempts.
* **Backfill:** On subscriber outage recovery, consumers may call the read API to reconcile state; no replay of historical events is provided.

***

## Failure Modes

| Failure                                                 | Behavior                                                                                                                                      |
| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Event publish fails (pg\_notify error)                  | Logged via PF observability; the originating CL mutation still commits. Reconciliation via PM-07 calling the read API on next encounter open. |
| Subscriber RLS denial on read API                       | Hook returns empty array; PM-07 falls back to manual diagnosis entry; no PHI leak.                                                            |
| ICD-10 code not in PF-70                                | `icd10_display` returns the raw code; UI surfaces an "unmapped code" warning (non-blocking).                                                  |
| Race: encounter created milliseconds before problem add | PM-07 banner refresh on event receipt; coder can re-pull suggested diagnoses.                                                                 |

***

## Related Docs

* Spec: [CL-46-problem-list-management-icd10.md](https://github.com/Encore-OS/encoreos/blob/development/specs/cl/specs/CL-46-problem-list-management-icd10.md)
* Tasks: [CL-46-TASKS.md](https://github.com/Encore-OS/encoreos/blob/development/specs/cl/tasks/CL-46-TASKS.md)
* Event registry: [EVENT\_CONTRACTS.md](/architecture/integrations/EVENT_CONTRACTS) → `cl_problem_list_updated`
* Cross-core matrix: [CROSS\_CORE\_INTEGRATIONS.md](/architecture/integrations/CROSS_CORE_INTEGRATIONS) → CL-46 row
* CL-08 CDS: [CL-08-clinical-decision-support-INTEGRATION.md](/architecture/integrations/clinical-decision-support-integration)
* Platform integration patterns: [PLATFORM\_INTEGRATION\_LAYERS.md](/architecture/integrations/PLATFORM_INTEGRATION_LAYERS)
* ADR-002 (cross-core FK policy): [ADR-002-cl-pm-cross-core-foreign-keys.md](/architecture/decisions/ADR-002-cl-pm-cross-core-foreign-keys)
