Bug: https://hola-tech.sg.larksuite.com/record/BK5GrTh5SeDvk9cu5z4lhJncgWc
Problem: Supply screen (USD) showed MAX 19,955.33 (the wallet) but submitting it was refused with "You can supply up to 9,968.99 USD": the per-user FIAT supply cap (10,000) minus what is already supplied or in flight.
Fix
- BE: GET /lending/quotes/supply?asset= returns { capRemaining } (cap headroom floored to the market decimals, null when uncapped), computed by the same cappedSupplyBalance + supplyCapHeadroom the supply refusal uses.
- FE: on FIAT markets MAX = min(wallet, capRemaining); CRYPTO unchanged. The quote is re-asked after a supply, a close or a SUPPLY_EXCEEDS_CAP refusal, and falls back to the wallet if it fails.
Tests
- BE unit + http specs; Postgres fiat-rail.postgres.spec (a MAX of exactly the headroom is accepted with a supply in flight), which fails without the fix.
- FE jest 1349/1349, tsc clean.
- Maestro fe/.maestro/app/supply-max-under-cap.yaml on the iOS simulator against a local BE: MAX 9,968.99 (not 19,955.33), Confirm, Completed; rerun with cap 15,000: MAX 5,000.00, Completed.
Review follow-up — ade691d5
- Supply-cap quotes now refresh through the existing lending socket invalidation helper on settled/failed events. Mounted real-hook regressions cover another session supplying, CLOSE_SUPPLY releasing headroom, and a failed supply returning its reservation. No polling or client-side money calculation added.
- Maestro now requires Completed beside Status, Supply beside Type, and the exact expected USD value beside Amount. Navigation away from the form is no longer enough.
Fresh verification
- Node 20.20.0: full FE 144 suites / 1546 tests passed; typecheck passed; full ESLint 0 errors / 30 warnings. Five assertions failed before the socket fix; the focused tests pass afterward. Prettier, commitlint and whitespace checks passed.
- Actual Maestro CLI AND local stdio MCP on an isolated iOS simulator with a strict localhost mock API: correct Completed Supply 9,968.99 USD passed. Pending, missing-operation error, Failed, wrong amount and wrong type each reached a fresh receipt and were rejected by the intended new assertion, after the old success checks had already passed.
- Native source audit: 1093 production/flow files, zero unintended mismatches; tested YAML and critical source hashes match this commit. Follow-up code and architecture review found no remaining blockers.
Boundaries
- Native follow-up proves mock-backed UI/form/receipt assertions, not real backend cap enforcement, ledger settlement or native socket transport. Socket/query-cache behavior is covered by the mounted-hook tests.
- Existing backend contract, advisory quote behavior and API-error wallet fallback are unchanged. No project dependencies added.
- Owned simulator/services were cleaned up; existing BE, Metro, Postgres, Redis and simulators preserved. No real financial/provider operation was performed. CI on this commit remains required before merge; no merge performed.