# 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
