Make ./install something you could hand a stranger

The audit's third tier: everything between this installer and a fresh machine
it has never met.

The one path that could cost a person their display: the interview probes
Secure Boot with mokutil, which install-packages had not installed yet, so on
a minimal base the MOK question silently never fired -- and install-hardware
still installed akmod-nvidia and blacklisted nouveau, arming a reboot into an
unloadable driver with its fallback disabled. The probe tools (pciutils,
mokutil, fwupd) now bootstrap beside gum, and install-hardware re-checks
Secure Boot for itself and refuses the driver rather than the display.

Secrets leave the checkout: the personal environment moves to
~/.config/panama/env at mode 600 by migration, and .bashrc sources it with a
permission check that quietly re-tightens drift. change-settings no longer
overwrites /etc/dnf/dnf.conf -- two performance keys are set additively, the
defaultyes=True that made every `dnf remove` treat Enter as yes is gone, and
a migration strips it from machines that already received it.

Package installation survives the world changing: the initial and desktop
lists run with --skip-unavailable and a report_missing pass that names what
was skipped (resolved through --whatprovides, so capability names like awk
do not cry wolf); the openh264, appstream and core-group extras go through
soft; RustDesk resolves its RPM for the machine's own architecture; and the
Claude Desktop repository script is fetched to a kept file and run, never
piped from the network into root.

The hardware predicates stop guessing: a wireless mouse's scope=Device
battery no longer turns a tower into a laptop, USB-PD-only machines read
their power state from the battery's own status instead of being permanently
"on AC", the lid falls back to logind's LidClosed where ACPI is silent, and
charge limits reach every pack of a two-battery machine in one authorization
-- with the reported percentage summed across packs.

And the parsers stop assuming this machine: snapper is read through
--machine-readable csv with named columns instead of a localized box-drawing
table, and reports whether snapshots are even possible so ext4 and
unconfigured-btrfs stop looking identical; fprintd is parsed under LC_ALL=C;
the hypridle drop-in resolves the binary it points at; the recorder's render
node became an "auto" token resolved at record time; update-grub writes the
config its firmware actually boots; the nvm prompt hook and the SSH tmux
takeover are guarded; hipblas and rocm-opencl move to an opt-in gpu-compute
category; and the two interactive python tools' libraries are declared.

Claude-Session: https://claude.ai/code/session_01Epx9ZC1gwm81K3jm9x9CKh
This commit is contained in:
Gabriel Brown
2026-08-23 12:10:03 -04:00
parent 44124d72fa
commit 153554b5df
22 changed files with 331 additions and 87 deletions
+17 -8
View File
@@ -14,14 +14,23 @@ source "$PANAMA_PATH/bin/ascii"
# installed, and nothing asks again afterwards. That is the whole bargain: the
# rest of the run takes twenty minutes and needs nobody watching it.
#
# gum is bootstrapped first because the interview is built on it and it cannot
# install itself -- it is declared in initial-packages, which install-packages
# installs, which runs after this. One small dnf call buys a real interface for
# the only part of the install a person actually interacts with.
if ! command -v gum >/dev/null 2>&1; then
echo "Installing gum, which the setup questions are built on"
sudo dnf install -y gum >/dev/null || {
echo "Could not install gum, so the setup questions cannot be asked." >&2
# The interview's tools are bootstrapped first because it cannot install them
# itself -- they are declared in the package lists, which install-packages
# installs, which runs after this. gum is the interface; pciutils, mokutil and
# fwupd are the interview's eyes.
# It probes for an NVIDIA card, Secure Boot state and updatable firmware
# BEFORE install-packages runs, and a missing probe tool degrades the answer
# silently to "no" -- which for Secure Boot once meant installing a driver
# that could never load. Workstation ships all four; a minimal base does not.
bootstrap=()
command -v gum >/dev/null 2>&1 || bootstrap+=(gum)
command -v lspci >/dev/null 2>&1 || bootstrap+=(pciutils)
command -v mokutil >/dev/null 2>&1 || bootstrap+=(mokutil)
command -v fwupdmgr >/dev/null 2>&1 || bootstrap+=(fwupd)
if (( ${#bootstrap[@]} > 0 )); then
echo "Installing what the setup questions are built on: ${bootstrap[*]}"
sudo dnf install -y "${bootstrap[@]}" >/dev/null || {
echo "Could not install ${bootstrap[*]}, so the setup questions cannot be asked." >&2
exit 1
}
fi