lct-hack/scripts/demo.sh
Ivan Gerasimov d55c8bc8cd feat: вход, роли и аудит действий (lct-23)
Самое крупное расхождение с ТЗ: входа не было вовсе, экраны открывались
ссылкой с номером занятия, и пускало знание адреса.

- Таблицы users и audit_log, миграция. Пароль argon2, сессия — подписанная
  cookie; роль на сокетах читается из той же cookie в момент рукопожатия,
  отдельного протокола авторизации в канале нет.
- Разграничение: control — преподавателю, observe — преподавателю и админу,
  call и station — обучающемуся и преподавателю. Отказ приходит событием
  error с кодом forbidden.
- Обучающийся не видит чужого: история подменяет фильтр на его собственный
  идентификатор, разбор и профиль сверяют trainee_id. ТЗ запрещает доступ
  к чужим результатам, а не только к чужим экранам.
- Администратору закрыта правка оценок — ТЗ запрещает это прямо.
- make users заводит по записи на роль и печатает случайные пароли один раз:
  зашитый в репозиторий admin/admin пережил бы сдачу.
- Экран входа и проверка роли на каждом маршруте фронта.

Наши инструменты не сломались: make lesson и тесты входят через dev-token
за флагом dev_auth_bypass, на стенде точка отвечает 404 — выключенной
функции не должно быть видно вовсе. У тестов появился conftest.py.

Role уехала в домен и в generated.ts через EventCatalog.principal: иначе
фронт переписывал бы список ролей руками.

181 тест зелёный (14 новых), make typecheck чистый.
2026-09-20 09:01:05 +03:00

64 lines
2.7 KiB
Shell
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# make demo: поднять стенд для занятия или показа.
#
# Postgres в контейнере, бэкенд и фронт — нативно: модели речи под WSL работают
# нативно, так они и мерялись (docs/LATENCY.md). Скрипт обкатывается заранее,
# а не пишется в последнюю ночь: им поднимают стенд в классе.
set -euo pipefail
cd "$(dirname "$0")/.."
say() { printf '\n\033[1m%s\033[0m\n' "$*"; }
say "1/5 Модели"
missing=0
for path in backend/models/e5-small/model_quantized.onnx \
backend/models/gigaam-v3-onnx/v3_rnnt_encoder.int8.onnx \
backend/models/silero-vad/silero_vad.onnx \
backend/models/silero-tts/v5_ru.pt; do
if [ ! -f "$path" ]; then echo " нет $path"; missing=1; fi
done
if [ "$missing" = 1 ]; then
echo " запусти: make models (Silero TTS качается вручную, скрипт подскажет)"
exit 1
fi
echo " все модели на месте"
say "2/5 База"
docker compose up -d postgres
( cd backend && uv run alembic upgrade head >/dev/null )
echo " миграции накатаны"
say "3/5 Сценарии и учётные записи"
make seed
make users
say "4/5 Бэкенд с голосом"
# Контейнерные бэкенд и фронт гасим: порты те же, а голос работает нативно.
docker compose stop backend frontend >/dev/null 2>&1 || true
# Подоболочка явно: `cd backend && команда &` уводит в фон всю связку,
# а родительская оболочка остаётся на месте — следующий `cd ..` увёл бы её
# из репозитория, и фронт запускался бы не оттуда.
( cd backend && OFFLINE=true exec uv run --extra voice uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 1 ) &
BACKEND=$!
trap 'kill $BACKEND $FRONTEND 2>/dev/null || true' EXIT INT TERM
for _ in $(seq 1 60); do
if curl -sf localhost:8000/api/health | grep -q '"models_ready":true'; then break; fi
sleep 2
done
curl -s localhost:8000/api/health; echo
say "5/5 Фронт"
npm --prefix frontend run dev -- --host 0.0.0.0 &
FRONTEND=$!
say "Стенд поднят"
cat <<'LINKS'
вход: http://localhost:5173/ (пароли печатает make users)
пульт преподавателя: http://localhost:5173/instructor
профили курсантов: http://localhost:5173/profile
ссылки на АРМ курсанта, монитор и ДДС печатает сам пульт
Ctrl+C гасит стенд.
LINKS
wait $BACKEND