Skip to content

Pre-launch ops checklist (Phase 1 → production) ​

The last Phase-1 box. Every feature is built; this is the operational pass that turns a green codebase into a live deployment. Work top-to-bottom; nothing here is code-writing — it's gates, config, data, and manual QA.

Legend: [auto] = runnable via scripts/pre-launch-checks.sh · [manual] = human action · [operator] = do only when explicitly ready (not part of a dry run).


1. Code gates [auto] ​

Run bash scripts/pre-launch-checks.sh (or the commands below). All must pass.

  • [ ] Typecheck — npx tsc -p apps/api/tsconfig.json --noEmit and the web tsc (part of npm --workspace=apps/web run build).
  • [ ] Unit/integration tests — npm test (all workspaces). API + web suites green.
  • [ ] Coverage thresholds — npm --workspace=apps/api run test:coverage and npm --workspace=apps/web run test:coverage meet 80/80/80/70 (lines/functions/statements/branches per CLAUDE.md). Document any pre-existing flake (e.g. search.routes.test) as out-of-scope, not a new regression.
  • [ ] Production builds — npm run build (web + admin). The bundle is what users get, not the dev server.
  • [ ] Dependency audit — npm audit --audit-level=high clean, OR every finding triaged (the known firebase-admin transitive advisory is pre-existing; no NEW high/critical introduced).

2. Secrets + config (Railway env) [manual] ​

Nothing below lives in git. Verify each is set in the target environment.

  • [ ] DATABASE_URL (Supabase, pooler), JWT_SECRET (≥64 random chars), JWT_*_EXPIRES_IN.
  • [ ] FRONTEND_URL set to the exact web origin (CORS is not *); admin origin too.
  • [ ] MSG91 — MSG91_API_KEY is a LIVE key; MSG91_SENDER_ID set. Register every template in the MSG91 dashboard and set its MSG91_TEMPLATE_ID_* (full list in .env.example). Until a template ID is set, that event's SMS is silently skipped (in-app still fires). Mandatory ones boot-fail in production (validateSmsTemplateEnv): OFFER_ACCEPTED, BID_ACCEPTED, OFFER/BID_AUTO_REJECTED_LEAD_EXPIRED.
  • [ ] Redis — REDIS_URL set (Railway private endpoint), reachable. The SMS worker + scheduled workers won't run without it (in-app notifications still write; SMS + sweeps don't).
  • [ ] R2 — R2_* set; bucket public-read, directory-listing OFF, CORS to our domain only.
  • [ ] Firebase — FIREBASE_* (OTP). OPENWEATHERMAP_API_KEY (nice-to-have).
  • [ ] Sentry — SENTRY_DSN (api) + VITE_SENTRY_DSN (web/admin) + SENTRY_ENVIRONMENT + SENTRY_RELEASE (git SHA). Empty DSN = quiet (fine for dev, NOT for prod).

3. Feature flags [manual] ​

  • [ ] EMANDI_TILED_REDESIGN_ENABLED — flip ON in production once smoke-tested (the tiled /sell /buy hubs + browse boards depend on it).

4. Data — DB wipe + reseed [operator] ⚠ DO NOT run during testing ​

The product owner triggers this only when production testing is finished — do NOT run it as part of a dry run.

  • [ ] Taxonomy wipe + reseed: npm run db:wipe-taxonomy (interactive — types DELETE EVERYTHING; refuses in production unless ALLOW_PRODUCTION=true). Recomputes trust scores after.
  • [ ] If keeping any pre-wipe batches: npm --workspace=apps/api run db:backfill-batch-sale-price (idempotent). N/A after a full wipe.
  • [ ] Confirm all CHG migrations are applied (pooler-safe prisma db execute + migrate resolve flow per the CHG notes).

5. Manual QA [manual] ​

  • [ ] Viewport sweep — 320 / 375 / 768 / 1024 / 1440 / 1920px on the key pages (Dashboard, Sell/Buy hubs + browse, product drawer, Reports, Profile, a deal detail). No horizontal scroll, no clipped tap targets, no empty-column imbalance.
  • [ ] Keyboard a11y — Tab/Enter/Space/Arrows/Escape through the board tables + overlays (unplug the mouse).
  • [ ] Core flow smoke (staging): signup→OTP→complete profile; post a sell + buy lead; offer/bid → accept → dispatch → buyer confirm-receipt (stock deducts on receipt, both batches reconcile); Buy Now; Reports page renders + CSV/XLS/PDF download; instant-push notification toast arrives.

6. Observability + monitoring [manual] ​

  • [ ] Staging Sentry receiving events (throw a test error) before prod deploy.
  • [ ] Better Uptime monitors: GET /api/v1/health (1-min) + web root (5-min); alert channel set.
  • [ ] Bull Board reachable at /admin/queues (admin auth) — SMS + scheduled queues visible.
  • [ ] /api/v1/health returns 200 with database: ok + redis: ok in prod.

7. Security final pass [manual] (CLAUDE.md §14) ​

  • [ ] npm audit --audit-level=high clean (or triaged).
  • [ ] No secrets in git history; all secrets in Railway only.
  • [ ] helmet headers present on API responses; HSTS on.
  • [ ] File-upload endpoints reject non-images (magic-byte check) with 400.
  • [ ] Rate limits verified on OTP + login.
  • [ ] No console.log of phone numbers / tokens.

8. Deploy [operator] ​

  • [ ] Staging deploy → run §5 smoke → product-owner sign-off (screenshots).
  • [ ] Production deploy (Railway). Tag the release SHA into SENTRY_RELEASE.
  • [ ] Post-deploy: re-check /api/v1/health, watch Sentry error rate for the first hour.

Order of operations on the real launch day: §1–§3 + §6–§7 first (safe, repeatable) → staging smoke (§5) → product-owner sign-off → then the §4 DB wipe → production deploy (§8). The wipe is last because it's destructive and the owner gates it.

Last updated:

Internal technical documentation — Cropto