docs(pilot): RUNBOOK GL-1 executed — agent 0.74.0 + golden 0.103.0 published
Agent = the live felhom-pve bytes (sha 1ec3f588..76af05, round-trip verified); golden baked clean-room in the drill VM (build-golden v2.0.0, controller 0.103.0, all integrity gates green, sha 8481e8a1..6026e) and published 201. Both anon-fetch-verified (Gate 3c: packages world-readable -> G3 read-only token rotation cannot break fetches; installer-side empty-token die is the real precondition). Drill VM restored to virgin. OPERATOR NEXT: Day-0 manifest bump to the four recorded values. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -2,92 +2,59 @@
|
||||
|
||||
> **Overwrite** this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in [hub/CHANGELOG.md](hub/CHANGELOG.md); the scripts history lives in [scripts/CHANGELOG.md](scripts/CHANGELOG.md).
|
||||
|
||||
## TASK GL-2 — BYO-host install profile (`--mode appliance|byo`) — host-install v1.10.0 (2026-07-07)
|
||||
## RUNBOOK GL-1 — publish agent 0.74.0 + bake/publish golden 0.103.0 (2026-07-07)
|
||||
|
||||
**Baseline confirmed:** felhom.eu @ `1a1e42ad`, `SCRIPT_VERSION="1.9.1"` → **`1.10.0`**.
|
||||
Implementation + static/dry validation only per spec §0 — **the live provision/uninstall runs are
|
||||
GL-6 (operator-supervised)**; the §13 STOP was honored (zero non-dry installer invocations anywhere).
|
||||
Full execution record with per-gate evidence:
|
||||
`documentation/pilot/RUNBOOK-GL1-publish-2026-07-07.md`. Docs-only commit; no code changed, no
|
||||
production host mutated (felhom-pve read-only; all root work inside the disposable drill VM).
|
||||
|
||||
### Files created / modified (single repo, `main`)
|
||||
### The four operator values (hub Day-0 manifest — Configs → Day-0 artifacts)
|
||||
|
||||
- `scripts/felhom-host-install.sh` — v1.10.0 (Parts 1–3; see scripts/CHANGELOG.md for the feature list)
|
||||
- `scripts/hostinstall-mode-harness.sh` — NEW (Part 4)
|
||||
- `documentation/runbooks/day0-install.md` — `--mode` in every command, new §C.5 (byo command +
|
||||
trust-model paragraph + preflight-only), §C.6 (pre-v1.10.0 resume note), 4 new troubleshooting rows
|
||||
- `scripts/CHANGELOG.md`, `REUSE.md` (install-profile-gate pattern row), `CONTEXT.md`, this file
|
||||
```
|
||||
AGENT_VERSION=0.74.0
|
||||
AGENT_SHA256=1ec3f58842edce1e9e32d022eaef15b7ff599c658c7a36bfe7833c708076af05
|
||||
GOLDEN_VERSION=0.103.0
|
||||
GOLDEN_SHA256=8481e8a14e2aa0abe3831cc40e5aea4c32f2017e7561c15dca8a674df6a6026e
|
||||
```
|
||||
|
||||
### Spec deviations / judgment calls (each verified against the real code)
|
||||
### Gate outcomes (all PASS)
|
||||
|
||||
1. **`--mode` collision:** v1.9.1 already used `--mode provision|dr`. Resolved: `appliance|byo` are
|
||||
the only install values, `provision` retired with a specific die, the `dr` stub dispatch kept
|
||||
verbatim (the documented 10D seam).
|
||||
2. **Spec §2 was wrong about the lan-resolver**: the config write did `setdefault('lan_resolver',
|
||||
{"enable": True})` — default-ON, so the spec's byo assert would have died on every byo install.
|
||||
Fixed by flipping the byo DEFAULT to off (appliance untouched); the assert still dies if a
|
||||
`--preserve-from` config carries true, which is the intended refusal.
|
||||
3. The byo skip line reads `break-glass (step 4b) SKIPPED (byo: …)` — NOT the spec's literal
|
||||
`"4b/8 …"` text, because Scenario B / harness H-B forbid the string `4b/8` in the byo transcript
|
||||
(an internal spec contradiction; the greppable invariant won).
|
||||
4. `--preflight-only` skips the byo typed ack (prints the disclosure, logs the skip) — nothing will
|
||||
be mutated, and a mandatory prompt would break its re-runnable/scripted purpose.
|
||||
5. `documentation/pilot/GO-LIVE-PACKAGE.md` is not in the repo and no operator copy arrived with the
|
||||
task — the G2/G4/G5 → "implemented, awaiting GL-6" flip is recorded in CONTEXT.md; add the doc
|
||||
when supplied.
|
||||
- **0a–0d**: baselines exact (`ced60ddf` / `59eb3bea` / `02d63ed0`; agent 0.63.0 + golden 0.98.3
|
||||
the last published, targets 404); drill VM + `virgin` snapshot intact; controller image
|
||||
0.103.0 resolvable; headroom ample.
|
||||
- **1a/1b**: felhom-pve's RUNNING binary (`readlink /proc/…/exe`, no pending A/B marker) is
|
||||
0.74.0; those exact bytes (hash-stable across both copy hops) published via
|
||||
`publish-agent.sh` from `main`@`ced60ddf` — PUT 201, round-trip GET sha match.
|
||||
- **2a/2b**: clean-room bake on the virgin-restored drill VM (build-golden.sh v2.0.0):
|
||||
overlay2 + both split-volumes as separate mounts, rootfs+mp0+mp1 ALL included in the vzdump
|
||||
(no exclusions, no FATAL), archive 583MB, publish HTTP 201; transcript token-leak grep = 0.
|
||||
Deviations: debian-13 template pveam-downloaded inside (virgin never has it, checksum
|
||||
verified); bake launched via `systemd-run` (bare nohup didn't survive ssh session close).
|
||||
- **3a/3b**: both artifacts fetched **ANONYMOUSLY** and hashed to exactly the published sha
|
||||
(golden 611 696 321 bytes, streamed+hashed+deleted); off-LAN HEAD 200 from the CC machine too.
|
||||
|
||||
### Harness results
|
||||
### Gate 3c finding (feeds G3) — read-credential sufficiency
|
||||
|
||||
Static tier (Windows Git Bash AND felhom-pve, identical): **bash -n, C1/C1b/C1c, C2a/C2b, C3/C3b/C3c,
|
||||
C4, C6-static, INV-1 (one appliance-gated break-glass call site), INV-2 (chpasswd unreachable outside
|
||||
step_break_glass), INV-3 (--mode in usage) — all PASS.**
|
||||
The specified reviewer read-only token (`8417…4140`) was not locatable by CC anywhere in reach —
|
||||
the gates ran with **no credential at all and passed**: the generic packages are anonymously
|
||||
world-readable. Therefore rotating the customer `git.token` to read-only **cannot break** the
|
||||
artifact fetch path (G3 unblocked from this side). Nuance: `resolve_git_creds` in host-install
|
||||
**dies on an empty token** even though Gitea would serve the fetch anonymously — the requirement
|
||||
is script-side; customer configs still need a (read-scoped) token until a small installer
|
||||
follow-up makes it optional. This also reframes GL-2's finding that demo-felhom's git credentials
|
||||
are EMPTY: the fetch would work, the installer's precondition is what fails.
|
||||
|
||||
PVE tier (felhom-pve, read-only, temp `FELHOM_INSTALL_STATE_DIR`): **C5 PASS live** (bogus
|
||||
`--acl-storages` entry → die naming it, pre-hub, pre-passphrase). H-A/H-B dry transcripts ran with
|
||||
the out-of-band demo passphrase (file→file, never printed) but **die at step 5 with rc=1 — a
|
||||
customer-data blocker, not a code bug**: demo-felhom's controller.yaml serves EMPTY
|
||||
`git.username`/`git.token`. The transcript span through the break-glass gate was validated manually
|
||||
instead: appliance transcript contains `4b/8`; byo transcript contains **no**
|
||||
`4b/8`/`chpasswd`/`recovery-credential` and **does** contain the disclosure block, the dry ack line,
|
||||
`acl storages all present`, and the host-DNS `:53` line (it correctly showed the live dnsmasq).
|
||||
`--preflight-only` proven live both ways: PASS verdict + rc 0 + **zero state entries**; bogus-storage
|
||||
run → specific die + `PRE-FLIGHT FAIL (exit 1)` verdict.
|
||||
### Drill-VM end state
|
||||
|
||||
**Red-proofs (run → fail → revert, against mutated scratch copies — the repo file was never mutated):**
|
||||
- RP-1 un-gated the break-glass call site → INV-1 FAIL (13/16). Reverted (scratch deleted).
|
||||
- RP-2 dropped the byo caps requirement → C1/C1b/C1c FAIL (11/16). Reverted.
|
||||
- RP-3 dropped the resume mode-mismatch check → C4 FAIL (13/16). Reverted.
|
||||
Guest 9100 destroyed (`--purge`), in-VM cred file shredded, VM powered off, qcow2 **restored to
|
||||
`virgin`** (verified) — environment exactly as found. Evidence kept: `~/drill/bake-0.103.0.log`
|
||||
on the build server.
|
||||
|
||||
### §9 rule 9 — the `_state_mark` dry-run finding
|
||||
### Follow-ups
|
||||
|
||||
Verified in code: **both** `_state_mark` and `_state_put` begin with `$DRY_RUN && return 0` — dry
|
||||
runs write nothing. Belt on top: the harness points `FELHOM_INSTALL_STATE_DIR` (new, harness-only
|
||||
env override — none existed) at a throwaway temp dir for EVERY invocation, so even non-dry refusal
|
||||
cases can never touch a live `state.json`. Confirmed live: felhom-pve's real state.json was
|
||||
byte-untouched (it only ever saw the temp dir) and the preflight-only runs left 0 entries.
|
||||
|
||||
### Shellcheck
|
||||
|
||||
v0.10.0 (build server 180 + felhom-pve; not installed locally). **Clean at `--severity=warning`**
|
||||
on both scripts. Full-severity: 2 pre-existing SC2015 *info* notes on untouched v1.9.1 lines
|
||||
(A&&B||C in step_verify) — triaged, not refactored (spec rule 2); 1 new SC2154 false positive on
|
||||
the EXIT trap (assignment inside the trap string) — targeted disable comment.
|
||||
|
||||
### NOT yet live-validated — awaiting supervised GL-6
|
||||
|
||||
- The full appliance AND byo installs end-to-end (rc=0 transcripts blocked today by the
|
||||
demo-felhom git-creds gap below).
|
||||
- The uninstall → re-provision drill under both modes.
|
||||
- C7: the verify pool/ACL asserts firing on real drift (needs a deliberately-broken live box).
|
||||
- The byo typed-hostname ack answered interactively (only its dry/preflight-only branches ran).
|
||||
|
||||
### Observations (documented, not acted on)
|
||||
|
||||
- **demo-felhom has EMPTY `git.username`/`git.token`** in its served controller.yaml — any step-5
|
||||
(re)install for that customer dies until real Gitea read creds are set (operator; ties into the
|
||||
standing "scope down + rotate the package-WRITE git token" security follow-up).
|
||||
- felhom-pve's live install predates `_state_put` — its state.json has only `completed` (no
|
||||
`customer_id`/`provisioned_vmid`/`mode`); a future `--uninstall` there needs an explicit `--vmid`,
|
||||
and §C.6 of the runbook covers the missing-mode resume.
|
||||
- A `--resume` that skips preflight never records `mode` into an old state file (it only writes
|
||||
during a full preflight) — harmless (C4 only fires when a mode IS recorded), noted for GL-6.
|
||||
- The live host-DNS line on felhom-pve shows the agent's own dnsmasq (lan_resolver is ON there —
|
||||
correct for an appliance; it is exactly what byo now refuses).
|
||||
1. **OPERATOR — hub Day-0 manifest bump** to the four values above (until then fresh installs
|
||||
land agent 0.63.0 + golden 0.98.3).
|
||||
2. **Operator-key pin** (out of GL-1 scope): day-0 ships no operator pubkey → self-update dormant
|
||||
on fresh boxes; pin the real key + a small host-install follow-up (candidate: fold into GL-4).
|
||||
3. **G3 rotation** unblocked per Gate 3c; also fixes demo-felhom's empty git credentials.
|
||||
4. **GL-6** consumes the bumped manifest end-to-end (deliberately not run here).
|
||||
|
||||
Reference in New Issue
Block a user