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.

Contract Version: 1.0 Created: 2026-03-24 Owning Cores: CL (Clinical & EHR), PM (Practice Management) Status: Draft ADR Reference: ADR-004: CL-FW Event Patterns
Purpose: Define the event contracts for asynchronous communication between CL and PM cores, focusing on clinical documentation → charge capture, referral acceptance → care coordination, and financial program cost → outcomes reporting.

Event Contracts

Event 1: clinical_note_finalized

Summary: When a clinical progress note is signed/finalized in CL-04, PM-07 creates a charge capture suggestion.
FieldValue
Event Nameprogress_note_signed
Channelcl_pm_events
PublisherCL (CL-04: Progress Notes & Session Documentation)
SubscribersPM (PM-07: Charge Capture), PF-10 (Notifications), FW (Audit)
TriggerCL-04 note status transitions to finalized (co-signature complete if required)
Frequency~50-200/day per organization (based on clinician volume)
Latency SLA< 5 seconds from finalization to PM charge suggestion
Payload Schema:
interface ProgressNoteSignedEvent {
  event: 'progress_note_signed';
  publisher: 'CL';
  subscriber: ['PM', 'PF', 'FW'];
  payload: {
    entity_id: string;          // cl_progress_notes.id (UUID)
    entity_type: 'progress_note';
    chart_id: string;           // cl_patient_charts.id
    encounter_id: string;       // pm_encounters.id (FK per ADR-002)
    rendering_provider_id: string; // pf_profiles.id of signing clinician
    service_date: string;       // ISO date (YYYY-MM-DD)
    billing_codes: string[];    // CPT codes derived from note type (e.g., ['90837', '90785'])
    modifiers?: string[];       // Modifier codes (e.g., ['GT'] for telehealth)
    duration_minutes: number;   // Actual session duration
    note_type: string;          // 'individual' | 'group' | 'family' | 'crisis'
    requires_cosignature: boolean;
    cosigned: boolean;
  };
  metadata: {
    organization_id: string;
    site_id?: string;
    user_id: string;            // Signing clinician
    timestamp: string;
    correlation_id: string;
    event_id: string;
  };
}
PM Consumer Action:
  1. Validate encounter_id exists in pm_encounters
  2. Check for duplicate event_id in processed events (idempotency)
  3. Create charge suggestion in pm_charge_suggestions with billing codes, modifiers, duration, and provider
  4. High-risk billing codes (compliance guard): Before auto-posting to pm_charges, evaluate CPT/HCPCS in event.payload.billing_codes against a curated high-risk list. Default list (same list MUST be used everywhere this guard is implemented; extend only via org config): 90839, 90840, 90785, H0038, H2035, H0004, T1017, 96127. Org customization: pm_module_settings.auto_post_high_risk_codes_list (text[] or JSON array of codes) replaces the default when set; empty array = use default. Definition — “high-risk”: codes that (a) require strong clinical documentation / medical necessity evidence, (b) draw payer or regulatory audit scrutiny, or (c) commonly require prior authorization — orgs SHOULD align overrides with their compliance policy.
    • Add boolean auto_post_high_risk_codes to pm_module_settings (default false).
    • Auto-post to pm_charges only when: orgSettings.auto_post_enabled === true AND (no high-risk code in payload OR orgSettings.auto_post_high_risk_codes === true).
    • Otherwise create or update pm_charge_suggestions for manual review (PF-10 notify billing as today).
  5. If auto-post rules pass, create pm_charges directly
  6. Send PF-10 notification to billing staff if manual review required
PHI Safety: No patient names, DOB, or narrative text. Only UUIDs and billing metadata.

Event 2: referral_accepted

Summary: When PM accepts an inbound referral, CL-12 creates a care coordination transition record.
FieldValue
Event Namepm_referral_accepted
Channelcl_pm_events
PublisherPM (PM-08: Referral Management)
SubscribersCL (CL-12: Care Coordination), PF-10 (Notifications)
TriggerReferral status transitions to accepted in PM
Frequency~5-20/day per organization
Latency SLA< 30 seconds
Payload Schema:
interface ReferralAcceptedEvent {
  event: 'pm_referral_accepted';
  publisher: 'PM';
  subscriber: ['CL', 'PF'];
  payload: {
    entity_id: string;           // pm_referrals.id (UUID)
    entity_type: 'referral';
    patient_id: string;          // pm_patients.id
    chart_id?: string;           // cl_patient_charts.id (if chart already exists)
    referring_provider_id: string;
    accepting_provider_id: string;
    referral_type: string;       // 'inbound' | 'outbound' | 'internal'
    service_type: string;        // e.g., 'behavioral_health', 'substance_use', 'psychiatric'
    priority: string;            // 'routine' | 'urgent' | 'emergent'
    authorization_number?: string;
  };
  metadata: {
    organization_id: string;
    site_id?: string;
    user_id: string;
    timestamp: string;
    correlation_id: string;
    event_id: string;
  };
}
CL Consumer Action:
  1. Check if cl_patient_charts exists for patient; if not, flag for chart creation
  2. Create cl_care_transitions record with referral context
  3. Assign care coordinator via CL-12 assignment rules
  4. Send PF-10 notification to accepting provider and care coordinator

Event 3: clinical_program_cost_allocated

Summary: When FA allocates program costs, CL-10 outcomes can correlate clinical outcomes with financial investment.
FieldValue
Event Namefa_program_cost_allocated
Channelfa_events
PublisherFA (FA-35: Program Cost Allocation)
SubscribersCL (CL-10: Outcomes, CL-15: Reporting)
TriggerFA completes monthly/quarterly program cost allocation
Frequency~1-4/month per organization
Latency SLA< 5 minutes (batch event, not time-critical)
Payload Schema:
interface ProgramCostAllocatedEvent {
  event: 'fa_program_cost_allocated';
  publisher: 'FA';
  subscriber: ['CL'];
  payload: {
    entity_id: string;            // fa_cost_allocations.id
    entity_type: 'cost_allocation';
    program_id: string;           // Program UUID
    program_name: string;         // e.g., 'IOP', 'PHP', 'Residential'
    period_start: string;         // ISO date
    period_end: string;
    total_cost: number;           // In cents (integer) to avoid floating point
    cost_per_patient_day?: number;
    patient_count: number;
    allocation_method: string;    // 'direct' | 'step_down' | 'activity_based'
  };
  metadata: {
    organization_id: string;
    user_id: string;
    timestamp: string;
    correlation_id: string;
    event_id: string;
  };
}
CL Consumer Action:
  1. Store cost data in CL-10 outcomes context for cost-effectiveness reporting
  2. Update CL-15 program quality dashboard with cost-per-outcome metrics
  3. No direct database writes to FA tables (read-only consumption)

Event 4: cl_crisis_episode_resolved

Summary: When a crisis episode is dispositioned with an assigned billing code (CL-13), PM-07 creates a crisis-specific charge suggestion and links it to the episode for audit.
FieldValue
Event Namecl_crisis_episode_resolved
Channelcl_pm_events
PublisherCL (CL-13: Crisis Intervention)
SubscriberPM (PM-07: Charge Capture)
TriggerCrisis disposition recorded and billing_code assigned
FrequencyVariable (crisis volume)
Latency SLA< 5 seconds to charge suggestion
Payload Schema:
interface CrisisEpisodeResolvedEvent {
  event: 'cl_crisis_episode_resolved';
  publisher: 'CL';
  subscriber: ['PM'];
  payload: {
    entity_id: string;              // cl_crisis_episodes.id
    entity_type: 'crisis_episode';
    chart_id: string;
    crisis_type: string;
    service_date: string;           // ISO date YYYY-MM-DD
    billing_code: string;           // e.g. S9484, S9485, H2011, 90839, 90840
    duration_minutes?: number;
    rendering_provider_id: string;
    encounter_id?: string;           // pm_encounters.id when linked
  };
  metadata: {
    organization_id: string;
    site_id?: string;
    user_id: string;
    timestamp: string;
    correlation_id: string;
    event_id: string;               // Idempotency key for PM consumer
  };
}
PM Consumer Action:
  1. Idempotency: same pattern as progress_note_signed using metadata.event_id in fw_domain_events
  2. Create crisis-specific pm_charge_suggestion with billing_code, service_date, rendering_provider_id
  3. For S9484 / H2011 and similar time-based codes, derive units from duration_minutes per org/payer rules in pm_module_settings (or PM-07 configuration)
  4. Link suggestion to cl_crisis_episodes via entity_id on suggestion metadata / extension table (implementation-specific) for audit
  5. Apply the same high-risk auto-post guard as Event 1 when codes overlap the high-risk list
Retry / idempotency: Treat event_id as the dedupe key; duplicates must not create a second suggestion.

Idempotency

All event handlers implement the following idempotency pattern:
async function handleEvent(event: DomainEvent): Promise<void> {
  // 1. Check for duplicate event_id — maybeSingle() so 0 rows returns null (first-time OK)
  const { data: existing } = await supabase
    .from('fw_domain_events')
    .select('id')
    .eq('event_id', event.metadata.event_id)
    .maybeSingle();

  if (existing) {
    logger.info(`Duplicate event ${event.metadata.event_id} — skipping`);
    return;
  }

  // 2. Process event
  await processEvent(event);

  // 3. Record processed event (store full payload for audit / replay)
  await supabase.from('fw_domain_events').insert({
    event_id: event.metadata.event_id,
    event_name: event.event,
    correlation_id: event.metadata.correlation_id,
    status: 'processed',
    processed_at: new Date().toISOString(),
    event_payload: event as unknown as Record<string, unknown>,
  });
}

Dead-Letter Queue

Failed events follow the DLQ pattern from ADR-004:
  1. On failure: write to fw_domain_events with status = 'failed', error message, retry count
  2. Cron edge function retries failed events (exponential backoff: 1s, 2s, 4s; max 3 retries)
  3. After final failure: PF-10 notification to system admin
  4. No retry on 4xx errors (except 429 rate limit)

E2E Test Plan

Test ScenarioStepsExpected Outcome
Note finalization → charge created1. Create encounter in PM; 2. Create progress note in CL-04; 3. Finalize note (sign)PM charge suggestion exists with correct billing_codes, encounter_id, duration_minutes, and modifiers (when present in event payload)
Referral acceptance → care transition1. Create referral in PM; 2. Accept referralCL-12 care transition record created; care coordinator assigned
Cost allocation → outcomes context1. Run FA cost allocation for programCL-10 cost-per-outcome metrics updated
Duplicate event → no double processing1. Publish progress_note_signed twice with identical metadata.event_idExactly one charge suggestion; handler logs a message equivalent to “Duplicate event — skipping” (or Duplicate event ${event_id} — skipping); no uncaught exception
Failed event → DLQ1. Publish progress_note_signed with invalid encounter_id until max retries exhaustedRow in fw_domain_events with status = 'failed', retry_count = 3, error_message non-null/non-empty, processed_at IS NULL after final failure; PF-10 admin notification fired