Skip to main content

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

ItemValue
Platform layer@/platform/codes
Core tablespf_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 dependenciesPF-01, PF-02
Consumed byCL-01, CL-04, CL-06, CL-08, CL-18, CL-19, PM-07, PM-08
Permissionspf.codes.read, pf.codes.admin
SECURITY DEFINER helperspf_can_read_code_set(p_code_set_id UUID), pf_can_manage_org_codes(p_organization_id UUID)

Integration Points (from Spec)

ConsumerUsagePhase Available
CL-01Problem list ICD-10-CM lookup from PF-70Phase 2
CL-04Diagnosis codes and CPT for progress notesPhase 2
CL-06NDC for prescriptions (deferred; table TBD or external)Future phase
CL-08ICD-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-18Z-codes (Z55–Z65) for SDOHPhase 2
CL-19HCPCS H0038, H2017 for peer servicesPhase 2
PM-07CPT/HCPCS and modifiers for charge capturePhase 2
PM-08Code validation for claims (pre-submission scrubbing via validateCode())Phase 2

API / Data Contracts

Search API — useCodeSearch / searchCodes

Import: import { useCodeSearch } from '@/platform/codes'; Parameters:
ParamTypeRequiredDescription
codeSet'ICD10CM' | 'CPT' | 'HCPCS' | 'LOINC'YesCode set to search (single set per request in Phase 1)
querystringYesMin 2 chars; matches code prefix OR description
effectiveDatestring (ISO date)NoDefault: today. Filters to codes effective on this date
bhOnlybooleanNoFilter to is_behavioral_health = true codes only
organizationIdstringYesTenant 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:
ParamTypeRequiredDescription
codestringYesCode to validate
codeSetstringYesCode set (ICD10CM, CPT, HCPCS)
modifiersstring[]NoModifiers to validate against pf_code_modifiers
serviceDatestring (ISO date)YesDate to validate effective range
payerIdstring (UUID)NoOptional; used to look up pf_payer_code_rules. When null, only global rules (payer_id IS NULL) and org-level rules apply.
organizationIdstringYesTenant isolation
Response: { valid: boolean; errors?: string[] } — errors are sanitized user-facing messages. Never exposes raw DB errors. Validation error message examples:
ScenarioUser-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

ContextRecommendation
Search loadingShow 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 errorUse 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

TableScopeSELECT PolicyMutation Policy
pf_code_setsPlatform (org NULL) + orgorganization_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_codesVia code_setpf_can_read_code_set(code_set_id)Admin only
pf_code_crosswalksPlatform-managed onlyTRUE (all authenticated) via SECURITY DEFINERAdmin only (platform team)
pf_code_modifiersOrg-scopedpf_has_org_access(organization_id, auth.uid())Admin: WITH CHECK required
pf_payer_code_rulesOrg-scopedpf_has_org_access(organization_id, auth.uid())Admin: WITH CHECK required
pf_code_favoritesUser-scopeduser_id = auth.uid()User owns their own rows
pf_code_recentUser-scopeduser_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.