Allow constructing credential stores with supplied keys - #522
Conversation
e9af717 to
b7741dd
Compare
There was a problem hiding this comment.
Pull request overview
This PR refactors credential storage initialization so hosts can construct CredentialStore using already-resolved StorageKeys (direct key or envelope-resolved), rather than requiring the store to retain a keystore/blob-store provider.
Changes:
- Export
StorageKeysconstructors for direct bytes and envelope resolution, plus an explicitdelete_storage_key_envelopehelper. - Update
CredentialStoreconstruction to accept(StoragePaths, StorageKeys)and stop retainingDeviceKeystore/AtomicBlobStore. - Update tests and test utilities to construct stores via resolved keys and validate reopen/wrong-key/destroy semantics.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| crates/walletkit-testkit/src/storage.rs | Updates filesystem testkit store construction to resolve StorageKeys up-front and pass them into CredentialStore::new. |
| crates/walletkit-core/tests/credential_storage_integration.rs | Switches integration test store construction to the provider helper (open_store). |
| crates/walletkit-core/tests/common.rs | Adds InMemoryStorageProvider::open_store() helper that resolves keys then constructs a store. |
| crates/walletkit-core/src/storage/traits.rs | Updates module-level docs to reflect host-owned key resolution and direct-key hosts. |
| crates/walletkit-core/src/storage/tests_utils.rs | Adds open_store() helper for storage unit-test utilities. |
| crates/walletkit-core/src/storage/mod.rs | Updates storage docs/exports and makes delete_database_file visible within the storage module. |
| crates/walletkit-core/src/storage/keys.rs | Introduces UniFFI-exported StorageKeys object constructors (from_bytes, from_envelope) and explicit envelope deletion function. |
| crates/walletkit-core/src/storage/credential_storage.rs | Refactors CredentialStore to retain only resolved keys, updates destroy semantics, and expands tests for direct-key behavior. |
| crates/walletkit-core/src/proof_request_credential_constraints_check.rs | Updates tests to use provider.open_store() after constructor changes. |
| crates/walletkit-core/src/issuers/recovery_bindings_manager.rs | Updates tests to use provider.open_store() after constructor changes. |
| crates/walletkit-core/src/authenticator/with_storage.rs | Updates docs/tests to reflect new destruction semantics and store construction changes. |
| crates/walletkit-core/src/authenticator/mod.rs | Updates authenticator tests to construct storage with resolved StorageKeys and adds coverage for that path. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.
Suppressed comments (1)
crates/walletkit-core/src/storage/credential_storage.rs:918
destroy_storagewraps file-deletion failures for both the vault DB and the cache DB inStorageError::VaultDb, which makes cache cleanup errors indistinguishable/misleading for callers that pattern-match onStorageErrorvariants.
if let Err(error) = super::delete_database_file(&file) {
first_error.get_or_insert_with(|| {
StorageError::VaultDb(format!(
"delete {}: {error}",
file.display()
))
});
82b960c to
13757ea
Compare
| /// | ||
| /// Removes the encryption keys, vault database, and cache database. | ||
| /// Releases the store's key reference and removes the vault and cache databases | ||
| /// on a best-effort basis. File deletion failures are logged, not returned. |
There was a problem hiding this comment.
If this is best effort then why Error is returned?
There was a problem hiding this comment.
it's refering to this part - an error here can actually be a mutex locking error
The merge-base changed after approval.
dabb788 to
829ec52
Compare
829ec52 to
54eb012
Compare
Allow hosts to construct
CredentialStorefrom resolvedStorageKeys, so a browser can supply a passkey PRF-derived database key and a mobile host can resolve its existing device-sealed envelope first.StorageKeys::from_bytesandStorageKeys::from_envelope; the store accepts paths and keys without retaining a device keystore or atomic blob store.Validation on the combined stack: 60 native storage tests, the credential-storage integration test, the mock-gateway authenticator construction test, and native Clippy pass.
First of two stacked PRs against the POC (#480). The follow-up updates the web package and demo for the new constructor and moves browser execution into a package-owned worker.
Note
High Risk
Breaking FFI/storage API and changed credential encryption key lifecycle on destroy affect logout, account deletion, and all native hosts that previously used provider-based construction.
Overview
Credential storage is built from resolved
StorageKeysplus paths, not from a retainedStorageProvider/ keystore / blob store. The public UniFFI constructor isCredentialStore::new(paths, keys);StorageKeys::from_bytessupports host-supplied 32-byte keys (e.g. passkey PRF). Device-sealed envelopes are handled separately via newopen_or_create_storage_keysanddelete_storage_key_envelopeinkey_envelope.rs.Logout / teardown semantics change:
destroy_storagedrops the store’s key handle and best-effort deletes vault/cache files only—it no longer removesaccount_keys.bin. Hosts must delete the envelope explicitly. A destroyed store cannot be re-initialized in place; callers need a new store (and typically new key resolution). Docs onAuthenticator::destroy_storageare updated to match.Tests and helpers (
InMemoryStorageProvider::open_store, testkit FS store) resolve keys first, then construct the store. New coverage exercises direct-key init, wrong-key failure, key refcount on destroy, and best-effort file cleanup.Reviewed by Cursor Bugbot for commit 54eb012. Bugbot is set up for automated code reviews on this repo. Configure here.