You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 856732e
Browse filesBrowse the repository at this point in the historyBrowse files
fix(config): migrate config.json to XDG config directory to prevent shell reload loop (#187)
- Relocate default config file from ~/.config/omarchy/plugins/icyleaf.bitwarden/config.json to ~/.config/omawarden/config.json
- Add support for OMAWARDEN_CONFIG_DIR env var
- Automatically migrate existing config.json from legacy plugin directory with 0600 permissions and clean up stale files
- Document architectural decision in docs/adr/0020-xdg-config-location-and-migration.md and update CONTEXT.md
- Add unit tests verifying default path, legacy migration, and cleanup
Copy file name to clipboardExpand all lines: CONTEXT.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -27,7 +27,7 @@
27
27
-**Atomic Credential Erasure**: Calling `auth logout` or updating to a different `server_url` triggers `clear_all()` across all `service=omarchy-bitwarden` entries in the OS keyring and purges local storage (see `docs/adr/0008-server-switching-credential-and-cache-invalidation.md`).
28
28
-**Zero-Leakage Memory Policy**: Sensitive cryptographic keys (`SymmetricCryptoKey`) and intermediate hashes derive `Zeroize` and `#[zeroize(drop)]` to enforce volatile memory destruction on drop.
29
29
-**Zero-Argv / Zero-Environ Security Seam**: To prevent credential leakage across Linux processes (`/proc/<pid>/cmdline` and `/proc/<pid>/environ`), secrets (Master Passwords, API Secrets, TOTP seeds, Clipboard text) are delivered exclusively through protected `stdin` streams or `0600` Unix Domain Sockets.
30
-
-**Strict File & Socket Permissions & XDG Data Isolation**: Disk storage (`data.json`) resides outside the inotify-watched plugin directory at `$XDG_DATA_HOME/omawarden/data.json` (defaulting to `~/.local/share/omawarden/data.json` with automatic migration from legacy paths) to prevent hot-reload loops, and enforces`0600` owner-only permissions along with the daemon Unix socket (`omawarden.sock`) (see `docs/adr/0015-xdg-data-storage-location-and-migration.md`).
30
+
-**Strict File & Socket Permissions & XDG Data Isolation**: Disk storage (`data.json`) resides outside the inotify-watched plugin directory at `$XDG_DATA_HOME/omawarden/data.json` (defaulting to `~/.local/share/omawarden/data.json`), and configuration (`config.json`) resides at `$XDG_CONFIG_HOME/omawarden/config.json` (defaulting to `~/.config/omawarden/config.json`), both featuring automatic transparent migration from legacy plugin directories to prevent hot-reload loops, and enforcing`0600` owner-only permissions along with the daemon Unix socket (`omawarden.sock`) (see `docs/adr/0015-xdg-data-storage-location-and-migration.md` and `docs/adr/0020-xdg-config-location-and-migration.md`).
31
31
-**Daemon In-Memory Cache & Scrubbing**: Decrypted vault items and keys are held exclusively in daemon memory while unlocked. Manual `auth lock`, `auth logout`, idle timeouts, or screen-lock events immediately trigger `{"action": "lock"}` IPC to purge all decrypted items and keys from memory.
32
32
-**Clipboard Guard**: Ephemeral clipboard management using Wayland native `wl-copy` with automatic 30-second TTL cleanup for copied passwords, PINs, and TOTPs.
33
33
-**Website Icon Privacy & Endpoint Isolation**: Resolution policy governing website favicon retrieval. Official Bitwarden cloud instances query `https://icons.bitwarden.net/{domain}/icon.png`. Self-hosted instances (e.g. Vaultwarden or self-hosted Bitwarden) strictly query the user's configured server endpoint (`${server_root}/icons/{domain}/icon.png`), preventing leakage of intranet or private domain names to public third-party services. If self-hosted icon retrieval fails (such as on air-gapped networks or when server icon proxying is disabled), the UI fails closed to default category icons (`\uf084`) and never falls back to public servers (see `docs/adr/0014-self-hosted-icon-service-endpoint-and-privacy-isolation.md`).
# ADR 0020: Relocate Configuration File to XDG Config Directory to Prevent Shell Reload Loops
2
+
3
+
## Status
4
+
Accepted
5
+
6
+
## Context
7
+
In ADR 0015, the encrypted vault storage `data.json` was relocated from `$XDG_CONFIG_HOME/omarchy/plugins/icyleaf.bitwarden/data.json` to `$XDG_DATA_HOME/omawarden/data.json` to eliminate hot-reload loops triggered by the host Omarchy desktop shell (`services/PluginRegistry.qml`), which actively monitors `$XDG_CONFIG_HOME/omarchy/plugins/` with `inotifywait -m -r -q -e close_write,create,delete,move`.
8
+
9
+
However, `config.json` remained located inside the watched plugin directory:
Whenever a user modified preferences in the GUI Settings modal (such as changing the server URL, auto-lock timeout, clipboard TTL, or max attachment size) and clicked Save, `omawarden config set` performed an atomic file write (`fs_util::atomic_write_str`) over `config.json`. Because this atomic write creates a temporary file and renames it inside the plugin directory, `inotifywait` immediately detected the modification, causing `omarchy-shell` to misinterpret the event as a plugin code update and trigger `shell.reloadPlugins()`. This tore down panels, widgets, and services, causing visual UI restarts and desktop panel flickering.
13
+
14
+
In addition, storing application configuration inside a third-party desktop plugin repository violates the Freedesktop XDG Base Directory Specification, which specifies `$XDG_CONFIG_HOME` for application-specific configuration files.
15
+
16
+
## Decision
17
+
1.**Relocate Default Configuration to `$XDG_CONFIG_HOME/omawarden/config.json`**:
18
+
-`ConfigManager::default()` now resolves `config.json` to `$XDG_CONFIG_HOME/omawarden/config.json` (defaulting to `$HOME/.config/omawarden/config.json`).
19
+
- This location resides completely outside the inotify-monitored Omarchy plugin hierarchy.
-`ConfigManager` checks the `OMAWARDEN_CONFIG_DIR` environment variable before falling back to `XDG_CONFIG_HOME`, allowing integration tests, containerized environments, and custom setups to override the configuration path.
23
+
24
+
3.**Transparent Legacy Migration**:
25
+
- Upon initialization, `ConfigManager` checks whether a legacy file exists at `$XDG_CONFIG_HOME/omarchy/plugins/icyleaf.bitwarden/config.json`.
26
+
- If the legacy file exists and the new target does not, `omawarden` atomically moves the file, ensures the parent directory has `0700` permissions, enforces `0600` permissions on the target, and removes the legacy file.
27
+
- If the target already exists, stale legacy files in the plugin directory are purged to avoid residual inotify events.
28
+
29
+
## Consequences
30
+
-**Elimination of Reload Loops on Settings Save**: Saving settings in the UI never touches the watched `omarchy/plugins` directory and no longer triggers Omarchy Shell plugin reloads or panel flickering.
31
+
-**XDG Specification Compliance**: Clean separation between plugin source code (`$XDG_CONFIG_HOME/omarchy/plugins/icyleaf.bitwarden/`) and application configuration (`$XDG_CONFIG_HOME/omawarden/config.json`).
32
+
-**Zero Disruption for Existing Users**: Automatic migration preserves existing user configurations (custom server URLs, remember email settings, timeout intervals, etc.) seamlessly.
0 commit comments