Break down the three initial crates (alknet-vault, alknet-core, alknet-call) into dependency-ordered task files for implementation agents. Structure: - tasks/vault/ (10 tasks) — drift fixes from ADR-025/026 refactor, review, spec sync. Vault is independent and can run fully in parallel with core/call. - tasks/core/ (6 tasks) — crate init, core types, config, auth, endpoint, review. Core is foundational; call depends on it. - tasks/call/ (12 tasks) — split into registry/ and protocol/ topic subdirs reflecting the two subsystems. CallAdapter is the merge point. Key decisions: - Drifts 3+9+10 grouped as one task (key-versioning-rotation) — the complete ADR-021 rotation feature that doesn't compile in pieces - Reviews injected at end of each crate phase (vault, core, call) - Vault spec-sync task removes the drift table and bumps doc status to stable - ACME deferred in core/endpoint (noted as TODO; X509 manual certs for now) - OperationEnv kept as a trait (load-bearing for ADR-024 layering) Validated: 28 tasks, no cycles, 11 generations of parallel work. Critical path runs through call (11 tasks). Vault completes by generation 4. 6 high-risk tasks identified (21%): irpc-removal, endpoint, operation-context, operation-env, call-adapter, abort-cascade.
5.8 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | |
|---|---|---|---|---|---|---|---|---|
| vault/key-versioning-rotation | Implement version-indexed encryption key paths, bump CURRENT_KEY_VERSION to 2, and add rotate method | pending |
|
moderate | medium | component | implementation |
Description
Fix drift items #3, #9, and #10 as one coherent feature: the version-indexed
key rotation mechanism from ADR-021. These three drifts are tightly coupled —
CURRENT_KEY_VERSION = 2 (drift #3), version-aware encrypt/decrypt via
encryption_path_for_version (drift #9), and the rotate method (drift #10)
form the complete key rotation feature. Splitting them would produce tasks that
don't compile independently.
Drift #3: Bump CURRENT_KEY_VERSION
Current: CURRENT_KEY_VERSION = 1 (but the key is HD-derived, and v1 is
reserved for the TypeScript PBKDF2 legacy per ADR-020).
Target: CURRENT_KEY_VERSION = 2 (HD-derived, per ADR-020).
Version semantics:
- v1: TypeScript predecessor's PBKDF2-encrypted data — the vault cannot decrypt it (different key derivation). Migration is a one-time re-encryption.
- v2: HD-derived at
m/74'/2'/0'/0'(PATHS::ENCRYPTION) — current. - v3+:
m/74'/2'/0'/1',m/74'/2'/0'/2', etc. — future rotation versions.
Drift #9: Version-aware encrypt/decrypt
Current: encrypt/decrypt always derive at PATHS::ENCRYPTION regardless of
the key_version parameter.
Target:
encrypt(plaintext, key_version): derive the encryption key atencryption_path_for_version(key_version), stamp the samekey_versionon the resultingEncryptedData.decrypt(encrypted): derive the key atencryption_path_for_version(encrypted.key_version)— the blob carries its own version, and each version maps to a distinct derivation path.
This requires:
encryption_path_for_version(version: u32) -> Result<String, DerivationError>already exists inderivation.rs— verify it returnsInvalidPathforversion < 2(v1 is TS legacy, v0 is meaningless).derive_encryption_key_for_version(version: u32) -> Result<DerivedKey, VaultServiceError>— a new method onVaultServiceHandlethat maps version → path → derive. Cached by path (same cache asderive_encryption_key).encryptanddecryptusederive_encryption_key_for_versioninstead of deriving at the fixedPATHS::ENCRYPTIONpath.
Drift #10: Implement rotate
Current: no rotate method exists.
Target:
pub fn rotate(&self, encrypted: &EncryptedData, to_version: u32) -> Result<EncryptedData, VaultServiceError>;
Decrypts with the old version's key (from encrypted.key_version), re-encrypts
with the new version's key (to_version). Returns the new EncryptedData —
the caller replaces the blob in storage. No new mnemonic needed; the same seed
produces all version keys via different derivation paths (ADR-021).
Implementation notes
derive_encryption_key(path)(the path-based API) remains as-is for deriving at arbitrary paths.derive_encryption_key_for_version(version)is the version-aware API used byencrypt/decrypt. Both share the same cache (keyed by derivation path).encryptanddecryptextract theEncryptionKeyfrom theDerivedKeyviaEncryptionKey::from_derived_bytes(see encryption.md).encryption_path_for_versionreturnsInvalidPathforversion < 2.derive_encryption_key_for_versionpropagates this asVaultServiceError::InvalidPath.
Scope
This task touches encryption.rs (CURRENT_KEY_VERSION), service.rs (encrypt,
decrypt, rotate, derive_encryption_key_for_version), and possibly derivation.rs
(verify encryption_path_for_version). It depends on the irpc removal task
(drift #4) because both modify service.rs.
Acceptance Criteria
CURRENT_KEY_VERSIONis2inencryption.rsderive_encryption_key_for_version(version)method added toVaultServiceHandlederive_encryption_key_for_versionreturnsInvalidPathforversion < 2encrypt(plaintext, key_version)derives atencryption_path_for_version(key_version)encryptstamps the passedkey_versionon the resultingEncryptedDatadecrypt(encrypted)derives atencryption_path_for_version(encrypted.key_version)rotate(encrypted, to_version)method implemented: decrypt old, re-encrypt newrotatereturnsEncryptedDatawithkey_version = to_version- Unit test: encrypt at v2, decrypt at v2 — round-trip succeeds
- Unit test: encrypt at v2, rotate to v3, decrypt at v3 — round-trip succeeds
- Unit test: decrypt v2 blob after rotation — old key still derivable (partial rotation safe)
- Unit test:
derive_encryption_key_for_version(1)returnsInvalidPath - Unit test:
derive_encryption_key_for_version(0)returnsInvalidPath cargo testsucceedscargo clippysucceeds with no warnings
References
- docs/architecture/crates/vault/README.md — Known Source Drift table items #3, #9, #10
- docs/architecture/crates/vault/encryption.md — Key Versioning, Rotation, EncryptionKey
- docs/architecture/crates/vault/service.md — encrypt, decrypt, rotate, derive_encryption_key_for_version
- docs/architecture/crates/vault/mnemonic-derivation.md — encryption_path_for_version, PATHS
- docs/architecture/decisions/020-hd-derivation-for-encryption-keys.md — ADR-020
- docs/architecture/decisions/021-key-rotation-via-version-indexed-paths.md — ADR-021
Notes
These three drifts are one feature: version-indexed key rotation (ADR-021). Splitting them would produce tasks that don't compile independently — bumping the version without version-aware encrypt/decrypt would make v2 blobs undecryptable, and rotate without version-aware encrypt/decrypt has no keys to work with. Depends on irpc removal because both modify
service.rs.
Summary
To be filled on completion