Journey: A retroactive income correction recomputes a SNAP overpayment

On this page

A SNAP household is approved; the system auto-enrolls it (#1014) and the settlement pass issues the current benefit month. A retroactive income correction then comes to light — the household was over-income as of its determination date. The caseworker recomputes the frozen determination snapshot against the corrected facts; the replay denies, so the benefits already paid are clawed back into an overpayment claim, and an overpayment notice is generated. The caseworker beats — authoring the correction and running the recompute — are followable click-by-click in the worker portal; enrollment and issuance are the system’s own production behavior, observed on the case.

NOTE

Reproducibility tier: Harness. The aged precondition this journey needs — an approved SNAP determination backdated ~3 months — is constructed by a one-command harness bring-up (the paired spec’s SnapCaseBuilder), not by hand and not through the applicant portal. For a live demo, run the paired spec (or its harness) to build the aged case, then walk the caseworker steps below against it.

IMPORTANT

This walkthrough is paired with the automated spec tests/e2e/specs/journey-snap-overpayment-recompute.spec.ts, covering scenario snap.integrity.claim-calculation-lookback. The screenshots below are captured by that spec (Test 1). See Verifying the journey to run it.

Personas & credentials

Persona Credentials / identity Role in the journey

Applicant

N/A for this journey. The aged case is built by the test harness — a determination backdated ~3 months is not portal-fileable (there is no worker "backdate-determination" action) — so no application is filed through /apply and there is no HH-… reference + passcode to sign back in with at /lookup. The applicant view-back is out of scope here (honest scope: a given-library case carries no ADR-026 credential, not a portal gap).

The household exists only as harness-constructed facts (a single working-age adult, reported wages) — the case the system enrolls + pays and the journey then recoups from.

Caseworker

Worker portal, Keycloak login jane.caseworker / password (see UAT Facilitator Guide).

Observes the system’s auto-enrollment on the case, authors the retroactive income correction, and recomputes the overpayment.

Bring-up & reset

cargo xtask dev start --profile full   # full devstack (SNAP + applications + enrollment + notices)
cargo xtask seed --seed 42             # deterministic fixtures

Reset between runs with cargo xtask migrate rollback (and a fresh browser / incognito window for the worker session). The Demo Runbook owns the full bring-up + reset detail; this page owns the click-by-click steps.

Concrete precondition

The paired spec’s harness builds exactly this aged case (all records backdated together to the determination date):

  • Household composition — a single working-age adult, head of household, no dependents (headMember, date of birth 1985-06-15).

  • Initial reported income$600/month in wages. That clears the SNAP gross-income test, so the application determines Approved — the starting point for the enrollment and issuances.

  • Backdated determination — the household, application, and determination are dated as of the first of the month ~3 months ago (asOf), so the paid months precede today.

  • Enrollment + paid benefits — approval auto-enrolls the household (#1014) and the settlement pass issues + settles the current benefit month at the determination’s net monthly benefit. That settled issuance is exactly the paid row the claim sizes against: the recompute window is pinned to the current month at both ends (the determination’s effective_date is the decision day), so backdated months could never contribute. A mailing address is also seeded so the overpayment notice can resolve its postal recipient (the #1091 gate).

  • Retroactive correction$9,000/month in wages, effective as of the determination date. This is a construction extreme (well over any SNAP gross-income limit), so the corrected replay denies and the overpayment is positive.

  • Recompute inputs — correction-as-of = the determination date; claim basis = Agency error.

The walkthrough, step by step

# Screen Action Expected Screenshot

01

Caseworker

Open the approved case (/cases/<HH-…>?program=snap) → Determination tab (a few seconds after approval).

The SNAP program shows Approved, and the SNAP enrollment section shows the auto-enrollment (#1014) with the current benefit month issued — no worker action; this is production behavior on approval.

Approved case with auto-enrollment

02

Caseworker

Open the Income tab → + Add income, record the corrected (higher) wages effective ~3 months ago.

The retroactive over-income fact is recorded, effective as of the determination date.

Retroactive income form

03

Caseworker

DeterminationActionsRecompute overpayment; enter the correction date + claim basis (Agency error).

The snapshot replays against the corrected facts; the corrected verdict denies, sizing an overpayment over the paid month.

Recompute form

04

Caseworker

Open the Notices tab.

The overpayment notice is listed (matched by its subject, not a bare count) — the human-visible consequence of the recompute (the claim opens in the SNAP ledger).

Overpayment notice

Expected outcome / oracle

The recompute replays the frozen determination snapshot against the corrected facts. Because the retroactive income is over the limit, the corrected verdict denies, so the benefits the system already paid (the settled current-month auto-issuance) are clawed back into an open overpayment claim in the SNAP ledger (agency_error basis, positive amount), and an overpayment notice is generated on the Notices tab.

The oracle is relational, never a literal policy dollar:

  • A claim opens with a positive amount (the construction extreme guarantees > 0) that equals the settled auto-issuance — the clawback is exactly what was paid.

  • Its overpayment notice surfaces on the Notices tab, matched by subject identity.

  • The replay is write-free — it mints no new determination.

  • The recompute is idempotent — re-running it returns the same claim (same amount, same id), never a second claim.

No policy dollar figure or threshold is asserted, so the journey holds under any jurisdiction’s values.

Honest scope

  • The aged case is a documented one-command harness bring-up. A determination backdated ~3 months with prior issuances the claim looks back on is neither hand-buildable nor portal-fileable (there is no worker "backdate-determination" action; the signed, snapshotted determination of ADR-002/028 is only reachable through the harness’s live apply→determine path). The paired spec constructs it; the caseworker beats after it are the human-followable part. A worker backdate-determination affordance (#999) would let this journey be filed at the portal front door and gain an applicant view — until then it is worker-only.

  • The applicant /lookup view is N/A. The given-library case files no portal application, so it carries no ADR-026 reference + passcode — there is no applicant view-back to demo (honest scope, not a portal gap).

  • Enrollment + issuance are the system’s own production path. Approval auto-enrolls the household (#1014) and the settlement pass issues + settles the current month; the journey waits for that instead of constructing it — a manual backdated enrollment cannot coexist with the auto-enrollment (#1130 one-live-enrollment), and the recompute window is pinned to the current month, so the auto-issuance is exactly the countable paid row.

  • Issued amounts equal the household’s net monthly benefit. The determination exposes only the household’s net benefit (not a gross maximum allotment), and the auto-enrollment issues that amount — the correct real-world issuance for a household with income.

  • The overpayment claim has no per-case worker screen. Its human-visible consequence is the overpayment notice on the Notices tab (the last step); the claim itself is verified programmatically in the paired spec.

Verifying the journey

cargo xtask e2e --devstack-profile full -- \
  specs/journey-snap-overpayment-recompute.spec.ts --project journey

Test 1 builds the approved, backdated SNAP household through the real apply→determine endpoints, waits for the system’s auto-enrollment to settle the current benefit month, then drives the worker arc through the portal — authoring the retroactive income correction and recomputing the overpayment — capturing the step screenshots into test-results/e2e/walkthroughs/… for commit into docs/modules/ROOT/assets/images/walkthroughs/…. The correctness oracle is relational: the recompute opens an overpayment claim in the SNAP ledger with a positive amount and generates an overpayment notice, while minting no new determination (the replay is write-free) and returning the same claim on re-run (idempotent) — no policy dollar figure is asserted, so it holds under any jurisdiction’s values. (Tests 2–3 exercise the recompute endpoint directly for the forward-effective rejection + the no-over-issuance case.)

See also

Edit this page · default