verex

Funding leg: Stripe test-mode checkout → internal USDCX ledger

Cause: Jayverse service #2 — jay’s “go ahead with the tasks for these three services”; design doc docs/features/jayverse-onboarding-mm.md in the rabbit repo (§4 onboarding flow, §6 sketch).

Reasoning: Money enters as a Stripe test payment and lives as an internal ledger credit (USDCX), never as redeemable crypto — the custody caveat is printed plainly in the UI. Webhook credit must be idempotent (Stripe redelivers), and the signature must be verified against the raw body. The order path reuses the existing checkExternalFunds read-and-refuse discipline rather than inventing a second guard style.

Change: POST /funding/checkout (Checkout Session via raw REST, refuses any non-sk_test_ key by prefix), POST /webhooks/stripe (raw-body HMAC + timestamp tolerance, idempotent credit keyed by event+session inside the credit transaction), Prisma Balance / LedgerEntry / StripeEvent models + migration 20260907000000_funding_and_mm_admin, USDCX guard + taker debit/credit inside the matching transaction in book.ts, redeem crediting in resolve.ts, web /funding screen (preset chips, custody line, post-return banners, mini ledger) and the header USDCX chip.

Result: tsc clean in api and web, both builds pass, root pnpm test 63 contract + 6 SDK green; runtime smoke against the local dev servers (balance/ledger shapes, checkout 503 without a key — by design, no Stripe keys in env). Known v1 gaps recorded: failed on-chain settlement does not reverse USDCX trade deltas; resting BUY limits are balance-checked at placement only; group worst-loss models the Yes side; external-address redeems don’t credit USDCX.

MM leg: operator ladder exposure + owner-gated /admin/mm

Cause: Same design doc, §6 “operator / admin page” — the MM is money-moving and always-on, so it needs a window and a switch.

Reasoning: Config splits by risk (jay’s standing v1 decision in the doc): pause/resume and a bounded spread are safe to change live; b and the collateral cap define max loss, so they stay read-only deploy-time env in v1. Every write is validated server-side and audit-logged — the page controls, the Authority Auditor later merely reports.

Change: mm-admin.ts (status aggregation: per-market inventory via one balanceOfBatch, net sold, best quotes, b·ln(n) cap and worst-loss headroom; global treasury/committed/PnL; audited config writes), kill-switch + spread honored in mm.ts (MAX_SPREAD_BPS = 500), MmConfig / MmAuditLog models + Market.mmPaused, mm flag on book levels with an “MM” tag in BookPanel, web /admin/mm (Status + Config tabs, operator #0 gate, confirms on writes), ~65 i18n keys EN/KO.

Result: Same verification run as above. Open for jay: suppress the auto-faucet chain-USDC for Stripe-funded wallets so USDCX is their only spendable balance? VEREX_WEB_URL must be set per environment for Checkout return URLs.

Next (tomorrow)