fix(migrations): revert migration 6 comment edit + pin immutability rule (LC-212) #255

Merged
nrupard merged 1 commit from fix/LC-212-migration-6-revert-comment-edit into main 2026-05-28 22:00:55 +02:00
Owner

Summary

  • Reverts the one-line comment edit LC-201 (commit 66801a8) made inside server/migrations/settings/0006_drop_smtp_settings.sql. The SQL payload is untouched; only the prose comment is restored to the pre-LC-201 wording. sqlx::migrate! BLAKE3-hashes the entire file (comments included) and records that hash in _sqlx_migrations on first apply, then rechecks on every subsequent start. Comment swap = hash drift = migration 6 was previously applied but has been modified panic from server/src/db/mod.rs:140, observed on c-01 staging during the LC-200 rollout.
  • Adds a new "Migration files are immutable once shipped (LC-212)" section to CLAUDE.md under ## Architecture > ### Database Domain Separation. Names the rule (never edit a shipped .sql file, comments included), names the why (sqlx checksum) and the symptom (the exact panic above), and points contributors at adding a new migration or updating doc comments in code (e.g., Mailer::from_env) instead of re-touching shipped files. Treats the rule as universal across migrators (refinery, golang-migrate, alembic, flyway).

Why this is safe

  • The SQL DELETE payload is byte-identical before and after the revert, so any database that has not yet applied migration 6 sees the same behaviour either way.
  • For databases that have applied migration 6 under the original hash, the file content now matches the recorded hash again and startup proceeds.
  • For databases that have already applied migration 6 under the LC-201 hash (none in production yet, since c-01 never finished startup after the LC-201 image rolled), reverting will flip the symptom: those operators would now see the same panic in the other direction. Resolution for that case is documented in LC-212 as a one-row UPDATE _sqlx_migrations SET checksum = ... WHERE version = 6; ops-hand fix. The c-01 settings.db is not in that bucket.

Verification

  • just check-server clean.
  • just test clean across all integration binaries (no test included or asserted on the migration comment text).
  • Image rebuilt + pushed to dev.a8n.run/a8n-tools-private/lets-chat:latest.
  • c-01 staging pulls + redeploys: container starts cleanly, no migration panic, settings.db is preserved, SMTP mailer configured log line appears (gated on the LC-200 docker-repo PR that lands the renamed env vars + SOPS keys).

Test plan

  • Redeploy on c-01 after the rebuilt image and the LC-200 docker-repo PRs (#80 and #81) are both live.
  • docker logs lets-chat-app shows SMTP mailer configured, not the migration panic and not SMTP mailer not configured.
  • Trigger a real password-reset email and confirm delivery From chat@a8n.run.
## Summary - Reverts the one-line comment edit LC-201 (commit `66801a8`) made inside `server/migrations/settings/0006_drop_smtp_settings.sql`. The SQL payload is untouched; only the prose comment is restored to the pre-LC-201 wording. `sqlx::migrate!` BLAKE3-hashes the entire file (comments included) and records that hash in `_sqlx_migrations` on first apply, then rechecks on every subsequent start. Comment swap = hash drift = `migration 6 was previously applied but has been modified` panic from `server/src/db/mod.rs:140`, observed on c-01 staging during the LC-200 rollout. - Adds a new "Migration files are immutable once shipped (LC-212)" section to `CLAUDE.md` under `## Architecture > ### Database Domain Separation`. Names the rule (never edit a shipped `.sql` file, comments included), names the why (sqlx checksum) and the symptom (the exact panic above), and points contributors at adding a new migration or updating doc comments in code (e.g., `Mailer::from_env`) instead of re-touching shipped files. Treats the rule as universal across migrators (refinery, golang-migrate, alembic, flyway). ## Why this is safe - The SQL `DELETE` payload is byte-identical before and after the revert, so any database that has not yet applied migration 6 sees the same behaviour either way. - For databases that have applied migration 6 under the original hash, the file content now matches the recorded hash again and startup proceeds. - For databases that have already applied migration 6 under the LC-201 hash (none in production yet, since c-01 never finished startup after the LC-201 image rolled), reverting will flip the symptom: those operators would now see the same panic in the other direction. Resolution for that case is documented in LC-212 as a one-row `UPDATE _sqlx_migrations SET checksum = ... WHERE version = 6;` ops-hand fix. The c-01 settings.db is not in that bucket. ## Verification - [x] `just check-server` clean. - [x] `just test` clean across all integration binaries (no test included or asserted on the migration comment text). - [ ] Image rebuilt + pushed to `dev.a8n.run/a8n-tools-private/lets-chat:latest`. - [ ] c-01 staging pulls + redeploys: container starts cleanly, no migration panic, settings.db is preserved, `SMTP mailer configured` log line appears (gated on the LC-200 docker-repo PR that lands the renamed env vars + SOPS keys). ## Test plan - [ ] Redeploy on c-01 after the rebuilt image and the LC-200 docker-repo PRs (#80 and #81) are both live. - [ ] `docker logs lets-chat-app` shows `SMTP mailer configured`, not the migration panic and not `SMTP mailer not configured`. - [ ] Trigger a real password-reset email and confirm delivery From `chat@a8n.run`.
fix(migrations): revert migration 6 comment edit + pin immutability rule (LC-212)
All checks were successful
check-secrets / Kingfisher (push) Successful in 5s
check-secrets / Nosey parker (push) Successful in 3s
check-secrets / TruffleHog (push) Successful in 3s
check-secrets / Nosey parker (pull_request) Successful in 3s
check-secrets / TruffleHog (pull_request) Successful in 5s
check-secrets / Kingfisher (pull_request) Successful in 7s
Check / clippy + fmt + tests (pull_request) Successful in 2m4s
Create release / Create release from merged PR (pull_request) Has been skipped
c844bc8ef2
LC-201 (commit 66801a8) edited the comment block in server/migrations/settings/0006_drop_smtp_settings.sql to swap SMTP_* for LETS_CHAT_SMTP_* in the env-var reference. The SQL payload was untouched, but sqlx::migrate! BLAKE3-hashes the entire file (comments included) when it records a migration in _sqlx_migrations on first apply, and rechecks on every subsequent start. Any operator whose settings.db had migration 6 recorded under the old hash now restart-loops on startup with:

  thread 'main' panicked at server/src/db/mod.rs:140:29:
  Failed to run settings migrations: migration 6 was previously applied but has been modified

Confirmed on c-01 staging during the LC-200 rollout. Migration files are immutable once shipped, full stop, no exceptions for comments.

Two changes:

- server/migrations/settings/0006_drop_smtp_settings.sql: revert the lone comment hunk to the pre-LC-201 wording so the file content matches the BLAKE3 hash deployed operators already have in _sqlx_migrations. The Mailer::from_env doc block in server/src/mail.rs:9-17 already documents the LETS_CHAT_SMTP_* names, so the migration comment doesn't need to keep pace with the rename.
- CLAUDE.md: new "Migration files are immutable once shipped (LC-212)" section under ## Architecture > ### Database Domain Separation. Names the rule, names the why (sqlx checksum) and the symptom, and points contributors at adding a new migration or updating doc comments in code instead of re-touching shipped files. Treat the rule as universal across migrators (refinery, golang-migrate, alembic, flyway) since they all hash on file content.

Verification: just check-server and just test both clean. No other LC-201 changes touched.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
nrupard deleted branch fix/LC-212-migration-6-revert-comment-edit 2026-05-28 22:00:56 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!255
No description provided.