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.
2.7 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | |
|---|---|---|---|---|---|---|---|---|
| vault/unlock-new-zeroizing-return | Change unlock_new return type from String to Zeroizing<String> | pending |
|
single | low | isolated | implementation |
Description
Fix drift item #8: unlock_new currently returns String, which is not
zeroized on drop. The mnemonic phrase is the root of trust — it must not linger
in freed heap memory. Change the return type to Zeroizing<String> (from the
zeroize crate, already a dependency).
Current state
pub fn unlock_new(&self, word_count: usize) -> Result<String, VaultServiceError>;
Target state
pub fn unlock_new(&self, word_count: usize) -> Result<Zeroizing<String>, VaultServiceError>;
Per docs/architecture/crates/vault/service.md → unlock_new:
The returned phrase is the root of trust — it is heap-allocated and zeroized on drop, so it does not linger in freed memory. The caller should extract the phrase for secure storage (write down, display to user) and let the
Zeroizing<String>drop when done. Do not clone the returned value or store it in a non-zeroizing container.
Caller adaptation
The assembly layer (CLI binary, not yet implemented) will call unlock_new and
extract the phrase. The Zeroizing<String> wrapper derefs to String, so
&*result or result.as_str() works for reading. The caller must not clone the
inner String into a non-zeroizing container.
Existing tests that call unlock_new need updating to handle the new return
type — use &*phrase or phrase.as_str() to read the string.
Scope
This task touches service.rs (the method signature and body) and test files.
It depends on the irpc removal task (drift #4) because both modify service.rs.
Acceptance Criteria
unlock_newreturn type changed fromResult<String, ...>toResult<Zeroizing<String>, ...>- Method body constructs
Zeroizing<String>from the generated phrase - Existing tests updated to handle
Zeroizing<String>return type - No
clone()of the returned value in non-test code cargo checksucceedscargo testsucceedscargo clippysucceeds with no warnings
References
- docs/architecture/crates/vault/README.md — Known Source Drift table item #8
- docs/architecture/crates/vault/service.md — unlock_new section
- docs/architecture/decisions/025-vault-local-only-dispatch.md — ADR-025 (resolves W7)
Notes
The mnemonic is the root of trust. Returning a plain
Stringmeans the phrase lingers in freed heap memory after the caller drops it.Zeroizing<String>zeroizes the bytes on drop. This resolves review #002 W7. Depends on irpc removal because both modifyservice.rs.
Summary
To be filled on completion