Repository navigation
BETA_LAUNCH_PLAN
Goal: Move from "deployed but pilot-blocked" to a beta where a real school can self-onboard and use the product daily without hand-holding.
Date: 2026-07-05 · Current version: 1.8.4.0 · Prod: https://classmode.inmodel.in
The product is feature-complete for a pilot: 37 pages, all core loops built (signup → onboard → classes → attendance → tests → grading → parent alerts). Infrastructure is production-grade: fail-closed tenant isolation (server/lib/tenant.ts), rate limiting, bcrypt, GCP Secret Manager, advisory-locked AUTO_MIGRATE.
The July 2 QA report (health 48/100, .gstack/qa-reports/) found 13 issues. Verified today: the 3 worst blockers are already fixed (schoolCode set at server/routes/onboarding.ts:198, passed through server/middleware.ts:60; class creation calls /api/onboarding/classes; quota metering uses ai_usage_logs). What remains is a shorter list of real gaps, plus hardening and proof-via-E2E before inviting a school.
The fixes exist in code but were never re-QA'd. Prove them before building anything.
- Fresh local DB → sign up a new school → complete onboarding → confirm dashboard, attendance, fees, student directory all load (no 403s)
- Teacher onboarding: create class → invite student → student accepts → appears in roster
- Run
npm run check && npm run lint && npm testandnpx playwright testas baseline
Exit criteria: a brand-new school can reach a working dashboard with zero manual DB edits.
-
API 404 guard (ISSUE-009) — unknown
/api/*paths fall into the SPA catch-all and return 200 + index.html, masking every missing/renamed route. Addapp.all("/api/*", → 404 JSON)before the catch-alls inserver/vite.ts:48(dev) andserver/vite.ts:90(prod). Do this first — it un-masks everything else. -
WebSocket handshake 400 (ISSUE-004) — Messages page stuck on "Connecting…". Debug upgrade/auth in
server/message/index.ts. If not quickly fixable, hide Messages nav for beta rather than ship a visibly broken feature. -
Dev migration pgvector (ISSUE-002) —
npm run migratefails onCREATE EXTENSION vector; switch dev compose image topgvector/pgvector:pg16(docker/docker-compose.yml) so onboarding doesn't hang locally. - Silent 403s (ISSUE-005) — Fees/attendance render permission errors as "No data yet" empty states. Distinguish 403 from empty in the shared query/error handling on the client.
- Staff invite path (ISSUE-006) — verify a principal can invite teachers after onboarding (workspace invites exist; confirm it's reachable from the principal/school-admin dashboard and add the entry point if not).
From docs/DATABASE_MIGRATION_CHECKLIST.md:
- Phase 7: run
npx tsx scripts/pg-backfill-users.ts, verify Mongo↔PG delta = 0 - Phase 8: monitor auth fallback rate; when zero, remove MongoDB fallback lookups
- Confirm Cloud SQL automated backups + point-in-time recovery are enabled (GCP console — nothing in code enforces this)
Beta users writing real attendance/fee data on a half-migrated store is the biggest data-loss risk in this plan; don't defer it.
-
Centralized error handler — one Express error middleware producing consistent JSON (
server/index.ts); today errors are per-route try/catch with inconsistent shapes. -
Error reporting — pipe
logger.errorto GCP Error Reporting (zero new vendor; structured logs already go to Cloud Logging). Add request-ID correlation. -
Alerting — GCP uptime check on
/api/health+ alert on error-rate spike. Today nobody is paged if beta breaks at night. -
Secrets audit — confirm all cloudbuild secrets exist; add
WHATSAPP_VERIFY_TOKEN(webhook verification reads it, cloudbuild doesn't inject it). - CI red cleanup (#272) — enable GitHub Code Scanning so CodeQL stops erroring; triage current Trivy CRITICALs once.
Playwright specs (only 4 exist today; none cover the flows that were broken):
-
school-onboarding.spec.ts— signup → verify → onboard → dashboard loads with no 403s (regression guard for ISSUE-001/010) -
teacher-class-flow.spec.ts— create class → invite student → student joins (guard for ISSUE-008) -
attendance.spec.ts— mark absent → alert dispatch recorded -
tenant-isolation.spec.ts— two schools in parallel; school A never sees school B data - Wire these into
ci.yml
- Deploy everything above; verify rollout (new-route JSON flip + uptime reset, per deploy runbook)
- Run
/qaagainst production; target health ≥ 85 (was 78) - Seed nothing — the pilot school onboards through the real signup flow (that is the test)
- WhatsApp: keep outbound fail-loud (v1.8.3.1) only. Per the demand-first decision, do not build the inbound webhook/automated Meta pipe until a principal validates willingness-to-pay
- Onboard 1 pilot school (50–200 students), set up a feedback channel, check
/api/health/detailed+ error dashboard daily for the first 2 weeks
Billing UI (Stripe backend done), study-plan drag-reschedule, recurring live classes, CSV export, AI-tutor web search, PBL, AI-gateway migration TODOs (server/lib/ai/gateway.ts), Anthropic adapter.
| Phase | Effort | Cumulative |
|---|---|---|
| 0 — Re-verify | ½ day | Day 1 |
| 1 — Blockers | 2–3 days | Day 4 |
| 2 — Migration | 1–2 days | Day 6 |
| 3 — Hardening | 2 days | Day 8 |
| 4 — E2E tests | 2 days | Day 10 |
| 5 — Launch + monitor | 1 week | ~Day 17 |
≈2 working weeks to a school actively using the product. Phases 2–4 can partially overlap if needed.
-
npm run check && npm run lint && npm testgreen -
npx playwright testgreen (including new specs from Phase 4) - Manual: fresh-school signup on prod completes with no 403s
- Prod
/qahealth ≥ 85;/api/health/detailedall green - Alert fires when health endpoint is forced to fail (test the pager once)