Skip to content

PATCH task-statuses: position field validated and returned but never persisted (SQL UPDATE omits it) #224

Description

@swarthyplacebo

Summary

PATCH /api/v1/projects/{projectId}/task-statuses/{statusId} accepts and validates a position field, and the domain-layer response reflects the new value correctly — but the change is never persisted. A subsequent GET shows the original, unchanged position. This makes it currently impossible to reorder task statuses via the API at all.

Root cause

In services/api/internal/repository/postgres/task_repository.go, UpdateTaskStatus:

func (r *TaskRepository) UpdateTaskStatus(ctx context.Context, s *taskdom.TaskStatus) error {
	_, err := r.db.ExecContext(ctx, `
		UPDATE task_statuses SET name=$1, color=$2, category=$3, updated_at=$4 WHERE id=$5`,
		s.Name, s.Color, string(s.Category), s.UpdatedAt, s.ID.String(),
	)
	...
}

The UPDATE statement has no position=$N clause at all. The domain-layer Service.UpdateTaskStatus (in services/task/task_service.go) correctly sets st.Position = *in.Position on the in-memory struct before calling this, and the handler returns that in-memory struct — so the API response looks correct — but the SQL write silently drops the field. A fresh GET afterward shows the original position, unchanged.

Repro:

curl -X PATCH ".../task-statuses/{id}" -d '{"position": 5}'
# response shows "position": 5
curl ".../task-statuses"
# this same status is still at its old position

Related, smaller bug in the same function

services/task/task_service.go, UpdateTaskStatus:

st.Color = in.Color

This unconditionally overwrites Color with whatever was in the request, including nil when the field is simply omitted (as opposed to the Name/Position/Category fields just above it, which correctly check for presence first). A position-only update ({"position": 5}, no color key) silently wipes the status's color to null. Likely wants the same "only set if provided" guard the other fields already have.

Impact

Task statuses created via the API (as opposed to the initial seed/migration data) are stuck at whatever position they were created with — there's no way to reorder a Kanban board's columns through the API, since every reorder attempt appears to succeed but never actually persists.

Environment

  • Paca: built from master (opensrc fetch, recent)
  • Confirmed via direct read of task_repository.go, task_service.go, and live API behavior

Filed with the help of Sally Sonnet.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions