The first pass fixed#111 where it was reported — confirm() and
uninstall_confirm() in bin/box — and stopped there, while the same defect
sat at two more destructive gates in this repo:
· host/revoke-user.sh:50 guards 'box revoke --purge', the prompt whose
own text says "this cannot be undone";
· host/teardown-host.sh:31 guards a full host teardown.
Both run under 'set -euo pipefail', so an unguarded 'read' returning
non-zero on EOF ends the run before the 'case' that names the abort —
exit 1, in silence, at the moment the script asked. Each now carries the
guard in its own script's wording rather than importing bin/box's die().
The three drill/ prompts are deliberately untouched: they run under
'set -u' only, so EOF falls through to the '*)' arm and already aborts
out loud. install.sh:65 was already guarded.
What keeps the class closed is a repo-wide sweep in test/cli.sh: every
statement-initial 'read' fed from stdin, in any file that turns on
errexit, must carry a '||' guard — 'while read' loops and '<<<'
herestrings excluded, since neither is a prompt. Removing any of the four
guards makes it fail and name the file:line; it flags nothing else across
the tree's fifteen shell files. The absence of exactly this check is why
the host/ pair was missed the first time.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
confirm() and uninstall_confirm() read the operator's answer with a bare
'read -r reply'. Ctrl-D makes read return non-zero, set -euo pipefail ends
the run on that line, and the case below — the only thing that ever says
"aborted." — is never reached. box exits 1 having printed nothing after
the question it just asked.
The cure is one token in each, 'read -r reply || die "aborted."', the same
one heavy-duty/rig#43 applied to rig's credential prompts.
The three answers a human can give (y, n, Ctrl-D) are now driven on a real
pty via util-linux 'script'. They were structurally untested before —
'[ -t 0 ]' sends a terminal-less suite to the refusal branch, so every
existing check stopped there, which is how this survived four releases.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>