fix(mcp): read the OS keychain key on native macOS/Windows package builds
Desktop enables os-keyring and provisions the data-encryption key in the OS keychain during the data security upgrade, but dbx-mcp/dbx-cli package builds compiled without any keyring backend (the feature became opt-in for the Linux cross builds), so every desktop-migrated profile made the MCP fail with DATA_MIGRATION_REQUIRED forever - the error even pointed users back at a migration they had already completed. - dbx-mcp gains an os-keyring forwarding feature; the native macOS and Windows MCP and CLI legs of the packages release build with it, Linux zigbuild legs keep the managed .dbx/secret.key fallback - LocalBackend::open now separates 'key unreadable in this process' (SECRET_KEY_UNAVAILABLE with the DBX_SECRET_KEY_FILE/DBX_SECRET_KEY escape hatch) from genuinely pending legacy data, keeping the DATA_MIGRATION_REQUIRED contract for the latter (test covered)
This commit is contained in:
3 files changed
+32
-2
No files matched your search
@@ -9,6 +9,11 @@ default = ["duckdb-sidecar", "mq-admin", "sqlite-bundled"]
|
||||
duckdb-sidecar = ["dbx-core/duckdb-sidecar"]
|
||||
mq-admin = ["dbx-core/mq-admin"]
|
||||
sqlite-bundled = ["dbx-core/sqlite-bundled"]
|
||||
# Native macOS/Windows builds enable this so CLI/MCP can read the OS
|
||||
# keychain key Desktop provisioned during the data security upgrade; the
|
||||
# Linux zigbuild legs cannot link the dbus Secret Service backend and keep
|
||||
# falling back to the managed .dbx/secret.key file.
|
||||
os-keyring = ["dbx-core/os-keyring"]
|
||||
transaction-test-hooks = []
|
||||
|
||||
[[bin]]
|
||||
|
||||
@@ -697,6 +697,24 @@ impl LocalBackend {
|
||||
let storage = Storage::open_unmigrated(path).await?.with_secret_key_creation(false);
|
||||
let migration = storage.inspect_data_migration().await?;
|
||||
if !migration.is_ready() {
|
||||
// The migration wizard may have already completed on Desktop with
|
||||
// the key provisioned in the OS keychain, which a keyring-less
|
||||
// CLI/MCP build cannot read. Pointing those users back at the
|
||||
// wizard loops forever, so separate the two failure shapes.
|
||||
let migration_data_remaining = migration.database_plaintext_count > 0
|
||||
|| migration.sync_credential_count > 0
|
||||
|| migration.legacy_json_files.iter().any(|file| file.exists);
|
||||
if !migration_data_remaining && !migration.key_provider_available {
|
||||
return Err(format!(
|
||||
"SECRET_KEY_UNAVAILABLE: this process cannot read the DBX data encryption key ({}). \
|
||||
If the data security upgrade was completed in DBX Desktop, its key may live in the OS \
|
||||
keychain: use an MCP/CLI build with OS keychain support, or expose the key to headless \
|
||||
tools via the DBX_SECRET_KEY_FILE / DBX_SECRET_KEY environment variables. Otherwise open \
|
||||
DBX Desktop or Web to complete the data security upgrade first.",
|
||||
migration.error_code.as_deref().unwrap_or("KEY_PROVIDER_UNAVAILABLE")
|
||||
)
|
||||
.into());
|
||||
}
|
||||
return Err("DATA_MIGRATION_REQUIRED: open DBX Desktop or Web to complete the data security upgrade".into());
|
||||
}
|
||||
let configs = storage.load_connections().await?;
|
||||
|
||||
Reference in new issue
Block a user