test: the teardown check must not inherit BOX_YES

The new check drives host/teardown-host.sh for real — the first check in
the suite to execute a destructive script rather than grep it or run it
against shims. teardown-host honours an inherited BOX_YES, and test/cli.sh
never sanitised it, so under `BOX_YES=1 bash test/cli.sh` the invocation
took the consent arm instead of the gate: a real teardown of the host the
suite was running on, reported red only afterwards.

BOX_YES is the documented automation switch for this family, so an
operator's CI wrapper exporting it is the expected case, not a contrived
one. The file header promises the suite is runnable anywhere; before this
the promise held under any environment.

Fixed at the call site with `env -u BOX_YES`, plus a file-level `unset` so
the promise cannot be broken again by the next check that drives something
destructive.

Refs #113
This commit is contained in:
dan-claude-bot 2026-07-19 23:57:19 +00:00
parent b3fa94a7d4
commit ecce72f025

View file

@ -7,6 +7,13 @@
# a fixture, or grep the load-bearing line so a deleted guard cannot ship green. # a fixture, or grep the load-bearing line so a deleted guard cannot ship green.
# Deliberately no `set -e` — the harness asserts on failing commands. # Deliberately no `set -e` — the harness asserts on failing commands.
set -u set -u
# BOX_YES is this family's documented automation switch, so an operator's CI
# wrapper may well export it. Checks that drive a destructive script for real
# would then take the CONSENT arm instead of the refusal they are asserting —
# turning this suite into `box uninstall --purge-host` on the host it runs on.
# Individual call sites use `env -u BOX_YES`; this is the belt to that braces,
# so the header's "runnable anywhere" promise cannot be broken by one export.
unset BOX_YES
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PASS=0 FAIL=0 PASS=0 FAIL=0
@ -1997,7 +2004,7 @@ check "teardown-host: points at box uninstall when done" 0 "" \
# terminal to ask on is a usage error, not a mute 'aborted'. Driven for real — # terminal to ask on is a usage error, not a mute 'aborted'. Driven for real —
# the gate sits above the first 'incus' call, so a daemon-free run reaches it. # the gate sits above the first 'incus' call, so a daemon-free run reaches it.
check "teardown-host: refuses without a TTY and names the override (#113)" 2 \ check "teardown-host: refuses without a TTY and names the override (#113)" 2 \
"--yes (or BOX_YES=1) means yes" bash "$ROOT/host/teardown-host.sh" </dev/null "--yes (or BOX_YES=1) means yes" env -u BOX_YES bash "$ROOT/host/teardown-host.sh" </dev/null
# #102's race, in the one other file that sets pipefail. A daemon-free run # #102's race, in the one other file that sets pipefail. A daemon-free run
# cannot exercise a UFW teardown, so the shape is pinned instead: no `ufw # cannot exercise a UFW teardown, so the shape is pinned instead: no `ufw