docs(secrets): interactive-console quickstart + discoverability sweep

- new task-first quickstart (deployment seeding + KEK-lockout walkthroughs)
- runbook: document the sixth ReferenceStatus (PresentUnverified) + quickstart link
- README + shared-contract + umbrella CLAUDE.md secrets row updated for 0.3.0 console
- CLI usage text now mentions the interactive console (was undiscoverable from --help)
This commit is contained in:
Joseph Doherty
2026-07-19 14:55:53 -04:00
parent 0139c90f89
commit baea6cc2e0
6 changed files with 206 additions and 5 deletions
@@ -8,6 +8,9 @@
[`kek-rotation.md`](kek-rotation.md) (the `rewrap-all` primitive the KEK-doctor remedy uses
under the hood) and [`clustered-secrets.md`](clustered-secrets.md) (replication topologies the
console does not manage).
**For a task-first walkthrough** of the two headline jobs (pre-startup seeding of a new
deployment; a 2am KEK/decrypt lockout) with illustrative menu transcripts, start with the
[quickstart](../interactive-console-quickstart.md); this document is the full reference.
---
@@ -115,7 +118,8 @@ whenever an app fails to start because a `${secret:NAME}` reference can't resolv
`SecretReferenceExpander` uses at app startup — so what you see here is exactly what the app
would try to resolve, including config keys documented via a `"_comment": "...${secret:x}..."`
convention, which are skipped the same way the expander skips them.
2. Each distinct referenced name is looked up against the store and classified:
2. Each distinct referenced name is looked up against the store and classified into one of the
six `ReferenceStatus` values:
- **Ok** — exists and decrypts under the session KEK. Nothing to do.
- **Missing** — no row at all. A fail-closed expansion would throw at app startup.
- **Tombstoned** — a soft-deleted row. Also unresolvable to the app.
@@ -124,6 +128,11 @@ whenever an app fails to start because a `${secret:NAME}` reference can't resolv
- **InvalidName** — the token text isn't a legal secret name (illegal characters, an
unfilled placeholder like `REPLACE_ME`). Can't be looked up or seeded — fix the token in
the config file itself.
- **PresentUnverified** — the row exists but the session is degraded (no KEK), so presence
is all that could be established — decryptability wasn't checked. You will **not** see
this status in the seed flow, which requires a KEK (the shell upgrades a degraded session
before dispatch); it only surfaces if the auditor is run without a key. In the seed flow
an existing row therefore always resolves to Ok or Undecryptable, never PresentUnverified.
3. A color-coded table renders every finding with the config key paths that reference it (so
you know exactly which setting(s) are affected), then the flow walks each seedable gap
(Missing / Tombstoned / Undecryptable) in turn, asking to seed it now. Accepting prompts for