Skip to content

Latest commit

 

History

History
119 lines (94 loc) · 6.54 KB

File metadata and controls

119 lines (94 loc) · 6.54 KB

Credential storage architecture

The shared SecretStore interface separates credential storage from application logic. Desktop and mobile builds use native credential services through Tauri. Browser builds route secret-store operations to the server's encrypted vault rather than browser storage.

For database keys, portable exports and restore behavior, see database encryption and backups.

Profile namespaces

Profiles wrap the platform store with a fixed ScopedSecretStore namespace. New profiles prefix logical keys with profile:<uuid>:; only the adopted legacy profile keeps existing unprefixed keys. This includes add-on fallback keys, profile lock records, and Connect/device credentials. Web profiles share one underlying encrypted vault instance. Password verification and recovery are described in the profile architecture.

Native credentials

The Tauri implementation of the shared SecretStore contract uses keyring-core and explicit platform backends:

Platform Backend
macOS Apple login Keychain (apple-native-keyring-store, keychain)
iOS Apple protected Keychain (apple-native-keyring-store, protected)
Android Android Keystore encryption with encrypted SharedPreferences (android-native-keyring-store)
Windows Windows Credential Manager (windows-native-keyring-store)
Linux / other configured desktop Unix targets D-Bus Secret Service (zbus-secret-service-keyring-store)

Credentials include authentication tokens, provider API keys, and device-sync secrets. Existing service identifiers and account names remain compatible with previous desktop storage. Initialization is lazy, with successful stores cached. Missing or locked native credential services return errors, with no plaintext or in-memory fallback. Linux requires a session D-Bus and an available Secret Service provider.

Sources: native store, shared contract.

Android lifecycle and backup

The Android backend crate implements encryption and credential persistence. Our JNI bridge only supplies the Java VM and application context before Tauri starts; it does not implement a custom credential store. Its JNI types match the backend's initialization API.

The crate stores ciphertext in shared_prefs/keyring-default.xml. Its encryption key remains in Android Keystore and cannot be carried to another device with an ordinary app-data backup. Android Keystore stores cryptographic keys; arbitrary API-token strings remain encrypted outside it.

The Android manifest selects backup rules that exclude keyring-default.xml from legacy full backup, cloud backup, and device-to-device transfer. Tauri stores its database directly in Android dataDir, so the rules also exclude the root domain: the database, encryption marker, maintenance files, and internal backups cannot be transferred without their device-bound key. This exclusion applies whether database encryption is enabled or disabled. Use Wealthfolio’s portable export and restore to move portfolio data to another device; credentials must be re-entered or recreated.

Android database encryption uses this persistent store, with an immediate key read-back before conversion. Enabling/disabling rebuilds the runtime in place, as on iOS; a process restart subsequently reopens the database with the retained key. Disabling keeps the key so older encrypted backups remain readable.

Sources: manifest, legacy backup rules, extraction rules.

Server credentials

The Axum server uses FileSecretStore, a JSON vault encrypted with ChaCha20-Poly1305 and a fresh nonce per write. The required master key comes from WF_SECRET_KEY or WF_SECRET_KEY_FILE. Both inputs use the same decoder and HKDF-SHA256 derivation, with separate wealthfolio-jwt and wealthfolio-secrets labels for session signing and vault encryption. File input is read once at startup. Native credential services are not required on the server host.

WF_SECRET_FILE selects the encrypted vault location. Its default is secrets.json alongside the database. File writes use the operating system's normal filesystem behavior: existing ownership, permissions, ACLs, symlinks, hard links, and individual file mounts are preserved. File creation follows platform permissions and the process umask.

A mutex serializes operations through one store instance. Writes happen in place and are not crash-atomic; independent processes must not write the same vault.

Sources: server store, key configuration, key derivation.

Compatibility and recovery

Existing derived-key encrypted files keep their format and key derivation. Supported raw-key files migrate to derived-key encryption. Legacy plaintext files remain readable and are encrypted on their next successful credential write. Empty files are treated as empty vaults. Invalid nonce lengths return errors instead of panicking. A malformed encrypted envelope is not treated as plaintext.

Vault read/decryption failures are reported by secret operations rather than blocking unrelated server features at startup. Failed reads do not trigger an automatic reset. An interruption during a write can still leave an incomplete file, so backups remain necessary.

Keep the master key in a separately protected recovery location from the vault backup. Losing it prevents decryption. Switching from environment input to file input must use the same key; changing its value is not a key-rotation procedure and also affects session signing and OIDC logout-token encryption.

For configuration and commands, see the server README and self-hosting guide.