Skip to content

Define eligibility domain contract and intake interaction model #250

Description

@mryhmln

Background

The eligibility domain is responsible for all eligibility logic — screening, pre-screening, and determination — across SNAP, Medicaid, and other programs. Currently the intake state machine has a flag-expedited transition (actors: [system]) that signals expedited status, but the evaluator — the component that applies federal expedited criteria against submitted application data — is not defined in any contract. The eligibility domain also interacts with intake at multiple points beyond initial screening, none of which are yet formally specified.

Three distinct eligibility domain interactions with intake have been identified through service blueprint design:

  1. Expedited screening at submission — evaluates submitted data against federal thresholds; emits eligibility.application.expedited
  2. Program pre-screening at submission and on re-evaluation — emits eligibility.application.prescreened with per-program eligibility indicators based on current (potentially unverified) data; informs caseworker expectations; not a legal determination
  3. Full determination when all verification items are resolved — runs the complete rules engine against verified data; legally binding; emits eligibility.application.determination_completed per person per program, then eligibility.application.all_determined when all combinations resolved

Pre-screening is not a one-time operation. Federal verification results arrive asynchronously (IEVS, FDSH, SSA). Income reported by the applicant may differ from what IEVS returns; citizenship status may be unclear until FDSH responds. The eligibility domain should re-evaluate and emit updated indicators at material trigger points throughout review — not only at submission. This follows the pattern used by IBM Curam (in-progress eligibilities), Salesforce Government Cloud (continuous eligibility), and CMS MES guidelines (rolling eligibility evaluation).

Design decisions

1. What events does the eligibility domain subscribe to?

  • application.submitted → expedited screening + initial program pre-screening
  • Verification result events → re-run pre-screening when material results arrive (IEVS income, FDSH citizenship, SSA disability status)
  • application.review_completed → full determination run for all undetermined program+member combinations

2. What events does the eligibility domain publish?

Event naming follows {domain}.{entity}.{action} convention:

  • eligibility.application.expedited — expedited criteria met; intake sets isExpedited = true; workflow subscribes directly to assign expedited SLA track
  • eligibility.application.prescreened — per-program indicators (likely_eligible | needs_review | likely_ineligible); fires at submission and on re-evaluation when material verification results arrive; informational only
  • eligibility.application.determination_completed — legally binding determination; fires per person per program as each resolves; may fire multiple times on a single application
  • eligibility.application.all_determined — fires once when no undetermined program+member combinations remain; triggers intake to update final application status and close the application

3. How does expedited status get set?

Federal criteria (7 CFR § 273.2(i) for SNAP) evaluated against submitted data:

  • Gross income < $150/month AND liquid resources ≤ $100
  • Combined monthly income and liquid resources less than monthly rent/mortgage and utilities
  • Migrant or seasonal farm worker household with little or no income

The eligibility domain applies these criteria at application.submitted and emits eligibility.application.expedited. Intake sets isExpedited = true on the application. Workflow subscribes directly to eligibility.application.expedited to assign the expedited SLA track — intake does not re-publish. The flag-expedited transition and application.expedited_flagged event are being removed from intake contracts (see #248).

4. How does pre-screening relate to final determination?

Pre-screening indicators are informational — they carry no legal weight and must not be surfaced to applicants as decisions. Caseworkers can see pre-screening indicators alongside verification obligations so they have full context when beginning review.

When all electronic checks at submission are conclusive (Medicaid auto-determination path, 45 CFR § 435.911), pre-screening directly produces a legally binding determination. In that case both eligibility.application.prescreened and eligibility.application.determination_completed fire at submission: prescreened serves caseworker visibility; determination_completed carries the legally binding result. When pre-screening is inconclusive, only prescreened fires at submission and the manual caseworker path proceeds.

5. Multi-program applications

Pre-screening indicators are produced per program. Results from shared federal checks (FDSH, SSA, SAVE) are shared across programs rather than re-run per program — IEVS is the exception as a SNAP-specific federal mandate. Eligibility also initiates its own data exchange calls — fdsh_medicare and fdsh_vci — to check existing coverage as a determination input. These are not intake Verification obligations: there is no applicant-facing document fallback, and the results inform eligibility determination directly.

6. Two paths to determination

Both paths converge at eligibility.application.all_determined:

  • Auto-determination (Medicaid only): Eligibility proceeds directly from conclusive pre-screening results at submission — no separate trigger event. eligibility.application.determination_completed fires per person per program before any caseworker assignment. When all combinations are resolved, eligibility.application.all_determined fires. Intake cancels the workflow intake task (which was created at submission but never routed) and closes the application.

  • Manual determination (SNAP always; Medicaid when checks inconclusive): After caseworker completes review and submits, intake fires application.review_completed. Eligibility runs the rules engine for all undetermined program+member combinations — skipping any already auto-determined at submission. Fires eligibility.application.determination_completed per person per program, then eligibility.application.all_determined. Caseworker records determination and rationale; supervisor approval may be required.

7. Open: how does intake record determination results?

When intake receives eligibility.application.determination_completed, it needs somewhere to record the per-person per-program outcome so caseworkers can see it and so the application knows when all programs are resolved. This likely requires a new entity (e.g., ProgramStatus) or fields on ApplicationMember. Not yet designed — to be resolved in the intake contract implementation issue.

What needs to be defined

  • packages/contracts/eligibility-openapi.yaml — new domain contract covering the eligibility API, entity schemas (EligibilityAssessment, EligibilityIndicator, Determination), and published events (x-events): eligibility.application.expedited, eligibility.application.prescreened, eligibility.application.determination_completed, eligibility.application.all_determined
  • packages/contracts/eligibility-rules.yaml — screening rules for expedited criteria and pre-screening logic per program
  • packages/contracts/intake-rules.yaml — subscribe to eligibility.application.determination_completed and eligibility.application.all_determined; wire pre-screening re-evaluation triggers
  • Intake contract updates — application.review_completed documented as the trigger for manual determination; eligibility.application.expedited and eligibility.application.all_determined added to subscribed events; application.expedited_flagged and flag-expedited transition removed (see Implement intake contract surface for application submission flow #248)

Validation

  • Eligibility domain contract defines all four events (eligibility.application.expedited, eligibility.application.prescreened, eligibility.application.determination_completed, eligibility.application.all_determined) with CloudEvents-compatible schemas
  • Pre-screening indicators clearly typed as informational (not determinations) in the schema
  • eligibility.application.determination_completed schema includes person and program identifiers
  • eligibility.application.all_determined schema includes application identifier
  • Intake rules subscribe to eligibility events at the correct trigger points
  • Re-evaluation trigger documented: submit application → mock IEVS result arrives → verify updated eligibility.application.prescreened event emitted
  • Expedited criteria are expressed as evaluable rules in eligibility-rules.yaml against submitted application fields

Metadata

Metadata

Assignees

No one assigned

    Labels

    designArchitectural design and documentationenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions