# Fix — `parent_student` → `parent_students` typo, server-wide > Plan reference: `.harness/plans/file-attachments.md` §13 follow-up cleanup. Picks up the loose ends from the `fix/file-attachments-parent-typo` branch, which only fixed 4 of the 8 occurrences in the tree. **Status:** ✅ branch `fix/parent-student-rbac-rest` based on `dev` (5277539). Build green, server smoke-tested. ## Scope (vs base `5277539`) | File | Change | Type | |---|---|---| | `server/src/controllers/assignments.controller.js` | `parent_student` → `parent_students` at line 957 (RBAC check in `/my/submissions?student_id=`) | SQL — runtime bug | | `server/src/controllers/homework.controller.js` | same fix at lines 103 + 190 (parent scope in `GET /api/homework`) | SQL — runtime bug | | `server/src/controllers/tests.controller.js` | same fix at lines 103 + 190 (parent scope in `GET /api/tests`) | SQL — runtime bug | | `server/src/controllers/subjects.controller.js` | same fix at line 216 (parent scope in `GET /api/subjects`) | SQL — runtime bug | | `server/src/controllers/users.controller.js` | `entityType: 'parent_student'` → `entityType: 'parent_students'` at lines 308 + 366 (audit log entity identifiers for LINK_PARENT_STUDENT / UNLINK_PARENT_STUDENT) | string — consistency fix, not a runtime bug | 5 files, 8 lines. ## Why these matter The first 7 changes (5 SQL queries, all in PR 2 + the new PR 4 work) were the same latent typo the previous fix branch caught. They were not exercised by the previous branch's smoke test (the previous fix only covered 4 of the 8 occurrences — `assignments`, `subjects`, `homework`, `tests` controllers in PR 3; this branch covers the rest of the tree). Each one would have 500'd with `"no such table: parent_student"` the first time a parent's request hit that controller path. PR 4 (`feature/file-attachments-realtime`) wires the parent-side realtime flow (`/api/assignments/my/submissions?student_id=…` plus the homework/tests return broadcasts), so the unfixed paths were about to be exercised in production for the first time. The 2 audit-log `entityType` strings don't cause a runtime bug, but they're inconsistent with the actual table name. Any future audit-log filter that looks for `entityType: 'parent_students'` (the new convention) would silently miss these rows. Tied to the SQL fix for consistency. ## Diff ```diff server/src/controllers/assignments.controller.js | 2 +- server/src/controllers/homework.controller.js | 4 ++-- server/src/controllers/subjects.controller.js | 2 +- server/src/controllers/tests.controller.js | 4 ++-- server/src/controllers/users.controller.js | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) ``` ## Verification `cd server && npm run db:init` — idempotent (no schema change). `node src/index.js` boot — clean (no `MODULE_NOT_FOUND`). Live smoke (server on :3001) with demo accounts `teacher@school.com` / `student@school.com` / `parent@school.com`: | Endpoint | Pre-fix | Post-fix | |---|---|---| | `GET /api/subjects` (parent) | `500 no such table: parent_student` | **HTTP 200** | | `GET /api/homework` (parent) | 500 | **HTTP 200** | | `GET /api/tests` (parent) | 500 | **HTTP 200** | | `GET /api/assignments/my/submissions` (parent) | 500 | **HTTP 200** | | `GET /api/assignments/my/submissions?student_id=6` (parent, linked child) | 500 | **HTTP 200**, 1 row | | `GET /api/assignments/my/submissions?student_id=999` (parent, unlinked) | 500 | **HTTP 403** — RBAC enforced | | `GET /api/assignments/my/submissions?student_id=6` (teacher) | (worked) | HTTP 200 (unchanged) | | `GET /api/homework/1` (parent) | 500 | **HTTP 404** (no such row, but no 500) | | `GET /api/tests/1` (parent) | 500 | **HTTP 404** (same) | The 403 on the unlinked child (`student_id=999`) is the smoking gun — `parent_students` lookup is now resolving, and the controller's RBAC check is firing correctly. ## Why not done in the previous fix branch `fix/file-attachments-parent-typo` (PR 3 follow-up) was scoped narrowly to controllers touched in PR 3. The `tests` and `homework` controllers' `parent_student` typos were PR-2-era carry-overs that weren't exercised by the parent flow at the time. The first PR-4 follow-up was already in flight before PR 4 wired the parent path, so it caught the same 4 sites but missed the rest. This branch picks up the remaining 4 sites. VERDICT: PASS