Skip to main content

Changelog

Every improvement, automatically tracked from our commit history.

Subscribe via Atom feed
← Prev Page 8 of 266 Next →
March 1, 2026
patch Desktop ShellServerServices

Fix disabled plugins not showing in Settings for re-enable

Server 1.68.6 | Desktop 1.68.6 | Services 1.68.6 | 888dfc6f
Details

Root cause: when a plugin is disabled, its assembly is deferred (not

loaded) at startup to save memory. But the Settings plugin list only

iterated over loaded plugins (_plugins), so deferred plugins were

invisible — the user could never re-enable them.

Fix:

  • Expose DeferredPluginDirs on IPluginRegistry — maps plugin IDs to

their discovered directory paths for plugins that were skipped

  • SettingsViewModel.LoadPluginItems() now appends deferred plugins to

the list with IsEnabled=false, allowing the user to toggle them on

  • Toggling on triggers the existing EnablePlugin() deferred path which

dynamically loads the assembly from the saved directory

  • HeadlessPluginRegistry implements the new property with an empty dict
patch CoreDesktop ShellServices

Fix fresh-install StorageError and update C# paths for SQLite migration

Core 1.15.3 | Desktop 1.68.6 | Services 1.68.6 | 1de039e7
Details

Root cause: on fresh install (no salt file, no existing DB), init_core()

opened an unencrypted on-disk database at data.privstack.db. When

auth_initialize() then tried to create an encrypted DB at the same path,

SQLCipher failed because the file already existed as unencrypted.

Fix (Rust FFI):

  • Fresh install now opens in-memory placeholder (same as encrypted mode)
  • Only open unencrypted on-disk for legacy databases that already exist
  • auth_initialize detects legacy unencrypted DB and skips SQLCipher

creation, just initializes vault on the existing DB

Fix (C# Desktop):

  • WorkspaceService: base path changed from "data.duckdb" to "data"

(Rust derives "data.privstack.db" via with_extension)

  • SetupWizardViewModel: same path change
  • PrivStackService: updated diagnostics to check .privstack.db,

.datasets.db, .privstack.salt instead of old .duckdb files

  • App.axaml.cs: updated orphan cleanup patterns and diagnostics
  • DashboardViewModel: updated file size checks and compact display
  • SystemMetricsService: updated file paths, WAL suffix (.wal → -wal)
patch Core

Add legacy DuckDB migration detection FFI exports

Core 1.15.3 | 33ae1900
Details

Since the Rust core no longer includes the DuckDB library, migration

from old .duckdb files must be orchestrated from the C# managed side.

These FFI functions support that workflow:

  • privstack_has_legacy_databases(path) → bool: detects if any .duckdb

files exist at the data path

  • privstack_list_legacy_databases(path) → JSON array of found files

with names, paths, and sizes

  • privstack_archive_legacy_databases(path): renames .duckdb files to

.duckdb.bak after successful migration, removes stale WAL files

The C# side should check for legacy databases on first launch with the

new version, run its migration logic (reading DuckDB via its own driver

and writing to the new SQLite/SQLCipher database), then call archive

to move the old files out of the way.

patch Core

Implement two-phase FFI initialization for SQLCipher encryption

Core 1.15.3 | 72d8000e
Details

The database can no longer be opened immediately at init time because

SQLCipher requires a password-derived key. This commit restructures

the FFI layer into a two-phase initialization:

Phase 1 (privstack_init): If a salt file exists (encrypted DB), opens

an in-memory placeholder so the handle exists for non-DB operations.

If no salt file exists (first run / legacy), opens unencrypted as before.

Phase 2 (auth_initialize / auth_unlock): Opens the real encrypted

database and swaps the Connection inside the shared Arc<Mutex<Connection>>.

All stores (entity, event, blob, vault) automatically use the new

connection on their next operation since they share the same Arc.

Key changes:

  • PrivStackHandle gains a main_conn field holding the shared connection Arc
  • PrivStackHandle::swap_connection() replaces the inner Connection and

re-initializes all store schemas on the new database

  • EntityStore, EventStore, BlobStore gain reinitialize_schema() methods

for re-running CREATE TABLE IF NOT EXISTS after a connection swap

  • VaultManager gains reinitialize_vaults() to clear cached Vault instances

so they re-create tables on the new connection

  • auth_initialize: generates salt, derives Argon2id key, creates encrypted

DB via open_db(), swaps connection, writes salt file, then inits vault

  • auth_unlock: reads salt, derives key, opens encrypted DB, swaps

connection, then unlocks vault

  • auth_lock: swaps back to in-memory placeholder for encrypted DBs
  • auth_change_password: rekeys DB with PRAGMA rekey + fresh salt
  • Recovery functions: rekey DB after vault password reset
  • auth_is_initialized: checks salt file existence as primary indicator
  • Salt file: 16-byte random salt at <db_path>.privstack.salt
  • derive_db_key helper: Argon2id -> raw hex key for SQLCipher
patch Core

Clean up remaining DuckDB references in comments

Core 1.15.3 | 5427eacd
Details

Replace stale DuckDB references with SQLite in comments across

cloud sync engine, datasets preprocessor/mutations/helpers, and

FFI dataset queries. No functional changes.

← Prev Page 8 of 266 Next →

Get notified about new releases