149 lines
5.3 KiB
Markdown
149 lines
5.3 KiB
Markdown
# 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
|
||
|
||
1. A remote-backed vault must always have a local cache KDBX file.
|
||
2. Opening a remote-backed vault should open the local KDBX first.
|
||
3. Shared remote configuration must be stored in the vault, not only in app state.
|
||
4. Remote credentials must not be stored in plaintext app-local state.
|
||
5. Remote credentials should be stored in the vault and resolved by a stable reference.
|
||
6. The app state file should keep only the metadata needed to reopen the local vault and find the remote binding.
|
||
7. Sync must support both manual and automatic modes.
|
||
8. 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
|
||
|
||
1. Open or create a local vault.
|
||
2. Create or edit a shared remote profile in that vault.
|
||
3. Create or select a credential entry in that vault.
|
||
4. Bind the local vault to the selected remote profile and credential reference.
|
||
5. Choose manual or automatic sync behavior.
|
||
|
||
### Reopen Existing Remote-Backed Vault
|
||
|
||
1. Open the local vault file from app state.
|
||
2. Resolve the selected remote profile from vault contents.
|
||
3. Resolve the credential entry from vault contents.
|
||
4. Offer or perform sync based on the binding policy.
|
||
|
||
### Bootstrap A New Android Device
|
||
|
||
1. Share the local KDBX file through Android Sharesheet.
|
||
2. Import and open that KDBX locally on the new device.
|
||
3. Select a remote profile stored in the vault.
|
||
4. Select or create that user’s credential entry in the vault.
|
||
5. Bind the local vault as the cache for the remote-backed setup.
|
||
|
||
## Migration Requirements
|
||
|
||
1. Migrate existing remote connections that save credentials in app state.
|
||
2. On first open after upgrade, move any recoverable remote credentials into the vault.
|
||
3. Replace saved plaintext credential state with a vault credential reference.
|
||
4. If migration cannot write into the vault yet, hold the old state only long enough to prompt the user to complete migration.
|
||
5. 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
|
||
|
||
1. Where in the vault should remote profiles live: custom metadata, dedicated entries, or another KDBX-compatible structure?
|
||
2. Should credential references point to entry UUIDs directly, or should KeePassGO maintain an additional logical identifier?
|
||
3. Should automatic sync run only on open/save initially, or also on app resume?
|
||
4. How should multiple remote profiles per vault be presented in the UI?
|
||
5. 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.
|