docs(architecture): remove derive_password and site_password_path from vault
The password-manager pattern (deterministic per-site passwords from HD
derivation) is not relevant to an RPC system's vault. Handlers call APIs
(using API keys, OAuth tokens, mTLS), not websites with passwords. The
vault is for cryptographic key derivation and credential encryption.
Removes:
- derive_password, derive_password_string from service.md
- site_password_path from mnemonic-derivation.md
- m/74'/1'/0'/{hash}' path from PATHS module and path semantics table
- derive_password row from the cache table
Resolves review #002 C9 (site_password_path hash mapping underspecified)
by removing the feature rather than specifying the non-standard
string→u32 mapping and Ed25519-as-password-entropy construction.
If deterministic password generation is ever needed (browser-automation
edge case), it can be re-added — the cost is near-zero. Removing it now
eliminates permanent API surface inherited from a prior project's
password-manager pattern.
This commit is contained in:
@@ -125,6 +125,7 @@ truth for drift tracking — if an item is fixed in source, update this table.
|
||||
| 4 | irpc dependency | `VaultProtocol` enum with `#[rpc_requests]`, `VaultServiceActor`, `Client<VaultProtocol>`, irpc/postcard deps | Remove entirely — direct method calls on `VaultServiceHandle` (ADR-025) | `protocol.rs`, `service.rs`, `Cargo.toml` | [ADR-025](../../decisions/025-vault-local-only-dispatch.md) |
|
||||
| 5 | `DerivedKey` dual serialization | JSON redacts, postcard preserves bytes | Always redact on serialize; reject `"[REDACTED]"` on deserialize with error (ADR-025, resolves W8) | `protocol.rs` | [protocol.md → Serialization Redaction](protocol.md#serialization-redaction), [ADR-025](../../decisions/025-vault-local-only-dispatch.md) |
|
||||
| 6 | `HashMap::clear` zeroization | `KeyCache::clear()` removes entries and relies on `CachedKey`'s `Drop` impl for zeroization | Verify `HashMap::clear()` actually drops values (it does, but worth a test) | `cache.rs` | [service.md → Security Constraints](service.md#security-constraints) |
|
||||
| 7 | `derive_password` / `site_password_path` | `derive_password`, `derive_password_string`, `site_password_path` methods exist | Remove entirely — password-manager pattern not relevant to RPC system's vault (ADR-025, resolves C9) | `service.rs`, `mnemonic-derivation.rs` | [ADR-025](../../decisions/025-vault-local-only-dispatch.md) |
|
||||
|
||||
## Public API
|
||||
|
||||
|
||||
@@ -199,9 +199,8 @@ pub mod PATHS {
|
||||
Helper functions construct parameterized paths:
|
||||
|
||||
```rust
|
||||
pub fn device_path(index: u32) -> String; // m/74'/0'/0'/{index}'
|
||||
pub fn site_password_path(site_hash: &str) -> String; // m/74'/1'/0'/{site_hash}'
|
||||
pub fn encryption_path_for_version(version: u32) -> String; // m/74'/2'/0'/{version-2}'
|
||||
pub fn device_path(index: u32) -> String; // m/74'/0'/0'/{index}'
|
||||
pub fn encryption_path_for_version(version: u32) -> String; // m/74'/2'/0'/{version-2}'
|
||||
```
|
||||
|
||||
### Path semantics
|
||||
@@ -211,7 +210,6 @@ pub fn encryption_path_for_version(version: u32) -> String; // m/74'/2'/0'/{vers
|
||||
| `m/74'/0'/0'/0'` | Primary node identity (Ed25519) | Ed25519 | TLS raw key (ADR-010), node identity |
|
||||
| `m/74'/0'/0'/{n}'` | Worker/device identity | Ed25519 | Multi-device nodes, workers |
|
||||
| `m/74'/0'/1'/0'` | SSH host key | Ed25519 | SSH handler |
|
||||
| `m/74'/1'/0'/{hash}'` | Site-specific deterministic password | Ed25519 bytes | Per-site passwords (not cached) |
|
||||
| `m/74'/2'/0'/0'` | Encryption key for external credentials | AES-256-GCM | Credential encryption (v2, see [encryption.md](encryption.md)) |
|
||||
| `m/44'/60'/0'/0/0` | Ethereum signing key | secp256k1 | Ethereum signing (feature-gated) |
|
||||
|
||||
|
||||
@@ -156,23 +156,6 @@ Derive a secp256k1 keypair at the given BIP-0032 path. Returns
|
||||
`UnsupportedKeyType` when the `secp256k1` feature is disabled. Returns a
|
||||
`DerivedKey` with `KeyType::Secp256k1` (33-byte compressed public key).
|
||||
|
||||
### derive_password(path, length) → Vec<u8>
|
||||
|
||||
```rust
|
||||
pub fn derive_password(&self, path: &str, length: usize) -> Result<Vec<u8>, VaultServiceError>;
|
||||
pub fn derive_password_string(&self, path: &str, length: usize) -> Result<String, VaultServiceError>;
|
||||
```
|
||||
|
||||
Derive deterministic password bytes at the given path, truncated to
|
||||
`length`. This is **not cached** — password derivation is cheap and
|
||||
passwords are typically one-shot (derive, use, discard). The string
|
||||
variant base64url-encodes the bytes (URL-safe, no padding).
|
||||
|
||||
`derive_password` is the mechanism for per-site deterministic passwords:
|
||||
the same seed + path always produces the same password. The path includes
|
||||
a site hash (`site_password_path(site_hash)`) so different sites get
|
||||
different passwords.
|
||||
|
||||
## Encrypt and Decrypt
|
||||
|
||||
### encrypt(plaintext, key_version) → EncryptedData
|
||||
@@ -250,13 +233,8 @@ pub struct CacheConfig {
|
||||
| `derive_ed25519` | Yes | Derivation is expensive; keys are reused |
|
||||
| `derive_encryption_key` | Yes | Same — encryption key reused across calls |
|
||||
| `derive_ethereum_key` | Yes | Same |
|
||||
| `derive_password` | No | Cheap derivation; passwords are one-shot |
|
||||
| `encrypt` / `decrypt` | Key cached | The encryption key (at `PATHS::ENCRYPTION`) is cached; the plaintext is not |
|
||||
|
||||
`derive_password` does not cache because it's a truncation of derived
|
||||
bytes, not a keypair that's reused. Caching it would grow the cache with
|
||||
unique paths (one per site hash) for no reuse benefit.
|
||||
|
||||
## Dispatch
|
||||
|
||||
The vault uses **direct method calls** on `VaultServiceHandle` — no actor,
|
||||
@@ -316,7 +294,7 @@ alknet-core error types at the assembly boundary (ADR-018).
|
||||
| RwLock for thread safety | — | Multiple readers (derive), exclusive writer (unlock/lock) |
|
||||
| TTL + LRU cache | — | Bounded memory, fresh keys, zeroized eviction |
|
||||
| Direct method calls (no actor) | [ADR-025](../../decisions/025-vault-local-only-dispatch.md) | No irpc, no message enum, no remote dispatch capability |
|
||||
| `derive_password` not cached | — | One-shot; caching grows cache with no reuse |
|
||||
| `derive_password` removed | [ADR-025](../../decisions/025-vault-local-only-dispatch.md) | Password-manager pattern not relevant to RPC system's vault; resolves C9 |
|
||||
|
||||
## Open Questions
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ perspective?**
|
||||
|
||||
The vault provides a `VaultServiceHandle` with `unlock`, `lock`,
|
||||
`derive_ed25519`, `derive_encryption_key`, `derive_ethereum_key`,
|
||||
`derive_password`, `encrypt`, and `decrypt` methods. Who is allowed to call
|
||||
these, and through what path?
|
||||
`encrypt`, and `decrypt` methods. Who is allowed to call these, and
|
||||
through what path?
|
||||
|
||||
The candidates:
|
||||
|
||||
|
||||
@@ -203,6 +203,19 @@ version of ADR-018's intent.
|
||||
exclusive writes (unlock/lock). The actor's sequential processing was
|
||||
actually *worse* for throughput than the RwLock. Removing the actor
|
||||
makes the concurrency model visible and correct.
|
||||
- `derive_password` and `site_password_path` are removed from the vault's
|
||||
API and path model. The password-manager pattern (deterministic per-site
|
||||
passwords from HD derivation) is not relevant to an RPC system's vault —
|
||||
handlers call APIs (using API keys, OAuth tokens, mTLS), not websites
|
||||
with passwords. The vault is for cryptographic key derivation and
|
||||
credential encryption. This resolves review #002 C9 (site_password_path
|
||||
hash mapping underspecified) by removing the feature rather than
|
||||
specifying the non-standard string→u32 mapping and Ed25519-as-password-
|
||||
entropy construction. If deterministic password generation is ever needed
|
||||
(browser-automation edge case), it can be re-added or implemented as a
|
||||
separate concern — the cost is near-zero, and removing it now eliminates
|
||||
permanent API surface that was inherited from a prior project's
|
||||
password-manager pattern.
|
||||
|
||||
**Negative:**
|
||||
|
||||
@@ -247,6 +260,11 @@ version of ADR-018's intent.
|
||||
in protocol.md goes away. If a future vault-server crate exposes some
|
||||
operations remotely, *that crate* defines the access policy in its own
|
||||
ADR.
|
||||
- **C9 (site_password_path hash mapping underspecified)**: resolved. The
|
||||
`derive_password` / `derive_password_string` / `site_password_path`
|
||||
methods are removed from the vault's API. The password-manager pattern
|
||||
is not relevant to an RPC system's vault. No hash mapping to specify,
|
||||
no Ed25519-as-password-entropy question to answer.
|
||||
|
||||
## Assumptions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user