Skip to content

fix(migration): guard 033 channel_database backfill — v4.11.5 hotfix (#3657)#3658

Merged
Yeraze merged 2 commits into
mainfrom
fix/3657-migration-033-channel-database-guard
Jun 22, 2026
Merged

fix(migration): guard 033 channel_database backfill — v4.11.5 hotfix (#3657)#3658
Yeraze merged 2 commits into
mainfrom
fix/3657-migration-033-channel-database-guard

Conversation

@Yeraze

@Yeraze Yeraze commented Jun 22, 2026

Copy link
Copy Markdown
Owner

🚨 Hotfix for #3657 — v4.11.4 broke Postgres / fresh-install startup

v4.11.4 has been retracted (unpublished). This PR fixes the regression and bumps to v4.11.5.

Root cause

#3640 (in v4.11.4) removed channel_database from migration 021's sourceId-add to stop the PG boot-loop (#3639). But migration 033 still runs UPDATE channel_database SET sourceId .... Migration order is 021 (add) → 033 (update) → 063 (drop). On PostgreSQL — which re-runs every migration on every boot — v4.11.3 worked because 021 re-added the column before 033 ran. With 021 no longer adding it, 033 crashes during DB init:

[ERROR] Database initialization failed: error: column "sourceId" does not exist

This also breaks fresh installs on all backends (021 → 033 with no column). It only triggers when ≥1 source is registered (the backfill is gated on sources.length > 0) — the CI fixtures have no sources, which is exactly why it slipped through.

Fix

Guard migration 033's channel_database backfill on the legacy sourceId column still existing — PRAGMA table_info (SQLite), information_schema.columns (PG/MySQL). channel_database is global-by-design (063 drops sourceId), so on current DBs the column is absent and the backfill is correctly a no-op; on a mid-upgrade DB where it's still present, it still runs.

Testing

Version

  • All five version files bumped 4.11.4 → 4.11.5.

🤖 Generated with Claude Code

Yeraze and others added 2 commits June 22, 2026 16:55
…ce (#3657)

Regression introduced by #3640 (v4.11.4): removing channel_database from
migration 021's sourceId-add left migration 033's
`UPDATE channel_database SET sourceId ...` referencing a column that no longer
exists. On PostgreSQL — which re-runs every migration on every boot — and on
fresh installs, 033 then crashed during DB init with
`column "sourceId" does not exist`, so the app couldn't start.

The crash only triggered when at least one source was registered (the backfill
is gated on `sources.length > 0`); the CI fixtures have no sources, which is why
it slipped through.

Fix: guard the channel_database backfill on the legacy `sourceId` column still
existing (PRAGMA table_info on SQLite, information_schema on PG/MySQL).
channel_database is global-by-design (063 drops sourceId), so on current
databases the column is absent and the backfill is correctly a no-op; on a
mid-upgrade DB where the column is still present it still runs.

Adds 033_per_source_permissions.test.ts: reproduces #3657 (source present +
channel_database without sourceId → no throw), confirms back-compat backfill
when the column is present, and the no-sources case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011JEaCGwY9Wz8jeV4e22GW4
Bumps all five version files 4.11.4 -> 4.11.5. v4.11.4 was retracted because
migration 033 crashed Postgres/fresh-install startup (#3657); this release
carries the fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011JEaCGwY9Wz8jeV4e22GW4
@Yeraze Yeraze added the system-test Trigger hardware system tests label Jun 22, 2026
@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown

Claude finished @Yeraze's task —— View job


PR Review: fix(migration): guard 033 channel_database backfill — v4.11.5 hotfix

  • Gather context and understand the PR
  • Review migration 033 changes
  • Review new test file
  • Assess overall quality and provide feedback

Summary

This is a well-targeted hotfix. The root cause analysis is accurate, the fix is surgical and correct, and the test coverage is solid. A few minor observations below.


Migration 033 Changes (033_per_source_permissions.ts)

The core fix is correct. All three backends (SQLite, PostgreSQL, MySQL) now check for the column's existence before attempting the channel_database backfill, which correctly handles both the "post-063 or fresh install" case (column absent → skip) and the "mid-upgrade" case (column present → run).

Minor observations:

  1. PostgreSQL information_schema query uses column_name = 'sourceId' (line 240). Column names in PostgreSQL information_schema are stored as-is (preserving case), so this is correct for a column that was created as "sourceId". No issue here, just worth noting for future readers.

  2. MySQL information_schema query similarly uses COLUMN_NAME = 'sourceId' (line 341). MySQL's information_schema comparisons are case-insensitive by default for column names on most collations, so this is fine.

  3. The guard is only applied when sources.length > 0 (lines 149, 238, 339). This matches the original gating and is consistent — the backfill was always guarded on having sources, and the new column-existence check is inside that same block. The PR description correctly identifies this gating as the reason CI never caught it (no sources in CI fixtures). This is fine.

  4. sources[0].id vs sources[0]: In the SQLite path (line 153), sources is typed as { id: string }[] so sources[0].id is correct. In the PostgreSQL path (line 243), sources is mapped via .map((r: any) => r.id) (line 178), so sources[0] is already the string ID — also correct. The asymmetry is a bit subtle but both are right.


New Test File (033_per_source_permissions.test.ts)

Coverage is good for the regression. Three cases:

One gap: There's no test for "no sources + column present" (a pre-063 DB with no sources registered). This is a very edge-case scenario, but since sources.length === 0 skips the entire block, this path is trivially safe — just not explicitly tested. Not a blocker.

Test setup: Using ':memory:' SQLite + beforeEach fresh DB is clean. The createBaseSchema helper is minimal and correct. The helper comment about skipping the table rebuild (pre-rebuild shape) is useful documentation.


Version Bumps

All five required files bumped 4.11.4 → 4.11.5 as documented in CLAUDE.md. ✅


Overall Assessment

Approved / Ready to merge. The fix is minimal, correct, and well-tested. The comments in the migration are clear about the reasoning. No security concerns. No performance concerns (column-existence checks are cheap metadata operations). The test file directly reproduces the reported failure condition.

@github-actions

Copy link
Copy Markdown
System Test Results

MeshMonitor System Test Results

Test Run: 2026-06-22 17:03:27 EDT

❌ Overall Result: FAILED

Aborted on first failing test (fail-fast mode). Remaining tests skipped.

Failed Test

  • Quick Start Test

@github-actions

Copy link
Copy Markdown
System Test Results

MeshMonitor System Test Results

Test Run: 2026-06-22 17:12:46 EDT

❌ Overall Result: FAILED

Aborted on first failing test (fail-fast mode). Remaining tests skipped.

Failed Test

  • Quick Start Test

@Yeraze Yeraze merged commit 43a66c0 into main Jun 22, 2026
22 of 24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

system-test Trigger hardware system tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant