From e0f5c6b37bc1bde6a353905eb2dd3e84c7352a2b Mon Sep 17 00:00:00 2001 From: Erik Simon Date: Sat, 19 Sep 2026 14:51:05 +0200 Subject: [PATCH] =?UTF-8?q?mars(kittentts):=20fix=20review=20round=203=20?= =?UTF-8?q?=E2=80=94=20eval,=20delivery=20and=20stale-venv=20bugs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - pkgs.setpriv does not exist (mars failed to eval); setpriv is in util-linux. - `sh` is not on a unit's PATH; call ${pkgs.runtimeShell} directly. - Drop `env HOME="$hermesHome"`: unset shell var under `set -u`, and unneeded. - Staging dir 0700 -> 0755: the uid-986 delivery step could not read it. - Rebuild the staging venv whenever the stamp misses, else an input bump delivered the old venv under the new stamp. - Add diffutils: `cmp` in the fast path was missing, so every boot re-delivered. Co-Authored-By: Claude Opus 5 --- hosts/mars/hermes-agent.nix | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/hosts/mars/hermes-agent.nix b/hosts/mars/hermes-agent.nix index 089a5f6..5151219 100644 --- a/hosts/mars/hermes-agent.nix +++ b/hosts/mars/hermes-agent.nix @@ -492,7 +492,8 @@ in # is ever actually used. # # Provisioner invariants (shaped by the Mnemosyne + KittenTTS review rounds): - # - Build in a ROOT-OWNED staging dir (/var/lib/hermes-kittentts, 0700): + # - Build in a ROOT-OWNED staging dir (/var/lib/hermes-kittentts, 0755 so + # the uid-986 delivery step can read it; nothing in it is secret): # stamp, staging venv, uv cache and staging model copies all live there. # Root never reads or executes anything the container can write — the # container cannot symlink-takeover the stamp (review #1) or plant a @@ -533,7 +534,8 @@ in "hermes-agent-prepare-dirs.service" ]; requires = [ "hermes-agent-prepare-dirs.service" ]; - path = [ pkgs.uv pkgs.coreutils pkgs.setpriv ]; + # diffutils: `cmp` in the fast path; missing, it silently re-delivers every boot. + path = [ pkgs.uv pkgs.coreutils pkgs.diffutils pkgs.util-linux ]; serviceConfig = { Type = "oneshot"; TimeoutStartSec = 600; @@ -556,7 +558,7 @@ in # any uid-986-writable path while running as root. stageDir=/var/lib/hermes-kittentts # Root-side staging of the DELIVERED TREE (venv + full HF hub layout - # including refs/main) — everything root writes lives here, 0700. + # including refs/main) — everything root writes lives here. # review2 #4: root never writes into hermesHome; delivery happens as # the container uid via setpriv, copying from these root-owned sources. stageVenv=$stageDir/venv @@ -595,14 +597,17 @@ in # running as root; symlink-takeover of stamps/refs/install targets is # structurally impossible. ---- mkdir -p "$stageDir" "$stageSnap" "$stageVenv" "$stageHub" - chmod 0700 "$stageDir" + # 0755: the setpriv'd uid-986 delivery below must be able to read it. + chmod 0755 "$stageDir" install -m 0444 ${kittenttsModelConfig} "$stageSnap/config.json" install -m 0444 ${kittenttsModelOnnx} "$stageSnap/kitten_tts_mini_v0_8.onnx" install -m 0444 ${kittenttsModelVoices} "$stageSnap/voices.npz" # Skip the venv REBUILD when staging is still valid (review2 minor: - # damaged delivery should be a copy, not a rebuild). - if ! [ -x "$stageVenv/bin/python" ] \ + # damaged delivery should be a copy, not a rebuild) — but only for the + # CURRENT inputs, else a bump delivers the old venv under a new stamp. + if [ "$(cat "$stampFile" 2>/dev/null)" != "$inputHash" ] \ + || ! [ -x "$stageVenv/bin/python" ] \ || ! [ -f "$stageVenv/lib/python3.13/site-packages/kitten_tts_stub.py" ]; then rm -rf "$stageVenv" UV_CACHE_DIR=$stageDir/uv-cache \ @@ -652,7 +657,7 @@ in # fresh staging tree in. cp-as-986 also fixes review2 #2: rm+cp in one # step, no mv -Tf rename-replace on a non-empty directory. setpriv --reuid=${hermesUid} --regid=${hermesGid} --clear-groups \ - env HOME="$hermesHome" sh -c ' + ${pkgs.runtimeShell} -c ' set -eu rm -rf "$1" "$2" cp -a "$3" "$1"