doorstep: console is Felhom's (ISO 1.27.0 source), passphrase hand-over copy (hub 0.113.0 source), rulings
gates / gates (push) Successful in 19s
gates / gates (push) Successful in 19s
Phase 0: the public ISO never auto-installs by construction (no answer.toml, G1); the operator re-affirmed the interactive installer 2026-09-14. - felhom-bootstrap.sh: mask pvebanner.service, write a Hungarian /etc/issue (no :8006 admin URL); pairing banner names the Tulajdonosi jelmondat and paints through the CONSOLE_DEV seam (R-496). Harness: 8 checks, red first; fake hub now sends a pairing code (the banner was never tested, R-502). - hub: created flash + Credentials block tell the operator to hand the phrase over; the self-bind mail names the operator (R-497). Tests red first. - iso-release-gate G14-G16; domain ruling in 01-topology + CONTEXT; R-494 narrowed to P3; R-502..R-504 filed; volunteer guide and day-0 A.2 aligned. ISO_VERSION 1.27.0 (not built, not published). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -1,3 +1,24 @@
|
||||
## ISO v1.27.0 — the console is Felhom's, and names the passphrase once (2026-09-14, R-496)
|
||||
|
||||
**Measured in the 2026-09-14 first-hour drill (screen s29):** the first text a household read on a fresh
|
||||
box was Proxmox's `Welcome to the Proxmox Virtual Environment … connect to https://<ip>:8006/` — the
|
||||
operator admin UI, in English — and the Felhom banner below it asked for „a jelszavadat", while the
|
||||
self-bind mail and page call the same secret „Tulajdonosi jelmondat".
|
||||
|
||||
**`felhom-bootstrap.sh` (the frozen ISO payload):**
|
||||
- `install_felhom_issue` runs first, before the network gate: masks `pvebanner.service` (it rewrites
|
||||
`/etc/issue` on every boot — overwriting alone would last one boot), writes a Hungarian Felhom text
|
||||
to `/etc/issue` with no admin URL, reloads agetty. Every step best-effort; never blocks the boot.
|
||||
- The pairing banner asks for „a Tulajdonosi jelmondatodat (az 5 szót a Felhom üzemeltetőjétől
|
||||
kaptad)", and paints through the `CONSOLE_DEV` seam instead of a hard-coded `/dev/console`.
|
||||
|
||||
**Harness (`scripts/iso/test/bootstrap-modes.sh`):** five R-496 checks, **red before the change**. Found
|
||||
on the way: the fake hub's register reply carried no `pairing_code`, so the pairing banner had **never
|
||||
been exercised by any test**; it now carries one. Still not run by any gate or CI (recorded as a row).
|
||||
|
||||
**Not changed, by operator ruling 2026-09-14:** the public ISO keeps the interactive Proxmox installer
|
||||
(no answer file). The 2026-07-31 ruling — disk selection is always a person's choice — stands.
|
||||
|
||||
## observations_gate.py reads EVERY observations section (2026-09-13, R-471)
|
||||
|
||||
`observation_items` returned the first `Observations` heading it found and stopped, so a report
|
||||
|
||||
@@ -48,7 +48,7 @@ set -euo pipefail
|
||||
# does not exist: the ISO is a frozen artifact, while felhom-host-install.sh is fetched at RUN TIME
|
||||
# from the website's git-sync of `main` (R-94/R-110), so whatever version an ISO carries, the script a
|
||||
# box runs is always current. Coupling them would invent a constraint. The claim is corrected instead.
|
||||
ISO_VERSION="1.26.1" # the ISO's own version. INDEPENDENT of felhom-host-install.sh's SCRIPT_VERSION,
|
||||
ISO_VERSION="1.27.0" # the ISO's own version. INDEPENDENT of felhom-host-install.sh's SCRIPT_VERSION,
|
||||
# which is fetched at run time from main and is not frozen into the image.
|
||||
IMAGE="${FELHOM_ISO_ASSISTANT_IMAGE:-felhom-iso-assistant:trixie}"
|
||||
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
@@ -69,11 +69,42 @@ print_pairing_banner() {
|
||||
printf ' Felhom — a doboz készen áll, és a párosításra vár.\n\n'
|
||||
printf ' Párosító kód: %s\n\n' "$code"
|
||||
printf ' Nyisd meg az e-mailben kapott linket, és add meg\n'
|
||||
printf ' ezt a kódot és a jelszavadat.\n\n'
|
||||
printf ' ezt a kódot és a Tulajdonosi jelmondatodat\n'
|
||||
printf ' (az 5 szót a Felhom üzemeltetőjétől kaptad).\n\n'
|
||||
printf ' Ez a képernyő magától frissül — nincs teendő a\n'
|
||||
printf ' doboznál, és nyugodtan itt hagyhatod bekapcsolva.\n'
|
||||
printf '================================================\n\n'
|
||||
} > /dev/console 2>/dev/null || printf 'Párosító kód: %s\n' "$code"
|
||||
} > "$CONSOLE_DEV" 2>/dev/null || printf 'Párosító kód: %s\n' "$code"
|
||||
}
|
||||
|
||||
# install_felhom_issue (R-496, v1.27.0) — the text above the console login prompt is Felhom's, not
|
||||
# Proxmox's. Measured 2026-09-14 (drill screen s29): the first thing a household read on a fresh box was
|
||||
# `Welcome to the Proxmox Virtual Environment … connect to https://<ip>:8006/` — the operator admin UI,
|
||||
# in English. pvebanner.service REWRITES /etc/issue on every boot (/usr/bin/pvebanner opens it '>'), so
|
||||
# overwriting the file alone would last one boot: the unit is MASKED, then the file is written.
|
||||
# Best-effort in every step — a banner must never block the boot or the pairing.
|
||||
ISSUE_FILE="${FELHOM_ISSUE_FILE:-/etc/issue}"
|
||||
install_felhom_issue() {
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
if systemctl mask pvebanner.service >/dev/null 2>&1; then
|
||||
log "console: pvebanner.service masked (it would rewrite $ISSUE_FILE with the Proxmox admin URL on every boot)"
|
||||
else
|
||||
log "console: could not mask pvebanner.service — the Proxmox banner may return on the next boot"
|
||||
fi
|
||||
fi
|
||||
local tmp="${ISSUE_FILE}.felhom-tmp"
|
||||
if { printf '\n'
|
||||
printf ' Felhom otthoni szerver\n\n'
|
||||
printf ' Ezen a képernyőn nincs teendőd, bejelentkezni sem kell.\n'
|
||||
printf ' A beállításhoz kövesd a Felhomtól kapott útmutatót.\n\n'
|
||||
} > "$tmp" 2>/dev/null && mv -f "$tmp" "$ISSUE_FILE" 2>/dev/null; then
|
||||
log "console: $ISSUE_FILE is the Felhom text (no admin URL)"
|
||||
else
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
log "console: could not write $ISSUE_FILE — continuing"
|
||||
fi
|
||||
command -v agetty >/dev/null 2>&1 && agetty --reload >/dev/null 2>&1
|
||||
return 0
|
||||
}
|
||||
|
||||
cleanup_pass() { [[ -e "$PASS_FILE" ]] && { shred -u "$PASS_FILE" 2>/dev/null || rm -f "$PASS_FILE"; }; return 0; }
|
||||
@@ -528,6 +559,9 @@ emit("FELHOM_EXTRA_ARGS", d.get("extra_args"))
|
||||
done
|
||||
}
|
||||
|
||||
# --- R-496: Felhom's text above the console login, before anything can wait on the network --------
|
||||
install_felhom_issue
|
||||
|
||||
# --- R-59/R-60 first-boot network gate: never proceed silently into a hub-unreachable install ------
|
||||
network_gate
|
||||
|
||||
|
||||
@@ -97,7 +97,9 @@ exit 0
|
||||
HI
|
||||
exit 0 ;;
|
||||
*"/appliance/register")
|
||||
echo '{"appliance_token":"TESTTOKEN123456","poll_interval_sec":30}'
|
||||
# pairing_code (R-27): without it print_pairing_banner returns early and the banner is never
|
||||
# painted — which is how the banner went untested until v1.27.0 (R-496).
|
||||
echo '{"appliance_token":"TESTTOKEN123456","poll_interval_sec":30,"pairing_code":"TST-CDE"}'
|
||||
exit 0 ;;
|
||||
*"/appliance/poll")
|
||||
if [ "$mode" = "200" ]; then
|
||||
@@ -113,15 +115,15 @@ exit 0
|
||||
CURL
|
||||
chmod +x "$FAKE/curl"
|
||||
|
||||
# fake systemctl (disable is a no-op)
|
||||
printf '#!/bin/bash\nexit 0\n' > "$FAKE/systemctl"; chmod +x "$FAKE/systemctl"
|
||||
# fake systemctl (disable is a no-op); logs every call so R-496's pvebanner mask is observable
|
||||
printf '#!/bin/bash\necho "$*" >> /work/systemctl.log\nexit 0\n' > "$FAKE/systemctl"; chmod +x "$FAKE/systemctl"
|
||||
|
||||
reset_state() {
|
||||
rm -rf /etc/felhom /run/felhom-bootstrap-pass /var/lib/felhom-install "$CALLS" /work/hostinstall.log \
|
||||
/work/poll-mode /work/sleep.count /work/sleep.flip /work/sleep.abort \
|
||||
/work/ip.log /work/ifreload.log /work/dhclient.log /work/hub-mode /work/dhcp-mode \
|
||||
/work/sys /work/interfaces /work/interfaces.felhom-bak /work/console.out \
|
||||
/run/felhom-interfaces.orig /work/run.log
|
||||
/run/felhom-interfaces.orig /work/run.log /work/issue /work/systemctl.log
|
||||
mkdir -p /etc/felhom
|
||||
}
|
||||
|
||||
@@ -150,7 +152,7 @@ iface nicB inet manual
|
||||
source /etc/network/interfaces.d/*
|
||||
IFACES
|
||||
}
|
||||
GATE_ENV="FELHOM_NET_SYS=/work/sys FELHOM_INTERFACES_FILE=/work/interfaces FELHOM_CONSOLE_DEV=/work/console.out"
|
||||
GATE_ENV="FELHOM_NET_SYS=/work/sys FELHOM_INTERFACES_FILE=/work/interfaces FELHOM_CONSOLE_DEV=/work/console.out FELHOM_ISSUE_FILE=/work/issue"
|
||||
|
||||
# ============================ Scenario D — direct mode, zero appliance calls =========================
|
||||
# Runs WITH the gate fixture (NICs + fallback-shaped interfaces) and the hub reachable: the G1
|
||||
@@ -179,6 +181,13 @@ check "G1: gate made zero ifreload calls" "[ ! -f /work/ifreload.log ]"
|
||||
check "G1: gate made zero dhclient calls" "[ ! -f /work/dhclient.log ]"
|
||||
check "G1: gate consumed zero sleeps" "[ ! -f /work/sleep.count ]"
|
||||
check "G1: interfaces fixture untouched" "grep -q 'bridge-ports nicA' /work/interfaces && grep -q '192.168.100.2' /work/interfaces"
|
||||
# R-496 (v1.27.0): the console's login banner is Felhom's, not Proxmox's — and it survives a reboot,
|
||||
# because pvebanner.service (which rewrites /etc/issue on EVERY boot) is masked, not merely overwritten.
|
||||
check "R-496: /etc/issue written" "[ -s /work/issue ]"
|
||||
check "R-496: /etc/issue is the Felhom text" "grep -q 'Felhom otthoni szerver' /work/issue"
|
||||
check "R-496: /etc/issue carries no admin URL (:8006)" "! grep -q '8006' /work/issue"
|
||||
check "R-496: /etc/issue does not say Proxmox" "! grep -qi 'proxmox' /work/issue"
|
||||
check "R-496: pvebanner.service masked" "grep -q 'mask pvebanner.service' /work/systemctl.log"
|
||||
|
||||
# ============ P: pairing loop (v1.21.0) — register, wait unbound INSIDE one invocation, deliver =====
|
||||
say "P: pairing env -> register + in-script 204 wait -> 200 delivery -> host-install, ONE invocation"
|
||||
@@ -188,7 +197,12 @@ FELHOM_HUB_URL=https://hub.example
|
||||
ENV
|
||||
echo 204 > /work/poll-mode
|
||||
echo 3 > /work/sleep.flip # after 3 in-script waits the hub "binds" (poll flips to 200)
|
||||
bash "$BSTRAP"; rc=$?
|
||||
rm -f /work/console.out
|
||||
env FELHOM_CONSOLE_DEV=/work/console.out FELHOM_ISSUE_FILE=/work/issue bash "$BSTRAP"; rc=$?
|
||||
# R-496: the pairing banner names the secret the way the self-bind mail and page do (R-323).
|
||||
check "R-496: banner painted to the console seam" "grep -q 'Párosító kód' /work/console.out"
|
||||
check "R-496: banner names the Tulajdonosi jelmondat" "grep -q 'Tulajdonosi jelmondat' /work/console.out"
|
||||
check "R-496: banner no longer says 'jelszavad'" "! grep -q 'jelszavad' /work/console.out"
|
||||
check "single invocation ran to done (exit 0)" "[ $rc -eq 0 ]"
|
||||
check "POSTed /appliance/register" "grep -q '/appliance/register' $CALLS"
|
||||
check "appliance token persisted 0600" "[ -f /etc/felhom/.bootstrap-done ] || { [ -f /etc/felhom/appliance-token ] && [ \"\$(stat -c %a /etc/felhom/appliance-token)\" = 600 ]; }"
|
||||
|
||||
Reference in New Issue
Block a user