diff --git a/docs/architecture/decisions/005-at-rest-key-custody.md b/docs/architecture/decisions/005-at-rest-key-custody.md index 0c05254..66c225c 100644 --- a/docs/architecture/decisions/005-at-rest-key-custody.md +++ b/docs/architecture/decisions/005-at-rest-key-custody.md @@ -60,11 +60,12 @@ both ends). themselves). The *decrypted plaintext* is the gap: alkvault's `decrypt` returns a plain `String`, so from the vault's return to the adapter's wrap the plaintext sits in unfenced heap. The - adapter owns the wrap (proven in POC-2) — recorded as the family - convention pending alkvault taking ownership of it - (`Zeroizing` out). This OQ was brought upstream; when - alkvault answers, this ADR is amended accordingly (OQ-07 is the - tracker and the ask). + adapter owns the wrap (proven in POC-2) — **that is the contract on + this path**; the vault-side improvement (a `Zeroizing`-out + API) is an upstream ask filed in alkvault's own tracker, not an + alkssh obligation — when it lands, this ADR's pointer updates as a + one-line doc touch (alkssh OQ-07 is closed at the + adapter-convention level). 4. **Failure modes are all fail-closed, with distinct error shapes.** Locked vault → no dial (and no server: a host key that can't load prevents server construction — verified at bootstrap). Absent diff --git a/docs/architecture/open-questions.md b/docs/architecture/open-questions.md index bdf85f4..5f97cc0 100644 --- a/docs/architecture/open-questions.md +++ b/docs/architecture/open-questions.md @@ -67,14 +67,12 @@ alkcall trackers have their own OQ spaces). - **Status**: resolved - **Resolution**: not an alkssh constraint. The crate takes vault handles the assembly injects; whether the assembly runs separate vault instances per role (client keys vs host keys) is assembly policy. ADR-005 records the boundary: vault handle in, key material out, version semantics owned by the vault. -### OQ-07: Is the alkvault `decrypt` plain-`String` zeroization gap closed at the vault or at the adapter? +### OQ-07: ~~Is the alkvault `decrypt` plain-`String` zeroization gap closed at the vault or at the adapter?~~ — resolved (at this level) - **Origin**: [poc-2-vault-keys.md](../research/poc-2-vault-keys.md) §2 + OQ seed 1 -- **Status**: open -- **Priority**: medium -- **Impacts**: an in-family cross-crate ask (alkvault API change vs alkssh-side convention). Blocks nothing functionally — POC-2 proves the adapter-side `Zeroizing` wrap correct — but decides where the security convention lives for the whole family (alkhttp secrets ride the same `&str`-out surface). -- **Resolution**: pending. Candidates: alkvault returns `Zeroizing` (family-wide fix, touches a published crate), or the adapter-side wrap is the recorded family convention (ADR-005). Bring to alkvault; if upstream accepts, ADR-005 cites the follow-up; if not, ADR-005 records the adapter obligation as the convention. -- **Cross-references**: OQ-05, ADR-005 +- **Status**: resolved — the alkssh-level answer is the adapter-side wrap; the vault-side improvement belongs upstream, not here. +- **Resolution**: **ADR-005 decision 3 is the contract on this path**: the adapter owns a `Zeroizing` wrap at the seam (POC-2-proven; bounds the plaintext from adapter-takeover onward; ssh-key zeroizes the decoded key bytes on drop). The remaining unfenced pre-wrap window is **alkvault's API shape to close** — the ask is filed in alkvault's own tracker (downstream/family-space concern; alkforge and every secrets-bearing crate benefits, not just alkssh). alkssh does not carry it, does not gate on it, and ADR-005 records only the adapter obligation. This tracker entry stays closed; when alkvault ships a `Zeroizing`-out API, ADR-005's reference here updates as a one-line doc touch, nothing else. +- **Cross-references**: ADR-005 §3, OQ-05 ## Theme D — session-request mapping details