Skip to main content
Spec: CL-29-EN-66 — FUA & FUI Follow-Up Measures · Status: spec draft, human-merge (regulated CL/SUD core) Companion trace: DS4P label propagation is documented separately in CL-29-EN-66-DS4P-PROPAGATION.md — this doc does not restate it. Regulatory: NCQA HEDIS FUA/FUI (MY2025 + MY2026), CMS Medicaid Adult Core Set / SUPPORT Act §5001, 42 CFR Part 2, HIPAA 45 CFR 164, AHCCCS DAP, Information Blocking (21st Century Cures). Sign-off: specs/cl/reviews/CL-29-EN-66-COMPLIANCE-SIGNOFF.md (Approved with Conditions). This is the integration picture for the two NCQA HEDIS SUD follow-up measures — FUA (Follow-Up After ED Visit for Substance Use) and FUI (Follow-Up After High-Intensity SUD Care) — each computed as a 7-day and a 30-day rate. CL-29-EN-66 is a measures-only spec: it emits an at-risk cohort to CL-35 and owns no outreach, and it extends the shipped EN-65 FUH/FUM substrate rather than standing up a parallel surface.
Honest status: the measure engine, substrate, RLS, ADT chokepoint, MY-versioned persistence, payer-export gate, and DS4P fail-close are built and tested on branch feat/cl-29-en-66-fua-fui. The runtime invoker that computes the FUA/FUI set under a resolved PF-96 Measurement Year and drives the persist / cohort-emit / CL-51 registration is the future CL-51 eCQM runner / PM-03 canonical path, which has not landed — several typed service wrappers (fuaAdtIngest.ts, hedisMeasurePersist.ts) intentionally have no production call site yet and are exercised by integration tests. Four external compliance gates ship fail-closed and remain human-verify-open (see §7).

1. PF-108 Contexture ADT consumer contract

Out-of-network ED-for-SUD visits are not visible in pm_encounters (the patient was seen at another facility), so FUA’s denominator needs an external admit/discharge/transfer (ADT) feed. That feed is PF-108 Contexture HIE. EN-66 consumes it into a dedicated table, cl_fua_adt_events — the sanctioned FR-7 exception (ADT shape ≠ aftercare-plan shape).
  • Ingest path. The sanctioned write surface is the SECURITY DEFINER RPC cl_ingest_fua_adt_event(...) (typed wrapper src/cores/cl/services/fuaAdtIngest.ts). It re-asserts tenancy server-side (cl_has_org_access42501; chart∈org → 42501) because DEFINER bypasses RLS. A NULL auth.uid() (service-role feed) is the accepted-risk H-2 path, mirroring PM-75 — the feed runs as service_role, not as an end user.
  • Direct-write chokepoint. The table is also directly writable (RLS only checks cl_has_org_access(organization_id)), so two BEFORE-row triggers fire on every write path (direct PostgREST, service-role feed, and the RPC) and cannot be bypassed:
    • cl_fua_adt_events_derive_biu() derives sud_indicated fail-closed — an absent / indeterminate / unparseable SUD signal resolves to true (presumed SUD, maximum Part 2 protection) — and sets ds4p_confidentiality_code := 'R' for SUD rows. It also enforces the chart∈org chokepoint (42501).
    • cl_fua_adt_events_ds4p_label_biu() fail-closes ds4p_security_label (see §5 / the DS4P trace doc).
  • SUD derivation is never a hardcoded code list. sud_indicated is derived from dx / CL-62 episode metadata + instrument NOMs domains, never an inline F10–F19 list (the CL-69 lesson; the SUD flag is also the RLS read-gate key).
  • Planning-stub caveat. PF-108 is a planning stub, not a live feed. The chokepoint, fail-close, and RLS isolation are proven by tests; live end-to-end ADT ingest is human-verify-open (gate, §7).

2. CL-51 measure-spec registration

The four measure variants — FUA-7, FUA-30, FUI-7, FUI-30 — are registered as MY-stamped snapshots in cl_quality_measure_periods via the hardened RPC cl_persist_hedis_measure_period(...) (typed wrapper src/cores/cl/services/hedisMeasurePersist.ts; measureId is the variant key).
  • MY selected from PF-96 at evaluation time. The active Measurement Year ruleset (MY2025 vs MY2026) is read from PF-96 ComplianceRules.active_measurement_year_version at evaluation time — never new Date().getFullYear() (AC-2). MY2025 applies the principal-position SUD-dx denominator rule; MY2026 applies any-position SUD dx and counts peer support + residential as qualifying follow-up. The measure-spec loader (src/cores/cl/utils/fua-fui-measure-spec.ts) builds all params from PF-96.
  • No hardcoded NCQA OIDs (NFR-config-1). The loader carries no NCQA value-set codes. Per-MY value-set OIDs are expected to be loaded into the CL-51 measure-spec registry from the licensed NCQA portal — that acquisition is gate 6, human-verify-open (§7). The engine encodes only the documented MY2025/MY2026 ruleset shape; the codes themselves come from the registry, not from source.

3. Denominator sourcing — interim proxy decision (PM-03 pending)

The canonical pm_encounters.encounter_type enum (outpatient | iop | php | crisis | group | telehealth | evaluation | residential_daily) has no ED or acute-inpatient value. Until PM-03 lands canonical encounter classes, EN-66 uses an EN-65-consistent interim proxy, entirely behind PF-96 config:
  • FUA denominatorcrisis / evaluation encounters with a SUD indication (plus the PF-108 ADT out-of-network ED events from §1).
  • FUI denominatorresidential_daily encounters. The NCQA-default high-intensity scope is residential + acute-inpatient SUD; the PF-96 opt-in fui_high_intensity_expansion adds PHP/IOP (FUI_HIGH_INTENSITY_EXPANSION_TYPES) — see the admin guide for the benchmarkability trade-off.
The canonical PM-03 path is explicitly stubbed TODO(PM-03) in code. This is a known interim decision, the same approach shipped and approved in EN-65; correctness is refined when PM-03 delivers canonical encounter types. The FUA/FUI denominator also enforces an explicit age floor — FUA_MIN_AGE = FUI_MIN_AGE = 13 (src/cores/cl/types/discharge.ts) — closing sign-off residual item 4 (NCQA SUD measures are 13+).

4. CL-35 care-gap emit

EN-66 is downstream of CL-35 for outreach: a member who is in the FUA/FUI denominator but has no qualifying follow-up within the 7- or 30-day window is surfaced to CL-35 as a care gap rather than acted on by EN-66 itself. The intended emit shape writes cl_care_gaps with gap_type = 'follow_up_not_scheduled' (a real CL-35 care-gap type) and a source_rule naming the measure/window (e.g. EN-66-FUA-7DAY, EN-66-FUI-30DAY). EN-66 owns no work-list UI — CL-35’s care-gap work list, clinician panels, and supervisor view consume the gap. As with §2/§3, the emit is driven by the not-yet-wired CL-51/PM-03 eCQM runner (the cohort capability is built and tested; the production call site lands with the runner). SUD ADT rows in cl_fua_adt_events are DS4P-labeled fail-closed at the DB chokepoint (ds4p_confidentiality_code = 'R', ds4p_security_label = '42CFRPart2,ETH|NORDSLCD'), and that label’s redisclosure obligation is operationalized as BLOCKING before any payer export by the T4.1 consent gate (cl_fua_payer_export_gate). The full propagation chain, the TS↔DB SSOT drift-trap test, the trigger fire-order, and the CL-63 boundary are documented in CL-29-EN-66-DS4P-PROPAGATION.md. A SUD row cannot reach a payer destination without active 42 CFR Part 2 consent.

6. T4.3 hardening-audit evidence

Read-only audit of every new DB security object on the branch. Columns: SD? = SECURITY DEFINER; sp? = SET search_path = public; own? = OWNER TO postgres; rev? = REVOKE EXECUTE FROM anon, PUBLIC; org-guard? = server-side tenancy re-assert raising 42501. Per-object verdict: all seven objects are hardened to the CL/SUD regulated bar. Every SECURITY DEFINER object carries search_path = public + OWNER postgres + a REVOKE that removes the repo baseline’s auto-EXECUTE from anon/PUBLIC. The four DEFINER objects that read or write cross-tenant data (the derive trigger, the ingest RPC, the persist RPC, and the export gate) each re-assert tenancy server-side and raise 42501. The two label/derive-only triggers and the immutability guard are correctly marked org-guard N/A (no cross-tenant read — tenancy is enforced by their callers or co-located triggers). The immutability guard is intentionally not DEFINER (a RAISE-only trigger needs no elevated privilege). Substrate anon-grant note: the Phase-1 substrate (20260701000016) copied a non-Part-2 sibling’s GRANT ALL ON TABLE cl_fua_adt_events TO anon; the very next migration (20260701000017) REVOKE ALL ON TABLE public.cl_fua_adt_events FROM anon, so the net state is no anon access to the SUD ADT table. Redisclosure-log immutability — verified, not recreated. The append-only immutability trigger for the payer-export-request ledger, cl_fua_payer_export_requests_immutable() / trg_cl_fua_payer_export_requests_immutable, already exists in 20260701000020 and is not recreated by any later migration. The CL-11 cl_redisclosure_log itself is owned by CL-11; 20260701000020 only INSERTs into it on the allowed-payer path and does not redefine the table or its CL-11 immutability trigger. Denominator-bridge VIEW — security_invoker confirmed. cl_hedis_fuh_fum_summary is created WITH (security_invoker = 'true') in both 20260701000016 (substrate) and 20260701000018 (denominator bridge) — the cross-tenant PHI-leak guard (the CL-69 lesson) is preserved across the recreate.

7. Human-verify-open compliance gates

Four external gates ship fail-closed and remain human-verify-open (same bar as PM-75 / CL-69; see CL-29-EN-66-COMPLIANCE-SIGNOFF.md items 6 / 10a-b / 10c / 8):
  1. Gate 6 — NCQA value-set OID acquisition (sign-off item 6). Ships: a measure-spec loader that hydrates OIDs from the CL-51 registry with zero NCQA codes inline (NFR-config-1). Human must verify: per-MY (MY2025 + MY2026) value-set OIDs acquired from the licensed NCQA portal and loaded into the CL-51 registry before denominator logic ships to prod.
  2. Gate 10a-b — CL-11 Part 2 export consent (sign-off item 10a-b). Ships: cl_fua_payer_export_gate fail-closes any payer-facing SUD export at the DB unless active cl_check_sud_consent() and an explicitly-enabled org payer-export flag, writing cl_redisclosure_log on every permitted redisclosure; internal org-scoped computation is allowed, payer-facing export disabled until live. Human must verify: a valid TPO consent / individual authorization / QSOA covers the disclosure purpose, and ADT-derived events are not stored with identifiable SUD dx absent active Part 2 consent.
  3. Gate 10c — DS4P label-propagation trace vs CL-63 (sign-off item 10c). Now documented — the T2/T4.2 trace CL-29-EN-66-DS4P-PROPAGATION.md proves the DB fail-close, the TS↔DB SSOT agreement, and BLOCKING-before-payer-export. Human must verify: live PF-108 / Contexture feed end-to-end propagation (PF-108 is a planning stub).
  4. Gate 8 — AHCCCS DAP per-year measure weighting (sign-off item 8). Ships: per-MY weighting externalized to PF-96 (no hardcoded weights). Human must verify: direct AHCCCS QM-team confirmation of whether FUA/FUI feed DAP for a given AZ payment year, recorded in the tracker before the first DAP submission that uses platform-generated rates.
Closed residual: the FUI age-floor (≥13, sign-off residual item 4) is enforced in code (FUI_MIN_AGE = 13; FUA_MIN_AGE = 13).