Problem
ensure_user_has_project_access(...) is called manually in each work-items handler that receives organization + project.
Current duplicates in toki-api/src/routes/work_items/mod.rs:
get_iterations (:142)
get_board (:157)
format_for_llm (:179)
get_image (:199)
move_work_item (:243)
This repeats authorization logic and increases the chance of missing the check on future endpoints.
Requested change
Move the work-items project access check to router level and remove these per-handler calls:
ensure_user_has_project_access(&app_state, &user, &body.organization, &body.project).await?;
(and equivalent query-based variants).
Scope
- Add a router-level guard/middleware for work-item routes that require
organization and project.
- Apply it to:
GET /work-items/iterations
GET /work-items/board
GET /work-items/image
GET /work-items/format-for-llm
POST /work-items/move
- Keep
GET /work-items/projects unguarded (it is used to resolve allowed projects).
- Remove handler-level
ensure_user_has_project_access(...) calls from the routes above.
Acceptance criteria
- Authorization behavior remains unchanged for allowed/forbidden users.
- Work-items handlers no longer contain duplicated access-check calls.
- Router wiring in
work_items::router() clearly shows where access enforcement happens.
- Add/update tests covering guard behavior for at least one query-based and one body-based route.
Problem
ensure_user_has_project_access(...)is called manually in each work-items handler that receivesorganization+project.Current duplicates in
toki-api/src/routes/work_items/mod.rs:get_iterations(:142)get_board(:157)format_for_llm(:179)get_image(:199)move_work_item(:243)This repeats authorization logic and increases the chance of missing the check on future endpoints.
Requested change
Move the work-items project access check to router level and remove these per-handler calls:
(and equivalent query-based variants).
Scope
organizationandproject.GET /work-items/iterationsGET /work-items/boardGET /work-items/imageGET /work-items/format-for-llmPOST /work-items/moveGET /work-items/projectsunguarded (it is used to resolve allowed projects).ensure_user_has_project_access(...)calls from the routes above.Acceptance criteria
work_items::router()clearly shows where access enforcement happens.