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.
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
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:
{
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
// 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...
}
// 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 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.