You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
Expedited screening at submission — evaluates submitted data against federal thresholds; emits eligibility.application.expedited
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
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?
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
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-expeditedtransition (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:
eligibility.application.expeditedeligibility.application.prescreenedwith per-program eligibility indicators based on current (potentially unverified) data; informs caseworker expectations; not a legal determinationeligibility.application.determination_completedper person per program, theneligibility.application.all_determinedwhen all combinations resolvedPre-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-screeningapplication.review_completed→ full determination run for all undetermined program+member combinations2. What events does the eligibility domain publish?
Event naming follows
{domain}.{entity}.{action}convention:eligibility.application.expedited— expedited criteria met; intake setsisExpedited = true; workflow subscribes directly to assign expedited SLA trackeligibility.application.prescreened— per-program indicators (likely_eligible | needs_review | likely_ineligible); fires at submission and on re-evaluation when material verification results arrive; informational onlyeligibility.application.determination_completed— legally binding determination; fires per person per program as each resolves; may fire multiple times on a single applicationeligibility.application.all_determined— fires once when no undetermined program+member combinations remain; triggers intake to update final application status and close the application3. How does expedited status get set?
Federal criteria (7 CFR § 273.2(i) for SNAP) evaluated against submitted data:
The eligibility domain applies these criteria at
application.submittedand emitseligibility.application.expedited. Intake setsisExpedited = trueon the application. Workflow subscribes directly toeligibility.application.expeditedto assign the expedited SLA track — intake does not re-publish. Theflag-expeditedtransition andapplication.expedited_flaggedevent 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.prescreenedandeligibility.application.determination_completedfire at submission:prescreenedserves caseworker visibility;determination_completedcarries the legally binding result. When pre-screening is inconclusive, onlyprescreenedfires 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_medicareandfdsh_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_completedfires per person per program before any caseworker assignment. When all combinations are resolved,eligibility.application.all_determinedfires. 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. Fireseligibility.application.determination_completedper person per program, theneligibility.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 onApplicationMember. 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_determinedpackages/contracts/eligibility-rules.yaml— screening rules for expedited criteria and pre-screening logic per programpackages/contracts/intake-rules.yaml— subscribe toeligibility.application.determination_completedandeligibility.application.all_determined; wire pre-screening re-evaluation triggersapplication.review_completeddocumented as the trigger for manual determination;eligibility.application.expeditedandeligibility.application.all_determinedadded to subscribed events;application.expedited_flaggedandflag-expeditedtransition removed (see Implement intake contract surface for application submission flow #248)Validation
eligibility.application.expedited,eligibility.application.prescreened,eligibility.application.determination_completed,eligibility.application.all_determined) with CloudEvents-compatible schemaseligibility.application.determination_completedschema includes person and program identifierseligibility.application.all_determinedschema includes application identifiereligibility.application.prescreenedevent emittedeligibility-rules.yamlagainst submitted application fields