From 099751b72c25836d1fd546e4d663fbee26e0560f Mon Sep 17 00:00:00 2001 From: librelad Date: Sun, 24 May 2026 14:36:22 +0100 Subject: [PATCH] fix(rootless): task processor status writes via runFileWrite, not bare redirect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updateTaskFields wrote its temp with a plain 'jq … > "$tmp"' shell redirect, which runs as the processor's own user (the manager). But TASK_DIR is owned by the docker install user and the manager can't create files in it, so the redirect failed and the status write silently no-op'd — every task stayed 'queued', got reprocessed in an endless loop, and follow-on tasks (e.g. the setup 'finalize' after 'config') never ran. The fix mirrors writeAtomic: capture jq's output, write the temp through runFileWrite (the privileged helper), then chmod + atomic mv. Co-Authored-By: Claude Opus 4.7 Signed-off-by: librelad --- scripts/crontab/task/crontab_task_processor.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/crontab/task/crontab_task_processor.sh b/scripts/crontab/task/crontab_task_processor.sh index 2a6522a..d93f598 100755 --- a/scripts/crontab/task/crontab_task_processor.sh +++ b/scripts/crontab/task/crontab_task_processor.sh @@ -81,8 +81,17 @@ updateTaskFields() { jqExpr="$jqExpr | .$key = \$$key" done + # The processor runs as the manager user, which CANNOT create files in the + # docker-install-owned TASK_DIR. A plain `jq … > "$tmp"` redirect therefore + # failed silently, so neither `status: running` nor `status: completed` was + # ever written and the task was reprocessed forever. Capture jq's output and + # write the temp via runFileWrite (the privileged helper, like writeAtomic), + # then chmod + atomic mv as before. + local updated + updated=$(jq "${jqArgs[@]}" "$jqExpr" "$taskFile" 2>/dev/null) || return 1 + [[ -z "$updated" ]] && return 1 local tmp="${taskFile}.tmp.$$" - jq "${jqArgs[@]}" "$jqExpr" "$taskFile" 2>/dev/null > "$tmp" \ + printf '%s' "$updated" | runFileWrite "$tmp" \ && runFileOp chmod 644 "$tmp" 2>/dev/null \ && runFileOp mv "$tmp" "$taskFile" }