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.

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

TableSpecMissing Columns
cl_cds_rulesCL-08created_by, updated_by
cl_cds_alertsCL-08created_by, updated_by
cl_outcome_measuresCL-10created_by, updated_by
cl_program_outcomesCL-10created_by, updated_by
cl_report_definitionsCL-15created_by
cl_pdmp_queriesCL-17created_by, updated_by, custom_fields
cl_pdmp_configurationCL-17created_by, updated_by
pm_claim_linesPM-08created_by, updated_by
pm_eligibility_checksPM-02updated_by
pm_appointment_remindersPM-03created_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 CategorySoft-Delete RequiredRationale
Clinical records (diagnoses, notes, assessments, plans, medications)YESHIPAA 6-year retention, regulatory audit trail
Financial records (claims, charges, payments, adjustments)YESBilling audit trail, payer disputes, regulatory retention
Patient demographicsYESCannot hard-delete patient records with clinical history
Consent recordsYES42 CFR Part 2 audit requirements
Safety-critical records (risk screenings, safety plans, crisis episodes)YESPatient safety, regulatory documentation
Reference/configuration tables (templates, instruments, rules, fee schedules)NOUse is_active flag instead
Immutable log tables (audit logs, disclosure logs)NONever 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

TableSpecAction
cl_consentsCL-11Add deleted_at
cl_assessmentsCL-02Add deleted_at
cl_treatment_plansCL-03Add deleted_at
cl_treatment_goalsCL-03Add deleted_at
cl_treatment_interventionsCL-03Add deleted_at
cl_medicationsCL-05Add deleted_at
cl_prescriptionsCL-06Add deleted_at
cl_risk_screeningsCL-07Add deleted_at
cl_safety_plansCL-07Add deleted_at
cl_crisis_episodesCL-13Add deleted_at
cl_group_sessionsCL-14Add deleted_at
cl_group_attendanceCL-14Add deleted_at
pm_claimsPM-08Add deleted_at
pm_appointmentsPM-03Add deleted_at
pm_chargesPM-07Add 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 NameSpecStandard Name
pm_can_access_patient()PM-01pm_has_org_access()
pm_claims_policy_check()PM-08pm_has_org_access()
can_access_consents()CL-11cl_has_org_access()
get_current_organization_id()PM-04pm_has_org_access()
cl_security.get_org_for_profile()CL-07cl_has_org_access()
cl_security.is_profile_in_org()CL-07cl_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

LevelDescriptionRequirements
PHIProtected Health Information (HIPAA)Access logging, encryption at rest, breach notification
SUD-PHISubstance Use Disorder records (42 CFR Part 2)All PHI requirements + consent-gated access + Part 2 notice
PIIPersonally Identifiable InformationStandard data protection
BusinessNon-sensitive business dataStandard access controls

Table Classification

TableSpecClassification
cl_patient_chartsCL-01PHI
cl_problemsCL-01PHI
cl_allergiesCL-01PHI
cl_progress_notesCL-04PHI (SUD-PHI if SUD-related)
cl_assessmentsCL-02PHI (SUD-PHI if substance_use type)
cl_medicationsCL-05PHI
cl_prescriptionsCL-06PHI
cl_risk_screeningsCL-07PHI
cl_safety_plansCL-07PHI
cl_consentsCL-11PHI
cl_disclosure_logCL-11PHI
cl_crisis_episodesCL-13PHI
pm_patientsPM-01PII + PHI
pm_insurance_policiesPM-02PII
pm_claimsPM-08PHI (contains diagnosis codes)
pm_appointmentsPM-03PHI
pm_chargesPM-07PHI (contains diagnosis codes)