fix(kanban): reject direct status transition to 'running' via dashboard API

The PATCH /tasks/:id endpoint allows setting status='running' via
_set_status_direct(), bypassing the dispatcher/claim path that creates
run rows, claim locks, expiry, and worker process metadata. This can
leave tasks stuck in 'running' with no active worker.

Fix: reject status='running' with HTTP 400, requiring all transitions
to 'running' to go through the canonical claim_task() path.

Closes #19535
This commit is contained in:
luyao618 2026-05-04 14:47:13 +08:00 committed by Teknium
parent 652f8e6f3e
commit 6b3efcee49

View file

@ -449,7 +449,12 @@ def update_task(task_id: str, payload: UpdateTaskBody, board: Optional[str] = Qu
ok = _set_status_direct(conn, task_id, "ready")
elif s == "archived":
ok = kanban_db.archive_task(conn, task_id)
elif s in ("todo", "running", "triage"):
elif s == "running":
raise HTTPException(
status_code=400,
detail="Cannot set status to 'running' directly; use the dispatcher/claim path",
)
elif s in ("todo", "triage"):
ok = _set_status_direct(conn, task_id, s)
else:
raise HTTPException(status_code=400, detail=f"unknown status: {s}")