# Queued findings + unlogged advice -- end-of-session sweep, 2026-07-26
#
# WHY THIS FILE EXISTS. The 2026-07-26 session ran long and produced two classes of
# content that lived only in the session transcript: committee findings that were
# ACKNOWLEDGED but deliberately NOT acted on, and a secrets-storage recommendation given
# verbally on request. A transcript is not a repo surface. This is the durable copy.
#
# NOTHING HERE IS RULED OR BUILT. These are logged findings and unruled advice (hard rule
# 1: findings are logged, never executed mid-step). Status lives in CURRENT-STATE only.
================================================================================
PART A -- ADVICE GIVEN VERBALLY THAT IS **NOT** ALREADY REPO-CARRIED
================================================================================
IMPORTANT FRAMING, checked before writing this: MOST of the secrets-storage
recommendation given in session was ALREADY in the repo and is NOT new.
- OpenBao / BUSL relicensing / the fork question .... docs/D-068-vault-1.8-vs-1.16-analysis.md
- Vault auto-unseal, root-Vault topology ............ same file + D-069 discussion
- `scripts/creds-mint.sh` (atomic mint->store->register, with modes, refusal-to-overwrite,
and a creds-audit gate) ........................... docs/design-decisions.md D-137, item 2(a)
A future session should read those FIRST and treat the items below as the delta, not as a
new proposal. Re-proposing what is already ruled is this project's measured failure mode.
--- A1. Tang / Clevis (NBDE) as the no-HSM unseal mechanism [NOT in repo: 0 hits]
No HSM or KMS is available (operator-confirmed 2026-07-26), which removes the standard
Vault auto-unseal path. Network-bound disk encryption (Tang servers + Clevis binding) is
the usual on-prem substitute: unseal material is recoverable ONLY while the host can reach
N Tang servers on the management network, so a disk that leaves the datacenter is inert.
It maps onto the existing per-DC isolation posture (SEC-012/-016 per-DC power keys) and
costs no hardware. Suggested shape: DC Vaults transit-unseal from an Office1 unsealer; the
unsealer's own material Tang-bound (plus TPM measurement if Roosevelt hardware has TPM 2.0
-- UNKNOWN, and it decides Tang-alone vs Tang+TPM); Shamir shares exist only as physical
break-glass, split across sites, never on a jumphost.
--- A2. MAAS 3.7 Vault integration is AVAILABLE AND DISABLED [MEASURED 2026-07-26]
ssh voffice1 'sudo maas config-vault status' -> status: disabled
unconfigured_regions: [voffice1]
MAAS 3.3+ can store its secrets in Vault instead of its database -- including power
credentials, the category behind SEC-012, SEC-016 and SEC-021. This is a native, supported,
in-stack capability that is simply switched off.
** CIRCULAR DEPENDENCY, design around it before enabling at Roosevelt: MAAS provisions
the metal, Vault runs on that metal, and MAAS-with-Vault will not start without Vault.
On bare metal that is a bootstrap-ordering problem, not a config step. The usual answer
is a management-site Vault that is NOT MAAS-provisioned. Enabling it in VR1 FIRST -- where
the substrate is virtual and recoverable -- is what a rehearsal is for.
--- A3. Vault SSH secrets engine (SSH CA) [NOT in repo: 0 hits]
Six of the twelve no-mint credentials in the research capture are ed25519 keypairs, and
every per-DC power key, edge key and service key is a static file that lives forever. An
SSH CA issuing short-lived certificates collapses that entire category: no file to
consolidate, no key to rotate, no matrix row that can go stale. Highest structural leverage
of anything discussed, and it depends on the fork decision (A-framing) landing first.
--- A4. Sequencing advice, and one recommendation to NOT do something
Recommended order: (1) resolve the Vault-vs-OpenBao fork question; (2) build the D-137
`creds-mint.sh` already specified in item 2(a) -- BEFORE Stage 5, because Stage 5 is the
largest credential-minting event in the project (per-DC MAAS keys, the Juju cloud
credential, bootstrap controller/CA/agent secrets, and behind them Vault init material,
the 8 Octavia PKI artifacts and admin-openrc); (3) MAAS->Vault rehearsed in VR1; (4) SSH CA;
(5) Juju + Barbican secret backends.
RECOMMENDED AGAINST: a sops/age encryption-at-rest stopgap. It was raised and then withdrawn
in the same session -- if the Vault path is real it is throwaway work, and tooling churn
that presents as progress is this project's own recorded failure mode (GA-F06).
================================================================================
PART B -- COMMITTEE FINDINGS ACKNOWLEDGED BUT **NOT** ACTED ON
================================================================================
From the six-lens audit, 2026-07-26. Each was reproduced or reasoned by its lens and left
deliberately. Ranked by consequence.
--- B1. `mint-ref` line pins rot SILENTLY [lens 6]
`s4_mint_ref` checks only that the target file exists and that the line number is <= EOF.
There is NO content assertion. Edit anything above a cited line and the mint-ref now points
at unrelated code while S4 still reports `[ok] every script:/runbook: reference resolves`.
30+ rows carry line pins into actively-edited runbooks and scripts. AT ROOSEVELT the
runbooks are rewritten for bare metal, so every line-pinned mint-ref becomes
wrong-but-passing simultaneously. Suggested fix: store an anchor token (step id, function
name, short literal) alongside or instead of the line, and assert it appears at/near the
cited line.
--- B2. Ruling-5 remediation and ruling-5 EVASION are indistinguishable to the checker [lens 4]
S6 groups by `id`. The sanctioned fix for the `maas-region-admin` conflation (migrate the 19
`maas admin` call sites to a service identity) and the evasion (rename one row's id to
`maas-region-admin-svc`) BOTH turn the check green. The notes warn humans not to do the
latter; nothing mechanical distinguishes them.
--- B3. No non-emptiness check in tier 2 [lens 2]
`creds-audit.sh:59` asserts `[ -s "$path" ]`; the matrix checker has no equivalent. A
zero-byte credential file reads as PRESENT and correctly-moded.
--- B4. `sec-ref` is never validated [lens 2]
Contrast S4 (mint-ref) and S7 (notes-ref), both of which resolve their references. A wrong
SEC pointer is exactly the class caught by hand FOUR times this session (SEC-015 once,
then both `juju-maas-user` rows, plus the tfstate row). A validator must parse the ledger's
TABLE form (`| SEC-006 |`), not `## SEC-` headings.
--- B5. No "source-of-record implies a consolidated copy" invariant [lens 2]
`netbox-secret-key` and `netbox-admin` are VM-resident with NO consolidated copy at all --
the exact founding SEC-009 shape ("a VM-minted secret has no forcing function to reach the
folder") -- and nothing flags it.
--- B6. `cardinality` is largely inert, with a one-token bypass [lenses 2 + 6]
Of 81 rows the field affects only S1's enum validation and S5's `per-DC` filter;
`singleton`, `per-site`, `per-node` and `per-tenant` have no semantic effect, and `per-node`
is used by no row. Relabelling a row `per-DC` -> `singleton` removes it from S5 entirely --
the cheapest way to silence the standing SEC-021 asymmetry findings, and nothing guards it.
The plan claims cardinality is "REQUIRED for Roosevelt transfer -- without it the matrix
cannot express '9 nodes'"; as built it expresses no such thing. Either make it load-bearing
(an `instances` field, or template expansion generating the per-DC/per-node/per-tenant row
set) or demote the claim. THIS IS A DESIGN QUESTION AND NEEDS AN OPERATOR RULING.
--- B7. S5 is structurally BINARY [lens 6]
`dcs = ["vr1-dc0", "vr1-dc1"]`, `DC_TOKEN_RE = dc[01]`, `SITE_KEY_RE` an enum of `vr1-*`
literals, and a pairwise set-difference. A third DC needs four source edits and S5 does not
generalise to N sites. Suggested fix: derive the site set from the matrix, validate
region-qualification by SHAPE not enum, and restructure S5 to group-by-normalised-shape
across N sites.
--- B8. T22's metadata-only guard is narrower than it reads [lens 1]
The wordlist omits `open()` -- the checker's actual read mechanism -- and `dd`, `sed`, `awk`,
`base64`. It also greps comments and docstrings, so prose alone can false-RED it (measured
twice this session: the word "more" tripped it). T51 partially covers the transfer half.
--- B9. `--dc` narrows only S5 [lens 1]
Its help text says it narrows the per-DC checks; in fact S1-S4, S6, S7 and tier 2 still
process all rows, so the flag WEAKENS a run rather than scoping it. Either make it narrow
the run or remove it.
--- B10. Low severity, recorded for completeness [lens 1]
Dead code at the `observed`-membership guard (unreachable since `observed` is pre-populated);
`s3_render_drift`'s unused `notes` parameter; `os.path.join(repo, path)` returns an absolute
mint-ref path unchanged, escaping the repo bound; S7's orphan scan only considers keys
prefixed `n-`.
================================================================================
PART C -- ALSO DEFERRED BY RULING (recorded so they are not mistaken for oversights)
================================================================================
- SEC-024 RETENTION: whether the two `terraform.tfstate.pre-*` state-surgery snapshots
should exist at all. Operator-deferred to stage close 2026-07-26. Both gates (G6, G16)
are CLOSED and the outer plan has converged to zero diff repeatedly since, but deletion
is irreversible with no other copy of that state.
- SEC-024 umask CAUSE: not investigated (outside the ruled scope). A future `tofu apply`
may write 0664 again; the P5 gate will catch it.
- `--render` source-field derivation from `vm-secret-locations`: not wired; two fields are
explicitly skipped as PENDING rather than silently matched.
- Manifests are not yet REPLACED by rendered output. Ruling 2 makes them generated; doing
the flip changes what `creds-audit` demands at three sites, so it stays operator-gated.