> ## 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.

# Medical Terminology & Code Libraries — Integration

> Feature ID: PF-70 Status: ✅ Complete Spec Reference: PF-70-medical-terminology-code-libraries.md Last Updated: 2026-02-27 Last Verified: 2026-02-27

**Feature ID:** PF-70\
**Status:** ✅ Complete\
**Spec Reference:** [PF-70-medical-terminology-code-libraries.md](../../../specs/pf/specs/PF-70-medical-terminology-code-libraries.md)\
**Last Updated:** 2026-02-27\
**Last Verified:** 2026-02-27

***

## Overview

PF-70 provides a centralized code library (ICD-10-CM, CPT, HCPCS, modifiers) with type-ahead search, favorites/recently used, effective-date-aware validation, and optional payer-specific rules. CL and PM cores consume this via the platform layer (`@/platform/codes`) for diagnosis (problem list, progress notes, SDOH), procedure (charge capture, claims), and modifier validation.

***

## Quick Reference

| Item                     | Value                                                                                                                                                                       |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Platform layer           | `@/platform/codes`                                                                                                                                                          |
| Core tables              | `pf_code_sets`, `pf_icd10_codes`, `pf_cpt_codes`, `pf_hcpcs_codes`, `pf_code_modifiers`, `pf_code_crosswalks`, `pf_payer_code_rules`, `pf_code_favorites`, `pf_code_recent` |
| Key dependencies         | PF-01, PF-02                                                                                                                                                                |
| Consumed by              | CL-01, CL-04, CL-06, CL-08, CL-18, CL-19, PM-07, PM-08                                                                                                                      |
| Permissions              | `pf.codes.read`, `pf.codes.admin`                                                                                                                                           |
| SECURITY DEFINER helpers | `pf_can_read_code_set(p_code_set_id UUID)`, `pf_can_manage_org_codes(p_organization_id UUID)`                                                                               |

***

## Integration Points (from Spec)

| Consumer | Usage                                                                                                                                                                                                                 | Phase Available                  |
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| CL-01    | Problem list ICD-10-CM lookup from PF-70                                                                                                                                                                              | Phase 2                          |
| CL-04    | Diagnosis codes and CPT for progress notes                                                                                                                                                                            | Phase 2                          |
| CL-06    | NDC for prescriptions (deferred; table TBD or external)                                                                                                                                                               | Future phase                     |
| CL-08    | ICD-10-CM, CPT, HCPCS, and LOINC codes for CDS rule conditions and display (e.g. lab LOINC in monitoring rules). **⚠️ LOINC deferred to future phase — CL-08 partially blocked until LOINC table is added to PF-70.** | Phase 2 (partial; LOINC blocked) |
| CL-18    | Z-codes (Z55–Z65) for SDOH                                                                                                                                                                                            | Phase 2                          |
| CL-19    | HCPCS H0038, H2017 for peer services                                                                                                                                                                                  | Phase 2                          |
| PM-07    | CPT/HCPCS and modifiers for charge capture                                                                                                                                                                            | Phase 2                          |
| PM-08    | Code validation for claims (pre-submission scrubbing via `validateCode()`)                                                                                                                                            | Phase 2                          |

***

## API / Data Contracts

### Search API — `useCodeSearch` / `searchCodes`

**Import:** `import { useCodeSearch } from '@/platform/codes';`

**Parameters:**

| Param            | Type                                       | Required | Description                                             |
| ---------------- | ------------------------------------------ | -------- | ------------------------------------------------------- |
| `codeSet`        | `'ICD10CM' \| 'CPT' \| 'HCPCS' \| 'LOINC'` | Yes      | Code set to search (single set per request in Phase 1)  |
| `query`          | `string`                                   | Yes      | Min 2 chars; matches code prefix OR description         |
| `effectiveDate`  | `string` (ISO date)                        | No       | Default: today. Filters to codes effective on this date |
| `bhOnly`         | `boolean`                                  | No       | Filter to `is_behavioral_health = true` codes only      |
| `organizationId` | `string`                                   | Yes      | Tenant isolation; included in query key                 |

**Response:** Array of `CodeSearchResult`:

```typescript theme={null}
{
  id: string;               // Row UUID for stable references
  code: string;
  description: string;
  code_set: string;          // e.g. 'ICD10CM', 'CPT', 'HCPCS'
  effective_from: string;
  effective_to: string | null;
  is_behavioral_health: boolean;
  is_sdoh?: boolean;
}
```

**Constraints:**

* **Result limit:** Cap at **25 results** per request.
* **Min query length:** 2 characters. Returns empty array (not error) when `query.length < 2`.
* **Debounce recommendation:** Consuming UIs should debounce search input by **300 ms** before calling the search API.
* **Single code set per request** in Phase 1. Multi-set search is deferred.

**LOINC note:** If `codeSet='LOINC'`, returns empty array with `{ loinc_unavailable: true }` metadata until a future phase adds the LOINC table. Do not throw an error.

### Validation API — `validateCode`

**Import:** `import { validateCode } from '@/platform/codes';`

**Parameters:**

| Param            | Type                | Required | Description                                                                                                                    |
| ---------------- | ------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `code`           | `string`            | Yes      | Code to validate                                                                                                               |
| `codeSet`        | `string`            | Yes      | Code set (ICD10CM, CPT, HCPCS)                                                                                                 |
| `modifiers`      | `string[]`          | No       | Modifiers to validate against pf\_code\_modifiers                                                                              |
| `serviceDate`    | `string` (ISO date) | Yes      | Date to validate effective range                                                                                               |
| `payerId`        | `string` (UUID)     | No       | Optional; used to look up pf\_payer\_code\_rules. When null, only global rules (`payer_id IS NULL`) and org-level rules apply. |
| `organizationId` | `string`            | Yes      | Tenant isolation                                                                                                               |

**Response:** `{ valid: boolean; errors?: string[] }` — errors are sanitized user-facing messages. Never exposes raw DB errors.

**Validation error message examples:**

| Scenario                           | User-facing message                             |
| ---------------------------------- | ----------------------------------------------- |
| Code not effective on service date | "Code is not effective for the service date."   |
| Invalid modifier for code set      | "Modifier \[X] is not valid for this code set." |
| Payer rule violation               | "Code does not meet payer requirements."        |
| Generic / unexpected               | "Something went wrong. Please try again."       |

**Scope:** Single-code validation in Phase 1. Batch validation (multiple lines in one request) is deferred.

### Favorites / Recently Used

**Import:** `import { useCodeFavorites, useCodeRecent } from '@/platform/codes';`

Per user + org; stored in `pf_code_favorites` and `pf_code_recent` tables. API to get/add/remove per user.

**`useCodeFavorites(organizationId)`** returns:

* `favorites: CodeSearchResult[]` — ordered by most recently added
* `addFavorite(code, codeSet, description): Promise<void>`
* `removeFavorite(code, codeSet): Promise<void>`
* `isLoading: boolean`

No hard cap on favorites in Phase 1.

**`useCodeRecent(organizationId)`** returns:

* `recent: CodeSearchResult[]` — ordered by `used_at DESC`, max **50 entries**
* `recordUsage(code, codeSet, description): Promise<void>` — upserts on the unique key `(user_id, organization_id, code_set, code)`, updating `used_at`. Excess rows beyond 50 are cleaned up after upsert.
* `isLoading: boolean`

***

## Consuming UI Guidance

PF-70 has no dedicated UI. Consuming features (CL/PM) own their code pickers (combobox, dialog, etc.). The following recommendations ensure consistent behavior across the product.

### Loading and Empty States

| Context                      | Recommendation                                                                                                         |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Search loading               | Show **skeleton rows** (3–5 lines) in dropdown/list. Never `return null`.                                              |
| No results (query ≥ 2 chars) | Display: **"No codes match your search."** Optionally add "Try a different term or code set."                          |
| Query too short (\< 2 chars) | Display: **"Type at least 2 characters to search."**                                                                   |
| API / network error          | Use `sanitizeErrorMessage(error)` and show in toast or inline. Prefer toast + retry. Never expose raw `error.message`. |
| LOINC unsupported            | (Optional) "LOINC codes are not available in this environment yet."                                                    |

### Layout

* **Code picker list:** Compact list — code (bold) + description (secondary) on one line. Use semantic tokens only.
* **Effective date:** Show in results only if the consuming feature needs it (admin/audit views). For typical clinician/billing type-ahead, code + description is sufficient.

***

### Code Examples

```tsx theme={null}
// CL-01 Problem List — ICD-10-CM type-ahead search
import { useCodeSearch } from '@/platform/codes';

function DiagnosisSearchField({ organizationId }: { organizationId: string }) {
  const [query, setQuery] = useState('');
  const { results, isLoading } = useCodeSearch({
    codeSet: 'ICD10CM',
    query,
    bhOnly: true,           // behavioral health context
    organizationId,
  });
  // render results in a combobox...
}
```

```typescript theme={null}
// PM-08 Claims — validate a code+modifier before submission
import { validateCode } from '@/platform/codes';

const result = await validateCode({
  code: '90837',
  codeSet: 'CPT',
  modifiers: ['GT'],
  serviceDate: '2025-11-01',
  payerId: payerUuid,
  organizationId,
});
if (!result.valid) {
  toast.error(result.errors?.[0] ?? 'Code validation failed.');
}
```

***

## RLS Architecture

| Table                                              | Scope                     | SELECT Policy                                                               | Mutation Policy                          |
| -------------------------------------------------- | ------------------------- | --------------------------------------------------------------------------- | ---------------------------------------- |
| `pf_code_sets`                                     | Platform (org NULL) + org | `organization_id IS NULL OR pf_has_org_access(organization_id, auth.uid())` | Admin only via `pf_can_manage_org_codes` |
| `pf_icd10_codes`, `pf_cpt_codes`, `pf_hcpcs_codes` | Via code\_set             | `pf_can_read_code_set(code_set_id)`                                         | Admin only                               |
| `pf_code_crosswalks`                               | Platform-managed only     | `TRUE` (all authenticated) via SECURITY DEFINER                             | Admin only (platform team)               |
| `pf_code_modifiers`                                | Org-scoped                | `pf_has_org_access(organization_id, auth.uid())`                            | Admin: WITH CHECK required               |
| `pf_payer_code_rules`                              | Org-scoped                | `pf_has_org_access(organization_id, auth.uid())`                            | Admin: WITH CHECK required               |
| `pf_code_favorites`                                | User-scoped               | `user_id = auth.uid()`                                                      | User owns their own rows                 |
| `pf_code_recent`                                   | User-scoped               | `user_id = auth.uid()`                                                      | User owns their own rows                 |

**SECURITY DEFINER helpers:**

* `pf_can_read_code_set(p_code_set_id UUID)` — returns TRUE if code\_set is platform-managed (org NULL) OR user belongs to the code\_set's organization. Uses `SET search_path = public`.
* `pf_can_manage_org_codes(p_organization_id UUID)` — returns TRUE if user is admin for the given org. Uses `SET search_path = public`.

***

## Escalation Notes

### ESCALATION-1 (C-3): payer\_id FK Boundary

`pf_payer_code_rules.payer_id` is a bare UUID — no FK to `pm_payers` to avoid PF→PM boundary violation. PM-layer code resolves the UUID to payer identity at call site. `payer_id` is nullable; NULL means "global rule applying to all payers."

### ESCALATION-2: LOINC Deferral — CL-08 Partial Block

CL-08 requires LOINC for lab monitoring CDS rules. PF-70 defers LOINC tables to a future phase. When CL-08 implementation begins, add a LOINC table to PF-70 (new task) before CL-08's CDS rules feature can complete. The search API contract already reserves `codeSet='LOINC'` to avoid a breaking change.

### ESCALATION-3: Code Set Data Load — Ownership Defined

Platform admin owns annual updates for platform-managed code sets. See [Admin Guide](../../pf/medical-terminology-admin-guide.md) for the update process, file format, and no-delete policy.

***

## Security and RLS

* Platform-managed code sets: `organization_id` NULL; readable by all orgs via SECURITY DEFINER helpers.
* Org-scoped: `pf_code_modifiers`, `pf_payer_code_rules`; RLS enforces `organization_id`.
* User-scoped: `pf_code_favorites`, `pf_code_recent`; filtered by `user_id = auth.uid()`.
* Read-only for clinicians/billing; admin write for code set updates and modifier/payer rules. Permission keys: `pf.codes.read`, `pf.codes.admin`.

***

## Related Docs

* [PF-70 Spec](../../../specs/pf/specs/PF-70-medical-terminology-code-libraries.md)
* [PF-70 Admin Guide](../../pf/medical-terminology-admin-guide.md)
* [Platform Integration Layers](./PLATFORM_INTEGRATION_LAYERS.md)
* [CL-08 Integration Doc](./clinical-decision-support-integration.md) (CL-08 is a confirmed PF-70 consumer)
* [CL-PM-SPEC-REVIEW Finding 2.2](../../../specs/reviews/CL-PM-SPEC-REVIEW.md) (Code Library / Terminology Spec)
