F6: P5 was measuring the wrong host's filesystem and reporting it as fact
This is what made the Stage-5 entry gate unreadable, and it is worse than the "could not look
is never nothing there" class this repo already knows: it looked in the wrong place and
asserted the answer.

ROOT CAUSE. vm-secret-locations declares jumphost paths with ssh-target `local`, implemented
as "the filesystem of whatever machine this run is on". Run on the headend, every
`jumphost ... ~/vr1-dcN-creds/*` location was probed against voffice1's OWN ~/vr1-dcN-creds/
directories -- the SEC-022 headend shadow stores -- so the jumphost's expected credential set
was compared against a different host's directories and the mismatches became findings.

Measured: 34 findings on voffice1 against the same tree's true 7 on vcloud, 26 pure artefact.
Combined with P3/P4 being runnable only on the headend (vcloud has no juju/maas/openstack), no
single host produced a correct full preflight verdict.

FIX. New declared binding creds-manifests/host-identity (role -> hostname), exhaustive by
construction exactly like stages-reached: a role using `local` that is unbound FAILS, and a
bound role using no `local` target is a stale declaration. Neither is defaulted -- both
defaults are wrong in a dangerous direction. On a hostname mismatch the location is NOT PROBED
and its scope joins the existing NOT-JUDGED set, so absence is never asserted over it.

DEMONSTRATED BOTH WAYS, plus all four refusal paths:
  declared host       -> unchanged 91 rows / 7 findings (no regression)
  simulated headend   -> 14 locations NOT PROBED instead of manufacturing findings
  absent binding / unbound role / stale declaration / malformed line -> each REFUSES
Harness 65/65 (was 60), cases T60-T64. T60 exists specifically so T61 proves something: a gate
that never probes would otherwise always "pass".

THE HARNESS HAD THE SAME BUG AS THE THING IT TESTS -- its fixtures fell through to the real
repo's binding file, the identical trap that once left V2 with zero cases. run() now derives a
fixture-scoped binding the way it already derives stages.

Also fixed, a coupling the F1 rename created: vm-secret-locations still pointed at the
pre-rename ~/octavia-pki/* and overlays/octavia-pki.yaml, which now match nothing. The Octavia
locations are declared PER DC, deliberately not as one shared `-` scope -- both DCs' workspaces
hold identically-named basenames, and a shared scope would collapse them into one namespace
where a missing dc1 file is indistinguishable from a present dc0 one.

repo-lint 0 fail.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
1 parent 3b91c6a commit b6429f987de9a7c3b415bac5ae44497adb3a978b
@JANeumatrix JANeumatrix authored 7 hours ago
Showing 5 changed files
View
creds-manifests/host-identity 0 → 100644
View
creds-manifests/vm-secret-locations
View
docs/CURRENT-STATE.md
View
scripts/creds-matrix.py
View
tests/creds-matrix/run-tests.sh