5.3 KiB
5.3 KiB
Local-First Remote Sync Plan
Goal
Redesign remote-backed vault handling so every platform uses the same local-first model:
- every vault is a local KDBX file first
- remote sync is an optional binding on top of that local file
- shared remote configuration lives in the vault
- user-specific remote credentials live in the vault
- app-local state stores only non-secret binding metadata
Android adds only one platform-specific capability on top of that model:
- share/import the initial local KDBX file between devices
Product Rules
- A remote-backed vault must always have a local cache KDBX file.
- Opening a remote-backed vault should open the local KDBX first.
- Shared remote configuration must be stored in the vault, not only in app state.
- Remote credentials must not be stored in plaintext app-local state.
- Remote credentials should be stored in the vault and resolved by a stable reference.
- The app state file should keep only the metadata needed to reopen the local vault and find the remote binding.
- Sync must support both manual and automatic modes.
- Android-specific sharing should transfer the KDBX file, not a bespoke remote-secret bundle.
Target Data Model
In-Vault Shared Remote Profile
Store a reusable remote profile in the vault with fields such as:
- profile ID
- profile name
- backend type, initially WebDAV
- base URL
- remote object path
- optional notes or labels
- default sync policy, if shared defaults are desirable
In-Vault User Credential Binding
Store user-specific credentials in the vault as normal vault data, referenced by:
- remote profile ID
- credential entry UUID, or another stable internal reference
- optional username field override if needed
The credential entry should contain the actual username/password or token.
Local App State
Persist only non-secret binding state such as:
- local vault path
- selected remote profile ID
- selected credential entry reference
- sync policy override
- last sync metadata
- conflict or recovery markers
Core Flows
Create Or Configure Remote Sync
- Open or create a local vault.
- Create or edit a shared remote profile in that vault.
- Create or select a credential entry in that vault.
- Bind the local vault to the selected remote profile and credential reference.
- Choose manual or automatic sync behavior.
Reopen Existing Remote-Backed Vault
- Open the local vault file from app state.
- Resolve the selected remote profile from vault contents.
- Resolve the credential entry from vault contents.
- Offer or perform sync based on the binding policy.
Bootstrap A New Android Device
- Share the local KDBX file through Android Sharesheet.
- Import and open that KDBX locally on the new device.
- Select a remote profile stored in the vault.
- Select or create that user’s credential entry in the vault.
- Bind the local vault as the cache for the remote-backed setup.
Migration Requirements
- Migrate existing remote connections that save credentials in app state.
- On first open after upgrade, move any recoverable remote credentials into the vault.
- Replace saved plaintext credential state with a vault credential reference.
- If migration cannot write into the vault yet, hold the old state only long enough to prompt the user to complete migration.
- Remove legacy local plaintext credential persistence after migration is complete.
Implementation Phases
Phase 1: Domain Model
- define remote profile structures independent of Gio UI
- define credential reference structures independent of Gio UI
- define sync binding state independent of Gio UI
- add behavior tests for local-first remote-backed vaults
Phase 2: Vault Storage
- persist remote profiles in the vault
- persist credential references in the vault
- resolve credentials from normal vault entries
- add behavior tests for read/write and lookup semantics
Phase 3: State And Open Flow
- shrink app state to non-secret metadata only
- update open flows to always prefer the local cache vault
- update reopen behavior on all platforms to use the same model
- add migration coverage for old remote state
Phase 4: Sync Binding
- bind a local vault to a selected remote profile
- support manual sync
- support automatic sync on open/save
- define conflict and remote-failure handling for the local cache model
Phase 5: Android Bootstrap
- add Android Sharesheet export of the current local KDBX
- add Android import flow for a shared KDBX
- keep the remote pivot flow consistent with desktop after local open
Open Questions
- Where in the vault should remote profiles live: custom metadata, dedicated entries, or another KDBX-compatible structure?
- Should credential references point to entry UUIDs directly, or should KeePassGO maintain an additional logical identifier?
- Should automatic sync run only on open/save initially, or also on app resume?
- How should multiple remote profiles per vault be presented in the UI?
- What should happen when the credential entry reference no longer resolves?
Recommended First Slice
Implement the shared domain model and tests first:
- model a local vault plus optional remote binding
- define in-vault remote profile and credential reference semantics
- add tests proving app state no longer needs plaintext remote credentials
That slice standardizes the architecture before any Android-specific sharing work begins.