PT-604: atomically claim the top task in the project ready set (PT-602) for `assigneeId`
POST/api/projects/:id/tasks/claim-next-ready
PT-604: atomically claim the top task in the project ready set (PT-602) for assigneeId. Race-free (READ COMMITTED conditional CAS — concurrent callers never both claim the same task; the loser advances to the next ready row) and audited in the same transaction. The claimed task moves to the project's first in_progress-category status (by sortOrder); a project with no such status keeps the task status unchanged. Returns { data: <task> } on success, or { data: null } (still HTTP 200) when nothing is ready.
Request
Responses
- 200
- 400
- 401
- 403
- 409
Successful response
Invalid body (malformed JSON, or assigneeId missing / not a UUID), or the assignee is not assignable to the project (no project access / Guest Customer). All 400s on this route are thrown through withErrorHandler, so they use the canonical error envelope.
Caller is not authenticated (returned directly as a plain error).
Forbidden — requires 'tasks.update.any' plus read access to the project. Two shapes: a project-access denial (also covers a non-readable / non-existent project, no existence oracle) is returned directly via projectAccessError as the plain shape, while a missing-permission denial throws ForbiddenError and surfaces as the canonical envelope through withErrorHandler.
The project has no organisation context (null tenant), so the claim cannot be safely tenant-scoped — rejected (returned directly as a plain error) rather than silently returning null.