Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions docs/migration-history-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Migration History Notes

## Date: 2026-06-03

### Context
During the review and integration of PR #19 and PR #20, the local workspace tracking for migrations diverged from the remote (Dev/Staging) database. To clean up the local history, a developer ran `pnpm supabase migration repair --status reverted` on 16+ migrations and then ran `pnpm supabase db push --include-all` against the dev/staging DB.
Comment thread
greptile-apps[bot] marked this conversation as resolved.

**Resulting State**:
- The schema effects of all migrations (from `202604300001` to `20260603100000`) were successfully applied (or already existed) on the Dev DB.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- However, the `schema_migrations` tracking table on the Dev DB had its rows removed by the `repair` command, resulting in Supabase CLI reporting them as "Unapplied" remotely.
- Furthermore, 6 old local mock schemas (`202601010000` through `202601010005`) were present in the migrations folder. These were superseded by `202604260001` which recreated all tables properly, meaning they were functionally present/replaced but historically unapplied.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Comment thread
greptile-apps[bot] marked this conversation as resolved.
### Pre-prod Reconciliation Steps Executed
To safely re-sync the history without breaking the functional dev schema, we executed the following steps:

1. **Safety First**: Verified the linked ref was `hibfpvmxynoonzxxdllu` (Dev).
2. **SQL Verification**: Checked directly via SQL that the schema effects for the unapplied migrations were physically present in the database (e.g. `idempotency_keys` table, `withdraw_wallet` function, `dispute_milestone` new auth logic).
3. **Tracking Repair**: Looped through all 30 unapplied timestamps (the 6 early ones + the 24 recent ones) and ran `pnpm supabase migration repair --status applied <timestamp> --linked`.
- **Why the 6 early ones?**: If left unapplied, `pnpm supabase db push --dry-run` would attempt to apply them and fail since their objects (e.g., `profiles`) were already created by `202604260001`. Marking them as applied bypasses execution and ensures a 100% clean pending queue.
4. **Clean Verification**: Ran `pnpm supabase migration list` and `db push --dry-run` to confirm exactly zero pending migrations.
Comment on lines +13 to +20

@coderabbitai coderabbitai Bot Jun 3, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

Critical issue: fabricating migration history with repair --status applied violates ADR invariant.

Line 18 documents using pnpm supabase migration repair --status applied to mark 30 migrations as applied without actually executing them through the canonical apply path. This violates ADR 0004's core requirement that "the history of schema changes in git matches the history of supabase_migrations.schema_migrations."

While the rationale in line 19 is pragmatically sound (avoiding duplicate object errors from superseded migrations), the solution creates falsified migration tracking where schema_migrations claims migrations were applied when they were not executed via the canonical MCP apply_migration path (ADR Rule 5).

Root cause analysis: The problem originated because:

  1. Superseded migrations (202601010000 through 202601010005) were committed to git but never properly applied
  2. A later migration (202604260001) recreated the same objects non-idempotently
  3. The repair command was used to retroactively falsify history

Correct approach per ADR 0004:

  • Migrations should be idempotent so re-running is safe
  • If old migrations are truly superseded, they should be removed from git BEFORE being applied anywhere (Rule 1 allows deletion of never-applied migrations)
  • Once applied, history cannot be rewritten

The documented approach leaves the repository in a state where schema_migrations does not reflect the actual sequence of SQL operations executed against the database.

As per coding guidelines, ADR 0004 Rule 5 states: "The canonical apply path is the Supabase MCP apply_migration tool... The author is responsible for confirming the applied row matches the file on disk."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/migration-history-notes.md` around lines 13 - 20, You marked 30
migrations as applied using "pnpm supabase migration repair --status applied",
which falsifies supabase_migrations.schema_migrations and violates ADR 0004/Rule
5; undo the repair rows and instead restore ADR-compliant history by either (A)
making the superseded files (202601010000–202601010005) idempotent and applying
them through the canonical MCP apply path (use apply_migration) so the DB and
git history match, or (B) if those files were never applied, remove them from
git before any apply, then apply the legit migrations (e.g., 202604260001) via
apply_migration; update docs to remove the repair workflow and reference ADR
0004 and supabase_migrations.schema_migrations to ensure future changes follow
the canonical apply path.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged. This process absolutely deviated from the strict forward-only rules mandated by ADR-0004. I've added a new 'Deviation from ADR-0004' section to the document to explicitly clarify this. This was a one-time, dev/staging-only recovery to fix the schema_migrations tracking table after an earlier wipe broke db push. We are not reverting the repair because that would re-break db push on dev. No migration files were edited, no schema objects were altered, and production was never touched. ADR-0004 remains fully in force for all future migrations.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shaiksohelll, thanks for the thorough context and for adding the explicit Deviation from ADR-0004 section — that's exactly the right mitigation when a clean-room undo isn't viable. Documenting the why, the scope (dev/staging only), and the guardrails (production untouched, no files edited) preserves institutional memory and makes the deviation auditable for anyone reviewing the repo later.

A couple of small suggestions to make the deviation section as airtight as possible:

  1. Explicitly state the trigger: note that this deviation was necessitated by an earlier repair --status reverted wipe of schema_migrations rows (the root cause), so it's clear this wasn't an elective shortcut.
  2. Add a "never-repeat" note: something like "This repair approach MUST NOT be used on the production database or for any future migrations; ADR-0004 Rule 5 (canonical apply_migration path) applies unconditionally going forward." Even though it's implied, making it explicit closes any ambiguity.

With those additions the document serves as a complete post-mortem. The concern is considered addressed given the explicit deviation documentation and the dev-only scope.

🐇 📋


### Deviation from ADR-0004
- **Context:** ADR-0004 mandates forward-only, immutable migrations applied via `apply_migration`. This reconciliation deviated from that and is scoped strictly as a ONE-TIME, dev/staging-ONLY recovery.
- **What changed:** ONLY the `supabase_migrations.schema_migrations` tracking table was updated by the recovery steps (via `migration repair`). No migration files were edited, and no SQL was re-run *during the tracking recovery* (though the incident itself involved a `db push`), and production was never touched.
- **Why it was necessary:** An earlier `migration repair --status reverted` wiped tracking rows for migrations whose schema effects were already live, leaving `db push` unable to proceed. Repairing tracking to reflect reality was the minimal fix.
- **Precedent:** ADR-0004 remains fully in force for all future migrations. This runbook is explicitly NOT a precedent for rewriting PRODUCTION migration history.

### Future Action (Pre-Launch Squash)
Before launching to production, we must squash and rename the local migrations to consolidate the numerous patches into a clean baseline sequence. This squash will cleanly combine the `202601010000` mock schemas and the fragmented PR #1/19/20 fixes into coherent numbered releases (e.g., Phase 1 Schema, Phase 2 Escrow).
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Comment on lines +28 to +29

@coderabbitai coderabbitai Bot Jun 3, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

Critical issue: planned squash/rename violates ADR 0004 forward-only principle.

The proposed pre-launch squash to "consolidate the numerous patches into a clean baseline sequence" directly violates ADR 0004 Rule 1: "Never edit, rename, or delete an existing migration file after it has been applied to any environment."

According to the reconciliation steps documented in line 18, all 30 migrations were marked as applied in the Dev database's schema_migrations table. Therefore, they are considered "applied to an environment" and cannot be squashed, renamed, or deleted per the ADR.

Impact: If these migrations are squashed:

  1. The Dev database schema_migrations table will reference timestamps that no longer exist in git
  2. Any attempt to apply migrations to a fresh environment will fail to reproduce the Dev schema
  3. The permanent git ↔ applied history mismatch becomes unfixable

Correct approach: Once migrations are marked as applied (even via repair), they become immutable per ADR 0004. If consolidation is desired:

  • It should have been done BEFORE any repair --status applied commands were executed
  • OR accept the fragmented history and move forward with properly disciplined migrations from this point

The combination of using repair --status applied (line 18) followed by planned squash (line 23) creates an irreconcilable state where the repository can never satisfy the ADR's core invariant.

As per coding guidelines, ADR 0004 Rule 1 states: "Migrations are append-only... Never edit, rename, or delete an existing migration file after it has been applied to any environment."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/migration-history-notes.md` around lines 22 - 23, The "Future Action
(Pre-Launch Squash)" plan must be removed because it conflicts with ADR 0004's
forward-only rule: do not edit/rename/delete migrations that are recorded as
applied in schema_migrations (and especially after using repair --status
applied). Replace that paragraph with an explicit statement that existing
migrations are immutable per ADR 0004 and update the migration strategy to: stop
any squash/rename plans, do not touch files already marked applied, and instead
create new append-only migrations (e.g., a new "Phase 1 Schema" migration file)
for any consolidation or corrective work; also reference ADR 0004 and the
schema_migrations table so reviewers can locate the related rules.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged. This process absolutely deviated from the strict forward-only rules mandated by ADR-0004. I've added a new 'Deviation from ADR-0004' section to the document to explicitly clarify this. This was a one-time, dev/staging-only recovery to fix the schema_migrations tracking table after an earlier wipe broke db push. We are not reverting the repair because that would re-break db push on dev. No migration files were edited, no schema objects were altered, and production was never touched. ADR-0004 remains fully in force for all future migrations.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shaiksohelll, thanks for the detailed explanation and for adding the explicit "Deviation from ADR-0004" section — that kind of transparency in the documentation is exactly the right approach for a one-time emergency recovery.

A couple of notes:

  1. The deviation documentation approach is correct. Since this was a dev/staging-only recovery to unbreak db push (and no migration files or schema objects were mutated), documenting it as a named exception is far better than pretending it didn't happen. Future reviewers and operators will understand the state of the schema_migrations table and won't be surprised.

  2. The squash plan text at line 23 still warrants a small update. Since you're committing to ADR-0004 going forward, the "Future Action (Pre-Launch Squash)" paragraph should either be removed or replaced with a note explicitly stating that no squash/rename will occur (referencing ADR-0004), and that any consolidation work will instead take the form of new, append-only migration files (e.g., a 20260603_phase1_baseline.sql that is additive and idempotent). This prevents any future developer from reading that paragraph in isolation and concluding a squash is still planned.

  3. The constraint going forward is clear: the 30 timestamps now recorded as applied in schema_migrations are immutable. New corrective or consolidation work must come as new migrations.

If you update line 23 to reflect the no-squash commitment, this comment can be resolved. Would you also like to open a follow-up issue to track the "clean baseline migration" work as an append-only alternative to the squash?

🐇 (⌒‿⌒) — well documented recovery!

Additionally, we will normalize the mixed 12-/14-digit timestamp prefixes (e.g. `202604300001`) to the standard 14-digit `YYYYMMDDHHMMSS` format during this squash.