Skip to content

Create federal CCDF infrastructure for scaling CCAP to all states #7764

@hua7450

Description

@hua7450

Summary

Create shared federal-level CCDF variables and parameters to avoid duplicating identical logic across 50 state + DC childcare assistance program implementations. Based on analysis of federal regulations (45 CFR Part 98) and existing state implementations (RI, MA, CO, TX, CA, NE).

Related: PR #7739 (RI CCAP implementation)

Background

Currently, each state CCAP implementation is fully self-contained — reimplementing federal rules from scratch. As we scale to all 51 jurisdictions, two components are truly identical across states and should be shared:

  1. Asset eligibility — $1M federal limit (45 CFR 98.20(a)(2)(ii)), no state variation
  2. Immigration eligibility — Qualified alien list from 8 USC 1641, nearly identical across states

What was considered but rejected for federal layer

Component Why it stays state-specific
Age eligibility Base age (under 13) is universal, but disabled extension varies widely — from 13 (no extension) to 24 (state-funded). No parameter override mechanism exists. Each state handles this in 3 lines within eligible_child.
Activity test States differ not just in thresholds but in structural design — MA checks each parent individually vs TX pools household hours. Different entity-level logic (Person vs SPMUnit). Cannot be parameterized.
Income thresholds States use different reference metrics (FPL vs SMI), different multipliers, and different dual-threshold (entry vs exit) structures.
Copay / family share Sliding fee scales are completely state-designed — FPL brackets (RI), FPG ratio interpolation (CO), per-child multipliers (MA), percentage of income (CA).
Provider reimbursement rates State market rate surveys with unique dimensions (geography, provider type, quality ratings, age groups, time categories).

Implementation Plan

Step 1: Enhance is_ccdf_asset_eligible (already exists)

File: policyengine_us/variables/gov/hhs/ccdf/is_ccdf_asset_eligible.py
Parameter: policyengine_us/parameters/gov/hhs/ccdf/asset_limit.yaml

The variable and parameter already exist and are correct ($1M limit per 45 CFR 98.20). No changes needed to the variable itself.

Action: States should reference is_ccdf_asset_eligible directly instead of creating their own (e.g., RI's ri_ccap_asset_eligible is redundant).

Step 2: Create is_ccdf_immigration_eligible_child

New variable: policyengine_us/variables/gov/hhs/ccdf/is_ccdf_immigration_eligible_child.py

Reuses the existing federal gov/dhs/immigration/qualified_noncitizen_status parameter (8 USC 1641) and adds a citizen check. No duplicate parameter file needed.

class is_ccdf_immigration_eligible_child(Variable):
    value_type = bool
    entity = Person
    definition_period = YEAR
    label = "Immigration eligibility for CCDF"
    reference = (
        "https://www.law.cornell.edu/uscode/text/8/1641",
        "https://www.law.cornell.edu/cfr/text/45/98.20",
    )

    def formula(person, period, parameters):
        p = parameters(period).gov.dhs.immigration
        immigration_status = person("immigration_status", period)
        immigration_status_str = immigration_status.decode_to_str()
        is_qualified_noncitizen = np.isin(
            immigration_status_str,
            p.qualified_noncitizen_status,
        )
        is_citizen = immigration_status == immigration_status.possible_values.CITIZEN
        return is_citizen | is_qualified_noncitizen

States that expand eligibility (e.g., adding TPS) create their own override variable. States that follow the federal list use this directly.

Step 3: Fix childcare_expenses.py scaling problem

Current issue (line 16):

STATES_WITH_CHILD_CARE_SUBSIDIES = ["CA", "CO", "NE", "MA"]

This hardcoded list won't scale to 51 jurisdictions. Created a federal aggregator variable child_care_subsidies (following the tanf.py pattern) that lists all state subsidy variables. childcare_expenses.py now references the aggregator instead of maintaining its own list.

Current state programs in the aggregator:

  • ca_child_care_subsidies — California (CalWORKs Stages 2-3 + CAPP)
  • co_child_care_subsidies — Colorado CCAP
  • ma_child_care_subsidies — Massachusetts CCFA
  • ne_child_care_subsidies — Nebraska Child Care Subsidy
  • tx_ccs — Texas Child Care Services

Step 4: Refactor existing state implementations

After creating federal infrastructure, refactor existing states to use shared variables:

State Drop (use federal instead)
RI ri_ccap_asset_eligible, ri_ccap_immigration_status_eligible_child
MA Asset check if duplicated, immigration check if duplicated
CO Asset check if duplicated, immigration check if duplicated
TX Asset check if duplicated, immigration check if duplicated
CA Asset check if duplicated, immigration check if duplicated
NE Asset check if duplicated, immigration check if duplicated

Step 5: Add tests

  • Unit tests for is_ccdf_immigration_eligible_child (11 cases: all qualified statuses + UNDOCUMENTED, DACA, TPS)
  • Verify existing is_ccdf_asset_eligible tests are adequate

Architecture Summary

Federal layer (gov/hhs/ccdf/):
  ├── is_ccdf_asset_eligible        ← ALL states reuse (identical $1M rule)
  ├── is_ccdf_immigration_eligible_child  ← Most states reuse (federal list via gov/dhs/immigration)
  ├── meets_ccdf_activity_test      ← Input stub (states implement their own)
  ├── child_care_subsidies          ← Federal aggregator (sums state programs)
  └── [existing variables unchanged]

State layer (gov/states/{st}/{agency}/ccap/):
  ├── {st}_ccap_eligible_child      ← Age check + references federal immigration
  ├── {st}_ccap_eligible            ← References federal asset + state-specific rules
  ├── {st}_ccap_income_eligible     ← Always state-specific
  ├── {st}_ccap_activity_eligible   ← Always state-specific
  ├── {st}_ccap_copay               ← Always state-specific
  ├── {st}_ccap_maximum_benefit     ← Always state-specific (provider rates)
  └── {st}_ccap                     ← Main benefit variable

Progress

Related Issues

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions