Files
alknet/tasks/vault/unlock-new-zeroizing-return.md
glm-5.2 098fd8b9b9 tasks: decompose vault, core, call crates into 28 atomic implementation tasks
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.
2026-06-23 12:41:47 +00:00

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
vault/irpc-removal
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_new return type changed from Result<String, ...> to Result<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 check succeeds
  • cargo test succeeds
  • cargo clippy succeeds 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 String means 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 modify service.rs.

Summary

To be filled on completion