Fix Windows startup recovery and SurrealDB boot path#213
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0ffb51e8a6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // Persist the embedded store with the local Mem engine. This keeps the | ||
| // runtime single-host and avoids SurrealKV's Windows write failures. | ||
| Surreal::new::<Mem>(endpoint_path) | ||
| .sync("never") |
There was a problem hiding this comment.
Restore a durable backend for file-backed persistence
PersistenceHandle::open() now routes every on-disk store through Surreal::new::<Mem>(endpoint_path). SurrealDB's Rust embedding docs describe Mem as the in-memory backend and use a file engine such as RocksDB/SurrealKV for persistence (https://surrealdb.com/docs/sdk/rust/embedding), so this cache only preserves state for the lifetime of the current process. After a full Abigail restart, the same memory.db path can come back empty, which would wipe persisted memories and the job queue even though the same path is reused.
Useful? React with 👍 / 👎.
| pub fn open_with_config(config: &AppConfig) -> Result<Self> { | ||
| if uses_legacy_layout(config) { | ||
| migrate_legacy_layout(config) | ||
| .map_err(|error| StoreError::Migration(error.to_string()))?; | ||
| } | ||
|
|
||
| let shared_path = shared_db_path(config); | ||
| if let Some(parent) = shared_path.parent() { | ||
| let db_path = config.db_path.clone(); | ||
| if let Some(parent) = db_path.parent() { | ||
| std::fs::create_dir_all(parent) | ||
| .map_err(|error| StoreError::Migration(error.to_string()))?; |
There was a problem hiding this comment.
Preserve legacy SQLite import on first
open_with_config
This change removes the migration step before opening the new Surreal store. IdentityManager::migrate_legacy_identity() still copies legacy abigail_memory.db / jobs.db files into the agent directory (crates/abigail-identity/src/lib.rs:738-755), and a repo-wide search now shows no remaining caller of migrate_legacy_layout(). For users upgrading from that layout, open_with_config() will skip the import entirely, so existing conversations, jobs, calendar, and KB rows stay stranded in the copied SQLite files and appear to disappear on first launch.
Useful? React with 👍 / 👎.
| if let Some(kek) = load_windows_kek_fallback_optional(&data_root)? { | ||
| tracing::warn!( | ||
| "Stable KEK recovered from DPAPI fallback file because OS keyring lookup failed" | ||
| ); | ||
| if let Err(error) = os_keyring_store_verified(&kek) { |
There was a problem hiding this comment.
Validate the DPAPI fallback before repairing the keyring
In the fallback-recovery path, the KEK loaded from vault.kek.dpapi is written back into the OS keyring before verify_or_create_sentinel() proves that it can actually decrypt the existing vault. If that fallback file is corrupted or stale, startup not only fails, it also overwrites the previously-good keyring entry with the bad key, leaving later launches stuck on the same recovery error until the user manually repairs the keyring. The keyring repair needs to happen only after sentinel validation succeeds.
Useful? React with 👍 / 👎.
Summary
Verification
Notes