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_emailsledger 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:
1authenticated user7waitlists38entries1referral
The more important finding was structural:
auth.usersheld the only real identity signalpublic.usersdid 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.oneuntil 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.