ADR-056: SG/NRSG (UAS 552/550) Guardianship-Subsidy Flow — Two-Step Enrollment, Witnessed Activation, Payments-Begin Boundary
On this page
Status
Accepted (2026-07-24). The #1070 program (epic &70 child (d)) lands as three MRs, each independently green: G0 the date-only noon-instants fix (#1111, MR !1035 — date-only form values previously landed a day early on the Eastern calendar, poisoning every date witness this flow derives), G1 the backend (this record), G2 the operator surface + close-out. Program plan: SG/NRSG guardianship flow. The plan was reshaped by an external review (2026-07-24, ~45 findings, all dispositioned in the plan’s index) before implementation began.
Amends (named): ADR-052 (the reserved pending → active activation seam is now used — by
exactly one witnessed path; the "generic create" it described is deleted), ADR-053 (the
generator’s month judgment gains the payments-begin boundary rule ahead of the active-as-of
rule), ADR-054 (the approval matrix gains CreatePending + ActivateGuardianship at county
floor, both single-purpose-bound; the sentence “create_agreement` … stays ApprovalStamp-based"
is superseded — only import_agreement_history remains stamp-based), and ADR-055 (the sentence
"the generic two-step create_agreement REFUSES program = err” now lives in
`create_guardianship_agreement’s validation; the created-event payload gains the additive
`initial_status key and its effective_from is arm-specific).
Context
GA 22.8: SG (Subsidized Guardianship, relative, UAS 552) and NRSG (non-relative, UAS 550) pay a monthly subsidy after a permanent-guardianship transfer. The Application & Agreement is signed BEFORE the transfer; ≥6 months of prior residence under DFCS supervision qualify (the manual carries a 6-vs-12 discrepancy — ⁂ #1073); payments start the 1st of the month AFTER the 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 or foster-home evaluation, County Director approval, and a non-reunification permanent-guardianship order. Enhanced variants (ERSG/ENRSG) closed to new entrants 2014-08-01. The 22.9 review cadence (12-month renewal + 6-month paper) runs from the initial or most recent APPROVAL.
The ADR-052 ledger reserved pending for exactly this shape ("SG signs BEFORE guardianship
transfer") and the transition endpoint reserved pending → active for this flow. Before #1070,
guardianship finalization was a generic placement ending that voided undisbursed payments and
stranded support silently — the financial consumer even dropped the producer’s end_reason.
Decision
Two-step creation, fully proof-typed (F3)
POST /v1/financial/subsidy-agreements is ONE program-tagged request
(#[serde(tag = "program")]): the err arm is the #1069 one-shot body VERBATIM (its untagged
serialization — and therefore every persisted F8 canonical hash — is unchanged; the wire gains
only the tag), the sg/nrsg arms share the guardianship body, and the four closed cohorts
refuse with the named closed-program problem (the #1071 import is their only path). Mixed
producer/consumer versions are a recorded pre-1.0 non-goal: deploy the BFF and financial
together.
The guardianship arms mint a PENDING agreement whose interval and revision-1 terms open at
signed_at. ALL attribution flows from a county-floor ApprovalAction::CreatePending proof —
the stamp-based generic create_agreement was DELETED outright (partial de-stamping would have
left status/terms dates, anchors, and names forgeable by any store caller); only the #1071
import remains stamp-based, for historical approvals no session can re-authorize. Creation takes
BOTH family history locks in a fixed order and enforces family exclusivity (one OPEN sg-or-nrsg
enrollment per child — they are alternative classifications, not parallel programs; a partial
unique index is the backstop), guardianship-family-only predecessor lineage (the ERR→SG handoff
deliberately carries NO predecessor link — it is a program handoff, not a re-application), and
the U3 classification rule: the caller chooses sg vs nrsg (no authoritative relationship
source exists — kinship placements include fictive kin), with the TANF degree-of-relationship
evidence reference REQUIRED for sg and optional for nrsg. The anchoring placement must exist and
be ACTIVE (S2S-verified): the placement IS the residence-under-supervision evidence;
deliberately NO placement-type constraint and NO residence floor at create (the floor binds
where the transfer exists — activation). Citizenship/residency, child income, funding
availability, and caregiver-identity-on-placement linkage are RECORDED UNVERIFIED manual
preconditions (attestations; #1114 tracks hard checks).
The witnessed activation (F4/F7)
POST /v1/financial/subsidy-agreements/{id}/activate performs pending → active at
business_date = transfer_on, where the transfer date is DERIVED — the anchoring placement’s
Eastern-projected end date from the S2S read — never operator-typed. Witnesses, API-side
fail-closed: the placement ended with end_reason = guardianship, child match, permanency goal
≠ reunification (the non-reunification-order proxy, ⁂), plus the REQUIRED court-order evidence
reference and the OPTIONAL past-dated TANF-termination attestation. The STORE re-derives every
DB-side rule from the locked row: strict signed_at < transfer_on (F1 — same-day is refused;
the pending interval would be empty, and the literal text says "before"; also a DB CHECK), the
residence floor from the stored placement_started_on snapshot (clamped calendar-month
arithmetic — the S2S check is advisory UX, the store check is the guarantee), never-future
dates, and the −12-month reconcile floor (older transfers need the #1115 backpay path).
Authority is ApprovalAction::ActivateGuardianship (county floor — the County Director approval
the policy names), whose mint-time binding admits exactly its own action AND the one
Transition{Pending→Active} shape it writes (the enforcement-leg precedent). The PUBLIC
transition path refuses native-family pending → active outright (the F4 belt); imported
pending rows have NO activation path (#1116 — decided by #1071/ADR-057: open-pending
imports are unrepresentable at the store, so this refusal is belt-only).
Replay honesty (F4): an exact retry after success — Active with the SAME derived transfer — is a recognized replay (200, zero writes, no event); any other non-pending state is an honest CAS-class 409, never the F5 bypass-guard message a fall-through would produce. Activation refuses while ANY other paying-capable (active/suspended) agreement exists for the child (U2): the predecessor ERR terminates FIRST, so the handoff order is deterministic and the generator never sees two payable programs (its MultiProgram fail-closed arbitration remains the backstop).
The payments-begin boundary (F2)
Activation derives and STORES payments_begin_month = max(first-of-month-after(transfer_on),
first-of-month-after(tanf_terminated_on)). The generator’s single month judgment gains one rule
— AFTER per-diem exclusivity, BEFORE the active-as-of rule: a month before the boundary skips
with the named BeforePaymentsBegin reason, counts, and voids stray undisbursed rows
(subsidy_reconciliation). Placement ahead of the active-as-of rule is the point: a transfer ON
the 1st leaves the agreement ACTIVE at month start while the strict "month after transfer" text
still forbids payment. The rule keys on the flow-written FACT: legacy/imported rows carry a NULL
boundary and keep the pre-#1070 judgment. Consequence, recorded prominently (⁂ #1073 item 5): a
1st-of-month transfer leaves that month unpaid by BOTH programs — the truth-dated ERR is
inactive at month start and the SG sits behind its boundary; mid-month transfers keep ERR’s full
final month (standing whole-month semantics).
Approval-anchored review dues (F5)
22.9 runs review clocks from the initial or most recent APPROVAL — never from the transfer.
Creation writes PROVISIONAL anchors (the create act’s business date +12/+6 months); activation —
itself a county-director approval act — re-derives both anchors from ITS date before
maintain_chain_after_transition materializes the cycle-1 slots. This is the ONE permitted
anchor rewrite: in-tx, on exactly the pending → active edge, guarded by a zero-review-rows
assertion (a bypass row would be silently orphaned — refused instead), audited by the
transitioned event + the interval’s approval stamp. Dues therefore can never pre-date
activation, and long pendencies have DEFINED behavior.
ERR→SG handoff completeness (F9)
placement.ended now rides a shared typed contract (PlacementEndedPayload — the producer’s
ad-hoc json! and the consumer’s reason-blind local mirror are gone). The financial consumer
branches its WARN arms on the reason: a guardianship ending names the handoff steps for a
stranded active ERR and the ready-to-activate pending family agreement (or the support gap when
none exists); a non-guardianship ending with a pending family agreement names withdraw/decline.
WARNs only — automation is deferred with its own consent knob (#1113, U5). The new
guardianship_finalized termination reason is ERR-only at the store (anchored placement
required), county floor (finalization is the EXPECTED permanency outcome —
guardianship_dissolved stays regional as the exceptional reversal), and the API witnesses it
S2S: the anchored placement ended by guardianship, child match, and business_date REQUIRED to
equal the derived end date (truth-dated; a typed refusal names the expected date).
The enrollment-consent knob (U4)
CRAIG_FINANCIALSUBSIDY_SGENABLED (default OFF; ONE knob for the family — sg and nrsg are
one A&A flow and one money-policy family) gates the create arms and the activate endpoint ONLY.
Existing agreements' lifecycle — generator, ALL transitions including the corrective
guardianship_finalized, reviews, sweep — is deliberately grandfathered: a knob-off flip must
never strand owed money or block the corrective ERR termination. The refusal direction is
test-pinned (typed 403 naming the knob); the grandfather direction is STRUCTURAL — no lifecycle
handler extracts the gate (a gate-off lifecycle pin would need a per-test env flip on the shared
devstack; recorded, not faked). Enabling is the operator’s recorded consent to the ⁂ #1073 readings (the twelve-item
list rides #1073): the 6-month residence floor, strict pre-transfer signing, transfer = the
placement’s end date, the TANF-shifted boundary with the attestation posture, the 1st-of-month
gap month, approval-anchored dues, the county-floor handoff reason, the family knob itself, no
placement-type constraint at create, the reunification-goal proxy, the unverified manual
preconditions, and the per-program relationship-evidence rule.
Consequences
-
The authz ruleset (v1.4.0) admits
operation: "activate"for supervisors; the real authority is the county-office proof + the U4 gate + the F7 witnesses at the service — the ruleset authorizes the operational axis only. -
financial.subsidy_agreement_createdcarries the additiveinitial_statuskey (activefor the one-shot arm,pendingfor the two-step) and an arm-specificeffective_from(ERR: the coverage start; guardianship: the signing date). The craig-security parser arm is unchanged (additive keys are parser-safe). -
Store-error surface:
ClosedProgrammaps to the namedclosed-programproblem;ActiveSiblingAgreementandLegalReferenceConflictare typed conflicts; the validation-class refusals (signing, residence floor, reconcile floor, witnessed-activation-required) ride the generic bad-request problem with their rich messages test-pinned (the ERR witness-refusal precedent; per-variant type URLs were considered and dropped). -
Three report-only invariants watch the flow’s facts: transfer == the earliest Active interval’s start (with a flow-scoped completeness arm and a never-activated-bypass arm), no live payment before the boundary, and the GA residence floor (Postgres interval clamping is equivalent to the store’s chrono clamping).
-
The U2 sibling refusal checks paying-capable (active/suspended) agreements — family pendings are unrepresentable (F12) and an imported cross-program pending pays nothing (recorded narrowing).
-
Known limits, filed: ended placements accept silent terminal-fact edits (#1112 — RESOLVED 2026-07-25: terminal facts are immutable, riding only the ending transition); imported-pending activation semantics (#1116 — RESOLVED by #1071/ADR-057: unrepresentable); late-activation backpay beyond the reconcile floor (#1115); hard eligibility checks (#1114); auto-activation on the guardianship ending (#1113 — RESOLVED 2026-07-25 as the one-step handoff below, deliberately NOT as automation).
Amendment (2026-07-25, #1113) — the one-step handoff; automation rejected
The deferred "auto-activation on `placement.ended(guardianship)`" was found unimplementable without fabricating operator attestations, and was reshaped (user-steered fork, recorded on #1113):
-
Why not automation. The witnessed activation demands two operator-only artifacts: the court-order evidence reference (required non-blank; part of the flow-shape CHECK’s transfer/boundary/court trio) and the TANF attestation (
tanf_terminated_on: NoneASSERTS "no TANF shift" — it movespayments_begin_month, and a machine cannot make that money-boundary attestation). ADR-054’sauthorize_systemis deliberately leg-bound to ENFORCEMENT shapes; extending system proofs to a money-creatingPending → Activewas rejected. Theplacement.endedconsumer keeps its U5 posture: WARN arms only. The automation-attestation questions ride the #1073 DFCS ledger. -
The one-step handoff (craig-web). The SS6 end-placement interstitial (the moment the operator holds the transfer court order) captures the two attestations plus an explicit activate-now consent, and the BFF chains the EXISTING witnessed endpoints as the acting worker: end placement → (separately consented) terminate the open ERR (
guardianship_finalized,business_date= the ending date — equal to the backend’s Eastern projection by the #1111 noon-UTC form convention) → activate the pending SG/NRSG. No new financial surface, no new authority (county-floorauthorize_workerproofs unchanged), no new knob (CRAIG_FINANCIALSUBSIDY_SGENABLEDconsent is inherited; nothing is automated — the human attests). -
Refusal posture. A pure pre-flight matrix refuses the WHOLE submit BEFORE the irreversible end (#1112) whenever the requested chain cannot proceed: no visible pending agreement, blank court key, ERR state unverifiable (unknown is refused, never treated as absence — the SS6 scope-honesty rule), or an open ERR without its own termination consent. Post-end refusals stop the chain with earlier acts standing and flash the backend problem VERBATIM, landing on the agreement detail page where the manual affordances live. The affordance follows the U6 floor (
county_director/admin). -
Coverage: the preflight matrix unit-tested; the composed chain + the unconsented-ERR refusal e2e-tested over the dedicated seed fixture G (a fixture-E twin owned exclusively by
subsidies-onestep.spec.ts); the manual arc keeps its own e2e over fixture E untouched.
Review record
Every substantive commit shipped behind a fresh-context J1–J8 review with findings remediated pre-commit (per-MR J-records live as MR notes). The C2 review deleted a fig leaf before it shipped (the mismatched-replay refusal now surfaces an honest CAS conflict instead of the F5 bypass message) and restored the exact-match approval-level probe the test port had lost; the C3 review forced the reconciling-arm void pin (without it the reconcile flag could flip undetected). The external review’s disposition index is preserved in the program plan.