Reconciliation — owner decisions (2026-08-05)
Answers to the open questions in fix-plan.md §3 and remittance-rematch-backfill. Where this
file and those disagree, this file wins — it was decided against production data, they were
written from the repo alone.
Evidence these were decided on
Every remittance line ever confirmed (19 checks, 54 lines with a printed ref), classified by
comparing the stored invoice_ref against the invoice the money actually landed on:
| Verdict | Lines | Detail |
|---|---|---|
| Ref honoured | 47 | includes 12 bare-ref lines (0901, 0963, …) that landed correctly by luck on date_amount; post-#105 they match deterministically as invoice_ref, same target |
| Ref named nothing in the pool → fallback | 4 | 0029 (JAN 0772, FEB 0772), 6418 (INV-002), 6990 (INV-0982) |
| Ref contradicts target | 3 | 6990: INV-0974 line → paid INV-0979; INV-0979 line → paid INV-0982. 7100: INV-0985 line → paid INV-1006 — but see below, INV-1006 was INV-0985 when we sent it |
Then, checking what those two checks actually applied to:
- 6990 ($1,800) → INV-0979, INV-0982, INV-1009. The fixed matcher produces the same set: the INV-0974 line correctly finds nothing (6418's fallback had already paid INV-0974), so its $600 goes to fallback. Mislabel, not misallocation. Nothing to correct.
7100 ($2,400) → INV-0970, INV-0988, INV-0991, INV-1006. The stub's 4th line named INV-0985 for $600. Post-#105 that line claims INV-0985 (fix 6 dropped the amount gate), applies its $426.93 balance, and $173.07 falls through to the fallback.Wrong — checked against production 2026-08-06. 7100 is correctly applied. Nothing to correct. INV-0985 was the Enclave invoice's own number until we took it away.scripts/fix-inv-0985.mjsresolved a duplicate: Pelham Parkway's $426.93 row kept INV-0985, and the Enclave's $600 invoice that shared the number was re-loaded as INV-1006 — carrying the same PDF, still namedINV-0985.pdf, issued 2026-05-11, due 2026-06-10. The facility is holding a paper invoice numbered INV-0985 for exactly that $600. Their stub cites the number we printed for them. Timeline: Pelham's INV-0985 created 06-16 17:23 → Enclave re-loaded as INV-1006 06-16 22:32:39 → check 7100 confirmed 06-17 02:34. By confirm time the ref matched nothing, sodate_amountcaught it on period_end2026-05-09+ $600 — the one Enclave invoice that fits, and the right one.
There is no historical correction. Both checks are mislabels; neither is a misallocation.
The re-target could not have happened anyway: the candidate pool is payer-scoped
(outstandingInvoicesForPayer, services/checks.ts:71), 7100's payer resolves through the
enclave/contains row to Rye only (covers_all_facilities: false), and Pelham's INV-0985
sits on a different facility. It was never a candidate.
Do not unapply and re-confirm 7100. Re-confirm re-runs the matcher against today's outstanding pool, not the pool as it stood on 2026-06-17. The upside is zero and the downside is real.
D1 — The oldest-first fallback stays. It is a business rule, not a guess.
Facilities run chronically late, so money that a stub can't place genuinely covers old debt. Applying it to the oldest unpaid invoice is the intended behaviour, including when a line named an invoice we cannot find (void, already paid, foreign numbering).
The obligation this creates: the reconciliation report must explain the placement, and must be available at any time so a facility can see which invoices are already paid.
Consequences:
report-scope.md§3 needs a 10th cause: "applied to oldest unpaid — your stub cited INV-XXXX, which was voided/already paid". Today's 9 causes have no chip for this, and it is the single most common thing the report will have to justify (~11% of all money reconciled, $3,270 of $30,038.73).- The facility-facing
/statement/[token]page (report-scope.md§5, PR-4) is no longer optional polish — it is the mechanism that discharges this obligation. - Do not add a rule that holds a remainder when a line names a missing invoice. Rejected explicitly.
D2 — No historical re-run. Correct by hand.
The full re-run (reconstruct outstanding-as-of-confirm-time, re-target, diff) is dropped. It
would exist to find 3 lines across 2 checks, of which only one moves money none of which move
money (2026-08-06: 7100 turned out to be correct too).
Instead:
Correct check 7100 once, via unapply (D3).Nothing to correct — see above.- Turn the classification query above into a permanent admin check, so this class can never accumulate silently again. Note what it must know: a ref that names an invoice we have since renumbered is not a mismatch. 7100 read as one for a day because the classifier compared the stub against today's numbering, and the facility remits against the number on the paper we sent.
This also settles a trap in the old plan: a re-run would have reported 6418 as same, because its
misattribution came from the fallback, not the matcher — the diff report structurally cannot see
fallback placements. Under D1 that is now correct behaviour rather than a blind spot.
Superseded: remittance-rematch-backfill's "full re-run" decision and fix-plan.md §5 in its
entirety.
D3 — Unapply is built, minimally.
One RPC: delete check_payment_applications rows, walk back invoices.amount_paid_cents /
status / paid_at, revert check_payments.status off confirmed — atomic, audit-logged. Plus
one button on the check detail page. No workflow, no partial per-row surgery.
Correcting 7100 is then: unapply → re-confirm through the normal path, which now targets INV-0985
correctly on its own. 7100 needs no correction (see the evidence section), so unapply ships on the
justification below alone — which is the stronger one anyway. No manual line-assignment UI is
needed anywhere.
A caveat for whoever uses the button: re-confirm re-runs the matcher against the outstanding pool as it is at that moment, not as it was at the original confirm. Unapplying restores this check's own targets to outstanding, but any other invoice paid, voided or issued since will change the placement. Unapply to correct a wrong amount or a wrong facility; do not unapply to "replay" an old confirm and expect the same answer.
Justification is no longer the backfill — it is that fix-plan.md fixes 3 and 5 both return
"unapply the payment first" for a flow that does not exist, so without this those guards are dead
ends for the operator.
D4 — Both confirm and unapply gate on requireDomain('billing').
Unapply takes the same gate as confirm. The isOwner restriction on the confirm button in
ReconcileCheck.tsx:270 is dropped — it was UI-only, the server action at
checks.ts:469 already accepted any billing-domain staff, so the button was hiding an action the
server would have allowed. A biller who can reverse a payment but not apply one is incoherent.
Still open
-
How much the facility statement narrates. "INV-002 was voided, so your $1,200 went to INV-0375 + INV-0974" tells a facility we cancelled an invoice they believed they owed. Wording is a trust decision, not a technical one.
-
One payer matches no
billing_payerspattern: Hebrew Home for Health & Rehabilitation LLC (1 check). "Hebrew" is ambiguous between two facilities that each have zero invoices. Worth checking whether it too is a legal name whose DBA is already on file — that is what the other half of this item turned out to be:East Northport Residential Health Care Facility, Inc. (2 checks, $3,472). No East Northport facility exists at all.Wrong — resolved 2026-08-05. East Northport is the legal name of the facility stored under its DBA, Huntington Hills Center for Health and Rehabilitation (53664f26-51aa-496a-a7c3-91fe8f0ee267); facilities are stored asdbaName || legalName, so no "East Northport" row exists by design. Confirmed against the facility's own intake response (facility_intakes, samefacility_id) andscripts/seed-facility-intakes.mjs:100-101. No money is misplaced — both checks were already placed on that facility by manual pick, and its 7 invoices show $5,292.00 paid, exactly those two plus the $1,820.00 "Huntington Hills" check. The only real gap was a missing payer pattern, since 0049'shuntington/containsrow cannot match the legal name; fixed forward-only by migration 0101 onfix/northport-payer-mapping. -
The
enclavepattern iscontains. It resolves payer "The Enclave at Port Chester" to facility "The Enclave at Rye". Confirmed correct today (Rye holds all 43 invoices and all 12 of those checks — it is the payer's corporate name on the check stock), but the pattern would silently swallow a second Enclave facility. -
Where 7100's $173.07 remainder lands after the correction — falls to oldest-first per D1, worth eyeballing once.Moot 2026-08-06 — there is no correction, so there is no remainder. -
All shipped (#113, #114, #115, #117), plus the PostgREST lockdown (#116, 0104) and unapply (#118, 0105).fix-plan.mdPRs 2–5 still to ship. PR 1 merged as6a5f0ab. -
New, from the 7100 check. Renumbering an already-sent invoice leaves the facility remitting against a number that no longer exists here, and nothing in the row records what it used to be. Today that is one invoice and it resolved by luck (
date_amountcaught it). Aprevious_numbercolumn, or an audit row the matcher consults, would make the ref match deterministically. Not urgent; worth deciding before the next renumber.