Panama learns what a server is: from a root login to running containers
A machine's role is now the interview's first question and the one answer Panama records. Servers get the same shell minus the screen: core packages, nvm, Bun, Claude Code and Codex (desktops get Codex too), linger, rootless ports from 80, firewalld, the nginx-bridge network, and a nightly image updater that replaced watchtower for cause. server/containers/ carries junior's 23 compose services -- secrets moved to per-machine .env files that never enter this public repo, every transformed compose proven to render byte-identical to what is live. 'panama server' enables, disables and relinks them; nothing here restarts a running service. 'boot --server' walks a fresh VPS from its root login to a normal install. Five new contracts pin the secrets rule, the catalog's shape, panama-server's behavior, the role plumbing, and the dotfile classification. Claude-Session: https://claude.ai/code/session_01NU5JGiN3JfzqrLQB6wmJ1E
This commit is contained in:
Executable
+56
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Every directory under config/dot is claimed by exactly one of
|
||||
# link-dotfiles' three lists -- universal (both roles), desktop, or handled
|
||||
# (linked or consumed some other way in that script). The failure this
|
||||
# prevents is quiet: a new dot directory added to the repo but classified
|
||||
# nowhere links on no server, or on every server, depending on which list the
|
||||
# author forgot -- and nothing says so until a machine is missing its config.
|
||||
#
|
||||
# The lists are lifted from the script itself rather than restated here, so
|
||||
# renaming them fails loudly instead of freezing a stale copy.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
link_dotfiles="$repo_dir/setup/scripts/link-dotfiles"
|
||||
dot_dir="$repo_dir/config/dot"
|
||||
|
||||
findings=()
|
||||
note() { findings+=("$1"); }
|
||||
|
||||
lists="$(sed -n '/^universal_dirs=(/,/^handled_dirs=(.*)$/p' "$link_dotfiles")"
|
||||
if [[ -z "$lists" ]]; then
|
||||
printf 'dotfile classification contract: link-dotfiles no longer defines the three lists\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
eval "$lists"
|
||||
|
||||
claimed=("${universal_dirs[@]}" "${desktop_dirs[@]}" "${handled_dirs[@]}")
|
||||
|
||||
for dir in "$dot_dir"/*/; do
|
||||
name="$(basename "$dir")"
|
||||
hits=0
|
||||
for entry in "${claimed[@]}"; do
|
||||
[[ "$entry" == "$name" ]] && hits=$((hits + 1))
|
||||
done
|
||||
if (( hits == 0 )); then
|
||||
note "config/dot/$name is claimed by no list, so servers silently skip or acquire it"
|
||||
elif (( hits > 1 )); then
|
||||
note "config/dot/$name is claimed by $hits lists"
|
||||
fi
|
||||
done
|
||||
|
||||
for entry in "${claimed[@]}"; do
|
||||
[[ -d "$dot_dir/$entry" ]] \
|
||||
|| note "link-dotfiles classifies '$entry', which config/dot does not contain"
|
||||
done
|
||||
|
||||
if (( ${#findings[@]} > 0 )); then
|
||||
mapfile -t findings < <(printf '%s\n' "${findings[@]}" | sort -u)
|
||||
printf 'dotfile classification contract: %d finding(s)\n' "${#findings[@]}" >&2
|
||||
printf ' - %s\n' "${findings[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf 'dotfile classification contract: PASS (%d directories classified)\n' "${#claimed[@]}"
|
||||
Reference in New Issue
Block a user