F1+F4 BUILT: the Octavia PKI generator is per-DC end to end, and the gitignore glob follows it
F1. The D-109 amendment rules per-DC independent Octavia CAs. R7 parameterised the CA
subject and the VIP gate but left every PATH fixed, so generating a second DC's PKI
overwrote the first DC's issuing-CA key, controller-CA key and both passphrases, and left
one fixed-name overlay carrying the wrong DC's CA for any later redeploy to pick up.

Step 1.0-GEN is now per-DC end to end: DC/DC_LABEL/REPO/VIP_OVERLAY/OCTAVIA_PKI_OVERLAY
export once in a rewritten 1.0-GEN.0; WORKDIR="$HOME/octavia-pki/$DC"; every WORKDIR
re-derivation and the overlay write carry ${DC:?} so an unset DC refuses rather than
silently reusing the old shared path.

Two gates added that did not exist:
- REFUSE-IF-PRESENT: aborts if this DC already has PKI material. Regeneration invalidates
  every amphora already issued against that CA, so it must be a deliberate act rather than
  the default outcome of re-running a step.
- F4 gate: `git check-ignore -q "$OUT"` immediately before writing key material, asserting
  the ACTUAL ignore decision for that path rather than a pattern someone has to remember.

F4. .gitignore:40 pinned the single exact path overlays/octavia-pki.yaml, so the per-DC
rename would have left a file holding CA key blobs plus a plaintext issuing-CA passphrase
UNIGNORED and committable, in a repo SEC-004 records as PUBLIC. Widened to
overlays/*octavia-pki.yaml and proven BOTH ways, not assumed: all per-DC and legacy names
read IGNORED, and a negative control (overlays/vr1-dc0-vips.yaml) reads NOT ignored, so the
glob is not swallowing tracked overlays.

Also fixed, same dc0-freeze: Step 1.3's VIP guard was a hand-rolled grep triple anchored on
the literal 10\.12\.4\. -- it hard-aborted on dc1, counted IPv4 only so R2's ruled v6 legs
were guarded by nothing (chain-audit finding 22), and its prose said 11/11/0 while its code
demanded 13. It now calls provider-bundle-check.py on the merged per-DC input, which already
encodes the bands, the count and the 2026-07-28 dual-family arity coupling.

The 2026-06-03 as-built line keeps the old command verbatim: it is history, not instruction.

repo-lint 0 fail / 615 files.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
1 parent ab4c842 commit e80a32ef4a0f893b8e5b1a8bb1212be33d1f3628
@JANeumatrix JANeumatrix authored 12 hours ago
Showing 3 changed files
View
.gitignore
View
docs/CURRENT-STATE.md
View
runbooks/phase-01-bundle-deploy.md