fix(cli): camelCase task fields match WebUI shape (createdAt, not created_at)

WebUI-created tasks emit camelCase initial fields (createdAt, startedAt,
completedAt, heartbeatAt, exitCode, errorMessage) per
tasks-manager.js / task-manager.js conventions, with createdAt in
ISO-UTC-with-ms (`2026-05-27T13:01:26.345Z`). The processor then layers
snake_case status fields (started_at, heartbeat_at, …) on top as the
task runs.

The CLI's cliTaskRun was writing snake_case only — `created_at` with
local-tz offset. The task panel's renderer reads `task.createdAt`
directly (no alias), so CLI-queued tasks showed blank Created/Started
columns until the processor wrote its own snake_case overlay
(which doesn't include createdAt at all). Visible symptom: dates
"broken" on CLI-queued tasks.

Now the initial JSON cliTaskRun writes matches what the WebUI's
"Install" button writes:

  {
    id, command, status: queued,
    createdAt: "<ISO-UTC-with-ms>",
    startedAt: null, completedAt: null, heartbeatAt: null,
    exitCode: null, errorMessage: null,
    type, app
  }

Processor side is unchanged (still adds snake_case overlay on
status transitions — that's how WebUI tasks already work). No JSON
shape change for in-flight tasks.

ALSO (out-of-repo): /home/user/Documents/Scripts/update.sh now restarts
the systemd `libreportal.service` task processor after the docker
`libreportal-service` container restart. Same reason — both pre-load
code at startup, both need a restart to pick up changes. Without this,
deploys silently kept a stale processor running old code while the
disk reflected the new code; the install task-routing recursion I just
saw was a direct consequence.

Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
librelad 2026-05-27 14:51:13 +01:00
parent ce7b704084
commit f252d7680b

View File

@ -37,28 +37,41 @@ _writeTaskFile() {
local task_id="$1" command="$2" task_type="$3" app_name="$4"
local task_dir; task_dir=$(_taskDir)
local task_file="$task_dir/${task_id}.json"
local created_at; created_at=$(date -Iseconds 2>/dev/null || date '+%Y-%m-%dT%H:%M:%S')
# ISO-8601 UTC with milliseconds. Matches the format the WebUI's
# tasks-manager.js emits (Date.now() → toISOString()), so the tasks
# panel's `new Date(task.createdAt).toLocaleString()` renders correctly.
# Falls back to seconds-precision if %3N isn't supported (busybox).
local created_at
created_at=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ" 2>/dev/null) \
|| created_at=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
[[ -d "$task_dir" ]] || runFileOp mkdir -p "$task_dir"
# CamelCase initial fields match the WebUI's task shape; processor adds
# snake_case status fields on top as it runs. Both task-manager.js and
# tasks-manager.js read camelCase directly (no alias needed for createdAt).
local task_json
if command -v jq >/dev/null 2>&1; then
task_json=$(jq -n \
--arg id "$task_id" \
--arg command "$command" \
--arg status queued \
--arg created_at "$created_at" \
--arg createdAt "$created_at" \
--arg type "${task_type:-}" \
--arg app "${app_name:-}" \
'{id:$id, command:$command, status:$status, created_at:$created_at}
'{id:$id, command:$command, status:$status, createdAt:$createdAt,
startedAt:null, completedAt:null, heartbeatAt:null,
exitCode:null, errorMessage:null}
+ (if $type != "" then {type:$type} else {} end)
+ (if $app != "" then {app:$app} else {} end)')
else
# Plain string interpolation — command is the only field that needs
# escaping. Strip control chars; the install dispatcher uses ascii
# only so this is sufficient without pulling jq in.
# escaping. Strip control chars; the dispatcher uses ascii only so
# this is sufficient without pulling jq in.
local esc="${command//\\/\\\\}"; esc="${esc//\"/\\\"}"
task_json="{\"id\":\"$task_id\",\"command\":\"$esc\",\"status\":\"queued\",\"created_at\":\"$created_at\""
task_json="{\"id\":\"$task_id\",\"command\":\"$esc\",\"status\":\"queued\",\"createdAt\":\"$created_at\""
task_json+=",\"startedAt\":null,\"completedAt\":null,\"heartbeatAt\":null"
task_json+=",\"exitCode\":null,\"errorMessage\":null"
[[ -n "$task_type" ]] && task_json+=",\"type\":\"$task_type\""
[[ -n "$app_name" ]] && task_json+=",\"app\":\"$app_name\""
task_json+="}"