install report: first cut, generated by the helpers

Every run writes a timestamped install-report.md recording what was installed,
changed, kept, skipped, started and run as root. Written for an adversarial read:
the person who just ran a setup script off the internet hands it to an agent of
their choosing and asks whether it did anything it should not have.

Recorded by the HELPERS rather than by the sections. pkg_install and
install_config report themselves, so anything installed or written through them
appears whether or not a section author remembered — a section that has to
remember is a section that will forget, and an incomplete report is worse than
none because it reads as a full account.

"Kept" is recorded as carefully as "changed". Leaving somebody's .zshrc alone is
the claim a reviewer most wants substantiated, and it is invisible unless stated.

Secrets are redacted at the moment of recording rather than filtered at render,
so a credential never sits in memory formatted for printing. Verified against a
POSTGRES_URL and an api_key/password pair.

REPORT_FILE is passed through the sudo re-exec. It was not, first time, and the
report silently vanished — the third variable this evening lost to env_reset.

Unfinished on purpose, paused mid-task at the owner's request: machine-setup's 26
sections still only report through the two shared helpers, so the sections that
change system state directly — systemd units, netplan, ufw, sshd drop-ins — are
not yet recorded. That is the half a reviewer would care most about.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-13 03:33:48 +00:00
co-authored by Claude Opus 5
parent 74b4c7908a
commit 77f1284925
7 changed files with 250 additions and 3 deletions
+23
View File
@@ -37,6 +37,7 @@ while [[ $# -gt 0 ]]; do
done
# shellcheck source=officer-setup/lib/base.sh
source "$SCRIPT_DIR/report.sh"
source "$SCRIPT_DIR/officer-setup/lib/base.sh"
# shellcheck source=officer-setup/lib/preflight.sh
source "$SCRIPT_DIR/officer-setup/lib/preflight.sh"
@@ -88,9 +89,12 @@ elif [[ "$EUID" -ne 0 ]]; then
OFFICER_ROOT="${OFFICER_ROOT:-}" \
SETUP_USERNAME="${SETUP_USERNAME:-}" \
MACHINE_ROLE="${MACHINE_ROLE:-}" \
REPORT_FILE="${REPORT_FILE:-}" \
bash "$SCRIPT_DIR/officer-setup.sh" "$@"
fi
trap report_flush EXIT
# ── what machine-setup already established ──
echo ""
if load_machine_answers; then
@@ -214,6 +218,7 @@ fi
#
# Before the repository, because the repository is cloned into it.
report_section "Layout"
step "Layout"
if ! skip; then
echo ""
@@ -257,6 +262,7 @@ fi
# 3. Repository
# =============================================================================
report_section "Repository"
step "Repository"
if ! skip; then
PLATFORM_DIR="$(platform_dir)"
@@ -329,6 +335,7 @@ fi
# 4. Dependencies
# =============================================================================
report_section "Dependencies"
step "Dependencies"
if ! skip; then
echo ""
@@ -383,6 +390,7 @@ fi
#
# POSTGRES_URL is set here and written by the environment section below.
report_section "Database"
step "Database"
if ! skip; then
echo ""
@@ -500,6 +508,7 @@ fi
# 6. Environment
# =============================================================================
report_section "Environment"
step "Environment"
if ! skip; then
echo ""
@@ -545,6 +554,7 @@ if ! skip; then
if confirm "Write it?"; then
write_env
ok "written, 0600, owned by ${USERNAME}"
report_changed "wrote $(env_file) (0600, owner ${USERNAME}) — PORT, PUBLIC_URL, POSTGRES_URL. No secrets: every key lives in the secret store."
[[ -f "$(env_file).before-officer-setup" ]] && echo " previous kept as $(env_file).before-officer-setup"
SUMMARY+=("Environment: $(env_file)")
else
@@ -564,6 +574,7 @@ fi
# races to create it, and an install that finishes without ever saying the words
# "back this up" is one where nobody learns the file matters until it is gone.
report_section "Secrets"
step "Secrets"
if ! skip; then
echo ""
@@ -583,6 +594,7 @@ if ! skip; then
if confirm "Create it?"; then
if bootstrap_secret_store; then
ok "created, 0600, owned by ${USERNAME}"
report_changed "created $(secret_store_path) (0600, dir 0700, owner ${USERNAME}) with keys for: jwt, headscale. Generated locally, never transmitted."
echo ""
warn "back up $(secret_store_path) — and keep it OUT of the backup that holds your database dump."
echo " Losing it signs everyone out and makes every encrypted column in"
@@ -607,6 +619,7 @@ fi
# 8. Schema
# =============================================================================
report_section "Schema"
step "Schema"
if ! skip; then
echo ""
@@ -629,6 +642,7 @@ if ! skip; then
if confirm "Push it?"; then
if OUT="$(push_schema)"; then
ok "schema applied"
report_changed "applied ${SCHEMA_TABLES} tables to Postgres with 'bun db:push' (drizzle-kit; no migration files)"
SUMMARY+=("Schema: ${SCHEMA_TABLES:-?} tables pushed")
else
warn "db:push failed"
@@ -646,6 +660,7 @@ fi
# 9. Build
# =============================================================================
report_section "Build"
step "Build"
if ! skip; then
echo ""
@@ -666,6 +681,7 @@ if ! skip; then
elif confirm "Generate it?"; then
if OUT="$(gen_index)"; then
ok "$(gen_index_output)"
report_changed "generated $(gen_index_output) from index.html, substituting PUBLIC_URL=${ENV_PUBLIC_URL}"
SUMMARY+=("Build: index.gen.html for ${ENV_PUBLIC_URL}")
else
warn "gen:index failed"
@@ -683,6 +699,7 @@ fi
# 10. Services
# =============================================================================
report_section "Services"
step "Services"
if ! skip; then
echo ""
@@ -702,6 +719,7 @@ if ! skip; then
if confirm "Write it and start them?"; then
write_ecosystem
ok "written — $(ecosystem_file)"
report_changed "wrote $(ecosystem_file) — six pm2 apps: $(printf '%s ' "${CORE_PROCESSES[@]%%|*}")"
# Starting against a database that is not answering is not fatal — the server
# waits and the agent retries forever — but it makes the Verify section below
@@ -713,12 +731,14 @@ if ! skip; then
if OUT="$(pm2_start)"; then
ok "processes started"
report_started "pm2 startOrRestart: $(printf '%s ' "${CORE_PROCESSES[@]%%|*}")"
pm2_save >/dev/null 2>&1 && ok "process list saved (survives a pm2 restart)"
echo ""
if confirm "Start them on boot too?"; then
if pm2_enable_startup; then
ok "pm2 will resurrect them at boot"
report_ran "pm2 startup systemd — installed a systemd unit so pm2 resurrects these at boot"
SUMMARY+=("Services: 6 processes started, enabled at boot")
else
warn "could not enable the boot hook — run 'pm2 startup' yourself and follow it"
@@ -743,6 +763,7 @@ fi
# 11. Verify
# =============================================================================
report_section "Verify"
step "Verify"
if ! skip; then
echo ""
@@ -791,3 +812,5 @@ fi
echo ""
echo -e "${BOLD} Pre-flight complete.${NC} The remaining sections are not built yet."
echo ""
report_mark_complete