PolicyEngine / PolicyEngine/policyengine-us

Lifeline categorical eligibility omits Veterans and Survivors Pension Benefit (47 CFR 54.409(a)(2))

Open
#9,388 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
162
Forks
212
Avg merge
3d 3h
Merged PRs (30d)
97

Description

## Summary

[47 CFR § 54.409(a)(2)](https://www.ecfr.gov/current/title-47/section-54.409#p-54.409(a)(2)) lists five programs whose participants qualify for Lifeline: Medicaid, SNAP, SSI, Federal Public Housing Assistance, and the Veterans and Survivors Pension Benefit. After #9378 (FPHA, closes #9376), `gov.fcc.lifeline.categorical_eligibility` covers four of the five. The pension route is still only a comment:

```yaml
# Also not implemented:
# - Veterans and Survivors Pension Benefit
```

Because `is_acp_eligible` reads the same Lifeline list, ACP has the same gap.

## Why it is not a one-line fix

The only veterans input is `veterans_benefits` (Person, YEAR, USD). It is the CPS ASEC `VET_VAL` total, which pools all VA payments: disability compensation, DIC, pension, education benefits, and other. There is no pension-only component in the data or the model, and `is_veteran` is defined as `veterans_benefits > 0` (see #5238).

Adding `veterans_benefits` to the list therefore treats any VA payment as the pension. The regulation qualifies only Veterans Pension and Survivors Pension recipients, which are themselves means-tested (38 U.S.C. 1521, 1541). A veteran receiving disability compensation with income above 135% FPG would be wrongly qualified.

## Options

1. **Add `veterans_benefits` as is**, with a comment documenting the over-inclusion. API partners can be told to populate it only with pension amounts for this purpose. Microsimulation aggregates are unaffected today because `phone_cost` and `broadband_cost` are never populated in policyengine-us-data, so `lifeline` is $0 for every record.
2. **Add a reported-receipt flag** for VA pension (parallel to `receives_ssi`, `receives_snap`, `receives_housing_assistance`) and put that in the list. Cleaner semantics, but it is a new input with no survey source.
3. **Leave the gap documented** and close this issue as won't-fix.

Option 1 or 2 should also be applied to `is_acp_eligible` implicitly via the shared list; no ACP code change is needed.

## Files

- `policyengine_us/parameters/gov/fcc/lifeline/categorical_eligibility.yaml`
- `policyengine_us/variables/gov/fcc/lifeline/is_lifeline_eligible.py`
- `policyengine_us/variables/gov/fcc/acp/is_acp_eligible.py`
- `policyengine_us/variables/household/income/person/veterans_benefits.py` (input, no formula)

## Related

- #9376 / #9378: FPHA route (this issue is the last missing program from the same regulation, raised as a follow-up in review there).
- #5238: consolidate `is_veteran`, which has the same root cause (`veterans_benefits` is an aggregate).
- #9389: the veteran and active-duty exception in the federal noncitizen rules needs a veteran-status signal that is likewise not derivable from `veterans_benefits`.

Contributor guide

Open the contributing guide

Research direction

Start with policyengine_us/parameters/gov/fcc/lifeline/categorical_eligibility.yaml and compare the shared eligibility logic in policyengine_us/variables/gov/fcc/lifeline/is_lifeline_eligible.py and policyengine_us/variables/gov/fcc/acp/is_acp_eligible.py. Read veterans_benefits.py and the related issues to resolve whether the aggregate input is acceptable or a new receipt signal is needed. Done means the chosen pension semantics are documented and applied consistently without changing unrelated veteran eligibility.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.