From 6d4ab9cc134d14e549b6e6dfdcfecf5b870d6a91 Mon Sep 17 00:00:00 2001 From: WebDevCody Date: Wed, 31 Dec 2025 23:30:44 -0500 Subject: [PATCH] feat: implement version-based migrations for global settings - Added versioning to global settings, enabling automatic migrations for breaking changes. - Updated default global settings to reflect the new versioning schema. - Implemented logic to disable sandbox mode for existing users during migration from version 1 to 2. - Enhanced error handling for saving migrated settings, ensuring data integrity during updates. --- apps/server/src/services/settings-service.ts | 30 +++++++++++++++++++- libs/types/src/settings.ts | 20 ++++++------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/apps/server/src/services/settings-service.ts b/apps/server/src/services/settings-service.ts index 288bde18..a88d2421 100644 --- a/apps/server/src/services/settings-service.ts +++ b/apps/server/src/services/settings-service.ts @@ -124,6 +124,8 @@ export class SettingsService { * Missing fields are filled in from DEFAULT_GLOBAL_SETTINGS for forward/backward * compatibility during schema migrations. * + * Also applies version-based migrations for breaking changes. + * * @returns Promise resolving to complete GlobalSettings object */ async getGlobalSettings(): Promise { @@ -131,7 +133,7 @@ export class SettingsService { const settings = await readJsonFile(settingsPath, DEFAULT_GLOBAL_SETTINGS); // Apply any missing defaults (for backwards compatibility) - return { + let result: GlobalSettings = { ...DEFAULT_GLOBAL_SETTINGS, ...settings, keyboardShortcuts: { @@ -139,6 +141,32 @@ export class SettingsService { ...settings.keyboardShortcuts, }, }; + + // Version-based migrations + const storedVersion = settings.version || 1; + let needsSave = false; + + // Migration v1 -> v2: Force enableSandboxMode to false for existing users + // Sandbox mode can cause issues on some systems, so we're disabling it by default + if (storedVersion < 2) { + logger.info('Migrating settings from v1 to v2: disabling sandbox mode'); + result.enableSandboxMode = false; + result.version = SETTINGS_VERSION; + needsSave = true; + } + + // Save migrated settings if needed + if (needsSave) { + try { + await ensureDataDir(this.dataDir); + await atomicWriteJson(settingsPath, result); + logger.info('Settings migration complete'); + } catch (error) { + logger.error('Failed to save migrated settings:', error); + } + } + + return result; } /** diff --git a/libs/types/src/settings.ts b/libs/types/src/settings.ts index 5b88478f..990c2ff6 100644 --- a/libs/types/src/settings.ts +++ b/libs/types/src/settings.ts @@ -470,6 +470,13 @@ export interface ProjectSettings { * Default values and constants */ +/** Current version of the global settings schema */ +export const SETTINGS_VERSION = 2; +/** Current version of the credentials schema */ +export const CREDENTIALS_VERSION = 1; +/** Current version of the project settings schema */ +export const PROJECT_SETTINGS_VERSION = 1; + /** Default keyboard shortcut bindings */ export const DEFAULT_KEYBOARD_SHORTCUTS: KeyboardShortcuts = { board: 'K', @@ -496,7 +503,7 @@ export const DEFAULT_KEYBOARD_SHORTCUTS: KeyboardShortcuts = { /** Default global settings used when no settings file exists */ export const DEFAULT_GLOBAL_SETTINGS: GlobalSettings = { - version: 1, + version: SETTINGS_VERSION, theme: 'dark', sidebarOpen: true, chatHistoryOpen: false, @@ -533,7 +540,7 @@ export const DEFAULT_GLOBAL_SETTINGS: GlobalSettings = { /** Default credentials (empty strings - user must provide API keys) */ export const DEFAULT_CREDENTIALS: Credentials = { - version: 1, + version: CREDENTIALS_VERSION, apiKeys: { anthropic: '', google: '', @@ -543,12 +550,5 @@ export const DEFAULT_CREDENTIALS: Credentials = { /** Default project settings (empty - all settings are optional and fall back to global) */ export const DEFAULT_PROJECT_SETTINGS: ProjectSettings = { - version: 1, + version: PROJECT_SETTINGS_VERSION, }; - -/** Current version of the global settings schema */ -export const SETTINGS_VERSION = 1; -/** Current version of the credentials schema */ -export const CREDENTIALS_VERSION = 1; -/** Current version of the project settings schema */ -export const PROJECT_SETTINGS_VERSION = 1;