--- id: spec-update-secret-service name: Update secret-service.md spec to close implementation-identified gaps status: completed depends_on: [] scope: narrow risk: low impact: phase level: implementation --- ## Description Update `docs/architecture/secret-service.md` to address seven gaps identified during the architect's initial implementation of alknet-secret. The tests pass and the code isn't "wrong," but the spec needs to be brought into alignment with what was learned and with what the implementation needs to be complete. This is a **spec-first** task — no code changes here, just documentation. The spec must be complete enough that the subsequent implementation tasks can be picked up without ambiguity. ### Gaps to Close 1. **irpc integration undefined** (biggest gap): The spec says `SecretProtocol` uses `#[rpc_requests(message = SecretMessage)]` but doesn't define the concrete wiring. How does a local `SecretServiceHandle` relate to the irpc protocol? What's the `Client` type? Where does the service run (in-process mpsc vs remote QUIC)? The current code has `pub type SecretMessage = SecretProtocol;` as a placeholder. 2. **Key caching strategy**: The security model table says "derived keys cached in RAM" but never specifies: what's the cache key? What's the TTL? Is it LRU? OQ-SVC-04 was resolved "yes, with TTL default 1 hour" but the spec doesn't reflect this resolution. Current implementation has no caching at all. 3. **`DerivedKey` security properties**: The struct carries `private_key: Vec` but doesn't derive `Zeroize`. ADR-038 says all sensitive material must zeroize. The spec should specify this. 4. **`DerivePassword` specification**: The `SecretProtocol::DerivePassword` variant exists but has no specification for how deterministic password derivation works: what hash function? What encoding? What character set? 5. **secp256k1/Ethereum derivation**: `DeriveEthereumKey` is in the protocol but the spec doesn't acknowledge that BIP-0032 secp256k1 (path `m/44'/60'/0'/0/0`) requires a fundamentally different derivation algorithm and crate than SLIP-0010 Ed25519. 6. **Test vectors requirement**: A crypto crate needs known-answer tests against published BIP39/SLIP-0010 test vectors. The spec doesn't reference any. 7. **`EncryptedData.salt` purpose**: The salt field is generated and stored but not used in key derivation. The spec should either specify that the salt is used in a KDF (PBKDF2/HKDF) to derive the AES key, or document it as reserved for future KDF-based key rotation. ### Changes to Make In `docs/architecture/secret-service.md`: - **Section: SecretProtocol irpc Service** — Replace the `SecretProtocol` enum definition with one that includes the irpc integration model: define `SecretServiceHandle` (local, in-process) vs `SecretProtocol` irpc client (remote), clarify the two dispatch paths, and specify that `SecretMessage` is the irpc wire type (generated by `#[rpc_requests]`). - **Section: Security Model** — Add a "Key Caching" subsection specifying: derivation path as cache key, TTL of 1 hour (configurable), LRU eviction, cache cleared on `Lock`. Per OQ-SVC-04 resolution. - **Section: Key Derivation** — Add a note after the `DerivedKey` struct that `private_key` must derive `Zeroize` per ADR-038. This means `DerivedKey` cannot use `#[derive(Clone)]` directly on the private key field; it needs a custom implementation that zeroizes the source on clone. - **Section: Key Derivation** (after derivation paths table) — Add a "Password Derivation" subsection specifying: `DerivePassword` uses HMAC-SHA512 at the derivation path, truncates to `length` bytes, and encodes as Base64url (no special character set in v1). The path format is `m/74'/1'/0'/{hash}'` where `{hash}'` is a site-specific hardened index. - **Section: Key Derivation** (after Ethereum path) — Add a "secp256k1 Derivation" note: `DeriveEthereumKey` uses BIP-0032 (not SLIP-0010) at path `m/44'/60'/0'/0/0`, requiring the `libsecp256k1` crate. This is a different derivation algorithm from Ed25519. The `alknet-secret` crate should gate this behind a `secp256k1` feature flag. - **Section: AES-256-GCM Encryption** — Specify that `EncryptedData.salt` is currently reserved for future KDF-based key rotation. In v1, the encryption key is derived directly from the seed at path `m/74'/2'/0'/0'` without a salt-based KDF. The `salt` field is included for forward compatibility: when key rotation is implemented, the salt will be used as input to HKDF or PBKDF2 for stretch-based key derivation. For now, the salt is random and stored but not used in key derivation. - **New Section: Test Vectors** — Require known-answer tests against: - BIP39 test vectors (mnemonic → seed) - SLIP-0010 test vectors (seed → master key, master key → child key at `m/74'/0'/0'/0'`) - IEEE P802.1ASck test vectors for AES-256-GCM (or equivalent published vectors) - **Section: Open Questions** — Mark OQ-SVC-04 as resolved (key caching: yes, TTL default 1 hour, LRU eviction). Add note about OQ-SVC-03 (EncryptedData compatibility: wire format stable, migration path is re-encrypt with new key version). - **Dependencies** section — Add `libsecp256k1` (behind `secp256k1` feature flag) and `hkdf`/`pbkdf2` (deferred, for Phase B KDF — listed as future dependency, not current). Update `irpc` line to clarify it's required but the integration model needs specification. - **Crate Structure** — Update to include `cache.rs` module for key caching. ## Acceptance Criteria - [ ] `secret-service.md` has a new subsection on irpc integration (local SecretServiceHandle vs remote SecretProtocol client, dispatch paths) - [ ] `secret-service.md` has a "Key Caching" subsection specifying derivation path as cache key, 1-hour TTL, LRU eviction, cleared on Lock - [ ] `secret-service.md` notes that `DerivedKey.private_key` must derive `Zeroize` per ADR-038 - [ ] `secret-service.md` has a "Password Derivation" subsection specifying HMAC-SHA512 → Base64url encoding - [ ] `secret-service.md` has a "secp256k1 Derivation" note specifying BIP-0032 algorithm and `secp256k1` feature flag - [ ] `secret-service.md` specifies that `EncryptedData.salt` is reserved for future KDF-based key rotation, not used in v1 key derivation - [ ] `secret-service.md` has a "Test Vectors" section requiring BIP39, SLIP-0010, and AES-256-GCM known-answer tests - [ ] OQ-SVC-04 is marked as resolved in `secret-service.md` - [ ] Dependencies section updated with secp256k1 (feature-gated) and noted future KDF deps - [ ] Crate structure diagram updated to include `cache.rs` ## References - docs/architecture/secret-service.md — The spec being updated - docs/architecture/decisions/038-seed-lifecycle-memory-security.md — ADR-038 (zeroize requirement) - docs/architecture/decisions/027-crate-decomposition.md — ADR-027 (crate independence) - docs/research/services.md — SecretProtocol definition source - crates/alknet-secret/ — Current implementation (reference for what exists) ## Notes > This is a spec-only task. No code changes. The goal is to make the spec complete enough that subsequent implementation tasks have zero ambiguity about what to build. > The architect's message (msg_eacbd63b2001DsTCHZn04meEpB) identified exactly these 7 gaps. This task closes them in the spec so that the implementation tasks can be done against a single source of truth. ## Summary > To be filled on completion