diff --git a/build/bin/verstak-desktop b/build/bin/verstak-desktop index 2474682..625e069 100755 Binary files a/build/bin/verstak-desktop and b/build/bin/verstak-desktop differ diff --git a/internal/core/appsettings/manager.go b/internal/core/appsettings/manager.go index 2fb026a..c13d8d4 100644 --- a/internal/core/appsettings/manager.go +++ b/internal/core/appsettings/manager.go @@ -61,6 +61,7 @@ func NewDefaultManager() *Manager { } // Load reads app settings from disk, creating defaults if missing. +// Supports migration from legacy v1 config format (vault_path field). func (m *Manager) Load() error { m.mu.Lock() defer m.mu.Unlock() @@ -74,6 +75,26 @@ func (m *Manager) Load() error { return fmt.Errorf("failed to read app settings: %w", err) } + // Try to detect legacy format (has "vault_path" instead of "currentVaultPath") + var raw map[string]interface{} + if err := json.Unmarshal(data, &raw); err == nil { + if _, hasLegacy := raw["vault_path"]; hasLegacy { + // Legacy v1 config — migrate + m.config = defaultConfig() + if vp, ok := raw["vault_path"].(string); ok && vp != "" { + m.config.CurrentVaultPath = vp + } + if theme, ok := raw["theme"].(string); ok && theme != "" { + m.config.Theme = theme + } + // Save migrated config + if err := m.saveLocked(); err != nil { + return fmt.Errorf("failed to save migrated config: %w", err) + } + return nil + } + } + var cfg Config if err := json.Unmarshal(data, &cfg); err != nil { // Corrupt config: backup and create defaults diff --git a/internal/core/appsettings/manager_test.go b/internal/core/appsettings/manager_test.go index 70e5b76..6f79a80 100644 --- a/internal/core/appsettings/manager_test.go +++ b/internal/core/appsettings/manager_test.go @@ -131,3 +131,35 @@ func TestAppSettings_NotInsideVault(t *testing.T) { t.Errorf("app settings path should be under .config/verstak, got %s", path) } } + +func TestLoad_LegacyMigration(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, "config.json") + + // Write a legacy v1 config + legacy := `{ + "version": 1, + "vault_path": "/home/user/Documents/MyVault", + "theme": "light", + "first_run_completed": true +}` + if err := os.WriteFile(path, []byte(legacy), 0o600); err != nil { + t.Fatalf("write legacy config: %v", err) + } + + m := NewManager(path) + if err := m.Load(); err != nil { + t.Fatalf("Load: %v", err) + } + + cfg := m.Get() + if cfg.CurrentVaultPath != "/home/user/Documents/MyVault" { + t.Errorf("CurrentVaultPath: got %q, want %q", cfg.CurrentVaultPath, "/home/user/Documents/MyVault") + } + if cfg.Theme != "light" { + t.Errorf("Theme: got %q, want %q", cfg.Theme, "light") + } + if cfg.SchemaVersion != 1 { + t.Errorf("SchemaVersion: got %d, want 1", cfg.SchemaVersion) + } +}