Final-review fixes for the card-funding + passcode-confirm work merged in !25 (merged).
Passcode boundary — Critical revert. POST /fireblocks/internal-transfer was
given PasscodeConfirmGuard on the assumption it had no frontend caller. It does:
fe/src/components/send/confirm-send-sheet.tsx:75 calls it and sends no passcode, so
the guard 401s every crypto user-to-user Send — and because the route is not in the
axios refresh exemption, the 401 triggers a token refresh that REPLAYS the transfer.
The guard and the DTO's passcode field are both reverted. Guarding this route needs a
frontend change that is out of scope here.
Coverage spec now tells the truth. passcode-confirm.coverage.spec.ts claimed to
assert "every money-moving route". It did not. It now carries an explicit
KNOWN_UNGUARDED list of the five FE-called money routes that still run AuthGuard only
(/fireblocks/internal-transfer, /chats/internal-transfer,
/chats/external-transfer, /reap/transfer/external, /reap/transfer/internal), so
the gap is documented and asserted rather than implied away.
Card top-up hardening.
-
DepositCardDto.amountis constrained to a positive decimal with at most 2 places, with a spec covering the rejected shapes. - Three early-return paths in
card-topup-settlement.service.tsnow go through the attempt counter, so a top-up that bails early is still visible to the escalation path instead of looking untried. -
reconciliation.service.tsreferenced migration1787330000001; the seeding migration is1787340000001.
Frontend. useDepositToCard now invalidates CARD_KEYS.detail(id) as well as the
card list and fiat balances — without it the screen a user returns to after a top-up
reads a 5-minute-stale detail cache and shows the pre-transfer balance, which reads as
"my money vanished". Covered by a new test.
Also seeds the previously-skipped internal-reserve.postgres.spec.ts so it runs red
before it runs green.
Unrelated ride-along from a parallel session: fe/scripts/prepare-icon-badge.js plus
its package.json entry.