fix: глубокое ревью онлайн-урока — 14 исправлений (P0-P3)

P0 — краши:
- CREATE TABLE classroom_hands в migrate.js (отсутствовала)
- emit→emitToUser для allowDraw/revokeDraw/mutePeer (WS доставка)
- deleteHistorySession обёрнут в db.transaction() + добавлена очистка hands/invites

P1 — гонки и безопасность:
- deletePage: 4 SQL в транзакции (race при параллельной записи)
- postStrokes: MAX(seq) внутрь транзакции (дубли seq)
- duplicatePage: добавлен seq в INSERT (NOT NULL crash)
- hasAccess для lowerHand/getHands/reactToMessage (утечка данных)
- loadTemplate: проверка owner шаблона
- attachment_url: только /uploads/* (XSS через javascript:/data: URI)
- wbFlushBatch: backoff при ошибке (было 12.5 req/s retry)
- pagehide leave: keepalive fetch для гарантированной доставки
- _wbOwnIds: cap 2000 (утечка памяти на длинных уроках)

P2-P3:
- simState: лимит 64KB (предотвращает OOM broadcast)
- ws-server кеши: cleanup drawCache при invalidateSession

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-04-16 09:22:39 +03:00
parent f1e6ed7f2d
commit 6cd0cf34d4
4 changed files with 92 additions and 36 deletions
+9
View File
@@ -2870,6 +2870,15 @@ db.exec(`
)
`);
// Raised hands (persisted — survives server restart)
db.exec(`
CREATE TABLE IF NOT EXISTS classroom_hands (
session_id INTEGER NOT NULL REFERENCES classroom_sessions(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id),
PRIMARY KEY (session_id, user_id)
)
`);
// ── Geometry (Planimetry) ────────────────────────────────────────────────────
// Saved geometry constructions (teacher-created tasks/templates)
db.exec(`