Row-level data scoping for groomer role (RBAC Phase 2) #118
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Phase 1 of RBAC (endpoint-level authorization) shipped in #88. This issue tracks Phase 2: row-level data scoping for the groomer role.
Problem
Groomers currently have read access to all clients, pets, and appointments. In a multi-groomer salon, a groomer can see every client and every appointment — not just their own. While they can't write to data outside their role, the privacy exposure is a concern for salon managers.
Scope
Filter data returned to groomers at the query level so they only see records they're actually working with:
GET /api/appointments) — return only appointments wherestaffIdmatches the authenticated groomer's staff IDGET /api/clients,GET /api/clients/:id) — return only clients who have at least one appointment assigned to this groomerGET /api/pets,GET /api/pets/:petId) — return only pets whose owner is a client assigned to this groomerManagers and receptionists retain full read access (no filtering).
Out of Scope
Implementation Notes
c.get("staff")(set byresolveStaffMiddleware) to get the current staff role and IDAcceptance Criteria
GET /api/appointmentsGET /api/appointments/:idreturns 403 if the appointment is not assigned to the requesting groomerContext
cc @cpfarhood
Row-level data scoping for groomer role is live on main (commit
9eb0c3d). All 6 endpoints scoped per spec. PR #125 closed as redundant — changes were already merged. Closing.