Keep what an archive unpacked in the engine's own state directory, never beside the archive, and stop no slower than the host waits (issue 1585, review round 1)
mesh/delivery merged: source.main moved to novox/mesh-host@998d8f737008
mesh/check being carried to 5dc3a8e17f97 on 998d8f737008 | from fabfdf04f78a

The journal of an unpack sat at <target>.unpacked.json, in a directory
the module's account may write: a forged one would make the root engine
remove or adopt any path it named. It now lives under
<statedir>/unpacked/<sha256 of the target>.json, mode 0600, names its
target, and is refused whole when an entry is not filepath.IsLocal or a
parent is not above the target. It goes when the archive is taken off,
whether its state record still said what it unpacked or not.

The launcher's stop grace for a host on trial rises from 20 s to 75 s and
the unit's TimeoutStopSec is 120 s (openrc the same), past the host's own
60 s wait for the apply in flight, so neither cuts a save off again.

Tests folded as rows into existing ones (the repository is over its unit
budget): the journal's rows, a forged entry and parent refused, the
journal gone with a record that lost its Unpacked; the test that passed
on main dropped; the stop test waits on its own line, not a sleep, and no
longer consumes the save it waits for.

Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
This commit is contained in:
2026-11-04 10:52:42 +01:00
parent 768f637bd0
commit 5dc3a8e17f
13 changed files with 234 additions and 175 deletions
+3 -1
View File
@@ -38,7 +38,9 @@ BACKOFF="${MESH_HOST_BACKOFF:-5}"
# How long a host on trial has to report, in seconds: to-be 45 §8's ten minutes from the apply.
BOUND="${MESH_HOST_TRIAL_BOUND:-600}"
TICK="${MESH_HOST_TRIAL_TICK:-5}"
GRACE="${MESH_HOST_STOP_GRACE:-20}"
# How long a host told to stop is waited for before it is killed, in seconds: past the 60 s the host itself waits for
# the apply in flight to end and save (novox/hq issue 1585), so a stop never cuts a save off.
GRACE="${MESH_HOST_STOP_GRACE:-75}"
ONCE="${MESH_HOST_RUN_ONCE:-}" # tests run one iteration; nothing else sets this
ATTEMPTS="$STATE_DIR/start-attempts"
+2
View File
@@ -5,4 +5,6 @@
name="nox-mesh-host"
command="/usr/lib/nox-mesh-host/launch"
supervisor="supervise-daemon"
# The same stop bound as the systemd unit's TimeoutStopSec (issue 1585): TERM, 120 s, then KILL.
retry="TERM/120/KILL/5"
depend() { need net; }
+3
View File
@@ -12,6 +12,9 @@ Restart=always
RestartSec=5s
StateDirectory=mesh-host
KillMode=mixed
# Past the launcher's own stop grace (75 s), which is past the 60 s the host waits for the apply in
# flight to end and save (novox/hq issue 1585): the service manager's kill is the last resort.
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target