Phase 15: Cutover - Discussion Log
Audit trail only. Do not use as input to planning, research, or execution agents.
Decisions are captured in CONTEXT.md. This log preserves the alternatives considered.
Date: 2026-10-04
Phase: 15-cutover
Areas discussed: MariaDB → Postgres data move, production switch and rollback, the "all routes green" gate, daily-use acceptance
Before the discussion started, the scout found that production runs on MariaDB (with a Redis queue), not Postgres. It also found that the parity manifest holds 175 routes (172 ported, 3 pending), not 154, and that Phases 14.1 and 12.1 have not started.
MariaDB → Postgres data move
| Option |
Description |
Selected |
| Go import command |
Reads MariaDB via DSN and writes into the migrated schema. Re-encrypts inline, testable with testcontainers, adds a MySQL driver |
✓ |
| pgloader + Go fix-up pass |
Staging schema copy, then a Go transform. Needs an external tool and runs in two steps |
|
| mariadb-dump → SQL rewrite |
Dump, rewrite the dialect, load. The most fragile option |
|
| Option |
Description |
Selected |
| Framework capability + per-plugin mappers |
Generic summer import:winter runner, plus HasWinterImport per plugin |
✓ |
| App-only command in fonoteka.go |
One-off command that knows every table |
|
Not carried over (multi-select): transient queue/job state ✓, sessions/caches/JWT blacklist ✓, Typesense index (reindex instead) ✓, old notifications ✓
| Option |
Description |
Selected |
| Rehearse on a prod dump + verify |
Counts, checksums, decrypt round-trip and file existence, then a timed dress rehearsal |
✓ |
| Rehearse + replay Nuxt/MCP flows on imported data |
Adds a manual click-through before the switch |
|
| Unit/integration tests only |
The first real-data run is the cutover itself |
|
Production switch and rollback
| Option |
Description |
Selected |
| Freeze, import, swap upstream |
Maintenance page, final dump, import, then repoint the nginx API locations on the same origin |
✓ |
| Staging subdomain first, then swap |
Needs a second Nuxt build |
|
| Shadow/mirror then swap |
nginx mirror, which only validates GET requests |
|
| Option |
Description |
Selected |
| Keep PHP+MariaDB frozen; rollback window, no reverse sync |
Rollback swaps nginx back; Go-side writes are lost |
✓ |
| Reverse export Go→MariaDB |
Doubles the import work |
|
| No rollback path |
Fix forward only |
|
| Option |
Description |
Selected |
| Supervisor, serve + worker as two programs |
Matches the 11.2 deploy and albumy-queue |
✓ |
| Supervisor, single process |
Simpler, but a deploy restarts jobs mid-flight |
|
| systemd units |
A new pattern on rome |
|
| Option |
Description |
Selected |
| User runs a runbook; Claude writes it |
CUTOVER.md plus per-step scripts, with output pasted back as evidence |
✓ |
| Claude runs it over SSH |
Needs SSH access to rome |
|
"All routes green" gate
| Option |
Description |
Selected |
| Every manifest route, zero pending |
175 entries; API-09/QA-05 reworded |
✓ |
| Exactly the 154 fonoteka routes.php routes |
The literal requirement |
|
| Option |
Description |
Selected |
| Existing corpus + a fresh PHP re-record |
Re-record before the freeze, with a drift report |
✓ |
| Existing committed corpus only |
Could miss PHP changes made after recording |
|
| Option |
Description |
Selected |
| Hard prerequisites (14.1, 12.1, Phase 14 UAT) |
A preflight gate in the first plan; 12.1 is added to depends-on |
✓ |
| Only 14.1 is a prerequisite |
12.1 can land after cutover |
|
| Fold the remaining work into Phase 15 |
14.1 would be removed |
|
| Option |
Description |
Selected |
| Yes, a read-only smoke run on the rehearsal import |
PHP on MariaDB against Go on imported Postgres from the same dump, diffed |
✓ |
| No, the seeded corpus is enough |
|
|
Daily-use acceptance
| Option |
Description |
Selected |
| 7 days of normal household use |
The scheduled jobs each run at least once, plus a CSV import and a Discogs match |
✓ |
| 48 hours |
|
|
| 14 days |
|
|
Scripted session (multi-select): Nuxt core session ✓, MCP + OAuth ✓, Sharing & invitations (not selected), Admin & ops (not selected)
| Option |
Description |
Selected |
| Stop & archive, delete later |
|
|
| Leave PHP running but unrouted |
Keep it up for a late rollback |
✓ |
| Full removal in-phase |
|
|
| Option |
Description |
Selected |
| Yes, a pg_dump timer replaces the MariaDB one |
Installed at the swap, with a restore drill |
✓ |
| No, handle separately |
|
|
PHP scheduler/queue worker follow-up: the user wrote: "I'll manage php sign off / stopping cron / workers, outside the plans, don't mind it."
Claude's Discretion
- The runner's internals (batching, FK ordering, the coercion table, the interface naming) and the verify-report format.
- How the runbook is split into scripts and how evidence is laid out; the supervisor program names.
- Whether the smoke diff reuses tide replay or adds a new
parity:* subcommand.
Deferred Ideas
- The WinterCMS vs SummerCMS benchmark (existing todo) can reuse the rehearsal dump and the dual-backend setup.
- PHP/MariaDB decommission: the user handles it outside the plans.