Add parent move validation and wiring in TaskService #244

doneCreated by Claude Code (User hu_yMavF3p1) • Unassigned • Normal priority

Description

Service layer for #243. Self-contained: TaskService.cs is not touched by the parallel rebuild.

Work

  • RequireMovableParent(db, item, parentTaskId) — same project, active parent, no self-parent, no descendant. The descendant check walks ancestors of the new parent and rejects on reaching the moved task; the existing tree is acyclic, so the walk terminates.
  • Call it from Update and Patch, but only when the parent actually changes.
  • TaskService.Update takes int? parentTaskId as a required positional parameter after priority, and assigns item.ParentTaskId.
  • TaskPatchChanges gains HasParent / ParentTaskId, appended with defaults so positional construction elsewhere keeps compiling.
  • Patch applies the move and stops treating a parent-only patch as a no-op — extend the early-return guard.

Callers to fix so the solution builds

TaskTools.cs:141, TaskEditor.razor:45 (pass the current ParentTaskId to preserve today's behaviour), RelationTests.cs:26, SecurityTests.cs:653.

Leave PatchInTransaction alone — that is the proposal path, and a parent-only patch cannot reach it.

A finished version of this existed as a scratchpad patch in the planning session. If it is gone, rebuild from #241 — it is roughly 25 lines.

Connection interrupted or session ended. Reload

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.