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.
Version: 1.0.0
Last Updated: 2026-02-17
Constitution Reference: Section 5.2.1 (Table Standards)
Source: CL-PM-SPEC-REVIEW Findings 3.3, 8.8
Overview
This document establishes consistent data model conventions for all CL (Clinical) and PM (Practice Management) tables, addressing gaps identified in the spec review.
1. Required Columns for All Business Entity Tables
Per constitution Section 5.2.1, every business entity table MUST include:
-- Standard columns (required on ALL business entity tables)
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id UUID NOT NULL REFERENCES pf_organizations(id),
custom_fields JSONB DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
created_by UUID REFERENCES pf_profiles(id),
updated_by UUID REFERENCES pf_profiles(id)
Tables Currently Missing Required Columns
| Table | Spec | Missing Columns |
|---|
cl_cds_rules | CL-08 | created_by, updated_by |
cl_cds_alerts | CL-08 | created_by, updated_by |
cl_outcome_measures | CL-10 | created_by, updated_by |
cl_program_outcomes | CL-10 | created_by, updated_by |
cl_report_definitions | CL-15 | created_by |
cl_pdmp_queries | CL-17 | created_by, updated_by, custom_fields |
cl_pdmp_configuration | CL-17 | created_by, updated_by |
pm_claim_lines | PM-08 | created_by, updated_by |
pm_eligibility_checks | PM-02 | updated_by |
pm_appointment_reminders | PM-03 | created_by, updated_by |
Exception: Immutable Log Tables
Tables that are INSERT-only by design (audit logs, disclosure logs) may omit updated_by and updated_at:
cl_disclosure_log (CL-11) — INSERT-only, no updates allowed
cl_data_exchange_log (CL-16) — INSERT-only
pf_audit_logs — INSERT-only
2. Soft-Delete Policy
Policy
| Table Category | Soft-Delete Required | Rationale |
|---|
| Clinical records (diagnoses, notes, assessments, plans, medications) | YES | HIPAA 6-year retention, regulatory audit trail |
| Financial records (claims, charges, payments, adjustments) | YES | Billing audit trail, payer disputes, regulatory retention |
| Patient demographics | YES | Cannot hard-delete patient records with clinical history |
| Consent records | YES | 42 CFR Part 2 audit requirements |
| Safety-critical records (risk screenings, safety plans, crisis episodes) | YES | Patient safety, regulatory documentation |
| Reference/configuration tables (templates, instruments, rules, fee schedules) | NO | Use is_active flag instead |
| Immutable log tables (audit logs, disclosure logs) | NO | Never deleted; INSERT-only |
Implementation
-- Add to all tables requiring soft-delete
deleted_at TIMESTAMPTZ -- NULL = active; set = soft-deleted
-- Add partial index for active records
CREATE INDEX idx_{table}_active ON {table}(organization_id)
WHERE deleted_at IS NULL;
Tables Currently Missing deleted_at
| Table | Spec | Action |
|---|
cl_consents | CL-11 | Add deleted_at |
cl_assessments | CL-02 | Add deleted_at |
cl_treatment_plans | CL-03 | Add deleted_at |
cl_treatment_goals | CL-03 | Add deleted_at |
cl_treatment_interventions | CL-03 | Add deleted_at |
cl_medications | CL-05 | Add deleted_at |
cl_prescriptions | CL-06 | Add deleted_at |
cl_risk_screenings | CL-07 | Add deleted_at |
cl_safety_plans | CL-07 | Add deleted_at |
cl_crisis_episodes | CL-13 | Add deleted_at |
cl_group_sessions | CL-14 | Add deleted_at |
cl_group_attendance | CL-14 | Add deleted_at |
pm_claims | PM-08 | Add deleted_at |
pm_appointments | PM-03 | Add deleted_at |
pm_charges | PM-07 | Add deleted_at |
3. RLS Helper Function Naming Convention
Standard Pattern
{core_prefix}_has_org_access() -- Tenant isolation check
{core_prefix}_has_permission(p) -- Role-based permission check
Current Inconsistencies to Resolve
| Current Name | Spec | Standard Name |
|---|
pm_can_access_patient() | PM-01 | pm_has_org_access() |
pm_claims_policy_check() | PM-08 | pm_has_org_access() |
can_access_consents() | CL-11 | cl_has_org_access() |
get_current_organization_id() | PM-04 | pm_has_org_access() |
cl_security.get_org_for_profile() | CL-07 | cl_has_org_access() |
cl_security.is_profile_in_org() | CL-07 | cl_has_org_access() |
Org Context Pattern
All RLS helpers MUST use the same pattern for obtaining the current organization:
-- STANDARD PATTERN: Use auth.uid() to get org from pf_profiles
CREATE OR REPLACE FUNCTION {core}_has_org_access(target_org_id UUID)
RETURNS BOOLEAN AS $$
BEGIN
RETURN EXISTS (
SELECT 1 FROM pf_profiles
WHERE id = auth.uid()
AND organization_id = target_org_id
);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER STABLE;
Do NOT use:
current_setting('app.current_org') (CL-08 pattern — fragile, requires app-level setting)
current_setting('jwt.claims.organization_id') (CL-12 pattern — JWT claim may not exist)
4. PHI Classification
Classification Levels
| Level | Description | Requirements |
|---|
| PHI | Protected Health Information (HIPAA) | Access logging, encryption at rest, breach notification |
| SUD-PHI | Substance Use Disorder records (42 CFR Part 2) | All PHI requirements + consent-gated access + Part 2 notice |
| PII | Personally Identifiable Information | Standard data protection |
| Business | Non-sensitive business data | Standard access controls |
Table Classification
| Table | Spec | Classification |
|---|
cl_patient_charts | CL-01 | PHI |
cl_problems | CL-01 | PHI |
cl_allergies | CL-01 | PHI |
cl_progress_notes | CL-04 | PHI (SUD-PHI if SUD-related) |
cl_assessments | CL-02 | PHI (SUD-PHI if substance_use type) |
cl_medications | CL-05 | PHI |
cl_prescriptions | CL-06 | PHI |
cl_risk_screenings | CL-07 | PHI |
cl_safety_plans | CL-07 | PHI |
cl_consents | CL-11 | PHI |
cl_disclosure_log | CL-11 | PHI |
cl_crisis_episodes | CL-13 | PHI |
pm_patients | PM-01 | PII + PHI |
pm_insurance_policies | PM-02 | PII |
pm_claims | PM-08 | PHI (contains diagnosis codes) |
pm_appointments | PM-03 | PHI |
pm_charges | PM-07 | PHI (contains diagnosis codes) |