ctx0 Schema Versioning System
This document describes the planned schema versioning and migration system for self-hosted ctx0 users.
Overview
The schema versioning system provides automatic updates for self-hosted ctx0 installations:
- Version Tracking - Track applied migrations in the database
- Update Detection - Daemon periodically checks for new migrations
- Desktop Notifications - Alert users when updates are available
- User-Approved Migration - Apply migrations only with user consent
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Desktop App │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Schema Update Notification Banner │ │
│ │ "A new ctx0 schema update is available (v2 → v3)" │ │
│ │ [View Changes] [Apply Update] [Dismiss] │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
▲
│ IPC: schema:updateAvailable
│
┌─────────────────────────────────────────────────────────────────┐
│ Daemon │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ SchemaVersionManager │ │
│ │ - checkForUpdates() → compares local vs DB version │ │
│ │ - applyMigration() → runs SQL with user approval │ │
│ │ - getChangeLog() → returns migration descriptions │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Scheduler (setInterval) │ │
│ │ - Runs every 6 hours when ctx0 self-hosted is configured │ │
│ │ - Emits 'schema:updateAvailable' when new version found │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Supabase (Self-Hosted) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ ctx0_schema_versions │ │
│ │ - version: 1, 2, 3... │ │
│ │ - applied_at: timestamp │ │
│ │ - migration_name: "001_ctx0_schema" │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Schema Version Tracking Table
A new table ctx0_schema_versions tracks which migrations have been applied:
sql
CREATE TABLE IF NOT EXISTS ctx0_schema_versions ( id SERIAL PRIMARY KEY, version INT NOT NULL UNIQUE, migration_name TEXT NOT NULL, description TEXT, applied_at TIMESTAMPTZ DEFAULT NOW(), applied_by TEXT DEFAULT 'bot0-daemon' );
Migration File Structure
packages/ctx0/migrations/
├── 001_ctx0_schema.sql # Initial schema
├── 002_schema_versioning.sql # Version tracking table
├── 003_future_migration.sql # Future migrations...
└── manifest.json # Migration metadata
manifest.json
The manifest describes all available migrations:
json
{ "currentVersion": 2, "migrations": [ { "version": 1, "name": "001_ctx0_schema", "description": "Initial ctx0 schema with entries, sessions, queries", "file": "001_ctx0_schema.sql" }, { "version": 2, "name": "002_schema_versioning", "description": "Added schema version tracking table", "file": "002_schema_versioning.sql" } ] }
Daemon Components
SchemaVersionManager
The SchemaVersionManager class handles version checking and migration execution:
typescript
class SchemaVersionManager { constructor(config: { supabaseUrl: string; supabaseServiceKey: string }); // Get current schema version from database (0 if table doesn't exist) async getCurrentVersion(): Promise<number>; // Get latest available version from bundled migrations getLatestVersion(): number; // Check if updates are available async checkForUpdates(): Promise<{ hasUpdates: boolean; currentVersion: number; latestVersion: number; pendingMigrations: SchemaVersion[]; }>; // Apply a specific migration async applyMigration(version: number): Promise<{ success: boolean; error?: string }>; // Apply all pending migrations in order async applyAllPending(): Promise<{ success: boolean; applied: number[]; error?: string }>; }
Scheduler
The daemon runs a scheduler when ctx0 is configured in self-hosted mode:
- Immediate check on daemon startup
- Periodic check every 6 hours
- Broadcasts
schema:updateAvailableevent to desktop when updates found
IPC Methods
schema:checkUpdates
Returns information about available schema updates.
Response:
typescript
{ hasUpdates: boolean; currentVersion: number; latestVersion: number; pendingMigrations: Array<{ version: number; migration_name: string; description: string; }>; }
schema:applyUpdates
Applies all pending migrations in order.
Response:
typescript
{ success: boolean; applied: number[]; // Version numbers that were applied error?: string; }
Desktop UI
Schema Update Banner
When updates are available, the desktop app displays a notification banner:
┌─────────────────────────────────────────────────────────────────┐
│ ● ctx0 schema update available (v1 → v2) │
│ │
│ [View Changes] [Apply Update] [×] │
└─────────────────────────────────────────────────────────────────┘
Features:
- Shows current and target version
- "View Changes" expands to show migration descriptions
- "Apply Update" runs migrations with loading state
- Dismiss button to hide (until next check)
Expanded View
┌─────────────────────────────────────────────────────────────────┐
│ ● ctx0 schema update available (v1 → v2) │
│ │
│ │ v2: Added schema version tracking table │
│ │
│ [Hide Changes] [Apply Update] [×] │
└─────────────────────────────────────────────────────────────────┘
User Flow
- User sets up self-hosted ctx0 during onboarding
- User runs the initial schema migration (001_ctx0_schema.sql)
- Daemon starts and detects ctx0 is configured
- Daemon checks current version vs available migrations
- If updates available, daemon broadcasts to desktop
- Desktop shows notification banner
- User clicks "Apply Update"
- Daemon executes migrations in order
- Success message shown, banner dismissed
Implementation Phases
Phase 1: Database Schema
- Create
002_schema_versioning.sqlmigration - Create
manifest.jsonwith migration metadata
Phase 2: Daemon Backend
- Create
SchemaVersionManagerclass - Add IPC handlers for schema methods
- Add scheduler to daemon startup
Phase 3: Desktop IPC Layer
- Add schema methods to daemon-client
- Expose schema API in preload
- Forward daemon broadcasts to renderer
Phase 4: UI Component
- Create
SchemaUpdateBannercomponent - Integrate into Terminal with state management
- Style to match dark theme
Future Considerations
- Rollback Support - Ability to rollback migrations (complex)
- Migration Lock - Prevent concurrent migration execution
- Backup Reminder - Prompt user to backup before major migrations
- Change Preview - Show SQL diff before applying
- Bytespace Sync - Coordinate with hosted version updates