--- name: BQ-System hardening initiative 2026-05 description: Execution plan for 8 hardening tasks (security/architecture) — handed off to Sonnet 4.6 sessions one task at a time type: project originSessionId: b6ce9f63-539c-44d6-b93f-a9a65b44f165 --- 8-task hardening plan started 2026-05-06. Each task = separate Sonnet session, separate commit. **Why:** security review found 17 P0/P1 issues (commit 952a54f). Code analysis showed `requireOwnership` middleware exists but used in only 1 of 169 `:id`-routes. classroomController.js is 1618 lines with 56 inline `req.user.role` checks. Auto-migrate runs on every server start. WS auth via query-string token (leaks to logs). **How to apply:** if user references "task 1-8" or "hardening plan", these are the 8 tasks (executed in order/parallel groups): - Group A (parallel): #1 ESLint-style auth check on :id routes, #2 remove auto-migrate from server startup, #3 WS auth via first-message instead of query string - Group B (parallel after A): #5 backup verification cron, #6 5-7 e2e security tests - #4 classroomController.js split (1618 lines → 6 domain files) — sequential, after Group A - #8 YAML seed importer (one collection migrated as proof) — after #4 - #7 versioned migrations (baseline = current schema) — last, riskiest **Pre-existing infrastructure (don't reinvent):** - `backend/tests/setup.js` has node:test + `inject()` helper — use for Task 6 - `npm run migrate` script exists in `backend/package.json` - WAL + FK + synchronous=NORMAL already enabled in `backend/src/db/db.js:27-31` - `backup.sh` already does VACUUM INTO + 7-day rotation - `requireOwnership({ table, ownerField, fetchFn })` factory exists in `backend/src/middleware/ownership.js` **Conventions enforced (from CLAUDE.md, must mention in every brief):** - ast-index FIRST for code search; Grep tool BANNED - No emoji in code (only inline SVG `.ic`) - After any change: `git add && git commit -m "..." && git push origin master` - Read with offset/limit, not full files