---
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 <files> && git commit -m "..." && git push origin master`
- Read with offset/limit, not full files
