Release v0.6.26: OpenBao settings synchronization with per-setting conflicts
This commit is contained in:
@@ -383,6 +383,105 @@ This is a working native implementation, not a claim of complete UI/release pari
|
||||
The Windows focus/injection rules still apply: an unelevated process cannot edit an elevated app.
|
||||
Conversion is cancelled rather than pasting into a different window or replacing unverified recent text.
|
||||
|
||||
## OpenBao synchronization (experimental, opt-in)
|
||||
|
||||
The **Sync...** button is available in Settings for everyone. Synchronization remains disabled
|
||||
until you configure your own OpenBao and enable it. Connection configuration is saved separately
|
||||
in `sync.json`. The portable data directory is normally `data/` beside the executable; installations
|
||||
without a writable application directory use the existing local-app-data fallback.
|
||||
No server address or account is included in the application.
|
||||
|
||||
The first provider is **OpenBao KV v2**. The dialog accepts an HTTPS server origin, username,
|
||||
password, KV mount (default `kswitcher`), profile path (default `personal/settings`) and userpass
|
||||
authentication mount (default `userpass`). Use the same profile on each of your PCs. This is
|
||||
administrator-provisioned private access, not public account registration. Non-root namespaces,
|
||||
reverse-proxy URL prefixes, MFA login flows and other providers are not implemented yet.
|
||||
|
||||
Enable synchronization and choose **Save / Sign in / Sync**. The dialog saves connection changes
|
||||
immediately; the main Settings window's Save/Cancel does not control this separate configuration.
|
||||
A blank password keeps the existing Windows credential for that server, login mount and username.
|
||||
The password is saved in Windows Credential Manager, not in settings exports, logs or the remote
|
||||
profile. HTTPS certificate validation is mandatory and redirects are refused. Login tokens are
|
||||
kept in memory for one sync attempt, with best-effort self-revocation afterwards. Configure bounded
|
||||
token lifetimes on the server as well (for example a 5-minute default and 10-minute maximum).
|
||||
**Disconnect / forget password** disables synchronization and removes the current connection's
|
||||
saved credential. A request already sent to the server may still complete; its downloaded settings
|
||||
will not be applied after the connection changes. Old credentials for other connection identities
|
||||
can be removed in Windows Credential Manager under `KSwitcher.Sync/`.
|
||||
|
||||
First connection is deliberately explicit:
|
||||
|
||||
- **Upload local** creates the remote profile or replaces it with this PC's saved shared settings.
|
||||
- **Download remote** replaces this PC's shared settings with the server profile.
|
||||
- If both profiles are identical, ordinary Sync can establish the baseline without a replacement.
|
||||
- Unsaved edits in Settings are not synchronized. Close and reopen Settings after a download;
|
||||
the existing stale-editor check prevents an old Settings window overwriting downloaded changes.
|
||||
|
||||
Once connected, the resident checks at startup, every **10 minutes**, and about two seconds after saving settings, on a separate
|
||||
network thread. Errors back off for 15 minutes; the Sync button allows a manual retry. Local use
|
||||
continues offline. Independent changes to different settings fields are merged against the last
|
||||
successful baseline. **Resolve individual conflicts...** shows the name and local/server values
|
||||
for each conflict. Choose either value for selected settings and apply your choices; unselected
|
||||
conflicts stay pending. Other, nonconflicting changes continue to synchronize. Choices are checked
|
||||
against freshly read values before writing, so a stale dialog cannot overwrite a newer edit.
|
||||
Conflicting shortcuts are separate settings, including bindings for individual keyboard layouts.
|
||||
Exclusions and personal dictionary words merge by membership. Ordered layout/dictionary lists
|
||||
remain single settings because their ordering affects behavior.
|
||||
|
||||
Snippets have persistent IDs that survive renaming. Different snippets merge independently;
|
||||
trigger and text edits within a snippet can merge too. Deleting a snippet retains a deletion
|
||||
marker, so an unchanged offline copy cannot bring it back. Deletion versus a concurrent edit
|
||||
is an explicit conflict, offering the deleted or edited version. Duplicate triggers and shortcut
|
||||
collisions created by independent edits are also presented for resolution. Deletion markers are
|
||||
retained without automatic expiry; recreating a snippet in the editor gives it a new ID.
|
||||
|
||||
Existing profiles migrate automatically: legacy snippet IDs derive deterministically from the
|
||||
original trigger, then are stored permanently. Sync writes use envelope version 2; older clients
|
||||
refuse this version instead of dropping IDs/deletions. Update all participating PCs before using
|
||||
the new merge behavior. Existing version-1 profiles and local baselines remain readable.
|
||||
|
||||
Download/Upload are still available for deliberate whole-profile recovery/initialization, not
|
||||
required for ordinary conflicts. Every server write uses the version just read as a CAS
|
||||
condition, including explicit Upload. A racing write is rejected rather than silently overwritten.
|
||||
Deleted server versions are not silently recreated.
|
||||
|
||||
Hotkeys, snippets, application exclusions, layout order, conversion, screenshot and autocorrection
|
||||
preferences are shared. Startup/elevation, keep-awake, logging, history enablement/limits,
|
||||
Tesseract executable/engine selection, connection details and credentials stay local. Clipboard
|
||||
history, screenshots and dictionary files are never uploaded. Missing keyboard layouts block
|
||||
applying a remote profile until those Windows layouts are installed, preventing lost bindings.
|
||||
Settings are JSON inside OpenBao; this is not end-to-end encryption from the vault administrator.
|
||||
|
||||
The last common profile (`sync-base.bin`) and the settings preceding the most recent downloaded
|
||||
change (`settings-before-sync.bin`) are protected with Windows DPAPI and belong to this Windows
|
||||
account/machine. Reinstallation recovery uses the remote profile and a fresh login; copying these
|
||||
local DPAPI files to a new machine does not recover them. For an older server snapshot, use OpenBao
|
||||
KV version history to restore that snapshot as the latest version, then choose Download remote.
|
||||
The app does not yet provide a server-history browser. Keep ordinary server backups too.
|
||||
|
||||
OpenBao administrator setup:
|
||||
|
||||
1. Enable a KV **version 2** engine at `kswitcher`; enable **Require Check-and-Set** and set
|
||||
maximum versions to a suitable value, such as 30.
|
||||
2. Create a dedicated userpass account, with a policy restricted to the chosen profile. Do not
|
||||
use the administrator account. For the defaults, the application needs only:
|
||||
|
||||
```hcl
|
||||
path "kswitcher/data/personal/settings" {
|
||||
capabilities = ["create", "read", "update"]
|
||||
}
|
||||
path "auth/token/revoke-self" {
|
||||
capabilities = ["update"]
|
||||
}
|
||||
```
|
||||
|
||||
3. Set bounded token lifetimes on that account/auth mount and enter its credentials in KSwitcher.
|
||||
Keep the server's address and TLS certificate reachable/trusted on each participating PC.
|
||||
|
||||
`SyncProvider` separates versioned read/conditional-write operations from merging, local state
|
||||
and UI integration, so another service can be added without replacing the synchronization logic.
|
||||
Protocol and conflict regressions run with `build.ps1 -Test` or CMake's `sync-regressions` test.
|
||||
|
||||
## Build
|
||||
|
||||
The easiest reproducible local route uses the pinned portable w64devkit toolchain:
|
||||
|
||||
Reference in New Issue
Block a user