scripts v1.21.0 — the pairing wait stops looking like a failure (R-33)
Waiting to be bound is the NORMAL state of a freshly installed box, and it must
not be reported as failure. The PAIRING poll loop used to BE systemd's
Restart=on-failure/RestartSec=30 — one poll per invocation, exiting non-zero
until the bind landed — so every 30s systemd printed "Failed to start Felhom
host bootstrap" on the physical console the CUSTOMER is watching. The
2026-07-18 N100 rehearsal measured 52 FAILED lines in ~11 minutes while nothing
was wrong (VALIDATION-n100-rehearsal-2026-07-18.md F6).
felhom-bootstrap.sh: run_pairing() is now a while-loop that sleeps
POLL_INTERVAL (30s — the hub-side rate is unchanged) between polls, so the unit
sits in `activating`. Registration split into register_appliance(), which
returns non-zero for a transient problem (no network yet, no identity, no
token) and is retried by the loop instead of taking the unit down. Cadence
constants: POLL_INTERVAL=30, BANNER_EVERY=10 (5 min), HEARTBEAT_EVERY=20
(10 min).
Quiet without going dark: a 204 is logged once on entry (worded so nobody reads
it as an error) and then only on the 10-minute heartbeat with elapsed minutes;
404 and unexpected codes degrade the same way. 410 STILL exits non-zero on
purpose — delivery consumed but no local env is a real crash window, and a
clean systemd restart is the right response.
Console banner: every 5 min instead of every cycle, single accented spelling
instead of the parositasra/párosításra double, and the reassurance the
rehearsal showed was missing ("Ez a képernyő magától frissül — nincs teendő a
doboznál").
felhom-bootstrap.service: TimeoutStartSec=infinity. This is load-bearing, not
cosmetic — a Type=oneshot ExecStart is killed at DefaultTimeoutStartSec (90s),
so without it systemd would kill the new in-script wait after 90 seconds and
Restart=on-failure would silently reinstate the exact spam this removes, after
appearing to work for the first three polls. Restart=/RestartSec= are kept
deliberately: they still cover the DIRECT path, a failed host-install, and 410.
Verified behaviourally, not assumed: driven in a throwaway Debian container
against a stub hub answering 204 five times then delivering — logged the wait
once plus one heartbeat, never exited between polls, then consumed the
delivery, wrote the 0600 env, fell through to the direct install in the same
invocation and exited 0. The old design produced five unit invocations and five
"Failed to start" console lines for that same sequence.
Hub endpoints, payloads, polling rate and one-shot delivery semantics are all
unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nn3VgQk9iwEGgyx6QJ2NvE
This commit is contained in:
@@ -1,5 +1,52 @@
|
||||
# Felhom scripts — Changelog
|
||||
|
||||
## build-felhom-iso.sh v1.21.0 — the pairing wait stops looking like a failure (R-33) (2026-07-18)
|
||||
|
||||
**Waiting is not failing, and must not be reported as failure.** Until now the PAIRING poll loop WAS
|
||||
systemd's `Restart=on-failure`/`RestartSec=30`: each invocation did register-if-needed plus exactly
|
||||
one poll, then exited **non-zero** so the unit would be restarted 30s later. Functionally fine — but
|
||||
every one of those exits made systemd print `Failed to start Felhom host bootstrap …` on the physical
|
||||
console **the customer is watching**. The 2026-07-18 N100 rehearsal measured **52 FAILED lines in
|
||||
~11 minutes** while nothing whatsoever was wrong: the box had registered correctly and was waiting to
|
||||
be bound, which is the normal state of a freshly installed appliance. That is the customer's literal
|
||||
first impression of the product
|
||||
(`documentation/tests/VALIDATION-n100-rehearsal-2026-07-18.md` finding F6, ROADMAP **R-33**).
|
||||
|
||||
- **`felhom-bootstrap.sh` — the wait moved INSIDE the script.** `run_pairing()` is now a
|
||||
`while true` loop that sleeps `POLL_INTERVAL` (30s — the hub-side rate is **unchanged**) between
|
||||
polls, so the unit sits in `activating` instead of failing. Registration was split out into
|
||||
`register_appliance()`, which returns non-zero for a *transient* problem (no network yet, identity
|
||||
not gatherable, hub returned no token) and is simply retried by the loop rather than taking the
|
||||
whole unit down. Three cadence constants at the top of the file: `POLL_INTERVAL=30`,
|
||||
`BANNER_EVERY=10` (console banner every 5 min), `HEARTBEAT_EVERY=20` (journal heartbeat every
|
||||
10 min).
|
||||
- **The journal got quiet without going dark.** A `204 not bound yet` is logged **once** on entry
|
||||
(worded so nobody reads it as an error) and then only on the 10-minute heartbeat with elapsed
|
||||
minutes. `404` and unexpected HTTP codes likewise degrade to the heartbeat instead of a line every
|
||||
30s. **`410` still exits non-zero on purpose** — the delivery was consumed but no local env exists,
|
||||
a genuine crash window where handing the box back to systemd for a clean restart is the right move.
|
||||
- **The console banner got calmer and less repetitive.** Printed every 5 min instead of every cycle
|
||||
(a customer may walk up at any time, but a banner every 30s is its own noise). Dropped the
|
||||
belt-and-braces `parositasra var / párosításra vár` double-spelling for a single accented line, and
|
||||
added the reassurance the rehearsal showed was missing: „Ez a képernyő magától frissül — nincs
|
||||
teendő a doboznál, és nyugodtan itt hagyhatod bekapcsolva."
|
||||
- **`felhom-bootstrap.service` — `TimeoutStartSec=infinity` (load-bearing, not cosmetic).** A
|
||||
`Type=oneshot` `ExecStart` is killed at `DefaultTimeoutStartSec` (90s). Without this line systemd
|
||||
would kill the new in-script wait after 90 seconds and `Restart=on-failure` would **silently
|
||||
reinstate the exact console spam this change removes** — a regression that would look like the
|
||||
feature working for the first three polls. `Restart=on-failure`/`RestartSec=30` are deliberately
|
||||
kept: they still cover the DIRECT path, a failed host-install, and the 410 crash window.
|
||||
- **Behaviour verified, not assumed.** Driven in a throwaway Debian container against a stub hub that
|
||||
answers `204` five times and then delivers: the script logged the wait **once** plus one heartbeat,
|
||||
**never exited between polls**, then consumed the delivery, wrote the 0600 env, fell through to the
|
||||
direct install in the same invocation and exited **0**. Under the old design the same sequence
|
||||
produced five separate unit invocations and five `Failed to start` console lines.
|
||||
|
||||
**Compatibility:** hub-side polling rate, endpoints, payloads and the one-shot delivery semantics are
|
||||
all unchanged; this is purely how the box waits and what it says while waiting. An older ISO against
|
||||
any hub keeps working exactly as before.
|
||||
|
||||
|
||||
## build-felhom-iso.sh v1.20.0 — console pairing-code banner for customer self-bind (R-27 slice 1) (2026-07-17)
|
||||
|
||||
Supports the hub's customer self-bind flow (hub v0.66.0). In PAIRING mode, `felhom-bootstrap.sh` now
|
||||
|
||||
Reference in New Issue
Block a user