Skip to content

L. Migration Feasibility & Phased Plan

← Back to README


Migration Principles

  1. No big-bang. Each phase is independently deployable and shippable.
  2. Product work continues in parallel. The migration is infrastructure work — feature development does not pause.
  3. Security before structure. Phase 0 (security fixes) blocks all other phases.
  4. Melissa migrates first. It is the cleanest codebase and the one receiving the most active development.
  5. Legacy portal is modernized, not frozen. reverb-react moves to apps/legacy-portal/ as a Next.js 16 rewrite — business logic is preserved, rendering and tooling layers are replaced.
  6. No business logic changes during structural migration. If you change behavior during a structural move, you cannot attribute bugs correctly.

Phase 0 — Security Fixes (Week 1)

Blocks all other phases. Non-negotiable.

Task Owner Notes
Revoke GitHub PAT in soreto-zoe/package.json Any engineer GitHub → Settings → Developer Settings → PATs
Audit PAT scope (what repos did it have access to?) Security lead Review GitHub PAT audit log
Replace soreto-arena GitHub dep Backend engineer Use upstream bull-arena or bull-board from npm
Verify SESSION_SECRET, TOKEN_SECRET, COOKIE_SECRET are set in all envs DevOps Check Heroku config vars
Check git history for other embedded secrets Any engineer git log -S "password" --all
Rotate any analytics tokens (Mixpanel, GA) if exposed DevOps Check what's in git history

Exit criteria: No secrets in source code. All environment variables verified. PAT revoked and replacement strategy in place.


Phase 1 — Foundation (Weeks 2–6)

Goal: Stop the bleeding on immediate risks before restructuring.

Node Version Stabilization

[ ] Add .nvmrc to reverb-backend  (current: 14 — document, don't upgrade yet)
[ ] Add .nvmrc to reverb-react    (current: 10 — modernization target: 24)
[ ] Add .nvmrc to soreto-melissa  (current: 22 — already correct)
[ ] Add .nvmrc to soreto-zoe      (current: 16 — document, don't upgrade yet)

CI/CD

[ ] Add GitHub Actions to soreto-melissa
    - steps: install, typecheck, lint, test, build
[ ] Add GitHub Actions to soreto-zoe
    - steps: install, typecheck, build
[ ] Migrate reverb-backend from Travis CI to GitHub Actions
[ ] Migrate reverb-react from Travis CI to GitHub Actions (build only — until Next.js rewrite is ready)

Dependency Quick Wins

[ ] Replace node-sass with sass in reverb-backend
[ ] Remove universal-analytics from reverb-backend (GA UA is dead)
[ ] Remove Google+ sharing code from reverb-react
[ ] Upgrade soreto-zoe: knex@0.16.3 → 0.21.x (first increment)
[ ] Run full reverb-backend test suite, fix any failures

Documentation Start

[ ] Create docs/spec/DOMAIN_MODEL.md (entity definitions)
[ ] Create docs/dependencies/UPGRADE_BLOCKERS.md (from audit)
[ ] Create docs/migration/REVERB_REACT_PARITY.md (feature checklist)

Exit criteria: All repos on GitHub Actions CI. soreto-melissa and soreto-zoe have working test/build pipelines. knex upgrade started on zoe. No deprecated integrations sending to dead APIs.


Phase 2 — Monorepo Bootstrap (Weeks 6–12)

Goal: Create the target structure. Migrate the cleanest app first.

Scaffold Creation

[ ] Create soreto-platform/ repository
[ ] Configure npm workspaces (workspaces field in root package.json)
[ ] Add Turborepo (turbo.json with build/test/lint pipeline)
[ ] Create apps/, packages/, tooling/, docs/ directories
[ ] Create root .nvmrc (24), .gitignore, root package.json
[ ] Create root CLAUDE.md (system overview)

First Package: @soreto/types

[ ] Extract types from soreto-melissa/types/
[ ] Extract ROLES, COUNTRIES, CAMPAIGN_TYPES from soreto-melissa/shared/constants.ts
[ ] Add type definitions for API response envelopes (ApiResponse<T>, PaginatedResponse<T>)
[ ] Add types for core entities: User, Campaign, CampaignVersion, Order, Reward, SharedUrl
[ ] Validate types against reverb-backend API responses
[ ] Publish as @soreto/types@1.0.0

First Tooling: @soreto/eslint-config and @soreto/tsconfig

[ ] Create shared ESLint config (extends recommended + TypeScript rules)
[ ] Create shared tsconfig base (strict, ES2022, NodeNext modules)
[ ] Create Next.js-specific tsconfig extension

Migrate soreto-melissa → apps/platform-ui/

[ ] Use git subtree or git mv to preserve history
[ ] Update package.json to use npm workspace protocol for @soreto/* deps
[ ] Update tsconfig to extend @soreto/tsconfig/nextjs.json
[ ] Update ESLint config to extend @soreto/eslint-config
[ ] Replace soreto-melissa/types/ usage with @soreto/types imports
[ ] Confirm CI passes in new location
[ ] Update deployment to point to apps/platform-ui/

Modernize reverb-react → apps/legacy-portal/ (Next.js 16 rewrite)

[ ] Move reverb-react into apps/legacy-portal/ (structural move, keep existing code intact)
[ ] Stand up Next.js 16 scaffold alongside existing src/ (parallel structure during rewrite)
[ ] Add CLAUDE.md: "Modernizing to Next.js 16 + React 19. Do not add features to src/ — add to app/ instead."
[ ] Port admin + client routes to Next.js App Router route groups
[ ] Migrate Redux 3 + Flux → Zustand (preserve business logic, replace state management)
[ ] Replace @@PLACEHOLDER@@ tokens → process.env.NEXT_PUBLIC_* variables
[ ] Rewrite components to PrimeReact 10.9.8 (API incompatible — rewrite, not migrate)
[ ] Deploy WAF in front of original Heroku reverb-react app during transition window
[ ] Target CI: GitHub Actions with typecheck + lint + build on Next.js scaffold

Exit criteria: soreto-platform monorepo exists. soreto-melissa successfully migrated and deploying from new location. @soreto/types available as a package.


Phase 3 — Backend Modernization (Weeks 12–20)

Goal: Migrate reverb-backend and begin TypeScript adoption.

Node Upgrade: reverb-backend 14 → 24

[ ] Replace node-sass with sass (prerequisite)
[ ] Upgrade connect-redis@3 → connect-redis@6 (API breaking change)
[ ] Upgrade Express 4.x → 5.x (now default on npm; run CI to catch API changes)
[ ] Test full suite on Node 16
[ ] Upgrade to Node 18 LTS — run CI — fix failures
[ ] Upgrade passport@0.3.2 → 0.7.x
[ ] Test seneca on Node 18 (may work without changes)
[ ] Upgrade to Node 20, then 22, then 24 — run CI at each step

Migrate reverb-backend → apps/platform-api/

[ ] Move into monorepo with git subtree (preserve history)
[ ] Update CI to run within Turborepo pipeline
[ ] Update package.json to reference @soreto/types for shared types
[ ] Update package.json: replace local_modules/soreto-cookie-jam with @soreto/auth-utils

TypeScript Introduction (Phased)

[ ] Add tsconfig.json (extends @soreto/tsconfig/node.json)
[ ] Enable "allowJs": true — no existing code breaks
[ ] Add JSDoc type annotations to new service files only
[ ] Convert AbstractService.js → AbstractService.ts
[ ] Convert new routes to TypeScript as they are written
[ ] Do NOT rewrite existing services — convert when touched

OpenAPI Specification

[ ] Add express-openapi-validator or swagger-ui-express
[ ] Document existing API routes iteratively
[ ] Publish @soreto/api-client based on OpenAPI spec

Exit criteria: reverb-backend in monorepo, Node 22, TypeScript introduced for new files, @soreto/api-client published with typed client methods.


Phase 4 — Zoe Modernization (Weeks 16–24)

Goal: Migrate soreto-zoe and eliminate the legacy TypeScript patterns.

Prerequisite: Complete Knex Upgrade

[ ] 0.16.3 → 0.21.x (from Phase 1)
[ ] 0.21.x → 0.95.7 (match reverb-backend)
[ ] 0.95.7 → 2.x
[ ] 2.x → 3.x (current)
[ ] Run full integration validation at each step

Node Upgrade: soreto-zoe 16 → 24

[ ] Upgrade puppeteer@9 → 25.x (16 major versions — significant API changes; test each processor individually)
[ ] Upgrade bull@3 → bullmq@5 (BullMQ 5.76.x is current; or keep bull@3 if no failures)
[ ] Upgrade Node 16 → 18 → 20 → 22 → 24 incrementally

TypeScript Refactor: AMD → ES Modules

[ ] Remove "module": "amd" and "outFile" from tsconfig.json
[ ] Convert namespace Zoe.* {} → import/export ES module syntax
[ ] Update module: to "NodeNext" or "CommonJS"
[ ] Remove two-tsconfig setup (tsconfig + tsconfig.service.json)
[ ] Update build script: tsc → single output

Type the Processors

[ ] Add ProcessorInput and ProcessorOutput interfaces to @soreto/types
[ ] Add JSDoc to processor files (do not rewrite — annotate)
[ ] Replace require('reverb') with require('@soreto/api-client')

Migrate soreto-zoe → apps/zoe/

[ ] Move into monorepo with git subtree
[ ] Update CI to run within Turborepo pipeline
[ ] Replace local_modules/reverb with @soreto/api-client
[ ] Replace config.js with @soreto/config

Exit criteria: soreto-zoe in monorepo, Node 24, ES module TypeScript, using @soreto/api-client instead of local_modules/reverb.


Phase 5 — Legacy Portal Cut-over (Weeks 20–36)

Goal: Complete the Next.js 16 rewrite of reverb-react and cut over production traffic.

[ ] Complete all route groups in apps/legacy-portal/ Next.js scaffold
[ ] Full QA pass: admin dashboard, client dashboard, campaign management, user management
[ ] Confirm feature completeness against reverb-react src/ (see docs/migration/REVERB_REACT_PARITY.md)
[ ] Deploy modernized apps/legacy-portal/ to Heroku (or new host)
[ ] Gradual traffic cut-over: 10% → 50% → 100%
[ ] Monitor error rates for 2 weeks post-cut-over
[ ] Decommission original reverb-react Heroku app (old Node 10 app)
[ ] Remove NEXT_PUBLIC_LEGACY_PORTAL_URL from melissa's env (if legacy portal URL changes)
[ ] Remove old src/ folder from apps/legacy-portal/ (rewrite complete)

Exit criteria: Modernized Next.js 16 legacy-portal is live on Node 24. Old Heroku reverb-react (Node 10) is decommissioned. All active code in apps/legacy-portal/ is TypeScript on Next.js 16.


Phase Dependencies

Phase 0 ──► All other phases (security blocks everything)
Phase 1 ──► Phase 2 (CI needed before monorepo migration)
Phase 1 ──► Phase 3 (node-sass removal needed before Node upgrade)
Phase 2 ──► Phase 3 (monorepo scaffold needed before adding platform-api)
Phase 2 ──► Phase 4 (@soreto/api-client needed before zoe migration)
Phase 3 ──► Phase 4 (API client published before zoe replaces local_modules/reverb)
Phase 4 ──────────── can overlap with Phase 3 (after scaffold is ready)
Phase 5 ──────────── can start once melissa is stable (Phase 2 exit)

Risk Register for Migration

Risk Phase Mitigation
seneca breaks on Node 18 3 Test on Node 18 before upgrading; have replacement plan ready
knex upgrade breaks zoe migrations 1/4 Staging database upgrade first; run migration validation
puppeteer API changes break affiliate processors 4 Test each processor individually; keep old version as fallback
reverb-react modernization scope expands 5 Time-box at 10 weeks; prioritize admin + client routes; defer edge features to Phase 5+
Monorepo CI becomes slow 2+ Turborepo caching from day 1; always use --filter=[HEAD^1] in CI