Changelog
All notable changes to tauri-plugin-keyring-store and tauri-plugin-keyring-store-api.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.3.2 - 2026-11-09
No behaviour changes.
Documentation
- Documentation site at https://s00d.github.io/tauri-plugin-keyring-store/ (guides, platforms, security notes, generated API / command / permission reference). The README is now a short overview.
- JSDoc for every
tauri-plugin-keyring-store-apiexport (shows up in editor hints) and doc comments for every Tauri command. homepageinCargo.tomlandpackage.jsonpoints to the site.
Fixed
split_prefixederror message: missing;in "only one separator allowed; use nested naming in the app layer" (now the same text assplitKeyPrefixin JS).
0.3.1 - 2026-11-08
No API changes.
Security
kp:guard ignores case. The password commands rejected only lowercasekp:accounts. Windows credential names are case-insensitive, soKP:…reached session store records and vault keys there. Now any letter case is rejected.
Fixed
- Backend init is retried. A failed keyring backend start (e.g. no D-Bus session yet) was cached for the life of the process. Now only success is cached; after a failure the next call tries again after a 2-second pause.
KeyringVault.remove(location)deleted from the vault theKeyringVaultwas opened for and ignored the vault inlocation. It now uses the location's vault.
Added
KeyringStore::with_store(...): use anykeyring-corestore (e.g.linux-keyutils-keyring-store) for one handle;init()is unchanged.
Documentation
- Linux without a desktop session: a Secret Service unlock prompt can block a call for a very long time.
- The session password is not verified.
- Windows: real limit for store records and vault secrets is about 960 bytes (Base64, then UTF-16 in a 2560-byte blob).
- Counter location
7and generic record"7"are the same record.
0.3.0 - 2026-11-08
Security
- Vault procedures no longer return private keys to the webview.
SLIP10GenerateandBIP39Recoverreturned the 65-byte extended private key,SLIP10Derivethe derived private key. They now return nothing / the chain code, as Stronghold does. - Password commands reject
kp:accounts. Vault keys and store records live underkp:v1:…accounts in the same service, sogetPasswordscould read vault key material directly andsetPasswordscould overwrite it. - No mnemonic words in errors. An invalid BIP39 mnemonic produced an error that named the unknown word (sent to JS and easy to log). Crypto errors now use fixed messages.
- No secrets in
Debugoutput.PasswordEntryDto,PasswordBackupEntryDtoandProcedureDtoredact secrets, mnemonics and passphrases. - Secrets, passphrases, decrypted backups, derived keys and seed buffers are wiped after use (
zeroize, also enabled inargon2/chacha20poly1305). SLIP10GeneratesizeBytesmust be within 16..=64 (any size was allocated before).
Fixed
generateBIP39returned key bytes instead of the mnemonic, so the generated phrase could never be backed up. It now returns the 24-word mnemonic (UTF-8 bytes) and writes the master key to the output location.- Binary ids were broken in guest-js.
Uint8Array/ArrayBuffer/ iterable client, vault, record and store keys were serialized as JSON objects and rejected by Rust; they are now sent as byte arrays. Values acceptUint8Arraytoo. - Byte store keys (
StoreKeyallowed them in TS) failed because Rust expected a string; a byte key now addresses the same record as the equal UTF-8 text key. - Imports were partial on error.
import_passwords_plain/import_passwords_encryptedwrote rows until the first invalid one and had no item limit; the whole backup is now validated first (max 256 rows). - Keyring I/O ran on async worker threads and could stall the runtime while the OS showed a keychain prompt or unlocked a collection; it now runs on blocking threads.
savenow requires a loaded session, like Stronghold.
Changed
- Breaking: procedure return values above;
Erroris#[non_exhaustive];KeyringStore::account_store_keytakesimpl AsRef<[u8]>. - Edition 2024, MSRV 1.88.
KeyringStoreerrors on entry creation (including iOS write modifiers) go through the same mapping, so a locked store reportsKeychainLockedthere too.argon20.6,chacha20poly13050.11 (encrypted backups from 0.1.x still decrypt),base640.23; removed unusedlog,randand thegeneric-arraypin. - guest-js built with Vite 8 (ESM + CJS), TypeScript 6, Vitest 5; separate
index.d.cts, nestedexports,sideEffects: false; dist checked with publint, attw and an export smoke test. Rollup and tslib removed. - Tests: IPC tests through
tauri::test, procedure tests on the keyring-core mock store, and a live write/read/delete test against the real OS store. - CI on Linux (gnome-keyring), macOS and Windows plus Android and iOS builds. Windows test binaries embed the Common-Controls v6 manifest.
- Example: tauri 2.12, password API from JS, vault demo, log rendered as text (it used
v-htmlwith secret values), autocorrect / autocapitalize off.
0.2.0 - 2026-05-22
Added
WriteAccessibility(iOS/macOS): configure Data Protection for new writes; default on iOS isAfterFirstUnlockviaaccess-policymodifiers onset_password/set_bytes.Builder::ios_write_accessibilityto set the write policy at plugin init.Error::KeychainLocked: distinct from genericKeyring(String)when the protected store is unavailable (device locked,errSecNotAvailable, etc.).KeyringAvailabilityandKeyringStore::availability()— probe-read without UIKit in the host app.- Background helpers:
get_password_for_background,get_bytes_for_background,exists_nonempty_for_backgroundreturnNone/falsewhen locked instead of surfacingKeychainLocked.
Changed
- iOS writes use
Entry::new_with_modifierswithafter-first-unlockby default; reads still useEntry::new(same service/account). - npm
tauri-plugin-keyring-store-apibumped to 0.2.0 (aligned with the Rust crate; guest-js API unchanged).
Notes
- Credentials written before 0.2.0 keep their previous accessibility until re-saved (
set_password/set_bytes). No automatic migration command in this release. - Downstream apps with exhaustive
matchonErrormust handleKeychainLocked(minor breaking within 0.x).
0.1.5 - 2026-05-13
Changed
- README: Recommend
pnpm run tauri add keyring-store(and npm/yarn/cargo equivalents) instead of a barecargo add“automatic” block; clarify snapshot path for all OSes; document guest-js API with examples forping, session/client/store/vault,Location, naming helpers, and direct account backup helpers.
0.1.4 - 2026-05-13
Fixed
- docs.rs: Drop
package.metadata.docs.rsrustc-args = ["--cfg", "docsrs"]. That flag was applied to the whole dependency graph and broke serde / serde_json / derives on nightly (see serde-rs/serde#2994). Skip the Linux D-Bus dependency usingcfg(doc)inCargo.tomlandbackend.rsinstead ofcfg(docsrs), so normal builds still link dbus whilecargo rustdoc/ docs.rs do not.
0.1.3 - 2026-05-13
Fixed
- docs.rs: Pin
generic-arrayto 0.14.9 socargo rustdocunder nightly--cfg docsrsdoes not compile 0.14.7 (still uses removeddoc_auto_cfg). Keepsdefault-target = "x86_64-apple-darwin"from 0.1.2.
0.1.2 - 2026-05-13
Fixed
- docs.rs: Set
package.metadata.docs.rsdefault-target = "x86_64-apple-darwin"so documentation builds do not use the default Linux graph (GTK/WebKit → oldwinnow/tomlcrates failing under nightly--cfg docsrs). Linux dbus stub +not(docsrs)deps remain for developers runningcargo docon Linux.
0.1.1 - 2026-05-13
Fixed
- docs.rs: Skip linking
dbus-secret-service-keyring-storewhencfg(docsrs)so documentation builds on Linux without host GLib/pkg-config (0.1.0 rustdoc build failed for this reason).
0.1.0 - 2026-05-13
Changed
- Breaking: Renamed distribution packages to avoid collisions on crates.io/npm: Rust crate
tauri-plugin-keyring-store(importtauri_plugin_keyring_store), npmtauri-plugin-keyring-store-api. Tauri plugin id iskeyring-store— IPCplugin:keyring-store|<command>, capability prefixkeyring-store:(e.g.keyring-store:default).
Added
- Initial release: OS keyring backend (
keyring-core+ platform stores). - Stronghold-shaped IPC and guest-js API (
KeyringSession, store, vault). - Optional
cryptofeature: SLIP10 / BIP39 / Ed25519 procedures viaiota-crypto. - Encrypted backup (Argon2id + ChaCha20-Poly1305) is always available; it does not depend on the
cryptofeature. - Rust
KeyringExt/KeyringPluginfor direct store access from backend code. - Permissions autogeneration and default capability set.
- Direct account IPC:
get_passwords,set_passwords,delete_passwords,password_exists(max 256 items per bulk call). - Plaintext backup:
export_passwords_plain/import_passwords_plain(secrets cross IPC in the clear — see README). - Encrypted backup:
export_passwords_encrypted/import_passwords_encrypted. - Rust
naminghelpers (join_prefix,split_prefixed) and guest-jsjoinKeyPrefix/splitKeyPrefix. - Guest-js:
getPasswords,setPasswords,deletePasswords,passwordExists,exportPasswordsPlain,importPasswordsPlain,exportPasswordsEncrypted,importPasswordsEncrypted.