# Mobile Internal Beta Checklist (Stage 3 Cutover) ## Purpose This document is the step-by-step runbook for releasing the monorepo mobile app (`mobile/`) to internal testers before broader rollout. **Prerequisite:** Stage 2 (web internal adoption) must be complete and stable through at least one full backend deploy cycle before beginning Stage 3. See `docs/CUTOVER_WEB.md`. --- ## Pre-Flight Gate Do not begin mobile beta until all of the following are true. ### Go / No-Go Checks ```bash # From monorepo root pnpm verify # must be green pnpm lint # must be green pnpm smoke:release # must pass — validates mobile platform contract compilation ``` ### Backend + Web Stability - [ ] Stage 2 (web internal adoption) signed off with no rollback triggers - [ ] Backend has been stable through at least one full deploy cycle since web cutover - [ ] `GET /health/live` returns 200 from the deployment that mobile will target - [ ] WebSocket `/trading` namespace is reachable from an external network (not just localhost) - [ ] Feature flags endpoint `GET /api/feature-flags` returns valid response ### Mobile Build Readiness - [ ] `EXPO_PUBLIC_PRODUCT_ID`, `EXPO_PUBLIC_PLATFORM_URL`, `EXPO_PUBLIC_TRADING_API_URL` set correctly for the target environment - [ ] App compiles cleanly: `pnpm --filter @bytelyst/trading-mobile typecheck` - [ ] Internal distribution channel ready (TestFlight for iOS, Internal Testing for Android, or Expo Go for dev) - [ ] Internal testers identified (typically the same operators who validated web) ### Rollback Readiness - [ ] Web dashboard remains fully operational as the primary operator interface - [ ] Mobile beta can be pulled from distribution without affecting backend or web - [ ] You know who owns the rollback decision --- ## Step 1 — Build and Distribute the Beta ### Option A — Expo Go (fastest for internal testing) ```bash cd mobile pnpm dev # starts Expo dev server; testers scan QR code with Expo Go app ``` ### Option B — Native build via EAS (recommended for realistic testing) ```bash # Requires EAS CLI and Expo account npx eas build --platform all --profile preview npx eas submit --platform all # submit to TestFlight / Google Play Internal Testing ``` Verify distribution: - [ ] Each internal tester can install the app on their device - [ ] App launches without crash on both iOS and Android (or whichever platforms are in scope) --- ## Step 2 — Fresh Install Sign-In Each tester performs a fresh install (no prior session): - [ ] App launches to the sign-in screen (no blank screen, no crash) - [ ] Sign in with platform credentials — same credentials as web - [ ] Session established — app navigates to the Overview tab - [ ] Confirm auth token is a platform JWT (check tester's device Expo logs) - [ ] `GET /api/me/profile` returns the correct user profile --- ## Step 3 — Session Restore - [ ] Close the app completely (background + remove from recents) - [ ] Reopen the app - [ ] App restores session without re-prompting for sign-in - [ ] Overview tab loads with live state (not a loading spinner indefinitely) - [ ] Confirm secure storage is working: token survives app restart --- ## Step 4 — Kill-Switch and Degraded-State Handling ### Kill-switch - [ ] Toggle maintenance mode on via platform-service - [ ] Reopen (or refresh) the mobile app — it must block access with a maintenance/unavailable screen - [ ] Toggle maintenance mode off - [ ] App recovers without requiring a reinstall or manual sign-in ### Degraded backend - [ ] Stop the backend service temporarily - [ ] App shows a degraded/offline state clearly (not a crash or blank screen) - [ ] Restart the backend — app reconnects automatically and restores live state --- ## Step 5 — Core Feature Validation Each tester validates their own user scope across all five tabs: ### Overview (index.tsx) - [ ] Portfolio summary loads with current positions and account snapshot - [ ] Live ticker or price updates are visible within 60 seconds - [ ] Trading control badge shows correct mode (RUNNING / PAUSED) - [ ] WebSocket connects to `/trading` namespace (check backend logs: `[API][/trading] Client connected`) ### Positions (positions.tsx) - [ ] Open positions list matches what the web dashboard shows - [ ] Each position shows symbol, side, size, entry price, unrealised PnL - [ ] Positions update live when the backend broadcasts `positions_update` ### History (history.tsx) - [ ] Closed trade history loads and matches web dashboard - [ ] Scroll loads older history correctly (if pagination is implemented) ### Strategies (strategies.tsx) - [ ] Trading profiles list loads for the authenticated user - [ ] Profile names, symbols, and active state are correct ### Settings (settings.tsx) - [ ] User email and account info display correctly - [ ] Sign-out works — returns to the sign-in screen and clears the session - [ ] Notification preference toggles are visible (even if push delivery is deferred) --- ## Step 6 — Real-Time Update Verification Leave the app running on the Overview tab for at least 5 minutes: - [ ] Symbol prices update at least once during the observation window - [ ] Health status reflects current backend loop health - [ ] If a trade closes during the observation window, it appears in History without a manual refresh - [ ] No unhandled exceptions appear in Expo logs during this period ### Polling fallback - [ ] Disable WebSocket connectivity (e.g., block the Socket.IO port via network settings) - [ ] App falls back to polling — data still refreshes (may be slower) - [ ] Restore connectivity — app reconnects to WebSocket automatically --- ## Step 7 — Offline / Poor-Connectivity Behaviour - [ ] Enable airplane mode while the app is running - [ ] App shows a clear offline or disconnected indicator (not a crash) - [ ] Restore network — app reconnects and reloads state without manual intervention - [ ] No stale or misleading data is shown during the offline period --- ## Step 8 — Safe Operator Controls Mobile v1 is intentionally monitor-first. Validate that the scope is correctly limited: - [ ] No destructive trading actions are available in the mobile UI (no "close position", no "pause trading" button) - [ ] No strategy editing available in mobile (strategies tab is read-only) - [ ] No admin panel or diagnostics UI visible to non-admin testers - [ ] Confirm no API calls are made to `POST /api/trade`, `POST /api/close`, or `/internal/trading/*` from mobile --- ## Step 9 — Parallel Run Period (Recommended: 3–7 days) Run the mobile beta in parallel with the web dashboard: - [ ] Testers use mobile for monitoring; web remains primary for operator actions - [ ] Testers report any data discrepancy between mobile and web - [ ] Collect feedback on performance, UX clarity, and any missing information - [ ] Monitor backend logs for unusual error spikes correlated with mobile connections --- ## Rollback Triggers Pull the beta build from distribution immediately if any of the following occur: | Condition | Action | |---|---| | Sign-in or session restore fails | Remove from distribution | | Tenant data leak — tester sees another user's data | Remove immediately + page oncall | | App crashes on launch for any tester | Remove and diagnose | | App shows incorrect or stale positions/history vs. web | Investigate before proceeding | | Backend error rate increases after mobile connections are established | Rollback and diagnose | ### Rollback Steps 1. Remove the beta build from TestFlight / Play Internal Testing 2. Notify testers to uninstall or stop using the app 3. File an incident report — include device, OS version, Expo logs, and `x-request-id` from any correlated backend errors 4. Do not modify Cosmos state as first-response rollback 5. Resolve the root cause before re-attempting the beta --- ## Post-Beta Monitoring (Ongoing during beta period) ### Watch during the beta - [ ] Platform auth failure rate is baseline — no spike correlated with mobile sessions - [ ] Token refresh failures from mobile clients are zero - [ ] WebSocket `/trading` namespace connection count is stable (no reconnect storm) - [ ] Backend `401` / `403` errors are baseline — no increase from mobile auth - [ ] Cosmos read latency is normal — mobile polling does not add unexpected load - [ ] Mobile degraded/offline state frequency is low (expected: near zero on good networks) --- ## Beta Sign-Off Complete after the parallel run period with no rollback triggers: - [ ] All internal testers confirm the app is working correctly on their devices - [ ] No open P0/P1 bugs from the beta period - [ ] Monitoring checks above are green for the duration of the beta - [ ] Feedback collected and triaged (decide what goes into a follow-up release vs. pre-GA fix) - [ ] ROADMAP.md: mark "Mobile internal beta" as `[x]` Done - [ ] OPERATIONS.md: update Staged Cutover section to reflect Stage 3 complete --- ## Next Stage After mobile internal beta is signed off: **Stage 4 — Controlled Operator Rollout** - Expand to a small group of external operators (e.g., power users, design partners) - Gate: mobile beta signed off + web adoption stable for ≥ 1 week - Monitor: same checks as post-beta, extended for 24–48 hours after each rollout increment **Stage 5 — Production Cutover** - Switch full operational ownership from legacy repos to this monorepo - Archive legacy `bytelyst-trading-dashboard-web`, `bytelyst-trading-bot-service`, and `bytelyst-trading-dashboard-mob` - Gate: Stage 4 stable + rollback owners confirmed + monitoring dashboards in place