Миграция 051: расширяет content_access.content_type на 'course'/'sim' (пересборка
таблицы — SQLite не умеет ALTER CHECK) + мост «открыть все включённые симуляции
всем существующим классам» → текущее поведение не меняется. GET /api/lab/sims
теперь фильтрует список для НЕпривилегированных по allowedRefs(uid,'sim'); admin/
teacher видят все. Ролевой simulations.access остаётся «модуль вкл.» (добавочно).
Тесты: lab-access (4/4, allowlist+класс+личное), lab-sims переведён на admin для
проверки полного каталога (видимость ученика — в lab-access). /api/lab в харнессе.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- lab.js: GET /api/lab/links/all?kind= — пакетный обратный поиск (byRef map),
чтобы каталог учебников не делал N+1 запросов
- tests/lab-links.test.js: +3 теста для /links/all (group/400/401) -> 21/21
- admin/sections/sims.js: inline-редактор курикулумных связей на карточке симуляции
(кнопка «Связи» -> панель: список связей с удалением + выбор учебника + добавить);
использует /api/access/catalog, POST/DELETE /links. Без LS.modal (inline-панель)
- textbooks.html: кнопка «В лабораторию» на карточке учебника, если есть связанные
симуляции (один батч-запрос /links/all при загрузке); deep-link /lab?sim=<id>
Двусторонняя навигация sim <-> учебник готова. Иконки .ic, без эмодзи.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GET /related и /links возвращали 200 без токена: они были ПОСЛЕ blanket
router.use(requireRole('admin')) (хрупкий порядок при повторном mount роутера
в тестах). Убрал blanket; каждая мутация (patch/reorder/links POST+DELETE)
имеет INLINE requireRole('admin'); read-роуты — auth-only.
Также lab-links seed переведён на seedRow() (NOT NULL дрейф схемы).
lab-links 18/18, lab-sims 11/11, route-auth: 0 роутов lab.js во флаге.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Миграция 043_lab_sim_links.sql: таблица связей (sim_id, kind[textbook|topic|
kmap|question], ref_id, label), UNIQUE(sim_id,kind,ref_id) + индексы. Применена.
- lab.js (расширение):
- GET /api/lab/sims/:id/related (auth inline) — связи по типам; label из
textbooks/topics; href для навигации
- GET /api/lab/links?kind=&ref_id= (auth) — обратный поиск включённых
привязанных симуляций (для кнопки «Открыть в лаборатории»)
- POST /api/lab/sims/:id/links (admin), DELETE .../links/:linkId (admin)
- graceful-degradation если таблица ещё не отмигрирована
- tests/lab-links.test.js: 18 тестов (auth/роли/related/reverse/валидация/дубль/
enabled-фильтр/удаление); seedRow() устойчив к NOT NULL дрейфу схемы
- plans: Фаза 5 done + handoff
Все мои тесты: lab-sims 11/11, lab-links 18/18. route-auth: новый :id-роут
защищён inline authMiddleware. Миграция применена к живой БД.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1. cirSim ReferenceError в _pauseAllSims/closeSim (регрессия Фазы 3): глобалы
экземпляров симуляций объявлены в ленивых файлах -> не существуют до открытия.
Предсоздаём их как window-свойства (null) -> guard'ы безопасны. (lab-init.js)
2. theory-data.js (вынос THEORY параллельной сессией) не подключался в lab.html
-> панель теории и fallback loadTheory ломались. Добавил перед _register-all.
3. _pilots.js удалён в Фазе 1, но lab.html ссылался -> 404. Убрал ссылку.
4. /api/lab/sims 500 на неотмигрированном/устаревшем инстансе -> деградация:
возвращаем пустой каталог + needs_migration вместо 500. (routes/lab.js)
Проверка: vm-доказательство (_pauseAllSims без throw), node --check всех файлов,
lab-sims тесты 11/11. ВАЖНО: на работающем dev-сервере нужен ПЕРЕЗАПУСК (сервер
не авто-мигрирует) — таблица lab_sims уже в live БД.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>