This commit is contained in:
2026-10-11 15:00:22 +07:00
parent 2b7b95fe2b
commit f25c48b57b
8 changed files with 222 additions and 6 deletions
+6 -3
View File
@@ -27,13 +27,13 @@
### ED-029 — Автономная площадка и панель организатора
- Статус: `IN_PROGRESS` — этап 3 принят пользователем без WAN; этапы 4–13 завершены; аппаратная приёмка этапа 8 подтверждена пользователем.
- Статус: `IN_PROGRESS` — этап 3 принят пользователем без WAN; этапы 4–14 завершены; автоматическая часть этапа 15 завершена, аппаратная приёмка остаётся; этап 8 принят пользователем.
- Репозитории: корневой, `evening_detective_server`, `evening_detective_frontend`.
- Цель: реализовать принятый пользователем план из 15 последовательных этапов: автономное окружение; локальные организаторы; прежние адреса через Cudy; пакет игры; экспорт со статусом офлайн-режима; локальный импорт; интерфейс передачи; полный билетный и игровой flow; пакет результатов; возврат онлайн; интерфейс возврата; устройства; панель состояния; сбор данных Cudy; Wi-Fi и испытание площадки.
- Критерии: проверяемый результат каждого этапа; цикл «онлайн → ноутбук → проведение → онлайн» через интерфейс с сохранением QR, билетов и связей; повторные импорты без дублей; мониторинг устройств и Wi-Fi; полный прогон без WAN, 100 клиентов и проверка покрытия.
- Ограничения: только тестовые игры до завершения возврата; существующие правила игры и формат `offline` сохраняются; без несогласованных новых зависимостей и отклонений от стандартов; без персональных списков игроков, CPU/памяти Cudy и автоматического переключения серверов; настройки роутера менять только по явному запросу пользователя; секреты и пакеты вне Git; commit/push выполняет пользователь.
- Проверка: Go-стандарт и `go test ./...`; PostgreSQL-интеграционные тесты для атомарности; frontend-стандарт, type-check, lint, lint:css и build; штатная генерация protobuf; ручные контрольные точки после этапов 3, 8, 11, 15.
- Прогресс: этапы 1–2 реализованы и проверены в локальном Docker-окружении. Добавлены отдельный Compose, подготовка образов заранее, постоянные тома, миграции перед стартом, healthchecks и прокси. Явный `APP_MODE=venue` отключает SMTP, фоновые письма и внешний webhook; почтовые операции аккаунта возвращают безопасную ошибку до изменения данных. Локальные аккаунты создаются штатным `dev-user.sql`, роли и правила автоматического подтверждения команд сохраняются. Этап 3 принят пользователем после проверки без WAN; формат и код пакета игры (этап 4) реализованы и проверены. Экспорт со статусом офлайн-режима (этап 5) и локальный импорт (этап 6) реализованы и проверены. Этап 7 реализован и проверен; этап 8 проверен на изолированном стенде и принят пользователем на аппаратной контрольной точке; этапы 9–13 реализованы и проверены; этапы 14–15 ещё не завершены.
- Прогресс: этапы 1–2 реализованы и проверены в локальном Docker-окружении. Добавлены отдельный Compose, подготовка образов заранее, постоянные тома, миграции перед стартом, healthchecks и прокси. Явный `APP_MODE=venue` отключает SMTP, фоновые письма и внешний webhook; почтовые операции аккаунта возвращают безопасную ошибку до изменения данных. Локальные аккаунты создаются штатным `dev-user.sql`, роли и правила автоматического подтверждения команд сохраняются. Этап 3 принят пользователем после проверки без WAN; формат и код пакета игры (этап 4) реализованы и проверены. Экспорт со статусом офлайн-режима (этап 5) и локальный импорт (этап 6) реализованы и проверены. Этап 7 реализован и проверен; этап 8 проверен на изолированном стенде и принят пользователем на аппаратной контрольной точке; этапы 9–13 реализованы и проверены; этап 14 реализован и проверен на настоящем TR3000; код и автоматические проверки этапа 15 завершены, ожидается аппаратная приёмка Wi-Fi.
- Дополнение по запросу пользователя: структура `venue` приведена к `prod` (`backend/`, `frontend/dist/`, `migrations/`, `Dockerfile.backend`, `docker-compose.yml`, `deploy.sh`); имена основных Compose-сервисов совпадают. Общая генерация `make build` / `make prod-build` готовит артефакты обеих папок; frontend собирается отдельно с настройками своего окружения. Текущие файлы `prod` при этой работе не изменяются; сборка проверяется с production-выводом в `/tmp`.
- Упрощение запуска: отдельные `init.sh` и `prepare.sh` удалены, всё собрано в `deploy.sh`. Единственная команда запуска — `make venue`: создаёт `.env` только при его отсутствии, при необходимости готовит зависимости/образы и автоматически создаёт организатора. Повторный готовый запуск не собирает и не скачивает образы. `make venue-update` явно пересобирает окружение с интернетом. Аккаунт организатора синхронизируется со значениями `.env` при каждом запуске. Первый запуск, повторный запуск без интернета и обновление проверяются `python3 tests/venue/deploy.py` с подставными командами; реальный готовый запуск проверен через Docker и API-smoke.
- Настройки площадки: по запросу пользователя необязательный `venue/.env.example` удалён; настройки создаются автоматически через `make venue`. Убраны ссылка и проверка примера; `python3 tests/venue/deploy.py` прошёл. Существующая `.env` не изменялась.
@@ -84,7 +84,10 @@
- Результат этапа 13 (2026-10-11): venue-вкладка «Состояние» `/games/:id?tab=state` показывает серверные connected/serverTime, количество доступных устройств/устройств без связи/подключений, UUID профиля, последние обращения и раскрываемые подключения с типом, ID команды/экрана, статусом, IP и User-Agent. Нет связи идёт первым, затем UUID; непривязанные браузеры исключает фильтр игры. Generated GetDevices вызывается сразу и каждые 5 секунд через useSimplePolling только на активной вкладке, без параллельных запросов; поздние ответы после смены игры, ухода и уничтожения игнорируются. Первичная загрузка, пустой список, встроенная ошибка, сохранение предыдущего снимка/времени и повтор реализованы без повторных toast. Вкладка доступна с клавиатуры. Игровые показатели, Cudy и история присутствия не добавлялись.
- Доступ этапа 13: GetGames/GetGame и UI permissions расширены для разработчика только в venue. Разработчик без организатора/администратора/автора получает явный whitelist ID/названия/описания/формата/места/планового начала/статуса; GetGame использует краткое чтение без сценария/команд. UI скрывает создание и результаты, показывает название и только состояние, нормализует другие tab, не загружает экраны/музыку/план/карту/ответы; heartbeat остаётся браузерным. Дополнительные роли, импорт и запреты игровых действий сохранены; prod новые права не получает. При смене роли полный поздний GetGame не применяется, приватные баннер/модалки скрываются.
- Проверки этапа 13: gofmt, полный go test ./..., race-тесты device_presence_service/app с управляемыми часами этапа 12; frontend type-check/lint/lint:css/build и self-check gameState прошли. Self-check покрывает сводку/сортировку, активность, отсутствие параллельных запросов, поздние ответы, ошибку/восстановление. Изолированные PostgreSQL/RustFS API-регрессии и Firefox проверили организатора, три подключения одного профиля, клавиатуру, смену контекста, пустой список, потерю/восстановление GetDevices, остановку запросов на другой вкладке, разработчика venue/prod, безопасные GetGame/GetGames и отсутствие закрытых фоновых запросов. API/protobuf/миграции/зависимости не менялись. Ручное ревью diff по Go/frontend-стандартам и независимое read-only ревью выполнены; пользовательские изменения prod/reproxy/backend-бинарника сохранены. Работающие окружения и Cudy не менялись.
- Следующий шаг: этап 14 — сбор данных Cudy. Этап 13 завершён; общая задача остаётся `IN_PROGRESS` и не переносится в архив. ZIP остаётся неподписанным. Фактический ZIP 1 ГиБ, нагрузка на 100 клиентов и покрытие Wi-Fi не проверялись; развёртывание, commit/push не выполнялись.
- Результат этапа 14 (2026-10-11): отдельный процесс того же backend-бинарника `--collect-cudy` читает текущих Wi-Fi-клиентов Cudy через штатный вход и GET страницы клиентов раз в 10 секунд. Проверен настоящий TR3000 V1 2.5.27-20260804-183625; настройки не менялись. Собираются только MAC/IP/диапазон/доступный сигнал dBm, без имён, трафика и истории. Пароль читается из локального файла, не выдаётся API/логами; `venue/cudy/` исключён из Git. URL ограничен числовым private/loopback IP, redirects тем же host/scheme, ответ 2 МиБ, HTTP timeout 5 секунд, сессия переиспользуется и восстанавливается. Неизвестная разметка вызывает ошибку вместо ложного пустого списка. Collector изолирован в entrance без БД/RustFS; backend сохраняет внутреннюю сеть и читает общий атомарный снимок read-only. Без credential-файла обращений к роутеру нет.
- Результат автоматической части этапа 15: Wi-Fi-блок вкладки состояния показывает весь Cudy независимо от игры, MAC/IP/диапазон/dBm или «Нет данных», число клиентов, последний успешный снимок, ошибку/устаревание. При ошибке collector сохраняет прежние данные и время, включая перезапуск; свежесть 30 секунд считает сервер, история не сохраняется. MAC не связывается предположениями с UUID браузера. Существующий GetDevices расширен Wi-Fi-полем с теми же venue/role guards, нового endpoint/миграций/зависимостей нет. Обновлены protobuf/OpenAPI и оба generated clients.
- Проверки этапов 14–15: gofmt, `go test ./...`, race Cudy/wifi/presence/app, frontend type-check/lint/lint:css/build и self-check состояния прошли. Mock Cudy проверяет hash/CSRF/session/readonly GET, DOM/оба диапазона/сигнал/неизвестную разметку; снимок проверен атомарно и с управляемыми часами; CLI self-check подтвердил сохранение клиентов/времени после перезапуска при недоступном роутере. Firefox выявил прежнюю гонку раннего возврата ZIP до загрузки ID игры; действия передачи/возврата теперь появляются только после загрузки положительного ID. Итоговый изолированный Firefox-прогон обоих форматов (1440/390 px) прошёл: Wi-Fi fixtures, устройства/роли/polling и полный цикл ZIP до повторного возврата после перезапуска. Полный API-flow с PostgreSQL/race-регрессиями также прошёл; временные стенды удалены. `load.py` прошёл на отдельном Docker-стенде без WAN: 100 виртуальных профилей, 25 команд, 60 секунд, 300 heartbeat, 1200 story, 50 ходов, 25 ответов и 12 опросов состояния; ровно 100 доступных устройств и ноль HTTP-ошибок. p95: heartbeat 118 мс, story 68 мс, move 109 мс, answers 45 мс, devices 138 мс (бюджет теста 2 с). Нагрузка backend идёт по HTTP напрямую; DNS/HTTPS/Nginx проверены отдельно `dns.py --docker`/`https.py --docker`. Ручное ревью по стандартам и независимое read-only ревью выполнены; замечание о ложном пустом DOM исправлено и покрыто регрессией.
- Следующий шаг: аппаратная контрольная точка этапа 15 по `tests/venue/README.md`: после отдельно согласованного обновления площадки Android/iPhone, отключённые WAN/мобильные данные, 100 настоящих Wi-Fi-устройств и покрытие зала. Пользователь выбрал автоматическую нагрузку 100 виртуальных клиентов с отдельной ручной аппаратной приёмкой. До её подтверждения ED-029 остаётся `IN_PROGRESS` и не переносится в архив. Всего 15 этапов. ZIP остаётся неподписанным, фактический ZIP 1 ГиБ не проверен; развёртывание, commit/push не выполнялись.
### ED-024 — Общая дизайн-система фронтенда