diff --git a/commands/bootstrap.sh b/commands/bootstrap.sh index c2197f8..f8f4822 100755 --- a/commands/bootstrap.sh +++ b/commands/bootstrap.sh @@ -531,7 +531,25 @@ if [ "$HOST" = "yes" ]; then # else — a warning, never an abort: box is the host extra, the OS+tailnet core # is already done. if curl -fsSL "$BOX_INSTALL_URL" | BOX_YES=1 bash; then - log "box installed and host set up — mint guest boxes with 'box new'" + # Don't trust the exit code — prove the effective state (issue #12). An + # installer can exit 0 having done less than it claims: box's setup-host + # is written for a sudo-capable user, and one of its paths exits 0 after + # 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. + 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" + 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 else warn "box install did not complete (no network, or box's installer failed); bootstrap's core work is done. Finish the host by hand: ${BOX_MANUAL}" fi diff --git a/test/cli.sh b/test/cli.sh index ef069e2..5449708 100644 --- a/test/cli.sh +++ b/test/cli.sh @@ -136,6 +136,36 @@ check "bootstrap: box install runs after the role marker write" \ # host whose box did not install is never left without the next move. check "bootstrap: box skip/failure keeps a pointer to the manual install" 0 "" \ grep -q "prepare Incus" "$ROOT/commands/bootstrap.sh" +# "Don't trust exit codes" (#12): box's installer can exit 0 having done less +# than it claims (its setup-host has a path that exits 0 after only adding a +# group, asking for a re-login). After a claimed success bootstrap must prove +# the one artifact it asked for — box on PATH — and a hollow success WARNS, +# never dies: box is the host extra. Exercising it needs root + the network, +# so grep the shipped script (repo precedent: the tag-refusal greps). Match +# the CALL, not the word — the rationale comment says `command -v box` too. +check "bootstrap: a box-install success is verified, not trusted" 0 "" \ + grep -qE '^[[:space:]]*if command -v box' "$ROOT/commands/bootstrap.sh" +check "bootstrap: a hollow box-install success warns, never dies" 0 "" \ + grep -q "reported success but no 'box' is on PATH" "$ROOT/commands/bootstrap.sh" +# Ordering: the effective check must sit AFTER the installer run it verifies. +# Line-number compare, defaults fail closed (same idiom as the marker/install +# ordering assert above; box_install_at is computed there). +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" +# --- 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 +# breaking (box's own installer was already bitten by the rename once). A +# negative grep (exit 1 = pass) keeps the stale slug from creeping back. +check "README: no stale heavy-duty/claudebox links" 1 "" \ + grep -n "heavy-duty/claudebox" "$ROOT/README.md" +check "README: points at heavy-duty/box" 0 "" \ + grep -q "github.com/heavy-duty/box" "$ROOT/README.md" if [ "$(id -u)" -ne 0 ]; then check "bootstrap: refuses non-root" 1 "must run as root" env TS_AUTHKEY=x "$ROOT/commands/bootstrap.sh" workload check "bootstrap: runner role parses, refuses non-root" 1 "must run as root" env TS_AUTHKEY=x "$ROOT/commands/bootstrap.sh" runner