Drift item #2: replace all .read().unwrap()/.write().unwrap() calls in
VaultServiceHandle with .unwrap_or_else(|e| e.into_inner()) to recover from
poisoned locks instead of bricking the vault. Added test_poisoned_lock_recovery
that poisons the lock via a panicking thread and verifies the vault remains
usable.
Refs: docs/architecture/crates/vault/README.md drift #2
Implements: ADR-025
# Conflicts:
# crates/alknet-vault/src/service.rs
Drift item #8: the mnemonic phrase is the root of trust — it must not linger in
freed heap memory. Changed unlock_new return from String to Zeroizing<String>
(zeroized on drop). Existing tests work via Deref coercion.
Refs: docs/architecture/crates/vault/README.md drift #8
Implements: ADR-025 (resolves W7)
Replace all .read().unwrap() and .write().unwrap() calls in
VaultServiceHandle methods with .unwrap_or_else(|e| e.into_inner())
so a panic while holding the lock does not brick the vault for all
subsequent operations. Add unit test that poisons the lock and
verifies the next call recovers.
Change unlock_new return type from String to Zeroizing<String>
so the generated mnemonic phrase is zeroized on drop and does not
linger in freed heap memory. Resolves drift item #8 / review W7.
Drop the password-manager pattern from alknet-vault (drift item #7,
ADR-025, resolves review #002 C9). Site-specific password derivation
is not relevant to an RPC system's vault.
Removed:
- derive_password method from VaultServiceHandle (service.rs)
- derive_password_string method from VaultServiceHandle (service.rs)
- site_password_path function from derivation.rs
- site-password derivation path row from derivation.rs doc table
- All password-derivation tests from service.rs and derivation.rs
- Now-unused base64 URL_SAFE_NO_PAD import from service.rs
Replace derived Deserialize with a custom impl that rejects
private_key == b"[REDACTED]" with an explicit error, and make the
custom Serialize impl always redact (drop the human-readable-only
branch). Updates the redaction-rejection and debug-no-leak tests.
Resolves drift item #5 (ADR-025 dropped the postcard/remote path).
ADR-025 / drift item #4: remove the irpc-based actor dispatch from the vault
crate. VaultServiceHandle (Arc<std::sync::RwLock<>>) is now the sole synchronous
API. Removed: VaultProtocol enum, VaultServiceActor, VaultService wrapper,
Client<VaultProtocol> usage, irpc/irpc-derive/tokio deps, postcard dev-dep,
Serialize/Deserialize on VaultServiceError. lib.rs re-exports match the vault
README Public API. The vault is now local-only by construction with zero async
runtime dependency.
Refs: docs/architecture/crates/vault/README.md drift #4
Implements: ADR-025
# Conflicts:
# Cargo.lock
Drop the irpc-based actor dispatch path from alknet-vault and convert to
direct method calls on VaultServiceHandle (drift item #4, ADR-025).
Removed:
- VaultProtocol enum with #[rpc_requests] derive from protocol.rs
- VaultServiceActor (mpsc + oneshot dispatch loop) from service.rs
- VaultService wrapper struct (only the handle is needed)
- Client<VaultProtocol> usage
- irpc, irpc-derive, tokio from [dependencies]
- postcard from [dev-dependencies]
- VaultMessage/VaultProtocol/VaultServiceActor re-exports from lib.rs
- Serialize/Deserialize derives from VaultServiceError
- postcard round-trip tests from protocol.rs
- actor tokio::test tests from service.rs
The vault now has zero async runtime dependency and zero RPC framework
dependency — it is local-only by construction. VaultServiceHandle is the
sole API: Arc<std::sync::RwLock<VaultServiceInner>> with synchronous
methods. lib.rs re-exports match the vault README Public API section.
Also fixes pre-existing clippy field_reassign_with_default warnings in
cache.rs tests so cargo clippy -- -D warnings passes.
Drift item #6: verify HashMap::clear()/remove()/replace drop CachedKey values
triggering ZeroizeOnDrop. Adds drop_tracker module proving Drop semantics,
plus LRU eviction, TTL expiry, and clear() tests. The lock()-clears-cache
criterion is covered by existing test_lock_clears_all_cache_entries in service.rs.
Refs: docs/architecture/crates/vault/README.md drift #6
Replace rand::random() with rand::rngs::OsRng for cryptographic nonce
and salt generation in encryption.rs. rand::random() uses thread-local
RNG which may not be a CSPRNG on all platforms; OsRng reads from the
OS entropy source, preventing catastrophic IV reuse under AES-GCM.
Drift item #1 (security-critical).
Rename the crate from alknet-secret to alknet-vault to better reflect its
purpose as a local key vault (seed management, key derivation, encryption)
rather than a network service.
Symbol renames:
- SecretService → VaultService
- SecretServiceHandle → VaultServiceHandle
- SecretServiceActor → VaultServiceActor
- SecretServiceError → VaultServiceError
- SecretProtocol → VaultProtocol
- SecretMessage → VaultMessage
- ServiceLocked → VaultLocked
- alknet_secret → alknet_vault (crate name)
Update ADR-008 with vault access pattern: the vault is a capability source,
not a service endpoint. The CLI injects derived/decrypted material into
operation contexts — handlers never hold vault references.