PolicyEngine / PolicyEngine/policyengine-us
Lifeline categorical eligibility omits Veterans and Survivors Pension Benefit (47 CFR 54.409(a)(2))
- 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
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