MBT v1 — Launch Readiness Checklist
Owner: Kristerpher Henderson Last updated: 2026-05-03 Anchor epic: #256 Deliverable card: #265
Pre-flight — what must be green before sign-off
| Gate | Status | Owner | Notes |
|---|---|---|---|
| All Wave 1 polish merged (#922 #923 #924) | ✅ 2026-05-03 03:53 UTC | feature-dev | Settings, StrategyComparison, Trading |
| Wave 2 polish merged (#926 #927 #928 #930) | ✅ 2026-05-03 04:05 UTC | feature-dev | Backtest, HistoricalData, Dashboard, SetupWizard |
ENABLE_OPTIONS_BACKTEST gate (#929/#257) |
✅ 2026-05-03 03:59 UTC | feature-dev | Default false — flag-gated, no UI exposure |
Backend deploy to raxx-api-prod |
⏳ Blocked on HEROKU_API_KEY GH secret refresh (#925) |
operator | Vault token valid; GH Actions secret stale |
| Antlers deploy to CF Pages | ✅ — auto-deploys per merge | CF Pages | Live within ~3 min of each merge |
Smoke test on raxx-api-staging (post-token-fix) |
⏳ | release owner | Run after HEROKU_API_KEY resync |
| Attorney sign-off (#197) | ⏳ | Matthew Crosby | Out of scope — last gate before GA |
Section 1 — End-to-end user flow walkthrough
Flow 1: First-visit SetupWizard → Dashboard
- User visits
app.raxx.appfor the first time → redirected to/setup-wizard - Header reads "Set up your account" (vendor-name-free per Confidence Engine direction)
- Step 1: pick paper / live mode. Live-mode guard — selecting Live surfaces an inline alert "Credentials required. Live trading will not execute unless…" before the user can advance.
- Step 2: enter API credentials (passwords masked).
- Step 3: validate connection → "Connected — retrieved N data feed(s) and verified broker access for $SYMBOL".
- Finish Setup → redirect to
/dashboard
Flow 2: Dashboard → Historical Data → symbol lookup
- Click "Historical Data" in nav.
- Enter symbol, pick date range.
- Empty state if no data: "No history yet — pick a symbol and date range to load chart" (no blank screen).
- Loading state: spinner + "Loading historical data…" while
/api/historical-dataresolves. - Error state: typed messages for
feed_unavailable,rate_limited,feed_disabled,feed_credentials_missing— each with a Retry button. - Chart shell renders with tabular numbers in any data tables.
Flow 3: Dashboard → Backtest → configure + run securities backtest → view results
- Click "Backtest". Header includes the persistent paper/live badge derived from
settings.tradingMode. - Configure: strategy + parameters + symbol + dates.
- Click "Run Backtest" → loading state with progress.
- Results render with metrics + equity curve + trade list.
- Options entry point (e.g. "Add Options Leg" toggle) — if
ENABLE_OPTIONS_BACKTEST=false, renders theOptionsBacktestComingSoonpanel instead of the options form. No options backtest can be triggered. - Errors mapped via
friendlyError()— no rawdelayed_sip/ internal feed IDs leak to UI copy.
Flow 4: Dashboard → StrategyComparison → compare two results
- Click "Strategy Comparison".
- Pick two saved backtests from dropdowns (or empty state with CTA back to Backtest).
- Side-by-side comparison table renders with metric tooltips on Sharpe, Max Drawdown, Profit Factor, Win Rate.
- Mobile (390 px viewport): table scrolls horizontally with shadow indicators.
Flow 5: Dashboard → Trading → options screening + paper options order
- Click "Trading". Persistent paper/live badge in the header reflects
settings.tradingMode. - Empty / loading / typed-error states cover the four broker conditions:
broker-credentials-missing,broker-rate-limited,broker-feed-disabled,broker-unavailable. - Submit a paper options order — confirmation modal renders before the POST fires.
- Live-mode submit (if mode=live) — already gated by the Settings live-mode confirmation modal earlier.
Flow 6: Settings → credential update + mode confirmation
- Click "Settings".
- Mode cards are
<button>elements (not bare<div>). - Click "Live Trading" → confirmation modal requires typing
LIVE TRADINGexactly before commit. - Credentials section: passwords masked, last-4 visible only after explicit "Show" tap.
- Feature-flag visibility tab: shows
ENABLE_OPTIONS_BACKTEST: falsewith a "Coming soon" badge + tooltip explaining the data-licensing gate.
Flow 7: Any entry point to options backtesting → "coming soon" panel
- Default state:
ENABLE_OPTIONS_BACKTEST=false. - Affected entry points: Backtest's options leg toggle, any explicit
/options-backtestroute, the StrategyComparison "Add options strategy" affordance. - Each renders
<OptionsBacktestComingSoon />instead of the actual options-backtest UI. - Backend
/api/backtest/optionsroute returns503 {"feature": "options_backtest", "enabled": false}when the flag is off (defense in depth — frontend may be cached).
Section 2 — Regression-test matrix
| Page / surface | Loading state | Empty state | Typed error states | Paper/live badge | Vendor-name-free | Mobile 390 px | 44 px tap targets |
|---|---|---|---|---|---|---|---|
| Dashboard | ✅ #928 | ✅ #928 | ✅ is_mock → demo |
n/a | ✅ #928 | ✅ | ✅ |
| HistoricalData | ✅ #927 | ✅ #927 | ✅ 4 feed states | n/a | ✅ #927 | ✅ | ✅ |
| Backtest | ✅ #926 | ✅ #926 | ✅ friendlyError() |
✅ | ✅ #926 | ✅ | ✅ |
| Backtesting | ✅ #926 | ✅ #926 | ✅ friendlyError() |
✅ | ✅ #926 | ✅ | ✅ |
| StrategyComparison | ✅ #923 | ✅ #923 | ✅ | n/a | ✅ #923 | ✅ scroll-x | ✅ |
| Settings | ✅ #922 | ✅ #922 | ✅ live-mode guard | n/a (controls mode) | ✅ #922 | ✅ | ✅ |
| Trading | ✅ #924 | ✅ #924 | ✅ 4 broker states | ✅ persistent header | ✅ #924 | ✅ | ✅ |
| SetupWizard | ✅ #930 | ✅ #930 | ✅ symbol validation | n/a | ✅ #930 | ✅ | ✅ |
Smoke-test contract (frontend/trademaster_ui/src/tests/smoke.contract.test.js):
- Setup wizard shell renders ✅
- Setup data-retrieval contract ✅ (regex tolerates pre/post-polish copy)
- Historical data chart shell renders ✅
Backend smoke (scripts/ci/run_smoke.sh):
- /api/health 200 ✅
- /api/settings 200 with feature_flags.ENABLE_OPTIONS_BACKTEST: false ✅ (after Heroku deploy)
- /api/backtest/options returns 503 when flag off ✅ (after Heroku deploy)
Section 3 — Staging smoke (run before GA)
⏳ Cannot run until
HEROKU_API_KEYGH Actions secret is refreshed (#925). After that:
# 1. Trigger deploy
gh workflow run deploy-heroku.yml -f environment=staging -f ref=main
# 2. Wait for deploy
gh run watch # pick the deploy-heroku.yml run
# 3. Verify staging
curl -sS https://api-staging.raxx.app/api/health
curl -sS https://api-staging.raxx.app/api/settings | jq '.feature_flags'
# expect: { "ENABLE_OPTIONS_BACKTEST": false }
# 4. Toggle flag on staging only
heroku config:set ENABLE_OPTIONS_BACKTEST=true -a raxx-api-staging >/dev/null 2>&1
curl -sS https://api-staging.raxx.app/api/settings | jq '.feature_flags.ENABLE_OPTIONS_BACKTEST'
# expect: true
# 5. Toggle back off before customer demo
heroku config:set ENABLE_OPTIONS_BACKTEST=false -a raxx-api-staging >/dev/null 2>&1
Walk Flows 1–7 against staging at https://app-staging.raxx.app (or local CRA proxied to staging API). Capture screenshots for the launch-readiness artifact.
Section 4 — Production rollout sequence
- ✅ All Wave 0–2 PRs merged
- ⏳ Resync
HEROKU_API_KEYGH Actions secret (operator action #925) - ⏳
gh workflow run deploy-heroku.yml -f environment=staging -f ref=main→ soak ~30 min on staging - ⏳ Walk Flows 1–7 on staging — log results in this doc as a "Staging smoke 2026-05-03" subsection
- ⏳
gh workflow run deploy-heroku.yml -f environment=production -f ref=main - ⏳ Verify production:
curl https://api.raxx.app/api/settings | jq '.feature_flags' - ⏳ Attorney sign-off (#197)
- 🚀 GA
Section 5 — Rollback plan
If the deploy is bad:
- heroku rollback v<previous> -a raxx-api-prod (Heroku release rollback is instant)
- Revert the offending PR via gh pr revert <num> and force-deploy
- Antlers: CF Pages preserves prior builds — toggle via CF dashboard if needed (no Antlers-side rollback strategy is automated yet — file as follow-up)
If ENABLE_OPTIONS_BACKTEST was flipped on by mistake:
- heroku config:set ENABLE_OPTIONS_BACKTEST=false -a raxx-api-prod >/dev/null 2>&1 (instant; takes effect on next request)
- Frontend cached settings refresh on next page load — communicate via Slack DM if customers active
Refs
- Epic: #256
- Wave 0 (gate): #257 → PR #929
- Wave 1: #264 → PR #922, #262 → PR #923, #263 → PR #924
- Wave 2: #258 → PR #926, #259 → PR #927, #260 → PR #928, #261 → PR #930
- Wave 3: #265 (this doc), #266 getraxx copy (in flight)
- Blocker: #925
GITHUB_API_SECRETS_TOKENfor autonomous secret rotation - Final gate: #197 attorney sign-off