Plan: SG/NRSG (UAS 552/550) Guardianship-Subsidy Flow (#1070 program)
On this page
- Status
- Context
- The flow at a glance
- Decisions
- Program shape
- G1 — backend (commits C1–C5, each J-reviewed)
- G2 — web + e2e + web docs + close-out
- Test matrix (all
@axis-tagged; representative) - Risks
- ⁂ #1073 additions (enabling
SUBSIDY_SG= recorded consent) - Review dispositions (external findings → where fixed)
Status
| Step | Description | Status |
|---|---|---|
Step 0 |
GitLab filing: #1070 weight 3→8 + |
Done (2026-07-24) — all filed; decision comment on #1070 |
G0 (fix MR) |
Date-only form values become noon-UTC instants: |
Done (2026-07-24) — MR !1035 (impl 1b4da28c697619827fb0b0dabd52db651a49b2f8, merge 5c0c07e92aeddefc7285b41ea0d0f3b2a67ee073); #1111 closed. Interleaved detour merged first on its own branch: #1117 occupancy-trigger stale-count race (MR !1034, merge 7c30f61a4953d6a31fe71aed8aafa705b30880a0) — it was failing every battery’s invariant sweep; forensics on the issue |
G1 (MR1) |
Backend: program-tagged create request (7-variant, closed-cohort typed |
Done (2026-07-24) — MR !1036 merged 64c24523836f09e4d44696e51f269a902d88c134; commits 80e135ab (plan) / 52577601 (C1) / 5855452a (C2) / 614bd688 (C3) / 364d7b11 (C4) / 6ce1f342 (C5), each fresh-subagent J-reviewed with all findings remediated pre-commit (highlights: the C2 honest-StaleHead replay fix, the C4 exact-match reason vocabulary killing a padded-token witness bypass, the C4-caught missing F9 witness, the C5 stale fixture comment). Full battery green (21 validate stages, unit/integration, 278 e2e, SDK suites). Discovered work filed: #1119 (pre-existing intake-edge-crypto flake). Deviations recorded in §C5 + Execution notes |
G2 (MR2) |
Web + e2e + close-out: guardianship enrollment form (program radio 552/550; per-render |
Done (2026-07-24) — the G2 MR: W1 454fbbb8 (the BFF surface, J-reviewed — SS6 factored into a pure unit-pinned decision, scope-honest wording), W2 the e2e layer (the dana.county 8-step arc on fixture E; 286-green full battery; J-reviewed — the midnight race + two comment nits fixed, pre-existing orphan spec filed as #1120), W3 docs + close-out (runbook, CHANGELOG, ⁂ on #1073, this archive move). Program complete — #1070 closes with this MR |
Issues: #1070 (tracking; G2 closes) · #1111 G0 (closed) · #1112 #1113 #1114 #1115 #1116 follow-ups · #1117 (closed, interleaved fix) · discovered mid-program: #1118 (seed ruleset DO-NOTHING fallback), #1119 (intake-edge-crypto e2e flake), #1120 (zero-project orphan spec)
Branches: fix/1111-date-only-noon-instants (merged) · feature/1070-sg-backend (this plan = first commit) · feature/1070-sg-web
Provenance: 3-reader recon + Plan-agent internal pass + primary verification pass (seed families A/B read in source) + the user’s external review (2026-07-24, ~45 findings — authoritative). The finding→disposition index is in §Review dispositions.
Context
The #1069 ERR program landed the machine: temporal agreement ledger (ADR-052), action-bound proofs
(ADR-054), the generator’s single expected_month_row judgment (ADR-053/055), F8 create
idempotency, the placement S2S eligibility read, default-off consent knobs, and the BFF/e2e
patterns.
SG (Subsidized Guardianship, relative, UAS 552) and NRSG (non-relative, UAS 550) are the
post-permanent-guardianship monthly subsidy per GA 22.8: the A&A is signed BEFORE the guardianship
transfer; ≥6 months prior residence under DFCS supervision (a 6-vs-12 manual discrepancy is ⁂ on
#1073); payments start the 1st of the month AFTER transfer — and when the caregiver received TANF
for the child, the month after TANF terminates, whichever is later; eligibility further requires
citizenship/residency, child income eligibility, an approved kinship assessment / foster-home
evaluation, County Director approval, a non-reunification permanent-guardianship order through age
18, and (SG only) the TANF degree of relationship. Enhanced variants (ERSG/ENRSG) closed
2014-08-01. 12-month renewal + 6-month paper reviews run from the initial or most recent approval
(22.9; the paper track is already generic in types_for_program).
Before this program, native SG enrollment was publicly unreachable (the store-level two-step
existed but was test-only and stamp-forgeable); the HTTP transition endpoint reserves
pending → active for this flow; guardianship finalization was a generic placement end that voids
undisbursed payments and silently strands support — financial’s consumer dropped the producer’s
end_reason. Two pre-existing defects surfaced by this plan’s review: date-only form values landed
a day early on the Eastern calendar (G0, fixed) and ended placements accept silent terminal-fact
edits (#1112, filed).
The flow at a glance
-
Sign — a county director creates a PENDING sg/nrsg agreement from the signed A&A. The anchoring placement is S2S-verified ACTIVE; child/case/worker and the residence-start snapshot derive from it. F8-idempotent. Provisional review anchors run from this approval act.
-
Finalize — the operator ends the placement with
end_reason=guardianship. If NO pending family agreement exists, the BFF refuses first and requires an explicit acknowledgement checkbox (support will stop) — the create-it-first prompt happens BEFORE the irreversible end. -
Hand off — the predecessor ERR is terminated with the new
guardianship_finalizedreason; its business date is REQUIRED to equal the placement’s derived end date (truth-dated). -
Activate — activation refuses while any other open agreement exists for the child (ERR first, deterministically). CRAIG derives
transfer_onfrom the placement’s end date, checks the witnesses (signed strictly before transfer; residence floor from the stored snapshot; guardianship ending; goal not reunification; court-order evidence), stores the money boundarypayments_begin_month = max(month after transfer, month after TANF termination), and re-derives the review anchors from this approval act (22.9’s "most recent approval"). -
Pay — the generator pays from
payments_begin_month; months before it are skipped with a named reason. ERR’s final month and SG’s first month never overlap; a transfer ON the 1st leaves that month unpaid by both programs (the strict texts' own artifact, ⁂ flagged).
Create + activate sit behind CRAIG_FINANCIALSUBSIDY_SGENABLED (default OFF) — an
ENROLLMENT-consent knob: existing agreements' lifecycle (generator, transitions including
guardianship_finalized, reviews, sweep) is deliberately NOT gated (grandfathered, tested).
Decisions
| # | Decision | Source |
|---|---|---|
U1 |
ONE create route: |
review-hardened |
U2 |
Two-step: create mints PENDING; |
user fork + review |
U3 |
550-vs-552 = caller-chosen |
review (meaning defined) |
U4 |
|
review (was contradictory) |
U5 |
Auto-activation on |
user fork |
U6 |
Full BFF surface; create/activate affordances visible to |
user fork + review |
F1 |
STRICT |
forced — see Rationale |
F2 |
Stored money boundary: activation writes |
review (absorbs TANF + the 1st-of-month edge + the too-broad-native predicate) |
F3 |
DELETE the generic stamp-based |
review (partial de-stamping still left forgeable fields) |
F4 |
|
review + user principle |
F5 |
Review anchors derive from APPROVAL dates (22.9), never from |
review (transfer-anchoring contradicted 22.9) |
F6 |
Create idempotency = the F8 pair, split out of |
house pattern |
F7 |
Activation witnesses: S2S re-read of the snapshotted |
review, sharpened |
F8 |
Create witness: placement EXISTS + ACTIVE (the residence-under-supervision evidence); derivations from S2S; no type constraint, no floor at create. Citizenship/residency, child income, funding availability, and caregiver-identity-on-placement linkage are RECORDED UNVERIFIED MANUAL PRECONDITIONS (form + runbook attestation text; ADR-056; #1114 for hard checks). ⁂ |
review (honest scope) |
F9 |
Handoff: shared typed |
review-hardened |
F10 |
Migration (§G1 C1): |
design + review |
F11 |
G0 fix-MR (#1111, merged): date-only form values → noon-UTC instants ( |
review (blocked the flow’s date truth) |
F12 |
SG/NRSG family exclusivity: one-open-per-child unique index over |
review |
Rationale for the non-obvious calls
-
F1 is structural: the pending interval opens at
signed_atandvalidate_transition_dateis strictly-after — same-day would need an empty interval[d, d). Matches the literal policy text; DFCS wanting same-day = an ADR-052 revision. -
F2 replaces an earlier TransferMonth-rule design: one stored boundary fact handles the strict "month after transfer", the TANF later-of rule, and the transfer-on-the-1st edge uniformly — and keying the generator on the fact (not "native shape") leaves seed families A/B and any legacy native-shaped rows untouched (verified in
tools/craig-seed/src/datagen.rs: A/B carry no F8 pair and will carry a NULL boundary; their pinned 2025 activation months sit below the 12-month generator reach; regression-pinned). -
F5’s re-grounding: 22.9 runs review clocks from approval, and the activation act IS a county-director approval (it mints the proof) — so "most recent approval" is modeled by the activation itself, dues can never pre-date activation, and no transfer-date anchoring exists to contradict policy. Long-pendency behavior is thereby defined, not accidental.
-
The 1st-of-month gap month is policy’s own artifact: ERR truth-dated to a day-1 transfer is inactive at month start (half-open intervals); SG starts the next month per the strict text. Nobody pays that month. Recorded ⁂ prominently — mid-month transfers keep ERR’s full final month (standing whole-month semantics).
-
F9’s floor:
guardianship_finalizedat COUNTY (expected permanency outcome);guardianship_dissolvedstays REGIONAL (exceptional reversal). -
Deleting
create_agreement(F3): partial de-stamping would leave status/terms dates, both anchors, andcreated_by_nameforgeable by any store caller. Two typed creation fns + the stamp-based import path is the complete story; a "generic create" has no remaining consumer.
Program shape
| MR | Branch | Ships |
|---|---|---|
G0 |
|
The F11 normalization fix + caller audit + tests (merged — see Status) |
G1 |
|
Contracts, migration, settings knob, store (typed creates, activate, reason token), generator boundary rule + invariants, API + events + ruleset v1.4.0, compose knob, seed family E (+ ERR E), one-line BFF ripple, backend docs (ADR-056, CHANGELOG, data-model, config-reference, implementation-guide event payloads, financial + placement API pages, shared-crates, state-machines, ADR-054/ADR-055 sentence amendments) |
G2 |
|
Guardianship form, detail-page Activate, end-placement interstitial + flash, e2e, web docs |
Per-MR: the standing pipeline — fmt/clippy/nextest → fresh-subagent J1–J8 per substantive commit → token-gated commit → battery push (pre-flight ALL cheap gates first: clippy, quality-budgets, plan-lint, route-role-coverage, axis-coverage, check-docs) → MR → merge → J-record → issue notes → Status row updated here.
G1 — backend (commits C1–C5, each J-reviewed)
C1 — contracts + migration + settings
-
craig-placement-contracts/src/subsidy.rs:PlacementSubsidyEligibilitygains#[serde(default)]ended_on: Option<NaiveDate>,end_reason: Option<String>,permanency_goal: Option<String>(additive; Eastern projection stays placement-side). -
craig-placement-contracts/src/events.rs:PLACEMENT_ENDEDconst + typedPlacementEndedPayload { placement_id, end_reason: Option<String> }; the const replaces string literals in the producer, financial’s subscription binding, AND the dispatch arm. -
craig-financial-contracts/src/subsidy_agreements.rs— the U1 tagged enum:-
CreateErrAgreementBody: today’s fields verbatim. -
CreateGuardianshipAgreementBody:client_request_id,placement_id,form_number,form_version,signed_at,agreement_document_key?,approving_county,legal_county?,relationship_evidence_key?(wire rule: required non-blank for sg, optional for nrsg — U3),caregiver_assessment_evidence_key(required — the approved kinship assessment / foster-home evaluation reference),legal_reference?,predecessor_agreement_id?(validated: same child, program ∈ {sg,nrsg}, terminal, terminated beforesigned_at— family re-application lineage ONLY; the ERR→SG handoff deliberately has NO predecessor link),parties,monthly_amount(wire string),amount_basis, and the ERR body’s four education fields. -
CreateClosedProgramBody {}forersg/enrsg/rcs/ercs. -
ActivateSubsidyAgreementRequest { expected_head_interval_id, court_order_evidence_key, tanf_terminated_on?, legal_reference? }— no dates beyond the TANF attestation;transfer_onderived. Garde: hand-implementValidateper-variant if the derive fights the tagged enum. -
Detail contract gains
guardianship_transfer_on,payments_begin_month,court_order_evidence_key,tanf_terminated_on(serde-defaulted).
-
-
craig-financial-contracts/src/subsidy_generation.rs:#[serde(default)]skipped_before_payments_begin: u64on the report. -
craig-common:SubsidySgSettings(mirror ofSubsidyErrSettings), fieldsubsidy_sg;problem_types::CLOSED_PROGRAM. Every settings literal / bootstrap test gains the field (compile-driven sweep). -
Migration (all on
subsidy_agreementsunless noted):-
ADD
guardianship_transfer_on DATE,payments_begin_month DATE,court_order_evidence_key VARCHAR(512),tanf_terminated_on DATE,caregiver_assessment_evidence_key VARCHAR(512). -
DROP
subsidy_agreements_approval_clock_valid; ADD the three-shape snapshot CHECK — all-NULL (legacy/import) | ERR clock pair (both set, due > start) | family residence (program IN ('sg','nrsg')∧placement_started_onset ∧ clock columns NULL). -
Flow-coupling CHECK:
guardianship_transfer_on IS NULL OR (program IN ('sg','nrsg') AND placement_started_on IS NOT NULL AND create_request_id IS NOT NULL AND court_order_evidence_key IS NOT NULL AND payments_begin_month IS NOT NULL AND guardianship_transfer_on > placement_started_on AND signed_at < guardianship_transfer_on). -
Boundary CHECK:
payments_begin_month IS NULL OR (payments_begin_month = (date_trunc('month', payments_begin_month::timestamp))::date AND payments_begin_month > guardianship_transfer_on). -
CREATE UNIQUE INDEX subsidy_agreements_one_open_guardianship_family ON subsidy_agreements (child_id) WHERE program IN ('sg','nrsg') AND current_status IN ('pending','active','suspended').
-
-
Constraint probes: each legal shape, each illegal mix, both boundary CHECKs, the family index (two children pass; one child two programs refused).
C2 — store
-
approvals.rs:CreatePending+ActivateGuardianship(county floor); bindings;ActivateGuardianshipadmits BOTH its own action AND exactlyTransition{Pending→Active}(the leg-binding precedent). -
store.rs:-
NEW
CreateGuardianshipParams+create_guardianship_agreement(conn, params, proof, today)— derives interval/terms starts fromsigned_at, provisional anchors from TODAY (the approval act, F5), attribution from the proof; store-checkssigned_at ≤ today; takes BOTH family history locks sorted (F12); F8 pair +placement_id+placement_started_on+ evidence keys written on identity; cross-family open check + predecessor validation + coverage overlap for both family programs. -
DELETE
create_agreement+CreateAgreementParams; port the test callsites (typed fns orimport_agreement_history). -
Split the F8 pair +
placement_started_on+relationship_evidence_keyout ofErrIdentityInsertinto shared optional identity-insert fields; aguardianshipbundle carries the assessment key. -
NEW
activate_guardianship_agreement(conn, params, proof, today)withActivateGuardianshipParams { agreement_id, expected_head_interval_id, transfer_on, tanf_terminated_on, court_order_evidence_key, legal_reference, residence_floor_months }: FOR-UPDATE lock → replay recognition (already Active with equalguardianship_transfer_on→ Ok(replayed), F4) → family/native/pending CAS →signed_at < transfer_on→ residence floor from the stored snapshot (clamped month-add; typed short-by-N refusal) →transfer_on ≥ current_month − 12→ no other open agreement for the child (ActiveSiblingAgreement, names it — U2 ordering) → derive + writepayments_begin_month,guardianship_transfer_on, court evidence, TANF attestation,legal_reference(NULL→set ok; equal no-op; different → typed conflict) → re-derive anchors from today (F5; assert zero review rows) → witnessed crate-private transition entry (close head attransfer_on, open Active, projection,maintain_chain_after_transition— slots + reconcile enqueue ride the existing machinery). -
transition_statusbelt: refuse native-familypending→activenaming the activate path. -
Vocabulary:
guardianship_finalizedin the craig-reference termination superset
ERR_ONLY_TERMINATION_REASONS; store arm requiresprogram == Err∧ anchored placement. -
New store-error variants mapped in
write_store_error(as-built, the ERR precedent):ClosedProgram→ the namedCLOSED_PROGRAMtype;ActiveSiblingAgreement
LegalReferenceConflict→ typed CONFLICTs; the validation-class refusals (SigningNotBeforeTransfer,ResidenceFloorShort,TransferBeforeReconcileFloor,WitnessedActivationRequired) ride the generic bad-request problem type with their rich messages PINNED by the C4 api tests (per-variant type URLs considered and dropped — ERR’s own witness refusals set the precedent).
-
C3 — generator + policy + invariants
-
generator.rs:SkipReason::BeforePaymentsBegin; rule after per-diem exclusivity, before active-as-of: agreement haspayments_begin_monthANDmonth_start < payments_begin_month→ None + counter (reconciling arm voids stray undisbursed rows via the existingreconcile_expected_nonemachinery, causesubsidy_reconciliation). -
policy.rs:guardianship_residence_months: u32(Georgia = 6, ⁂) onSubsidyPolicy. -
Invariants (test-lib SQL), keyed on the flow fact so legacy rows never fire:
-
sg_transfer_matches_activation.sql: rows WHEREguardianship_transfer_on IS NOT NULL— equals the earliest Active interval’seffective_from; completeness arm — family program ∧create_request_id IS NOT NULL∧ an Active interval EXISTS ∧ transfer NULL → fires (keyed on interval existence, not the current projection, so termination can’t hide it). -
sg_no_payment_before_boundary.sql: rows WHEREpayments_begin_month IS NOT NULL— no live payment withpayment_month < payments_begin_month. -
sg_residence_floor.sql(GA devstack): transfer set ⇒placement_started_on + 6 months ≤ guardianship_transfer_on.
-
C4 — API + events + handlers + ruleset
-
api/subsidy_create.rs+subsidy_create_wire.rs: tagged dispatch — closed arms → typedCLOSED_PROGRAM;errarm = today’s pipeline with the LEGACY tag-free canonical hash (U1);sg/nrsgarm:SUBSIDY_SGgate FIRST → wire validation (shared helpers; U3 per-program relationship-key rule) → tagged canonical hash → authz (operation:"create",programattr) →require_georgia→ F8 idempotency BEFORE volatile deps → policy → S2S active-placement witness → one tx (mintCreatePendingproof → create → created event) → 200; race-loser re-runs idempotency. -
NEW
api/subsidy_activate.rs: gate FIRST → garde → preread → authz (operation:"activate") →require_georgia→ policy → S2S witnesses (F7) → tx { recheck assignment, mint proof, store activate, publish transitioned } → 200 detail. Registered inapi/mod.rs+ utoipa. -
subsidy_mutations.rs:PlacementClientinjected;guardianship_finalized→ pre-tx S2S witness (ended + guardianship + child match) ANDbusiness_date == ended_onrequired (typed refusal naming the expected date); S2S down = 503. NOT gated (U4). -
Events:
publish_subsidy_agreement_createdgainseffective_from+initial_statusparams — an ADDITIVE payload key for ERR too (stated honestly; parser arm unaffected; family tests updated). Financial’s local ended-payload replaced by the shared contract;handle_placement_endedF9c WARN arms (guardianship ± pending sg/nrsg; non-guardianship end
pending family agreement; absentend_reasondegrades to today’s behavior); the placement producer +subsidy-eligibilityprojection updated.subsidy_generation_completedgains theskipped_before_payments_beginkey (manually enumerated payload + telemetry aggregation). -
Ruleset v1.4.0:
operation:'activate'row; ruleset tests extend the enumerated operation coverage (allow/deny × program × jurisdiction × role + unknown-operation). -
main.rs:Extension(SubsidySgSettings)wired besidesubsidy_err;docker-compose.ymlknob"true"beside the ERR knob; BFF ripple: the ERRcreate_bodygains"program": "err".
C5 — seed + battery
-
Family E: child + caregiver persons, ACTIVE kinship placement E started
as_of − 7 months − a few days, plus an ACTIVE native ERR agreement E on placement E (fixture-C shape) — the e2e’s raw material for the FULL handoff arc. As-built money/clock shape (deviation recorded): the approval clock is future-dated DECOUPLED from start+120 (the placement started ~7 months back, so the policy-derived due lapsed; a fresh seed must not show an overdue badge), and E seeds exactly ONE payment row — the as-of month’s Full unit month — because the deployment-wide generation contract test pinsgenerated == 0for a scope-All current-month run over a fresh seed; the ~6 back months stay unpaid and unreachable by any automated path (scheduled batches generate only the current month; the reconcile queue holds no pairs for E), keeping the e2e’s handoff-money slate clean. Families A/B UNCHANGED (see Rationale). Re-blessFINANCIAL+PLACEMENT+CASESSHAs (persons live in cases); regeneratetests/e2e/lib/seed.ts; update the pinned-ID exclusion test.verify-seed+ fullcargo xtask invariantsgreen on a fresh keyed reseed.
G2 — web + e2e + web docs + close-out
-
NEW
routes/financial/subsidy_guardianship.rs+subsidy_agreement_new_guardianship.html: program radio ("Relative (552)" / "Non-relative (550)"), per-renderclient_request_id,signed_athelp text, the F8 manual-preconditions attestation text, verbatim-4xx flash, PRG. GET/financial/subsidy-agreements/new-guardianship+ POST/financial/subsidy-agreements/guardianship; NEW POST/financial/subsidy-agreements/:id/activateBFF handler (hiddenexpected_head_interval_id,court_order_evidence_key, optionaltanf_terminated_on+legal_reference; PRG; verbatim 4xx). All three routes layered + role-comment-markered; visibility gatedcounty_director/admin(U6). Module registration,main.rswiring, list button, ftl keys. -
Detail page: transfer date + payments-begin month + court-order key rendered; Activate form ONLY for flow-shaped pending rows (family program ∧ pending ∧
create_request_idpresent ∧ no import provenance — BFF-computed from the detail contract); the generic transition form suppresses the guaranteed-to-failactivetarget for pending rows; provisional review anchors on pending rows marked non-actionable. -
end_placement: reason=guardianship + NO pending family agreement + no acknowledgement → PRG-refuse with flash + an acknowledgement checkbox ("support will stop") — the pre-finalization check. Post-end flash is TEXT-ONLY (flashes are escaped): names the pending agreement when one exists, no fake links. The pending lookup = two list calls (sg, nrsg); partial failure → WARN
conservative message. -
e2e
subsidies-guardianship.spec.ts— added to the county project’stestMatch(subsidies-(county|guardianship)), dana.county, ONE serial arc on fixture E (retry posture documented: state-mutating, reseed-first, county-spec precedent): attempt end (guardianship) → interstitial refusal (no pending agreement); create pending SG withsigned_atback-dated to yesterday (Eastern — F1 makes a same-day create+transfer arc impossible); F8 replay of the same rendered form → same agreement; premature activate → verbatim "placement is still active" refusal; end placement E (guardianship) → passes the pending check; activate → refused naming the ACTIVE ERR (U2); terminate ERR E via the transition UI, reasonguardianship_finalized(witnessed); activate → success; detail shows active
transfer date + payments-begin month. The existing placement spec’s arbitrary-active-placement selector is pinned AWAY from fixture placements.bobsmith.spec.ts: button absence
/new-guardianship403 (write-parity). Closed-cohort / floors / money boundaries stay API/store-level (deterministic dates). -
Web docs + runbook (developer-guide: enrollment → finalization → handoff → activation walk, TANF-still-active note, generator cadence); ⁂ comment on #1073; AC walk + close #1070; epic tick; plan → archive + nav; CLAUDE.md status pointer.
Test matrix (all @axis-tagged; representative)
| Layer | Case | Axis |
|---|---|---|
store/create |
Typed guardianship create atomic; attribution = proof; |
happy, sad, evil, conc |
store/activate |
Mid-month: head closed |
happy, sad, evil, conc, replay |
store/terminate |
|
happy, sad |
generator |
Boundary pins: transfer 1st / mid / last day; TANF later than transfer shifts the boundary; months < boundary skipped + counted; boundary month pays Full; truth-dated ERR + SG around the boundary (mid-month → ERR full final month, no overlap; 1st-of-month → gap month ⁂ pinned); un-terminated ERR into SG months → MultiProgram fail-closed backstop; NULL-boundary rows (seed A/B shape) untouched — regression pin |
happy, sad, replay |
api/create |
ERR regression (LEGACY hash: pre-upgrade stored hash still replays 200); tagged sg/nrsg 200
pending; closed → |
happy, sad, evil, fault, replay |
api/activate |
Happy; each F7 witness refusal typed (type URLs pinned); S2S down 503; caseworker 403; gate-off 403 naming the knob; stale CAS 409; replay 200 |
happy, sad, evil, fault, replay |
api/transition |
|
sad, fault |
constraints |
Three snapshot shapes, flow-coupling, boundary month-start, family index, |
evil |
settings/gate |
Knob OFF: create+activate 403; existing SG still generates, transitions, reviews (U4 grandfather pins) |
sad, replay |
events + handler |
Created payload (pending SG: |
happy, sad, replay |
ruleset |
Activate operation coverage (allow/deny/program/jurisdiction/unknown-op) |
sad, evil |
e2e |
The dana.county 8-step arc + bobsmith parity |
happy, sad, replay |
Risks
| # | Risk | Mitigation |
|---|---|---|
1 |
U1 changes the ERR wire |
Legacy-stable ERR hash (durable state safe); lockstep-deploy CHANGELOG note; BFF ripple in G1; ERR api suite re-pins |
2 |
F5 anchor rewrite touches the open head terms row |
Two columns, one edge, in-tx, zero-review-rows asserted; ADR-056 defines one-time semantics |
3 |
F2 sits inside the ONE month judgment |
Boundary battery + |
4 |
Deleting |
Compile-driven port to the typed fns / import path; the diff names every site |
5 |
S2S coupling (create, activate, terminate) |
Fail-closed 503; mock-server fault seam |
6 |
Seed churn (3 SHAs + seed.ts + exclusion test) |
One C5 commit, dated comments |
7 |
Placement terminal facts remain mutable (#1112, filed) |
Activation snapshots at its instant; invariant stays internally consistent |
⁂ #1073 additions (enabling SUBSIDY_SG = recorded consent)
-
Residence floor = 6 months (manual 6-vs-12 discrepancy), clamped calendar-month arithmetic.
-
STRICT
signed_at < transfer_on; same-day refused. -
transfer_on= the anchoring placement’s end date. -
Payments begin
max(month after transfer, month after TANF termination); TANF termination is an UNVERIFIED operator attestation; TANF-still-active ⇒ activate after it ends. -
A 1st-of-month transfer leaves that month unpaid by BOTH programs (strict-text artifact — flagged for explicit confirmation); mid-month transfers keep ERR’s full final month.
-
Review anchors run from the initial / most-recent APPROVAL act (create, then activation).
-
guardianship_finalizedERR termination at county floor, truth-dated to the transfer. -
One family knob = ENROLLMENT consent; existing-agreement lifecycle grandfathered.
-
No placement-type constraint at create; placement existence = supervision evidence.
-
permanency_goal ≠ reunificationas the non-reunification-order proxy at activation. -
Citizenship/residency, child income, funding availability, caregiver-identity linkage: unverified manual preconditions (attested, recorded; #1114).
-
sg requires degree-of-relationship evidence; nrsg’s relationship key is optional documentation.
Review dispositions (external findings → where fixed)
| Finding | Disposition |
|---|---|
Eligibility facts missing (citizenship/income/assessment/court order/CD approval/TANF relationship) |
F7 (court evidence, goal proxy), F8 (assessment key, manual preconditions + #1114), U3 (relationship meaning per program), F4 (the county proof IS the CD approval) |
No caregiver↔placement linkage provable |
F8 recorded limit + attestation + #1114 |
Review clock contradicts 22.9 / no approval date modeled |
F5 re-grounded on approval acts; interval |
TANF boundary omitted |
F2 + F7 |
Date-only → midnight-UTC off-by-one |
G0 fix-MR (F11, merged !1035) |
ERR handoff date forgeable / 1st-of-month contradiction / generation ordering |
F9 ( |
Post-end "create one" impossible |
The pre-finalization interstitial + acknowledgement (G2); text-only flash |
Tagged request breaks durable idempotency |
U1 legacy-stable ERR hash; lockstep-deploy note; pre/post-upgrade replay test |
Gate semantics unsafe/contradictory |
U4 enrollment-consent + grandfathered lifecycle, both tested; |
Store still forgeable |
F3 deletes the generic create; typed params derive everything |
SG+NRSG both open |
F12 family index + sorted locks + conc test |
Delayed activation vs 12-month floor |
F7 floor refusal + #1115 |
|
F2 keys on |
Store can’t recheck residence / month arithmetic undefined |
F7 store-side floor from the snapshot; clamped month-add + leap/EOM pins |
Migration under-constrained |
F10 flow-coupling + signed<transfer + boundary CHECKs; family index |
Completeness invariant hides after termination |
C3: keyed on Active-interval existence |
Predecessor semantics conflated |
C1: family re-application only; ERR handoff has NO link |
Re-anchor vs existing review rows |
C2: zero-review-rows assertion |
Append-only violations un-audited |
F5 ADR-056 one-time semantics; identity writes enumerated; |
Placement terminal facts mutable |
#1112 filed; Risk 7 |
|
F9 child match |
CAS ≠ idempotency |
F4 replay recognition → 200 |
|
C2 conflict rule; the |
Only CLOSED_PROGRAM typed |
C2 store-error variants + pinned type URLs |
Transfer date absent from read surfaces |
C1 detail contract + G2 views |
No BFF activation route |
G2 activate handler/route |
Flash links impossible |
G2 text-only flashes |
Single-program list filter |
G2 two calls + partial-failure posture |
Imported/legacy pending affordances |
G2 flow-shaped-only Activate; transition form suppresses |
Supervisor-vs-CD visibility |
U6 role-gated visibility |
Missing nav/button/ftl/registration |
G2 enumerated |
Pending review anchors exposed |
G2 non-actionable marking |
Nonexistent generation-report surface |
Dropped from G2 |
Playwright project mismatch |
G2 |
Serial arc retry safety |
Documented reseed posture (county-spec precedent) |
Placement spec consumes fixture E |
G2 selector exclusion |
Fixture E lacks ERR → handoff untested |
C5 adds ERR E; the 8-step arc covers the full handoff |
CASES sha + seed.ts + exclusion test |
C5 |
Counter missing from event/telemetry |
C4 completion event + aggregation |
Settings injection + literals |
C4 wiring + compile-driven sweep |
Ruleset test enumeration |
C4 coverage additions |
PLACEMENT_ENDED literals / "payload unchanged" claim |
C1 const sweep; C4 states the additive key honestly |
G1 not doc-complete / wrong event-catalog page |
Backend docs moved into G1; implementation-guide targeted |
Wrong assertions (unreachable/CAS/identical/untouched) |
Corrected throughout |