diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..b80b5ce7c29 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Add MinnesotaCare for undocumented children under 19 with income at or below 200% FPL. diff --git a/policyengine_us/parameters/gov/states/mn/dhs/minnesotacare/child/eligibility/age_limit.yaml b/policyengine_us/parameters/gov/states/mn/dhs/minnesotacare/child/eligibility/age_limit.yaml new file mode 100644 index 00000000000..b23ca699c8b --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/dhs/minnesotacare/child/eligibility/age_limit.yaml @@ -0,0 +1,15 @@ +description: >- + Maximum age for children's eligibility for MinnesotaCare. + Per Minnesota Statutes 256L.04 subdivision 10(c), undocumented noncitizens + age 18 or older have restricted eligibility, meaning children must be + under age 18 to qualify for ongoing coverage. +metadata: + unit: year + period: year + label: MinnesotaCare children maximum age + reference: + - title: Minnesota Statutes 256L.04 Subd. 10(c) - Eligibility for MinnesotaCare + href: https://www.revisor.mn.gov/statutes/cite/256L.04 + +values: + 2020-01-01: 18 diff --git a/policyengine_us/parameters/gov/states/mn/dhs/minnesotacare/child/eligibility/in_effect.yaml b/policyengine_us/parameters/gov/states/mn/dhs/minnesotacare/child/eligibility/in_effect.yaml new file mode 100644 index 00000000000..808ee2c74e3 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/dhs/minnesotacare/child/eligibility/in_effect.yaml @@ -0,0 +1,22 @@ +description: >- + Whether MinnesotaCare coverage for undocumented children is in effect. + The 2023 Minnesota Legislature expanded MinnesotaCare to include undocumented + individuals, with coverage beginning January 1, 2025. While coverage for + undocumented adults was later restricted effective June 15, 2025, children + under 19 continue to be eligible. Coverage is state-only funded and delivered + on a fee-for-service basis. +metadata: + unit: bool + period: year + label: MinnesotaCare for undocumented children in effect + reference: + - title: Minnesota Statutes 256L.04 Subd. 10 - Eligibility for MinnesotaCare + href: https://www.revisor.mn.gov/statutes/cite/256L.04 + - title: DHS Bulletin 24-21-10 - MinnesotaCare Eligibility Expansion + href: https://www.dhs.state.mn.us/main/groups/publications/documents/pub/mndhs-068276.pdf + - title: MinnesotaCare coverage changes for undocumented adults (June 2025) + href: https://www.dhs.state.mn.us/main/idcplg?IdcService=GET_FILE&RevisionSelectionMethod=LatestReleased&Rendition=Primary&allowInterrupt=1&dDocName=MNDHS-070570 + +values: + 2020-01-01: false + 2025-01-01: true diff --git a/policyengine_us/parameters/gov/states/mn/dhs/minnesotacare/child/eligibility/income_limit.yaml b/policyengine_us/parameters/gov/states/mn/dhs/minnesotacare/child/eligibility/income_limit.yaml new file mode 100644 index 00000000000..ad1654f6972 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mn/dhs/minnesotacare/child/eligibility/income_limit.yaml @@ -0,0 +1,14 @@ +description: >- + Income limit for children's eligibility for MinnesotaCare as a fraction of FPL. + Per Minnesota Statutes 256L.04 subdivision 1, children with family income at or + below 200 percent of federal poverty guidelines are eligible. +metadata: + unit: /1 + period: year + label: MinnesotaCare children income limit as fraction of FPL + reference: + - title: Minnesota Statutes 256L.04 Subd. 1 - Eligibility for MinnesotaCare + href: https://www.revisor.mn.gov/statutes/cite/256L.04 + +values: + 2020-01-01: 2.0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_eligible.yaml new file mode 100644 index 00000000000..bcd74a9c327 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_eligible.yaml @@ -0,0 +1,119 @@ +- name: Eligible undocumented child under 200% FPL + period: 2025 + input: + households: + household: + state_code: MN + members: [child] + people: + child: + age: 10 + immigration_status: UNDOCUMENTED + medicaid_income_level: 1.5 # 150% FPL + output: + mn_minnesotacare_children_eligible: true + +- name: Ineligible - citizen child (should use federal programs) + period: 2025 + input: + households: + household: + state_code: MN + members: [child] + people: + child: + age: 10 + immigration_status: CITIZEN + medicaid_income_level: 1.5 + output: + mn_minnesotacare_children_eligible: false + +- name: Ineligible - undocumented child over income limit + period: 2025 + input: + households: + household: + state_code: MN + members: [child] + people: + child: + age: 10 + immigration_status: UNDOCUMENTED + medicaid_income_level: 2.5 # 250% FPL - above 200% threshold + output: + mn_minnesotacare_children_eligible: false + +- name: Ineligible - undocumented adult (must be under 18) + period: 2025 + input: + households: + household: + state_code: MN + members: [adult] + people: + adult: + age: 25 + immigration_status: UNDOCUMENTED + medicaid_income_level: 1.5 + output: + mn_minnesotacare_children_eligible: false + +- name: Ineligible - program not in effect before 2025 + period: 2024 + input: + households: + household: + state_code: MN + members: [child] + people: + child: + age: 10 + immigration_status: UNDOCUMENTED + medicaid_income_level: 1.5 + output: + mn_minnesotacare_children_eligible: false + +- name: Eligible at exactly 200% FPL + period: 2025 + input: + households: + household: + state_code: MN + members: [child] + people: + child: + age: 10 + immigration_status: UNDOCUMENTED + medicaid_income_level: 2.0 # Exactly 200% FPL + output: + mn_minnesotacare_children_eligible: true + +- name: Eligible 17-year-old (still under 18) + period: 2025 + input: + households: + household: + state_code: MN + members: [teen] + people: + teen: + age: 17 + immigration_status: UNDOCUMENTED + medicaid_income_level: 1.5 + output: + mn_minnesotacare_children_eligible: true + +- name: Ineligible 18-year-old (at age limit) + period: 2025 + input: + households: + household: + state_code: MN + members: [teen] + people: + teen: + age: 18 + immigration_status: UNDOCUMENTED + medicaid_income_level: 1.5 + output: + mn_minnesotacare_children_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_immigration_status_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_immigration_status_eligible.yaml new file mode 100644 index 00000000000..ff9cf323d5a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_immigration_status_eligible.yaml @@ -0,0 +1,51 @@ +- name: Undocumented - eligible for state program + period: 2025 + input: + households: + household: + state_code: MN + members: [person] + people: + person: + immigration_status: UNDOCUMENTED + output: + mn_minnesotacare_children_immigration_status_eligible: true + +- name: Citizen - should use federal programs + period: 2025 + input: + households: + household: + state_code: MN + members: [person] + people: + person: + immigration_status: CITIZEN + output: + mn_minnesotacare_children_immigration_status_eligible: false + +- name: Legal permanent resident - should use federal programs + period: 2025 + input: + households: + household: + state_code: MN + members: [person] + people: + person: + immigration_status: LEGAL_PERMANENT_RESIDENT + output: + mn_minnesotacare_children_immigration_status_eligible: false + +- name: Refugee - should use federal programs + period: 2025 + input: + households: + household: + state_code: MN + members: [person] + people: + person: + immigration_status: REFUGEE + output: + mn_minnesotacare_children_immigration_status_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_income_eligible.yaml new file mode 100644 index 00000000000..75c022e2998 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_income_eligible.yaml @@ -0,0 +1,51 @@ +- name: Income eligible - under 200% FPL + period: 2025 + input: + households: + household: + state_code: MN + members: [person] + people: + person: + medicaid_income_level: 1.5 # 150% FPL + output: + mn_minnesotacare_children_income_eligible: true + +- name: Income eligible - exactly at 200% FPL + period: 2025 + input: + households: + household: + state_code: MN + members: [person] + people: + person: + medicaid_income_level: 2.0 # 200% FPL + output: + mn_minnesotacare_children_income_eligible: true + +- name: Income ineligible - above 200% FPL + period: 2025 + input: + households: + household: + state_code: MN + members: [person] + people: + person: + medicaid_income_level: 2.1 # 210% FPL + output: + mn_minnesotacare_children_income_eligible: false + +- name: Income eligible - at 0% FPL + period: 2025 + input: + households: + household: + state_code: MN + members: [person] + people: + person: + medicaid_income_level: 0 + output: + mn_minnesotacare_children_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_cost_if_enrolled.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_cost_if_enrolled.yaml new file mode 100644 index 00000000000..43e74786086 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_cost_if_enrolled.yaml @@ -0,0 +1,47 @@ +- name: Eligible child cost + period: 2025 + absolute_error_margin: 1 + input: + households: + household: + state_code: MN + members: [child] + people: + child: + age: 10 + immigration_status: UNDOCUMENTED + medicaid_income_level: 1.5 # 150% FPL + output: + mn_minnesotacare_cost_if_enrolled: 3_775.59 # 2,382,000,000 / 631,000 + +- name: Ineligible person - zero cost + period: 2025 + absolute_error_margin: 0.01 + input: + households: + household: + state_code: MN + members: [adult] + people: + adult: + age: 30 + immigration_status: CITIZEN + medicaid_income_level: 1.5 + output: + mn_minnesotacare_cost_if_enrolled: 0 + +- name: Child over income - zero cost + period: 2025 + absolute_error_margin: 0.01 + input: + households: + household: + state_code: MN + members: [child] + people: + child: + age: 10 + immigration_status: UNDOCUMENTED + medicaid_income_level: 2.5 # Over 200% FPL + output: + mn_minnesotacare_cost_if_enrolled: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_group.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_group.yaml new file mode 100644 index 00000000000..9a73bd301c4 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_group.yaml @@ -0,0 +1,44 @@ +- name: Eligible child maps to CHILD group + period: 2025 + input: + households: + household: + state_code: MN + members: [child] + people: + child: + age: 10 + immigration_status: UNDOCUMENTED + medicaid_income_level: 1.5 + output: + mn_minnesotacare_group: CHILD + +- name: Ineligible person maps to NONE group + period: 2025 + input: + households: + household: + state_code: MN + members: [adult] + people: + adult: + age: 30 + immigration_status: CITIZEN + medicaid_income_level: 1.5 + output: + mn_minnesotacare_group: NONE + +- name: Undocumented child over income maps to NONE + period: 2025 + input: + households: + household: + state_code: MN + members: [child] + people: + child: + age: 10 + immigration_status: UNDOCUMENTED + medicaid_income_level: 2.5 # Over 200% FPL + output: + mn_minnesotacare_group: NONE diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/integration.yaml new file mode 100644 index 00000000000..56f05ec303c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/dhs/minnesotacare/integration.yaml @@ -0,0 +1,87 @@ +- name: Full eligibility flow - undocumented child under 200% FPL + period: 2025 + absolute_error_margin: 1 + input: + households: + household: + state_code: MN + members: [child] + people: + child: + age: 10 + immigration_status: UNDOCUMENTED + medicaid_income_level: 1.5 # 150% FPL + output: + mn_minnesotacare_children_income_eligible: true + mn_minnesotacare_children_immigration_status_eligible: true + mn_minnesotacare_children_eligible: true + mn_minnesotacare_group: CHILD + mn_minnesotacare_cost_if_enrolled: 3_775.59 + +- name: Citizen child - eligible for federal, not state program + period: 2025 + input: + households: + household: + state_code: MN + members: [child] + people: + child: + age: 10 + immigration_status: CITIZEN + medicaid_income_level: 1.5 + output: + mn_minnesotacare_children_income_eligible: true + mn_minnesotacare_children_immigration_status_eligible: false + mn_minnesotacare_children_eligible: false + mn_minnesotacare_group: NONE + mn_minnesotacare_cost_if_enrolled: 0 + +- name: Household with undocumented child and citizen parent + period: 2025 + absolute_error_margin: 1 + input: + households: + household: + state_code: MN + members: [parent, child] + people: + parent: + age: 35 + immigration_status: UNDOCUMENTED + medicaid_income_level: 1.5 + child: + age: 8 + immigration_status: UNDOCUMENTED + medicaid_income_level: 1.5 + output: + # Parent is not eligible (must be under 19) + # Child is eligible + mn_minnesotacare_children_eligible: [false, true] + mn_minnesotacare_group: [NONE, CHILD] + mn_minnesotacare_cost_if_enrolled: [0, 3_775.59] + +- name: Multiple children - mixed eligibility + period: 2025 + absolute_error_margin: 1 + input: + households: + household: + state_code: MN + members: [child1, child2, child3] + people: + child1: + age: 10 + immigration_status: UNDOCUMENTED + medicaid_income_level: 1.5 # Eligible + child2: + age: 10 + immigration_status: CITIZEN + medicaid_income_level: 1.5 # Not eligible - citizen + child3: + age: 10 + immigration_status: UNDOCUMENTED + medicaid_income_level: 2.5 # Not eligible - over income + output: + mn_minnesotacare_children_eligible: [true, false, false] + mn_minnesotacare_cost_if_enrolled: [3_775.59, 0, 0] diff --git a/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_eligible.py b/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_eligible.py new file mode 100644 index 00000000000..e5f080c2913 --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_eligible.py @@ -0,0 +1,56 @@ +from policyengine_us.model_api import * + + +class mn_minnesotacare_children_eligible(Variable): + value_type = bool + entity = Person + label = "Eligible for MinnesotaCare for children" + definition_period = YEAR + defined_for = StateCode.MN + reference = [ + "https://www.revisor.mn.gov/statutes/cite/256L.04", + "https://www.dhs.state.mn.us/main/groups/publications/documents/pub/mndhs-068276.pdf", + ] + documentation = """ + MinnesotaCare provides state-funded health coverage for undocumented + children under age 18 with family income at or below 200% FPL. + + The 2023 Minnesota Legislature expanded MinnesotaCare to include + undocumented individuals, with coverage beginning January 1, 2025. + Per subdivision 10(c), undocumented noncitizens age 18 or older have + restricted eligibility (only those enrolled as of June 15, 2025, and + losing eligibility January 1, 2026). Children under 18 continue to + be eligible. + + Per Minnesota Statutes 256L.04 subdivision 10: + "Notwithstanding subdivisions 1 and 7, eligible persons include families + and individuals who are ineligible for medical assistance by reason of + immigration status and who have incomes equal to or less than 200 percent + of federal poverty guidelines." + """ + + def formula(person, period, parameters): + p = parameters( + period + ).gov.states.mn.dhs.minnesotacare.child.eligibility + + # Program must be in effect (started January 1, 2025) + in_effect = p.in_effect + + # Must be under age 18 per subdivision 10(c) + age = person("age", period) + age_eligible = age < p.age_limit + + # Must meet income requirements (at or below 200% FPL) + income_eligible = person( + "mn_minnesotacare_children_income_eligible", period + ) + + # Must be undocumented (ineligible for federal programs) + immigration_eligible = person( + "mn_minnesotacare_children_immigration_status_eligible", period + ) + + return ( + in_effect & age_eligible & income_eligible & immigration_eligible + ) diff --git a/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_immigration_status_eligible.py b/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_immigration_status_eligible.py new file mode 100644 index 00000000000..eafdd875a92 --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_immigration_status_eligible.py @@ -0,0 +1,39 @@ +from policyengine_us.model_api import * + + +class mn_minnesotacare_children_immigration_status_eligible(Variable): + value_type = bool + entity = Person + label = "Has eligible immigration status for MinnesotaCare for children" + definition_period = YEAR + defined_for = StateCode.MN + reference = [ + "https://www.revisor.mn.gov/statutes/cite/256L.04", + "https://www.dhs.state.mn.us/main/groups/publications/documents/pub/mndhs-068276.pdf", + ] + documentation = """ + MinnesotaCare for undocumented children covers those who are ineligible + for federal medical assistance by reason of immigration status. + + Per Minnesota Statutes 256L.04 subdivision 10: + "Notwithstanding subdivisions 1 and 7, eligible persons include families + and individuals who are ineligible for medical assistance by reason of + immigration status and who have incomes equal to or less than 200 percent + of federal poverty guidelines." + + This state-funded coverage is for undocumented children who cannot access + federal Medicaid or CHIP due to their immigration status. Coverage is + delivered on a fee-for-service basis. + """ + + def formula(person, period, parameters): + immigration_status = person("immigration_status", period) + + # Only undocumented immigrants are eligible for this state-funded program + # Citizens and lawfully present immigrants should access federal programs + undocumented = ( + immigration_status + == immigration_status.possible_values.UNDOCUMENTED + ) + + return undocumented diff --git a/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_income_eligible.py b/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_income_eligible.py new file mode 100644 index 00000000000..48ba0097996 --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/child/eligibility/mn_minnesotacare_children_income_eligible.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class mn_minnesotacare_children_income_eligible(Variable): + value_type = bool + entity = Person + label = "Meets MinnesotaCare for children income eligibility" + definition_period = YEAR + defined_for = StateCode.MN + reference = [ + "https://www.revisor.mn.gov/statutes/cite/256L.04", + ] + documentation = """ + MinnesotaCare for children uses MAGI-based income at or below 200% FPL. + Per Minnesota Statutes 256L.04 subdivision 1, children with family income + at or below 200 percent of federal poverty guidelines are eligible. + """ + + def formula(person, period, parameters): + p = parameters( + period + ).gov.states.mn.dhs.minnesotacare.child.eligibility + + # Use MAGI-based income level (as fraction of FPL) + income_level = person("medicaid_income_level", period) + + # Eligible if at or below 200% FPL + return income_level <= p.income_limit diff --git a/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_cost_if_enrolled.py b/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_cost_if_enrolled.py new file mode 100644 index 00000000000..af5e993e550 --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_cost_if_enrolled.py @@ -0,0 +1,41 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.medicaid.costs.medicaid_group import ( + MedicaidGroup, +) + + +class mn_minnesotacare_cost_if_enrolled(Variable): + value_type = float + entity = Person + label = "Per capita MinnesotaCare cost by eligibility group" + unit = USD + definition_period = YEAR + defined_for = StateCode.MN + reference = [ + "https://www.revisor.mn.gov/statutes/cite/256L.04", + ] + documentation = """ + Calculates the per-capita cost of MinnesotaCare coverage based on the + person's eligibility group. Uses Minnesota state Medicaid cost data + by eligibility category. + + Note: MinnesotaCare for undocumented children is 100% state-funded + and delivered on a fee-for-service basis. + """ + + def formula(person, period, parameters): + group = person("mn_minnesotacare_group", period) + + p = parameters(period).calibration.gov.hhs.medicaid + + is_child = group == MedicaidGroup.CHILD + + # Use Minnesota state Medicaid cost data + child_spend = p.spending.by_eligibility_group.child["MN"] + child_enroll = p.enrollment.child["MN"] + + spend = where(is_child, child_spend, 0) + enroll = where(is_child, child_enroll, 0) + + # Calculate per-capita cost, avoiding divide-by-zero + return np.where(enroll > 0, spend / enroll, 0) diff --git a/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_group.py b/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_group.py new file mode 100644 index 00000000000..257b4b22365 --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/dhs/minnesotacare/costs/mn_minnesotacare_group.py @@ -0,0 +1,33 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.medicaid.costs.medicaid_group import ( + MedicaidGroup, +) + + +class mn_minnesotacare_group(Variable): + """Maps MinnesotaCare eligibility to Medicaid spending groups. + + MinnesotaCare for undocumented children → CHILD + """ + + value_type = Enum + possible_values = MedicaidGroup + default_value = MedicaidGroup.NONE + entity = Person + label = "MinnesotaCare spending group" + definition_period = YEAR + defined_for = StateCode.MN + reference = [ + "https://www.revisor.mn.gov/statutes/cite/256L.04", + ] + + def formula(person, period, parameters): + children_eligible = person( + "mn_minnesotacare_children_eligible", period + ) + + return where( + children_eligible, + MedicaidGroup.CHILD, + MedicaidGroup.NONE, + )