forked from heavy-duty/rig
fix(bootstrap): gate the host-set-up claim on 'box doctor', not on PATH
All three reviewers, same substance: 'command -v box' proves the CLI landed, not that setup-host took effect — and the success line claimed both. The claim is now split to match its proofs: PATH proves the install; 'box doctor' (box's own effective-state verdict — the daemon stays box's domain) gates "host set up". A failed doctor WARNS with the verdict verb and the manual path, and claims nothing it cannot prove. Also: the coolify marker guard matched 'role=control-plane ' by its trailing space, coupling it to the marker's field formatting — a bare 'role=control-plane' line now reads the same (claude-bot's nit), with a fixture proving it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
900697bdc2
commit
cee7d4575e
4 changed files with 34 additions and 15 deletions
|
|
@ -537,16 +537,21 @@ if [ "$HOST" = "yes" ]; then
|
|||
# only adding a group, asking for a re-login. That is the sshd first-wins
|
||||
# bug's exact shape — asserting what was REQUESTED (here: the installer's
|
||||
# claimed success) instead of what actually TOOK. The check stays
|
||||
# deliberately LIGHT: box on PATH is the one artifact rig asked the
|
||||
# installer for. Anything deeper — the incus daemon, the pool, the
|
||||
# network — is box's domain, and rig never interrogates Incus (the same
|
||||
# delegation law as the install itself: box owns the daemon); box ships
|
||||
# its own effective-state verdict as `box doctor`, so the success line
|
||||
# hands the operator that verb instead of half-reimplementing it here.
|
||||
# And a failed check WARNS, never dies: box is the host EXTRA, and the
|
||||
# OS+tailnet core above is already done and asserted.
|
||||
# Two proofs, one claim each. `command -v box` proves the CLI landed
|
||||
# (box's root install symlinks into /usr/local/bin, already on this
|
||||
# shell's PATH — no login shell needed). "Host set up" is a separate
|
||||
# claim and gets box's OWN effective-state verdict, `box doctor` —
|
||||
# the daemon, the pool, the network stay box's domain (the same
|
||||
# delegation law as the install itself: box owns the daemon), rig
|
||||
# just refuses to claim what that verdict does not answer. Both
|
||||
# failures WARN, never die: box is the host EXTRA, and the OS+tailnet
|
||||
# core above is already done and asserted.
|
||||
if command -v box >/dev/null 2>&1; then
|
||||
log "box installed and host set up — mint guest boxes with 'box new'; 'box doctor' verifies the host end to end"
|
||||
if box doctor >/dev/null 2>&1; then
|
||||
log "box installed and host set up — 'box doctor' passed; mint guest boxes with 'box new'"
|
||||
else
|
||||
warn "box is on PATH but 'box doctor' does not pass — the CLI landed, the host stack is unproven. Run 'box doctor' for the verdict, then 'box setup-host' (or finish by hand: ${BOX_MANUAL})"
|
||||
fi
|
||||
else
|
||||
warn "box's installer reported success but no 'box' is on PATH — the install did not take effect. Finish the host by hand: ${BOX_MANUAL}"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ done
|
|||
# prove it non-root (RIG_ROLE_MARKER points it at fixtures, repo precedent).
|
||||
MARKER_LINE="$(read_role_marker "${RIG_ROLE_MARKER:-/etc/rig/role}")"
|
||||
case "$MARKER_LINE" in
|
||||
""|"role=control-plane "*) ;;
|
||||
""|"role=control-plane"|"role=control-plane "*) ;;
|
||||
*) warn "this box's role marker says '${MARKER_LINE}' — not a control-plane box. The nightly dump targets Coolify's own database, which lives on role control-plane; if this is the wrong box, stop here and re-check your SSH session." ;;
|
||||
esac
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ fi
|
|||
# (repo precedent: users-apply, users-close-root).
|
||||
MARKER_LINE="$(read_role_marker "${RIG_ROLE_MARKER:-/etc/rig/role}")"
|
||||
case "$MARKER_LINE" in
|
||||
""|"role=control-plane "*) ;;
|
||||
""|"role=control-plane"|"role=control-plane "*) ;;
|
||||
*) warn "this box's role marker says '${MARKER_LINE}' — not a control-plane box. Coolify belongs on role control-plane; if this is the wrong box, stop here and re-check your SSH session. Repurposing it on purpose? Re-run 'rig bootstrap control-plane' first so the marker tells the truth." ;;
|
||||
esac
|
||||
|
||||
|
|
|
|||
22
test/cli.sh
22
test/cli.sh
|
|
@ -153,10 +153,19 @@ check "bootstrap: a hollow box-install success warns, never dies" 0 "" \
|
|||
box_check_at="$(grep -nE '^[[:space:]]*if command -v box' "$ROOT/commands/bootstrap.sh" | head -n1 | cut -d: -f1)"
|
||||
check "bootstrap: the effective check follows the installer run" \
|
||||
0 "" test "${box_install_at:-999999}" -lt "${box_check_at:-0}"
|
||||
# rig's delegation law caps the check's depth: rig never interrogates Incus, so
|
||||
# the deeper verdict is handed to box's own verb rather than reimplemented.
|
||||
check "bootstrap: the deeper host verification is delegated to box doctor" 0 "" \
|
||||
grep -q "box doctor" "$ROOT/commands/bootstrap.sh"
|
||||
# rig's delegation law caps the check's depth: rig never interrogates Incus —
|
||||
# the host verdict is box's own verb, and the "host set up" CLAIM is gated on
|
||||
# it. Two asserts: the gate exists as a call (not just prose naming the verb),
|
||||
# and the claim line sits inside/after it (line order, fail-closed defaults —
|
||||
# a claim that outruns its proof is exactly the overclaim this closes).
|
||||
check "bootstrap: the host-set-up claim is gated on box doctor" 0 "" \
|
||||
grep -qE '^[[:space:]]*if box doctor' "$ROOT/commands/bootstrap.sh"
|
||||
doctor_at="$(grep -nE '^[[:space:]]*if box doctor' "$ROOT/commands/bootstrap.sh" | head -n1 | cut -d: -f1)"
|
||||
claim_at="$(grep -n 'box installed and host set up' "$ROOT/commands/bootstrap.sh" | head -n1 | cut -d: -f1)"
|
||||
check "bootstrap: the claim follows the doctor gate" \
|
||||
0 "" test "${doctor_at:-999999}" -lt "${claim_at:-0}"
|
||||
check "bootstrap: a failed doctor warns without claiming the host" 0 "" \
|
||||
grep -q "the CLI landed, the host stack is unproven" "$ROOT/commands/bootstrap.sh"
|
||||
# --- README: the box rename (#12) --------------------------------------------
|
||||
# The philosophy line must point at heavy-duty/box — the old claudebox slug
|
||||
# only works through a GitHub redirect that one squatted rename away from
|
||||
|
|
@ -217,11 +226,16 @@ marker_warns() { # marker_warns <marker_path> <cmd...> — how many warnings fir
|
|||
MARKER_FIX="$(mktemp -d)"
|
||||
printf 'role=workload class=server host=no join=authkey\n' > "$MARKER_FIX/workload"
|
||||
printf 'role=control-plane class=server host=no join=authkey\n' > "$MARKER_FIX/control-plane"
|
||||
printf 'role=control-plane\n' > "$MARKER_FIX/bare-control-plane"
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
check "coolify: warns on a non-control-plane marker" 0 "1" \
|
||||
marker_warns "$MARKER_FIX/workload" "$ROOT/commands/coolify-install.sh" --version 4.1.2
|
||||
check "coolify: control-plane marker stays silent" 0 "0" \
|
||||
marker_warns "$MARKER_FIX/control-plane" "$ROOT/commands/coolify-install.sh" --version 4.1.2
|
||||
# A bare marker line with no trailing traits must read the same as the full
|
||||
# one — the guard must not couple to the marker's field formatting.
|
||||
check "coolify: a bare 'role=control-plane' line (no traits) stays silent" 0 "0" \
|
||||
marker_warns "$MARKER_FIX/bare-control-plane" "$ROOT/commands/coolify-install.sh" --version 4.1.2
|
||||
check "coolify: absent marker stays silent (advisory, not a gate)" 0 "0" \
|
||||
marker_warns "$MARKER_FIX/absent" "$ROOT/commands/coolify-install.sh" --version 4.1.2
|
||||
# The warning must stay a warning: the run proceeds past it and stops at the
|
||||
|
|
|
|||
Loading…
Reference in a new issue