Skip to content

fix: schema-drift check compared against wrong table + stale Neon DB - #92

Merged
Skeyelab merged 1 commit into
masterfrom
fix/schema-drift-check-target
Sep 23, 2026
Merged

Skeyelab merged 1 commit into
masterfrom
fix/schema-drift-check-target

Conversation

@Skeyelab

Copy link
Copy Markdown
Member

Two bugs, one always-red workflow

  1. collect.ts read migration history from drizzle.__drizzle_migrations, which only exists when drizzle-kit migrate runs directly. Production applies migrations via the app's own applyCommittedMigrations(), tracked in public.__clawproxy_migrations — a table drizzle-kit never touches. The check was querying a table that doesn't exist in prod's migration flow.

  2. DRIFT_CHECK_DATABASE_URL was set up ~11h before PR feat: move auth to Coolify Postgres #88 (move auth to Coolify Postgres) merged, so it still pointed at the old Neon DB. Neon stopped receiving writes once the app cut over, so the check was permanently comparing against a frozen pre-cutover snapshot.

Fix

  • collect.ts now reads public.__clawproxy_migrations.
  • New scripts/schema-drift/apply-migrations.ts + db:drift:seed-expected seeds the CI throwaway DB using the app's real migrator, so both sides of the diff use the identical mechanism production uses.
  • Rotated DRIFT_CHECK_DATABASE_URL to a new least-privilege read-only role (clawproxy_drift_ro, SELECT-only, no write access) on the current Coolify clawproxy-postgres instance, and made that DB briefly publicly reachable (was previously LAN-only) so GitHub Actions can reach it.

Verified

Ran the full check locally against real production:

✓ production matches the migrated schema (50 columns, 21 indexes, 6 migrations)

Test plan

  • yarn lint
  • yarn test:run (289 passed)
  • Local end-to-end drift check against prod (passed, see above)

…nd stale Neon DB

Two independent bugs made the schema-drift workflow always fail:

1. collect.ts read migration history from drizzle.__drizzle_migrations,
   which only exists when 'drizzle-kit migrate' runs directly against a
   DB. Production applies migrations via the app's own
   applyCommittedMigrations() (app/lib/db/migrations.ts), which tracks
   them in public.__clawproxy_migrations instead. The check was
   comparing against a table that never existed in prod.

2. DRIFT_CHECK_DATABASE_URL (the GitHub secret) was configured against
   the old Neon database before PR #88 moved auth to Coolify's internal
   Postgres. Neon stopped receiving writes once that PR shipped, so the
   check was diffing against a frozen, pre-cutover snapshot -- it would
   never see the new auth_* tables regardless of what actually merged.

Fixes:
- collect.ts now reads public.__clawproxy_migrations (matches
  production's real migration tracking).
- Added scripts/schema-drift/apply-migrations.ts + a new
  db:drift:seed-expected script that seeds the CI throwaway DB using
  the app's actual migrator, not drizzle-kit migrate, so both sides of
  the diff use the same mechanism.
- Rotated DRIFT_CHECK_DATABASE_URL to a new least-privilege read-only
  role (clawproxy_drift_ro, SELECT-only) on the current Coolify
  clawproxy-postgres instance.

Verified locally end-to-end against real production:
  ✓ production matches the migrated schema (50 columns, 21 indexes, 6 migrations)
@strix-security

strix-security Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Strix Security Review

No security issues found.

Review summary

Reviewed the schema-drift check fix, which corrects the migration-history table (public.__clawproxy_migrations) and introduces a CI seeding script (apply-migrations.ts) that applies committed migrations via the same mechanism as production. The changes are minimal and correct: the new script sources its connection string from the environment, the modified query is a static parameterized statement with no attacker-controlled input, and the workflow only swaps the expected-schema build command. No hardcoded secrets, injection vectors, or authorization changes were introduced. Static analysis (semgrep) surfaced no findings.

Updated for cb28021.


Reviewed by Strix
Re-run review · Configure security review settings

@Skeyelab
Skeyelab merged commit 7ef5228 into master Sep 23, 2026
3 checks passed
@Skeyelab
Skeyelab deleted the fix/schema-drift-check-target branch September 23, 2026 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant