ReviewOS

stacks/uplink

fix(app): SqliteStore has no migration path, so any new column breaks every installed app

#9
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Part of #4.

Part of the Codex tracking issue. This blocks the engine column, not the other way round.

What is there today

The downloadable app does not use the framework's migrations. SqliteStore creates its tables with CREATE TABLE IF NOT EXISTS (app/Uplink/sqlite-store.ts#L22), and the file comment at #L10 states the design plainly: no framework, no migrations to run.

On a Mac that already has ~/Library/Application Support/Uplink/uplink.sqlite, IF NOT EXISTS is a no-op. A column added to SCHEMA never appears in the existing file. createRun then builds its INSERT from RUN_COLUMNS (app/Uplink/sqlite-store.ts#L49), so the first insert after the update fails, for every existing user, on every text they send.

There is no released version with a second column yet, so this is cheap to fix now and expensive to fix later.

Proposal

  1. Add a user_version-based migration step to SqliteStore: read PRAGMA user_version, apply the ordered ALTER TABLE statements above it, set the new version. SQLite's PRAGMA user_version is the standard place for this and needs no extra table.
  2. Keep SCHEMA as the create-from-nothing path so a fresh install takes one statement, and make the migration list the only thing that changes when a column is added.
  3. Cover it with a test that opens a database written by the current SCHEMA, runs the new store against it, and asserts the column exists and an insert succeeds.

Requirements

  • A failed migration must not take the app down. The watcher runs under launchd and a throw here is a restart loop. Log it, surface it in the menubar the way messagesError already is (app/Uplink/desktop-agent.ts#L199), and keep serving.
  • Forward-only. No down migrations: the app ships as one binary and never needs to roll back a schema.
  • The framework-backed ModelStore (app/Uplink/model-store.ts) is unaffected; it gets its columns from buddy generate:migrations as usual.

Acceptance

  • A test proves an old database gains the column and accepts an insert.
  • A test proves a fresh database is created correctly and reports the current user_version.
  • Deleting uplink.sqlite and starting the app still works.

Sign in to comment on this issue.