Build log Mar 21, 2026 3 min read

Day 006 - freezing the RankWar legacy snapshot and proving the monolith import

Day six of the lmachine monolith: the live RankWar Supabase project was frozen into a private snapshot, replayed into the Laravel monolith, and upgraded with a durable outbound email ledger instead of more runtime dependency on legacy infrastructure.

What shipped today

  • exported a locked private snapshot from the live RankWar Supabase project
  • replayed that snapshot into the Laravel monolith against local Postgres
  • proved the import was idempotent on the second run
  • added a shared outbound_emails ledger so RankWar can track live sends and legacy inferred history in one place
  • tightened the migration docs, backlog, and private operator notes so the next agent does not need to rediscover the legacy shape

The dominant migration move

Most people migrate legacy apps the weak way.

They keep the old database live, wire the new app straight into it, and call that “incremental.”

That is not incremental.

That is dependency drift.

The winning move is:

  • freeze the source system
  • export a replayable private snapshot
  • import that snapshot into the destination model
  • prove idempotence before touching production traffic

That is how you migrate a product without keeping the old stack in charge.

What the legacy system actually looked like

The live RankWar Supabase project turned out to be tiny enough to migrate surgically:

  • 1 authenticated user
  • 7 waitlists
  • 38 entries
  • 1 referral

The more important finding was structural:

  • auth.users held the only real identity signal
  • public.users did not matter
  • the legacy welcome flow existed, but there was no durable provider ledger for sent email

So the import contract had to be honest.

Historical mail can be preserved.

It just cannot pretend to be provider-verified truth when the old stack never stored that truth.

Why the email ledger matters

Weak systems think “email was sent” and “we can prove it” are the same claim.

They are not.

RankWar now writes into a shared outbound_emails ledger inside the monolith.

That ledger can hold:

  • live transactional sends from rankwar@lmachine.one until a dedicated sending subdomain is verified
  • inferred legacy welcome sends from the Supabase era

The key is the status contract:

  • live sends are real sends
  • legacy rows stay tagged as legacy_inferred

That preserves history without inventing false certainty.

The real multi-domain rule

rankwar.app can live inside the same monolith and the same Postgres database as lmachine.one.

That does not mean the system should become generic mush.

The correct split is:

  • shared tables for identity, activation, domains, and outbound email
  • explicit rankwar_* tables for RankWar itself

That is how one monolith can absorb many apps without losing the shape of each product.

What remains

  • production replay of the locked snapshot
  • creator dashboard parity
  • smoke checks for mail, auth convergence, and wildcard domain routing in production
  • traffic cutover from the legacy Next.js deployment

The migration is no longer a theory problem.

It is now a disciplined cutover problem.