Journey: a TANF case closing for employment freezes SNAP into a transitional certification

On this page

A public-assistance household is on both SNAP and TANF with no earned income. The applicant files the SNAP application through the real portal front door; the caseworker runs the SNAP determination, files and approves TANF over the shared facts, then records the new earnings when the family gets a job — earnings that close the TANF case for an employment reason. Rather than let the SNAP benefit swing, the agency freezes the SNAP allotment at its pre-closure level for a five-month transitional certification and relieves the household of reporting (7 CFR 273.26-273.29 / PAMMS SNAP 3704). The caseworker reads the frozen transitional certification back on the SNAP Determination tab, and the applicant signs back in to view their home and letters.

NOTE

Reproducibility tier: Worker-driven. The applicant files an identity-and-composition-only shell at the portal (the wizard captures who is in the household and which income categories apply — never dollar amounts). Every fact that drives the outcome — the new earnings, both determinations, the TANF closure — is recorded by the caseworker in the worker portal. For a live demo that means the story reproduces deterministically from the worker clicks; the only applicant-portal beats are the initial filing and the closing view-back.

IMPORTANT

This walkthrough is paired with the automated spec tests/e2e/specs/journey-snap-transitional-benefits-on-tanf-closure.spec.ts, covering scenario snap.certification.transitional-benefits-on-tanf-closure. The screenshots below are captured by that spec. See Verifying the journey to run it.

Personas & credentials

Persona Credentials / identity Role in the journey

Applicant

Files at the portal /apply front door (canopy-portal, :8090, unauthenticated). A reference number (HH-…) + 12-digit passcode are revealed on submit; signs back in at /lookup with that pair.

Files the SNAP application (identity + two dependent children, no amounts), then signs back in to view their home + letters.

Caseworker

Worker portal (canopy-web, :8080), Keycloak login jane.caseworker / password (a see-all worker; see UAT Facilitator Guide).

Runs the SNAP determination, files + approves TANF, records the earnings, re-determines TANF (closing it), reads back the frozen cert.

Bring-up & reset

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

Reset between runs (so the applicant files a fresh case each time):

cargo xtask migrate rollback             # roll the demo DBs back
# then re-seed, and use a fresh browser / incognito window for the applicant

The full demo procedure and the seeded applicant cast live in Applicant Portal Seed Credentials and the UAT Facilitator Guide.

Concrete precondition

The exact inputs the journey depends on:

  • Applicant filed at /apply — head of household Tanya Brooks, DOB 1985-06-15, no earned income at filing.

  • Two dependent children on the application — Miles Brooks (DOB 2016-04-10) and Nora Brooks (DOB 2019-08-22), each relationship child. The two dependent children are what make the household TANF-eligible (orchestrator-inferred deprivation) and set the SNAP household size that fixes the frozen allotment.

  • Earnings the caseworker records — new Wages of $5,000 / month for the head, effective the day of the demo, recorded once through the Income tab. This is the "got a job" life-event that pushes the household over the TANF ceiling. It is a construction input, not an oracle — no dollar figure is asserted anywhere.

No address or expense facts are needed (this journey does not exercise those editors). The portal-filed case starts with zero income/expense facts by construction.

The walkthrough, step by step

# Screen Action Expected Screenshot

01

Applicant

At /apply, file the SNAP application: About you (Tanya Brooks, no income), add the two children, no safety flag, "No one works right now", submit.

The confirmation screen reveals the reference number (HH-…) and 12-digit passcode.

Applicant credential reveal

02

Caseworker

Open the portal-filed case (/cases/<HH-…>?program=snap) → Action ▾ → Run Determination.

SNAP is Approved at the maximum allotment (zero income) — the pre-closure level that will be frozen.

SNAP approved

03

Caseworker

Open the top-bar Action ▾ dropdown → under File application, tick TANF and click File application.

Redirects to the case’s TANF view — the household now has a pending TANF application.

File TANF application

04

Caseworker

Open Action ▾Run Determination on the TANF view.

TANF is Approved over the shared household facts — the household is on TANF + SNAP.

TANF approved

05

Caseworker

Open the Income tab → the head of household’s + Add income → record the new Wages ($5,000 / month), submit.

The earnings are recorded once in the shared fact store; the page returns to the Income section.

Report earnings

06

Caseworker

Re-run the TANF determination (Action ▾ → Run Determination on the TANF view).

TANF flips to Denied for earned income — the case closes, triggering the transitional certification.

TANF closed

07

Caseworker

Return to the SNAP Determination tab (/cases/<HH-…>?program=snap).

A Transitional SNAP certification card shows the frozen allotment (= the pre-closure allotment), the five-month period, the closure reason, and that reporting is waived.

Transitional SNAP certification

08

Applicant

Sign back in at /lookup with the HH-… reference number + passcode.

Lands on the applicant home with the personalised greeting.

Applicant home

09

Applicant

Open the Letters page and click the latest letter.

The Notice of Action (the SNAP approval) is listed and opens — the portal→worker→portal loop closes.

Applicant letter

Expected outcome / oracle

The relations the spec asserts (never a literal policy dollar or threshold):

  • A five-month transitional SNAP certification appears — polled, because the tanf.case_closed subscriber opens it asynchronously in canopy-snap’s own DB; its absence would mean the closure→TSNAP pipeline did not fire.

  • The freeze holds: the frozen allotment equals the pre-closure SNAP allotment, and both are > 0 (the pre-closure allotment is read back — no dollar asserted).

  • Reporting is waived (reporting_required = false) and the closure reason is an employment trigger (one of employment / earned_income / increased_hours / new_employment) — pinning the closure as employment-driven.

  • The window is exactly five whole months (certification_end - certification_start).

  • Every one of those values is displayed on the SNAP Determination tab (the data-tsnap-* hooks match the polled cert).

  • The applicant round-trip: signing back in lands on the home greeting, and at least one letter (the SNAP approval NOA) is present on the Letters page.

Honest scope

  • Closure is modelled as a denying re-determination. There is no dedicated "close TANF case" action — the platform emits tanf.case_closed on any TANF denial, so the job that pushes income over the TANF ceiling and denies the re-determination is the closure that triggers the transitional certification.

  • The applicant portal captures categories, not amounts. The wizard records who is in the household and which income categories apply, never dollar figures, so the portal-filed case starts with zero income/expense facts — the caseworker records every dollar the journey needs (this is why the tier is Worker-driven).

  • The pre-closure SNAP allotment is the max allotment here. The household starts at $0 earned income (living on the TANF grant), and the SNAP determination is computed without the TANF grant in its income stack (a construction simplification), so the frozen figure is the maximum allotment for the household size. The relation that matters — frozen = the pre-closure allotment — holds regardless; no dollar is asserted.

  • The removed-TANF-grant amount is not shown. It is not carried on the closure event, so the display omits it rather than showing a misleading zero.

  • The cert fields are a read-back, not enforced workflow. The five-month reevaluation-before-end and the reporting relief are shown as certification facts; the platform does not yet drive the end-of-period recertification as a workflow.

  • TANF deprivation is orchestrator-inferred (marked provisional), so the TANF leg exercises the demo-grade deprivation path; the income test that drives the closure is real.

  • The display is program-scope gated. The Transitional SNAP certification is SNAP data — a worker not in SNAP program scope does not see it.

Verifying the journey

cargo xtask e2e --devstack-profile full -- \
  specs/journey-snap-transitional-benefits-on-tanf-closure.spec.ts --project journey

The spec files the SNAP application through the real /apply wizard (an applicant context against :8090), runs the SNAP determination, files + approves TANF through the worker Action ▾ actions, records the new earnings through the Income tab, and re-runs the TANF determination to close the case — capturing the step screenshots (step-NN-… worker, app-NN-… applicant) into test-results/walkthroughs/… for commit into docs/modules/ROOT/assets/images/walkthroughs/…. The correctness oracle polls the transitional certification and asserts the relational invariants: the frozen allotment equals the pre-closure allotment (both > 0), reporting is waived, the closure reason is an employment trigger, and the window is exactly five months — then confirms every value is displayed on the SNAP Determination tab and that the applicant can sign back in and read their letter.

Edit this page · default