docs(10): correct D-03's gate signal — key_exists is true on every booted node
D-03 named NodeIdentity::key_exists as one of the two gate signals. Server::new (server.rs:63-72) calls load_or_create on both branches, and load_or_create (identity.rs:48-51) generates and writes a random temporary node key when none exists — so key_exists is true on any node that has booted once, onboarded or not. A gate keyed on it would refuse seed.generate on a fresh node and brick onboarding fleet-wide. The flaw came from the audit's own suggested remediation (§214-221) and was repeated in the planning brief; the planner caught it against the code. D-03's intent (two signals, OR-ed, fail safe on drift) is unchanged. Corrected signal set: is_setup() / is_onboarding_complete() / seed_exists(), pinned by a test rather than a comment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
04c4d3460c
commit
2781bd5a6c
@@ -40,11 +40,26 @@ derivation paths, word counts, or the at-rest encryption envelope.
|
||||
from `UNAUTHENTICATED_METHODS` — so this path does not need to be built, and it is not itself
|
||||
a bypass.
|
||||
|
||||
- **D-03:** The gate **refuses if *either* signal says onboarded** — the on-disk key file
|
||||
(`NodeIdentity::key_exists`, `identity.rs:117`) **or** the onboarding flag
|
||||
(`AuthManager::is_onboarding_complete`, `auth.rs:182`). Fails safe when the two disagree,
|
||||
which is a real state: `auth.rs:196-207` already carries auto-heal logic for exactly that
|
||||
drift. Do not pick one signal and trust it alone.
|
||||
- **D-03:** The gate **refuses if *either* signal says onboarded** — never one signal trusted
|
||||
alone. Fails safe when signals disagree, which is a real state: `auth.rs:196-207` already
|
||||
carries auto-heal logic for exactly that drift.
|
||||
|
||||
- **D-03a (mechanism correction, 2026-08-01 — intent of D-03 unchanged):** D-03 originally named
|
||||
`NodeIdentity::key_exists` (`identity.rs:117`) as one of the two signals. **That signal is
|
||||
unusable and would have bricked onboarding on every fresh node.** `Server::new`
|
||||
(`server.rs:63-72`) calls `NodeIdentity::load_or_create` on *both* branches of its
|
||||
fresh-vs-existing check, and `load_or_create` (`identity.rs:48-51`) generates and writes a
|
||||
random temporary node key when none exists. So `key_exists` is `true` on every node that has
|
||||
booted even once, onboarded or not — a gate keyed on it refuses `seed.generate` on a node that
|
||||
has never been onboarded.
|
||||
|
||||
This flaw was inherited from the audit's own suggested remediation
|
||||
(`ENTROPY-SEED-AUDIT-2026-07-31.md:214-221`) and repeated in the planning brief; the planner
|
||||
caught it against the code. The corrected signal set is `is_setup()` /
|
||||
`is_onboarding_complete()` / `seed_exists()` — all false on a fresh node and during the seed
|
||||
steps, all true afterwards. `key_exists` and `fips_key_exists` are rejected with recorded
|
||||
verdicts, and the correction is pinned by a test
|
||||
(`allows_on_fresh_temp_dir_even_though_node_key_exists`), not a comment.
|
||||
|
||||
- **D-04:** 10-01 covers **every method in `UNAUTHENTICATED_METHODS` that can mutate identity
|
||||
or credentials**, behind the same gate and one shared test suite — not just the two endpoints
|
||||
|
||||
Reference in New Issue
Block a user