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: PM-02
Status: ๐Ÿ“ Planned
Last Verified: 2026-02-18
Spec Reference: PM-02-insurance-eligibility-verification.md
Last Updated: 2026-02-18

Table of Contents


Overview

PM-02 provides multiple insurance policies per patient, real-time and batch eligibility verification via X12 270/271 and AHCCCS, benefit detail capture, coordination of benefits, and coverage gap detection. It depends on PM-01 (patient registration); integrates with PM-08 (claims), PM-15 (clearinghouse), and AHCCCS (direct eligibility).

Quick Reference

ItemValue
Core tablespm_insurance_policies, pm_eligibility_checks, pm_payers
Key dependenciesPM-01, PM-08, PM-15, AHCCCS
Required permissionspm.insurance.view/manage, pm.eligibility.run, pm.payers.view/manage
Traceabilityrequest_trace_id required for external eligibility requests

Decision Trees

Eligibility execution path

  1. Select active policy by coverage priority.
  2. Choose check type (real_time, batch, or manual).
  3. Send X12 270/271 through PM-15 or direct AHCCCS path.
  4. Persist normalized result in pm_eligibility_checks.
  5. Surface status to PM-08 claims flow gate.

Coverage gap handling

  1. Evaluate policy effective and termination dates.
  2. If gap detected, flag workflow and route to staff for remediation.
  3. Record remediation actions in policy and audit history.

Pattern Library

PatternUsage
Data + API dual integrationPM-02 stores policy state and calls PM-15/AHCCCS for verification
Request trace contractExternal eligibility calls include trace IDs for replay/audit
Claims gate patternPM-08 checks PM-02 eligibility status before claim submission

Integration Points (from Spec)

DependencyPatternPurpose
PM-01 (Patient Registration)DataPatient linked to insurance policies; pm_insurance_policies.patient_id โ†’ pm_patients.id
PM-08 (Claims)Data / EventEligibility verified before claim submission; eligibility result informs claim workflow
PM-15 (Clearinghouse)API270/271 transactions via clearinghouse; request_trace_id for auditing
AHCCCSAPIDirect eligibility verification (member ID, CIS ID, MCO assignment)

API / Data Contracts

Insurance Policies โ€” pm_insurance_policies

Invocation pattern: supabase.from('pm_insurance_policies').select(...).eq('organization_id', orgId).eq('patient_id', patientId)
Authentication: Supabase JWT; RLS enforces org isolation. Application layer also filters by organization_id (defense-in-depth).
RBAC: pm.insurance.view (read), pm.insurance.manage (write)
Tenant enforcement: organization_id required on all mutations; RLS USING + WITH CHECK on UPDATE.
Idempotency: Policy uniqueness enforced by UNIQUE(organization_id, patient_id, payer_id, policy_number).
Request schema (Insert):
interface InsurancePolicyInsert {
  organization_id: string;       // UUID โ€” required
  patient_id: string;            // UUID โ€” FK to pm_patients
  payer_id: string;              // UUID โ€” FK to pm_payers
  policy_number: string;         // Required
  group_number?: string;
  subscriber_name?: string;
  subscriber_dob?: string;       // DATE (ISO 8601)
  relationship_to_subscriber?: 'self' | 'spouse' | 'child' | 'other';
  coverage_type?: 'commercial' | 'medicaid' | 'medicare' | 'tricare' | 'self_pay' | 'sliding_scale' | 'other';
  priority_order: number;        // 1 = primary, 2 = secondary, etc.
  effective_date: string;        // DATE (ISO 8601)
  termination_date?: string;
  copay?: number;
  coinsurance_pct?: number;
  deductible?: number;
  oop_max?: number;
  bh_benefits?: Record<string, unknown>;
  status?: 'active' | 'inactive' | 'terminated';  // default: 'active'
  deleted_at?: string | null;    // TIMESTAMPTZ; null = active record
}

Eligibility Checks โ€” pm_eligibility_checks

Invocation pattern: supabase.from('pm_eligibility_checks').insert({ ... }).eq('organization_id', orgId)
Authentication: Supabase JWT; RLS enforces org isolation.
RBAC: pm.eligibility.run (create), pm.insurance.view (read results)
Traceability: request_trace_id REQUIRED for every external 270/271 or AHCCCS call.
Caching: Eligibility results cached in pm_eligibility_checks; use next_check_due to determine when re-verification is needed.
Performance SLA: Real-time p95 < 5s; history load p95 < 1s (NFR-1).
Request schema (Insert):
interface EligibilityCheckInsert {
  organization_id: string;       // UUID โ€” required
  patient_id: string;            // UUID โ€” FK to pm_patients
  policy_id?: string | null;     // UUID โ€” FK to pm_insurance_policies (optional)
  check_type: 'real_time' | 'batch' | 'manual';
  request_trace_id?: string;     // Required for external calls (audit trail)
  response_status?: string;      // e.g. 'active_coverage', 'inactive', 'not_found', 'error'
  eligible?: boolean;
  benefit_details?: BenefitDetails;
  next_check_due?: string;       // TIMESTAMPTZ (ISO 8601)
}

// benefit_details JSONB schema (spec Errata E-2)
interface BenefitDetails {
  deductible?: { individual: number; family: number; met: number; remaining: number };
  copay?: { office_visit: number; specialist: number; emergency: number };
  coinsurance?: { in_network_pct: number; out_of_network_pct: number };
  out_of_pocket_max?: { individual: number; family: number; met: number };
  visit_limits?: { bh_outpatient?: number; bh_inpatient_days?: number; used?: number };
  preauth_required?: boolean;
  referral_required?: boolean;
  behavioral_health_carveout?: { payer_name: string; payer_id: string; phone: string };
}

Payers โ€” pm_payers

Invocation pattern: supabase.from('pm_payers').select(...).eq('organization_id', orgId).is('deleted_at', null)
RBAC: pm.payers.view (read), pm.payers.manage (write)
Soft delete: is_active = false for logical disable (hidden from dropdowns); deleted_at for true soft-delete.
PHI Logging Guidelines:
  • Allowed log fields: check_id, patient_id (UUID only), check_type, eligible, organization_id
  • Prohibited: benefit_details contents, policy_number, subscriber_dob, subscriber_name
  • Retention: Audit trail in pf_audit_logs; no PHI in application logs or edge function stdout
Error response schema:
interface PM02ErrorResponse {
  code: number;         // 4001 = tenant violation, 4002 = duplicate policy, 4003 = eligibility timeout
  message: string;      // Sanitized user-facing message (never raw DB error)
  field?: string;       // Field causing the error (for validation errors)
}

Labeled Code Examples

Example: eligibility check request payload

const eligibilityCheckInsert: EligibilityCheckInsert = {
  organization_id: 'org-uuid',
  patient_id: 'patient-uuid',
  policy_id: 'policy-uuid',
  check_type: 'real_time',
  request_trace_id: 'trace-271-uuid', // REQUIRED for external calls
};

Example: normalized eligibility result with structured benefit_details

const eligibilityResult = {
  eligible: true,
  response_status: 'active_coverage',
  benefit_details: {
    deductible: { individual: 1500, family: 3000, met: 250, remaining: 1250 },
    copay: { office_visit: 25, specialist: 50, emergency: 150 },
    coinsurance: { in_network_pct: 20, out_of_network_pct: 40 },
    out_of_pocket_max: { individual: 5000, family: 10000, met: 275 },
    visit_limits: { bh_outpatient: 30, bh_inpatient_days: 20, used: 4 },
    preauth_required: true,
    referral_required: false,
    behavioral_health_carveout: {
      payer_name: 'Beacon Health Options',
      payer_id: 'BHO-001',
      phone: '800-555-0100',
    },
  },
  next_check_due: '2026-03-18T00:00:00Z',
};

Event Contracts

  • Outbound: Eligibility check completed may be consumed by PM-08 (claims) or workflow; document in EVENT_CONTRACTS.md if events are added.
  • Inbound: None specified in PM-02 spec.

Security and RLS

  • RLS on pm_insurance_policies, pm_eligibility_checks, pm_payers. Use SECURITY DEFINER helpers that resolve organization and profile access via pf_user_role_assignments. All UPDATE policies include WITH CHECK (constitution ยง5.2.4).
  • Eligibility and benefit data are PHI; no cross-tenant visibility. Permission keys: pm.insurance.view, pm.insurance.manage, pm.eligibility.run, pm.payers.view, pm.payers.manage.

Common Mistakes

MistakeImpactFix
Missing request_trace_idHard-to-debug payer responsesRequire trace ID for every external request
Ignoring policy priority orderIncorrect COB behaviorEnforce priority_order during checks and claims gating
Incomplete RLS WITH CHECK rulesTenant write leakageEnsure UPDATE policies include USING + WITH CHECK

Pre-Flight Checklist

  • Validate RLS on all PM-02 tables.
  • Validate permission keys and role mappings.
  • Validate real-time + batch eligibility test flows.
  • Validate PM-08 blocks claims when eligibility is missing/failed.
  • Validate AHCCCS and clearinghouse fallback behavior.