98 KiB
98 KiB
Задачи проекта
Активный список задач для разработки и работы агента.
Новые задачи добавляются сюда после уточнения требований; отдельный файл-план
для нетривиальной задачи не создаётся. Завершённые задачи переносятся в
COMPLETED_TASKS.md.
Формат задачи
Каждая активная задача содержит:
- цель и ожидаемый результат;
- критерии готовности;
- проверку и ручной smoke-сценарий, если он нужен;
- ограничения и явно исключённые из задачи изменения;
- следующий конкретный шаг.
Статусы
TODO— готово к работе.IN_PROGRESS— выполняется.BLOCKED— заблокировано, причина указана в задаче.DONE— завершено и проверено.
Активные задачи
ED-029 — Автономная площадка и панель организатора
- Статус:
IN_PROGRESS— этап 3 принят пользователем без WAN; этапы 4–13 завершены; аппаратная приёмка этапа 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 ещё не завершены. - Дополнение по запросу пользователя: структура
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не изменялась. - Группировка проверок:
deploy.pyиsmoke.pyсобраны вtests/venue/с поясняющим README, пути к площадке и команды в документации обновлены; для обычного запуска эти файлы не нужны.python3 tests/venue/deploy.pyиpython3 tests/venue/smoke.py --verifyпрошли; diff проверен. - Уточнение названия: автономная площадка называется
venue, чтобы не смешивать её с локальной разработкой. Папка, Make-команды, образ, Docker-проект, режимAPP_MODE=venueи настройкиVENUE_*переименованы; существующая.envперенесена с сохранением секретов и учётной записи. Служебные имена прежних томов сохранены для сохранности данных; тома подключаются как внешние и создаются автоматически при первом запуске. Go-тесты, тест запуска и API-smoke после переименования прошли;prodне изменён. Ручное ревью diff по стандарту Go выполнено. - Проверка дополнения завершена:
make build PROD_DIR=/tmp/evening-artifacts-checkпрошёл, backend и миграции в обоих наборах совпадают; type-check и две frontend-сборки прошли. Проверены Compose config, shell-синтаксис и diff. Local собран и запущен через новыйdeploy.sh; API-smoke и Firefox подтвердили вход, тестовую игру, подтверждённую команду и сохранность материала. Контрольные суммы файловprodдо и после работы совпадают. Проверка production-запуска не выполнялась; существующие файлы и конфигурацияprodне изменены. - Результат проверки этапов 1–2: ручное ревью diff по Go- и frontend-стандартам выполнено, отклонений нет;
gofmt,go test ./..., frontendtype-check,lint,lint:css, сборка и полныйsh venue/prepare.shпрошли. Compose config и shell-синтаксис проверены. Smoke через API создал тестовую игру, подтверждённую команду и материал; послеdown/up --no-build --pull neverвсё сохранилось. Firefox без окна подтвердил реальный вход, экран игры и команду после перезапуска. Приложение не имеет внешнего маршрута сети. Повторная инициализация не перезаписывает секреты. Инструкции запуска и повторяемый API-smoke находятся в корневом README иtests/venue/smoke.py. Проверка телефонов при отключённом WAN ещё не выполнена. - Внешние данные: запрошены модель/IP Cudy, постоянный IP ноутбука, доступ к проверенной прошивке и возможность DNS-проверки для сертификатов. Проверки телефонов, 100 клиентов и покрытия требуют оборудования.
- Привязка ноутбука на Cudy по явному запросу «закрепи сам»: перед изменением подтверждены текущие IP 192.168.10.155 и MAC BC:D2:2C:29:4A:96. Через штатную форму IP/MAC Binding добавлена запись
Venue laptop, выполнен Save & Apply; повторное чтение подтвердило ровно одну новую запись с нужной парой IP/MAC и сохранность обеих существующих привязок. DHCP/DNS-настройки и прошивка не менялись. Проверка DNS venue по UDP/TCP после сохранения прошла. Принудительное переподключение ноутбука для проверки новой DHCP-аренды не выполнялось; проверка телефонов без WAN остаётся обязательной. - Локальный DNS по согласованию пользователя добавлен: CoreDNS 1.14.7 запускается с venue на TCP/UDP 53 только на
VENUE_BIND_IP; оба домена возвращают этот IPv4, AAAA-запросы не получают внешних адресов. Отдельные локальные зоны не пересылаются upstream; остальные домены направляются в 1.1.1.1/8.8.8.8 при доступном WAN. DNS подключён только к сети публикации портов и не имеет доступа к внутренней сети приложения/БД. Образ закреплён по версии, скачивается при отсутствии и используется повторно; новая инфраструктурная зависимость явно согласована пользователем. Локальная.envизменена только вVENUE_BIND_IP=192.168.10.155, секреты сохранены.make venueуспешно пересобрал образ из готовых файлов, выполнил миграции и перезапустил HTTPS/DNS с сохранением томов. Настройки Cudy не менялись. - Проверки DNS:
python3 tests/venue/deploy.py,python3 tests/venue/https.py --docker,python3 tests/venue/dns.py --docker,python3 tests/venue/dns.py --server 192.168.10.155, shell-/Python-синтаксис иgit diff --checkпрошли. Реальный CoreDNS в отдельной внутренней Docker-сети подтвердил локальные ответы по UDP/TCP и отсутствие внешних IPv6-ответов без WAN до/после перезапуска. Проверены Compose mount/порты/DNS-IP и изоляция backend; обычный внешний домен успешно разрешается через upstream на запущенной площадке. HTTPS-smoke с принудительным разрешением обоих имён только в IP ноутбука и обычной проверкой TLS подтвердил вход организатора, сохранность тестовой игры/команды/материала, SPA и отключённые email-операции. Ручное ревью diff выполнено; код Go/Vue и protobuf не менялся. Проверка DNS через DHCP Cudy и телефонов без WAN ещё требуется; IP ноутбука пока динамический. - Проверка реального Cudy: TR3000, прошивка 2.5.27 DE, панель доступна на 192.168.10.1; текущий DHCP-IP ноутбука 192.168.10.155 ещё не закреплён. По предоставленному пользователем файлу выполнен вход и прочитаны Custom DNS и DHCP. В этих разделах нет формы статических записей «домен → IP»: Custom DNS выбирает upstream DNS, DHCP позволяет выдавать клиентам Preferred/Alternate DNS. Настройки роутера не менялись. Для сохранения штатной прошивки предложен отдельный локальный DNS на ноутбуке с двумя записями и выдачей его адреса через DHCP; это дополнение к прежнему плану требует согласования инфраструктуры. Пользовательский pass.txt защищён режимом 600 и исключён из Git; пароль и сессионные данные не выводились. Следующий шаг — согласовать реализацию локального DNS, закрепить IP, настроить DHCP и выполнить аппаратную приёмку.
- Выпуск сертификата по запросу пользователя начат: скачан официальный образ Certbot, отдельный ACME-аккаунт и запрос на два домена созданы в игнорируемом
venue/certificates/acme/с ограниченным доступом. Certbot ожидает добавления двух TXT-записей DNS-01 в публичный DNS; доступ к DNS в среде отсутствует, значения переданы пользователю. Сертификат ещё не выдан и не установлен; production-ключи и настройки не использованы, площадка не перезапускалась. После появления записей проверить публичный DNS, завершить валидацию, установить полную цепочку и ключ вvenue/certificates/и проверить их перед запуском. - Результат выпуска сертификата: после добавления пользователем TXT-записей оба значения проверены через публичный DNS, DNS-01 успешно пройден. Отдельный сертификат Let's Encrypt для обоих прежних доменов установлен в
venue/certificates/fullchain.pem, ключ — вprivkey.pemс режимом 600; каталог и ACME-файлы вне Git, production-ключ не использован. Срок действия до 2027-01-08 06:53:26 UTC. OpenSSL подтвердил системное доверие полной цепочке, оба домена и соответствие ключа; игнорирование обоих файлов проверено. Автопродления нет: до истечения срока повторить DNS-01 и установить обновлённые PEM-файлы. Площадка в рамках выпуска сертификата не перезапускалась; Cudy и телефоны без WAN ещё не проверены. - Актуальный запуск по последующему запросу пользователя:
make venueвсегда использует HTTPS-дополнение, выполняетdocker compose build --pull=falseиз заранее подготовленных артефактов иup --force-recreate --no-build --pull never; тома данных сохраняются.venue-updateиvenue-https— алиасы единого запуска. Сертификат проверяется до Docker; Go/Vue и npm-зависимости при деплое не собираются. Отсутствующие runtime-образы и базовый Alpine скачиваются, имеющиеся не обновляются автоматически. HTTPS теперь используется smoke-проверкой по умолчанию. README и тесты приведены к единому поведению;python3 tests/venue/deploy.py, shell-синтаксис, Python-синтаксис, dry-run всех трёх Make-команд иgit diff --checkпрошли; diff вручную проверен. Реальный перезапуск площадки с публичным сертификатом и сборка Docker-образа без WAN не выполнялись; Cudy и проверка телефонов остаются внешней контрольной точкой. - Уточнение сборки по запросу пользователя: деплой больше не вызывает
make build, Go/Vue-сборку или установку npm-зависимостей. Артефакты заранее готовятся существующимmake prod-buildв обеих папках; при отсутствии бинарника, Goose, bootstrap SQL, frontend или SQL-миграций запуск завершается до Docker с понятной ошибкой.make venue-updateтолько упаковывает готовые файлы в Docker-образ и подготавливает runtime-образы. README обновлён; тесты первого, автономного и update-запуска подтверждают отсутствие make/npm, ошибки отсутствующих артефактов и сохранность настроек.python3 tests/venue/deploy.py,python3 tests/venue/https.py,bash -n venue/deploy.sh,git diff --checkпрошли; diff вручную проверен. Повторная реальная сборка приложения и запуск площадки не выполнялись; код дочерних репозиториев не менялся. - Подготовка этапа 3: добавлены
make venue-https, отдельное Compose-дополнение и Nginx-конфигурация для прежних доменов интерфейса/API. HTTP перенаправляется на HTTPS с сохранением пути и параметров; API и материалы доступны через домен интерфейса и прежний API-домен. HTTPS-дополнение задаёт публичные адреса ссылок без изменения.env. Сертификат и ключ подключаются только для чтения из игнорируемого каталога; до Docker проверяются доверие полной цепочке, оба домена, срок действия и соответствие ключа. Повторный HTTPS-запуск перечитывает сертификат без пересборки. Обычный HTTP-запуск сохранён; добавлены HTTPS-smoke и инструкции DNS-01, LAN, продления и ручной приёмки. Код Go/Vue, protobuf, схема БД и конфигурацияprodне менялись; новых зависимостей нет. - Проверки подготовки этапа 3:
python3 tests/venue/deploy.py,python3 tests/venue/https.py --docker,bash -n venue/deploy.shиgit diff --checkпрошли; Python-файлы проверены на синтаксис. Проверены реальный Compose merge, прежние тома и внутренняя сеть backend. Временные Docker-контейнеры с тестовым CA подтвердили проверяемый TLS/SNI, оба домена, redirects, API/материалы, SPA-пути с параметрами, перезапуск и замену сертификата через reload; свои ресурсы тест удалил. Проверки сертификатов покрывают отсутствующие/повреждённые файлы, неверный и зашифрованный ключ, недоверенную/неполную цепочку, отсутствие каждого домена и истечение срока; ошибка возникает до Docker, повторный готовый запуск не скачивает и не собирает образы,.envсохраняется. Ручное ревью diff выполнено; стандарты Go/Vue не затронуты. Реальное HTTPS-развёртывание, системное доверие телефонов, Cudy и WAN-off smoke не проверены из-за отсутствия оборудования/сертификата. Commit/push не выполнялись. - Подтверждение пользователя: venue работает в браузере ноутбука и на телефоне после настройки DNS. Проверка Android/iPhone при отключённом WAN и мобильных данных ещё не подтверждена.
- Проверка ноутбука после изменения настроек роутера пользователем: системный DNS разрешает UI-домен в 192.168.10.155; HTTPS UI и API возвращают HTTP 200 с этого IP, сертификат проходит проверку. В DHCP также получен второй DNS 192.168.10.10; его назначение не проверено. Пользователь подтвердил открытие venue на телефоне, проверка без WAN ещё не выполнена. В браузере ноутбука остаётся проверить обновление DNS-кэша и использование системного DNS.
- Результат настройки DHCP: по запросу пользователя в Cudy сохранён Preferred DNS=192.168.10.155, Alternate DNS пустой. Повторное чтение формы подтвердило значения и сохранение остальных настроек DHCP; проверка локальных доменов по UDP/TCP прошла. Получение DNS клиентами после обновления DHCP-аренды ещё не проверено.
- Приёмка этапа 3: пользователь сообщил «все проверил работает» после контрольного списка LAN-портов, обновления DNS устройств и проверки Android/iPhone с отключёнными WAN и мобильными данными. Аппаратный блокер снят по подтверждению пользователя; агент самостоятельно эти проверки не повторял.
- Результат этапа 4: добавлен
GamePackageServiceдля потоковой сборки и автономного чтения ZIP версии 1 из подготовленного снимка. Пакет сохраняет исходные ID, пароли QR, хеши/статусы билетов, email капитанов, сценарий с ответами, план экранов, карту команд/стола, плейлисты и все медиа. Внешние HTTP/HTTPS-медиа скачиваются с проверками адресов DNS/соединения/перенаправлений; локальные файлы доступны через адаптер существующего хранилища. Совпадающие файлы хранятся один раз. Архив и распакованный объём ограничены 1 ГиБ, файл — 64 МиБ, JSON — 8 МиБ, количество записей — 4096. Проверяются версия, связи, размеры, SHA-256, MIME, опасные пути, дубли и отсутствующие/посторонние файлы; временные каталоги и файлы имеют права 0700/0600 и очищаются на ошибке. БД, API, protobuf, зависимости и текущий архив сценария не изменены. Контракт и владение временными файлами описаны вevening_detective_server/docs/GAME_PACKAGE.md. - Проверки этапа 4:
gofmt,go test ./internal/services/game_package_service -count=1, полныйgo test ./...иgit diff --checkпрошли. Табличные тесты проверяют сохранение данных/секретов QR/билетов, оба назначения плейлистов, автономное чтение, внешние/локальные URL, дедупликацию, запрещённые адреса и redirects, повреждённые пакеты, масштабированные лимиты ZIP/распакованного объёма и отмену во время извлечения с сохранением родительского каталога. Потоковое чтение проверено на генерируемых медиа 1 и 16 МиБ с ограниченным размером чтения. Ручное ревью всего нового кода по Go-стандарту и независимое ревью проведены; замечания исправлены. Реальный пакет на 1 ГиБ, скачивание с внешнего production-хостинга и перенос игры между БД не проверялись; UI/экспорт/импорт реализуются на следующих этапах. Commit/push не выполнялись. - Результат этапа 5: сохранён согласованный SQL-снимок и одна активная попытка экспорта на игру. Снимок учитывает выбранную музыку в
game_music_states, команды, билеты, сценарий, план экранов и карту. Пакет собирается в фоне, потоково хранится в закрытом RustFS; PostgreSQL-очередь, heartbeat 30 секунд, аренда 2 минуты, timeout 30 минут и защита от устаревшего worker сохранены. API и оба protobuf-клиента сгенерированы; права трёх ролей и запрет экспорта вvenueпроверены. Повторное скачивание отдаёт те же байты, обрыв не меняет состояние. - Изменение решения (2026-10-11): по запросу пользователя жёсткая блокировка полностью удалена; функции/триггеры БД не используются. Все обычные операции игры, команды, билеты, прогресс, музыка, карта, экраны и почтовые задания продолжают штатную работу. В списке игр и на странице управления показываются подготовка офлайн-пакета (
preparing) и «Игра в офлайн-режиме» (ready). Это информационная отметка, без изменения игровогоstatusилиformat; при ошибке она исчезает. Онлайн-изменения после запуска не попадают в сохранённый пакет; локальный импорт реализован на этапе 6; возврат ещё не реализован. - Проверка этапа 5: ранее прошли реальный тестовый RustFS-цикл с перезапуском, проверкой ZIP кодеком, приватностью объекта, потоковой выдачей/обрывом и повторным скачиванием одинаковых байтов. После упрощения прошёл полный
go test ./...с PostgreSQL: снимок, редактирование вpreparing/ready, конкурентный запуск, аренда, устаревшая публикация, ошибка/повторный запуск и завершение/очистка после удаления игры. Frontendtype-check,lint,lint:cssи Vite build в/tmpпрошли;gofmtи diff проверены. Проверка интерфейса в браузере и повторный реальный RustFS-цикл в этом уточнении не выполнялись. API описан в backenddocs/GAME_PACKAGE.md. Production-развёртывание, commit и push не выполняются. - Результат этапа 6: добавлен потоковый
POST /api/games/import(сырой ZIP, JWT, роли admin/developer/organizer, только venue) и соответствующий protobuf-контракт. Кодек проверяет пакет до записи; игра, команды, билеты, сценарий, плейлисты, треки, план экранов, карта и метаданные публикуются одной транзакцией после загрузки медиа в локальный RustFS. ID игры/команд/билетов, пароли QR, хеши и состояния билетов сохранены. Сценарий/плейлисты/треки получают отдельные локальные ID; сценарий принадлежит импортирующему пользователю, исходные пользовательские ссылки не связываются с локальными аккаунтами. Исходный снимок и соответствия ID сохраняются в закрытом реестре импорта. Занятые ID/хеши и другой пакет той же игры отклоняются; повтор того же ZIP ничего не меняет, в том числе после локального редактирования или удаления игры. Реестр, heartbeat 30 секунд, аренда 2 минуты и timeout 30 минут защищают публикацию; очистка ошибок повторяется после перезапуска и не удаляет медиа при неопределённом ответе commit. Для маршрута импорта venue-прокси настроены лимит 1 ГиБ и потоковая передача; production-конфигурация не менялась. - Проверки этапа 6: штатные
make generateиnpm run proto:gen; полный обычныйgo test ./...; PostgreSQL-тесты импорта, экспорта и API;go test -raceдля imports repo/service и app; frontend type-check, lint, lint:css и Vite build в/tmp;python3 tests/venue/deploy.py,python3 tests/venue/https.py --dockerи diff-проверки прошли. Тесты покрывают связи исходных ID, локальные копии, QR/билеты, пустые наборы данных, последовательности, повтор/конкурентность, конфликты до/после загрузки, изменённые байты под тем же package ID, rollback, отмену, аренду/timeout, ошибки очистки и неопределённый commit. Реальный HTTP/RustFS smoke прошёл в отдельной internal Docker-сети без WAN, с отдельными PostgreSQL/RustFS, чтением медиа, перезапуском хранилища и повторным импортом; тестовые контейнеры и данные удалены. Nginx проверен на обоих HTTPS-доменах, включая POST импорта. Ручное ревью изменений по Go/frontend-стандартам выполнено. Пакет на 1 ГиБ, реальные телефоны и обновление работающей площадки не проверялись; новая миграция20261011120000_create_game_imports.sqlтребуется при обновлении. Commit/push не выполнялись. - Результат этапа 7: в настройках игры на подтверждённом prod доступны подготовка и скачивание пакета, состояния из
game.exportвосстанавливаются через существующий polling; ошибка допускает повтор подготовки, готовый ZIP — повтор скачивания. Добавлены пояснения о снимке и отсутствии подтверждения импорта. На venue в списке игр добавлена Naive UI-модалка импорта одного непустого ZIP до 1 ГиБ с именем/размером; загрузка блокирует повтор, смену файла, Escape и закрытие. После импорта обновляется список, показаны обычный/повторный результат и открытие с проверкой доступности игры; удалённая игра не восстанавливается. Действия доступны admin/organizer/developer, при неизвестной среде скрыты. Бинарный клиент сохраняет JWT-refresh, отправляет исходный File сapplication/zip, использует generated тип импорта, поддерживает обе формы ошибок и имя из Content-Disposition; object URL освобождается. Backend/API, зависимости и маршруты не менялись. - Проверки этапа 7: frontend type-check, lint, lint:css, Vite-сборка в
/tmpи diff-проверка прошли; ручное ревью по frontend-стандарту выполнено. Все 17 тестовnode src/stores/__tests__/auth.test.tsпрошли, включая ZIP-body/JWT-refresh, результат импорта, оба формата серверных ошибок, сетевую ошибку и UTF-8-имя скачивания. Firefox с подставным API на 1440/390 px проверил export polling, восстановление подготовки после обновления, ошибку/повтор и скачивание; импорт, повтор, удалённую игру, конфликт и сетевую ошибку; пустой файл, расширение, лимит; блокировки отправки/выбора/закрытия, Escape, клавиатурный focus в модалке, роли и неизвестную среду. Реальный перенос между серверами, телефоны и Blob-пакет на 1 ГиБ в этом этапе не проверялись; развёртывание не выполнялось. - Результат автоматической части этапа 8: добавлены повторяемые
tests/venue/flow.pyиflow_browser.py, команды и ручной контрольный список в README проверок. Актуальный код собирается в/tmp; стенд запускает два настоящих backend prod/venue с отдельными PostgreSQL/RustFS в Docker internal-сети без WAN, SMTP направлен в локальный sink. API проверяет оба формата, экспорт/импорт ZIP, исходные ссылки/ID/пароли команд и билетов, статусы участия, QR/PDF, обычный/повторный/конкурентный приём билетов, отказ без авторизации и неверные ссылки, локальные команды/билеты, старт/ходы/выдачу материалов/паузу/продолжение/завершение, ответы и баллы, результаты, перезапуск всех venue-сервисов и повторный импорт без потери прогресса. Проверена независимость источника и площадки; ограничения форматаofflineсохранены. После проверки удаляются только ресурсы стенда; ошибка очистки одного ресурса не останавливает попытки очистить остальные. - Исправления этапа 8: общий gameplay-сервис проверяет
runдо записи хода и подтверждения участия, одинаково для API/MCP; безопасная ошибка отображается как FailedPrecondition. Кнопка хода блокируется внеrunи при отправке; отказ показывается пользователю и сохраняет код. Кнопкам lifecycle добавлены доступные имена. Конкурентный приём билета теперь перечитывает текущее состояние и сообщает «билет уже использован», а не ошибочно «игра уже завершена». PostgreSQL-тест конкурентности синхронизирует запросы блокировкой строки: до исправления воспроизводил ошибку, после исправления проходит. - Проверки этапа 8:
python3 tests/venue/flow.py --browserпрошёл с реальными API/хранилищем и отдельным браузерным стендом. Firefox проверил полный UI-flow на 1440 px (online) и 390 px (offline), реальное скачивание/загрузку ZIP, билеты, ходы и polling, паузу с введённым кодом, двойную отправку, отказ с сохранением ввода, выдачу материала, оценивание/результаты, завершённый экран игрока, неверный пароль и клавиатурный focus в модалке. Внутри стенда прошли PostgreSQL-регрессии gameplay/lifecycle, tickets, MCP и app; отдельно прошёл полныйgo test ./.... Frontend type-check, lint, lint:css и сборка в/tmpпрошли; синтаксис Python,gofmt, diff-проверки, ручное ревью по Go/frontend-стандартам и независимое ревью затронутого flow выполнены. API/protobuf, миграции и зависимости не менялись. Работающие окружения и Cudy не изменялись; существующие пользовательские изменения бинарника иprodсохранены. - Приёмка этапа 8: пользователь подтвердил «Этап 8 принят» при согласовании следующего этапа. Отдельный повтор аппаратной проверки агентом не выполнялся.
- Результат этапа 9: добавлен серверный сервис подготовки и проверки ZIP результатов версии 1, без новых API/UI, protobuf, миграций и зависимостей. Read-only PostgreSQL-снимок
REPEATABLE READсвязывает завершённую импортированную venue-игру с ID/SHA-256 исходного пакета. Сохраняются итоговые команды/участие, исходные и новые билеты, явные удаления, пароли QR/хеши билетов, порядок и время ходов/MCP, материалы и их выдача, ответы и nullable баллы. Исходные ссылки пользователей восстанавливаются из реестра; локальные исполнители вынесены в отдельное пространство. Материалы ссылаются на исходный ZIP, без локальных адресов RustFS. Изменённый игровой сценарий/формат и неизвестные материалы отклоняются. Повторная подготовка создаёт новый снимок с актуальными оценками и не меняет игру; кодек проверяет состав, версию, размеры/CRC/SHA-256, лимиты JSON/ZIP, уникальность и связи. Контракт описан в backenddocs/GAME_PACKAGE.md. - Проверки этапа 9: полный
go test ./..., unit-тесты кодека/снимка иpython3 tests/venue/flow.py --resultsпрошли. Изолированный PostgreSQL/RustFS-стенд проверил обе игры, связь с исходным ZIP, новые локальные записи, прогресс/выдачу/ответы/баллы, свежий снимок после оценивания, конкурентное оценивание, сохранность предыдущего пакета, повтор после перезапуска и отсутствие изменений исходных игр. Unit-тесты проверяют удаления, пустые наборы, повторные/неизвестные ходы/MCP, исходных и локальных исполнителей, повреждённые ZIP и связи, лимиты, отмену и ошибки записи.gofmt, Python-синтаксис, diff-проверки, ручное ревью по Go-стандарту и независимое read-only ревью выполнены. Frontend-код не менялся; его штатная сборка в/tmpпрошла в составе стенда. Тестовые пакеты/контейнеры удалены; работающие окружения и Cudy не менялись. Commit/push и развёртывание не выполнялись. - Результат этапа 10: серверный
GameResultsApplyServiceпринимает ZIP только вprod, проверяет источник/игру/ID/SHA-256 экспорта и сохранённый исходный ZIP из закрытого хранилища. Источник команд/билетов/сценария/материалов/вопросов сверяется с ZIP, формат неизменяем. По уточнению пользователя ZIP считается источником истины: возвращаемые поля, включая онлайн-прогресс/баллы/формат и игровой сценарий, перезаписываются без сравнения с исходным или последним применённым состоянием. Изменённый сценарий восстанавливается отдельной копией для игры, не меняя сценарии других игр; исходные онлайн-ссылки материалов сохраняются. ОднаSERIALIZABLEтранзакция с блокировками и максимум тремя попытками при serialization failure/deadlock записывает итоговые команды/участие, билеты, удаления и связи карты, ходы/MCP, материалы/выдачу, ответы, nullable баллы,finishи фактические даты. Баллы не пересчитываются; оформление, плановая дата, музыка, карта и экраны сохраняют онлайн-изменения. Исходные ID сохраняются; новые команды сохраняют venue-ID/пароль, новым билетам/ходам/уликам выделяются онлайн-ID с реестром соответствий. Материалы возвращаются в исходные онлайн-ссылки без новых загрузок и скачивания URL. Онлайн-ссылки пользователей и технические почтовые поля сохраняются, локальные исполнители остаются в закрытом реестре; новые почтовые задания/токены не создаются, возвращённые игры исключены из очереди новых напоминаний об отзыве. - Реестр этапа 10: миграция
game_returnsсохраняет ID/хеш ZIP, экспорт, исходный ID игры, точное UTC-время подготовки с наносекундами, время применения, соответствия ID (включая сценарий), локальных исполнителей и инициатора. Реестр остаётся после удаления игры. Повтор тех же байтов возвращает сохранённую запись, включая старый пакет после нового и повтор после удаления игры; тот же ID с другими байтами отклоняется. Новый пакет требует строго более позднегоcreated_at, без поправок часов.game.exportскрывается в игре/списке после успешного возврата соответствующего экспорта; исходный экспорт остаётсяready, ZIP сохраняется. Входной ZIP проходит приватный staging, чтобы проверенные данные и SHA-256 относились к одним байтам; временные файлы 0600/0700 удаляются при успехе, отказе и отмене. - Проверки этапа 10: полный
go test ./...с отдельным PostgreSQL, релевантныйgo test -race, unit-тесты источника/материалов/пользователей/безопасных ошибок/private staging, PostgreSQL-регрессии rollback/удалений/ID и хеш-коллизий/последовательностей/точных повторов/конкурентности/порядка пакетов (включая шаг 1 нс)/исправленных баллов/онлайн-редактирования/почтовых заданий прошли.python3 tests/venue/flow.py --applyпрошёл для обоих форматов с настоящими venue-ZIP, prod PostgreSQL/private RustFS, исправлением баллов, прежними и новыми ссылками, сохранением оформления, исчезновением офлайн-отметки и повтором старого пакета после нового/перезапуска prod.gofmt, Python-синтаксис, diff-проверки, ручное ревью по Go-стандарту и независимое read-only ревью выполнены. Контракт обновлён в backenddocs/GAME_PACKAGE.md; API/UI, protobuf и зависимости не менялись. Тестовые контейнеры/ZIP удалены; рабочие окружения и Cudy не менялись. Commit/push и развёртывание не выполнялись. - Уточнение этапа 10 (2026-10-11): по запросу пользователя возвращаемый ZIP — источник истины, включая игровой сценарий. Удалены сравнения с исходным/последним онлайн-состоянием и поле
snapshotреестра. При отличии сценария создаётся копия для игры с исходными вопросами и онлайн-ссылками материалов; другие игры сохраняют свой сценарий, ID копии записывается в соответствиях. Проверки после изменения: полныйgo test ./...с отдельным PostgreSQL, race для return repo/results service/export service,flow.py --applyобоих форматов с перезапуском prod,gofmt, diff-проверка и ручное ревью по Go-стандарту прошли. PostgreSQL-регрессии проверяют перезапись онлайн-команд/ответов/баллов/формата, удаление добавленных онлайн-команд, смену/правки общего сценария и отсутствие повторного копирования неизменённого сценария. Онлайн-правки возвращаемых данных теряются намеренно; проверки источника, порядка пакетов, коллизий и атомарность сохранены. - Ограничение этапа 10: подлинность ZIP криптографически не подтверждается.
nextvalPostgreSQL не откатывается: большие разрывы venue-ID расходуют sequence даже при отказе. Продвижение выполняется пакетами с пределом пять секунд, затем данные откатываются и выдаётся безопасная повторяемая ошибка; INT32-потолок отклоняется. Перед поддержкой таких площадок требуется расширение типов ID; лимит отмеченshortcut:в коде и контракте. - Результат этапа 11 (2026-10-11): подключены сервисы подготовки/применения, protobuf/OpenAPI и отдельные HTTP handlers
results-package/downloadиresults-package/apply. Venue выдаёт свежий ZIP завершённой импортированной игры после полной подготовки в файле 0600; prod принимает ограниченный поток до 1 ГиБ без обязательного Content-Length. Положительный ID и совпадение с manifest проверяются до повтора и изменений; временные файлы очищаются. Ответ содержит только gameID/packageID/appliedAt; безопасные ошибки 400/413/409/503, права организатора/администратора/разработчика. В настройках игры добавлены скачивание и применение ZIP, явное предупреждение о перезаписи данных/сценария и сохранении оформления/музыки, клиентская валидация, обновление авторизации, загрузка и блокировка повторного запроса. После успеха страница пересоздаётся и перечитывает данные без старых ответов/черновиков; повтор сообщает «Результаты приняты». Возврат остаётся доступен после снятия офлайн-отметки. Обновлены репозиторные proxy configs (1 ГиБ/30 минут), контракт и изолированный стенд; работающие серверы не менялись. - Проверки этапа 11: штатная генерация обоих репозиториев, gofmt,
go test ./..., PostgreSQL/race-регрессии return repo/results/export service и HTTP поверх реального сервиса, frontend type-check/lint/lint:css/build, diff-проверки и ручное ревью по обоим стандартам прошли. Независимое ревью не выявило замечаний.python3 tests/venue/flow.py --apply --browserпрошёл полный цикл реальных API/PostgreSQL/RustFS/Firefox для online (1440 px) и offline (390 px): кнопка свежего ZIP → страница prod → результаты, прежние ссылки/билеты, сохранённые название/описание, снятая офлайн-отметка, исправленный балл, перезаписанный онлайн-ответ, повтор старого ZIP после нового и перезапуска. Проверены чужой ID до/после применения, права, MIME, заявленный размер, поток без Content-Length, безопасные ошибки и очистка файлов. Аппаратный прогон на телефонах не повторялся. - Результат этапа 12 (2026-10-11): добавлены потокобезопасный сервис присутствия в памяти, wiring, protobuf/OpenAPI
POST /api/devices/heartbeatиGET /api/devicesс фильтром игры. Проверяются UUID, взаимоисключающие контексты, JWT/существующие права игры, пароль команды и неотменённое участие без загрузки сценария/прогресса, существующая сессия экрана; ID игры команды/экрана определяет сервер. Реестр хранит только проверенные связи, UUID, серверные времена и последние IP/User-Agent; credentials не сохраняются и не выдаются. Полная замена/очистка контекста, граница связи строго менее 60 секунд, удаление через 15 минут при обновлении/чтении, предел 1024 сResourceExhaustedбез вытеснения существующих записей. В prod heartbeat явно возвращаетenabled=false, список недоступен. - Браузер этапа 12: общий heartbeat в App сразу/каждые 20 секунд без параллельных запросов, при видимости/восстановлении сети и смене контекста. UUID профиля отдельно от авторизации в localStorage с временным fallback, UUID подключения на экземпляр приложения. Контекст страницы очищается при уходе, отозванный lifecycle не может восстановить старые связи; смена игры/пароля пересоздаёт page-компонент. Generated client и обновление JWT организатора переиспользованы; публичные credentials команды/экрана не запускают обновление JWT. После
enabled=falsepolling прекращается. Ошибки не показывают toast и повторяются по интервалу. UI списка устройств не добавлен. - Проверки этапа 12: штатная генерация обоих репозиториев, gofmt,
go test ./..., race для presence service/app, frontend type-check/lint/lint:css/build, self-check UUID/store/composable и diff-проверки прошли. Unit-тесты с управляемыми часами покрывают повтор/вкладки/смену и очистку связей, границы 60 секунд/15 минут, лимит и конкурентное чтение/обновление; API-тесты — роли, режимы, safe errors и отсутствие секретов.python3 tests/venue/flow.py --browserпрошёл изолированные реальные API/PostgreSQL/RustFS/Firefox: credentials/отменённое участие, UUID/поля, группировку вкладок игрока/организатора/экрана, фильтр и привязку экрана, SPA-навигацию, прекращение heartbeat и восстановление сети, повторную регистрацию штатным интервалом после перезапуска backend. Независимое ревью выявило два замечания (публичный heartbeat не должен обновлять JWT, обрезка User-Agent должна сохранять UTF-8); оба исправлены и покрыты регрессиями. Итоговое ручное ревью по Go/Frontend стандартам выполнено; замечаний не осталось. - Результат этапа 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 не выполнялись.
ED-024 — Общая дизайн-система фронтенда
- Статус:
TODO - Приоритет:
P1 - Репозиторий:
evening_detective_frontend - Цель: создать единый источник правил, по которому можно последовательно делать новые экраны, компоненты и другие визуальные материалы.
- Контекст: во фронтенде уже есть визуальный язык на основе
base.css,main.css, бумажных и металлических текстур, шрифтаa_OldTyper, собственных компонентов иnaive-ui; его нужно формализовать без смены общего характера. - Решение: создать в фронтенде документ дизайн-системы и CSS-токены в существующем стиле проекта; описать цвета, типографику, размеры, отступы, сетку, адаптивность, поверхности, текстуры, состояния, фокус и доступность; зафиксировать правила для кнопок, полей, карточек, панелей, списков, таблиц, модальных окон, уведомлений, навигации, загрузки и ошибок; описать правила иконок, изображений, иллюстраций, именования и примеры правильного использования.
- Критерии: по системе можно без дополнительных устных решений спроектировать новый экран и написать его Vue/CSS-код; токены имеют однозначные имена и назначение; описаны основные состояния и доступность; правила согласуются с текущим визуальным языком; существующий фронтенд не меняет поведение и внешний вид в рамках этой задачи.
- Ограничения: не менять существующие страницы и компоненты; не делать редизайн приложения; не добавлять зависимости; переиспользовать текущие стили, ассеты и
naive-ui; не создавать Figma-файл или полноценную отдельную библиотеку компонентов. - Не входит: миграция текущих экранов на новые токены; реализация всех описанных компонентов; изменение API и продуктовой логики.
- Проверка: проверить полноту и однозначность документа и CSS-токенов; выполнить
cd evening_detective_frontend && npm run type-check && npm run lint && npm run lint:css. - Следующий шаг: изучить текущие
base.css,main.css, стили и повторяющиеся паттерны компонентов, затем подготовить минимальный документ и набор токенов без миграции существующих экранов.
ED-018 — Удаление неиспользуемых пользовательских файлов
- Статус:
TODO - Приоритет:
P1 - Репозиторий:
evening_detective_server - Цель: автоматически удалять с диска пользовательские файлы, которые больше не используются приложением.
- Контекст: после удаления или перезаписи файла его физическая копия может оставаться на диске и занимать память.
- Решение: при удалении или перезаписи пользовательского файла проверять отсутствие ссылок на него в базе данных и сразу физически удалять файл с диска. Удалять только файлы, загруженные пользователями.
- Критерии: удалённый пользовательский файл исчезает с диска; старая версия перезаписанного файла исчезает с диска; файл, на который есть ссылка в базе данных, не удаляется; очистка выполняется сразу; удаление не оставляет файлового мусора.
- Ограничения: не удалять файлы без подтверждённого отсутствия ссылок в базе; не добавлять корзину, задержку или отдельную инфраструктуру без необходимости; не затрагивать системные и статические файлы.
- Не входит: пакетная очистка уже накопившихся orphan-файлов без проверки текущих ссылок; восстановление удалённых файлов; изменение политики хранения пользовательских данных.
- Проверка:
cd evening_detective_server && go test ./... - Ручная проверка: загрузить файл, удалить его и проверить отсутствие на диске; загрузить новую версию вместо старой и проверить удаление старой копии; проверить, что используемый файл сохраняется.
- Следующий шаг: изучить полный flow загрузки, удаления и перезаписи пользовательских файлов, места хранения и все ссылки на них в базе, затем выбрать общую точку физического удаления.
ED-021 — Магазин игр: каталог и доступ к сценариям
- Статус:
TODO - Приоритет:
P1 - Репозитории:
evening_detective_server,evening_detective_frontend - Цель: дать игроку возможность выбрать опубликованный сценарий в магазине, получить одну игру по нему и запустить её.
- Решение: автор или администратор отправляет сценарий на модерацию; администратор одобряет или отклоняет публикацию; одобренный сценарий появляется в каталоге магазина и на странице игры; администратор может бесплатно выдать игроку доступ.
- Критерии: опубликованный сценарий проходит модерацию; одобренный сценарий виден в магазине; отклонённый сценарий не публикуется; игрок получает доступ к одной игре по сценарию и может её запустить; администратор может выдать доступ вручную; используются существующие данные сценария для карточки магазина.
- Ограничения: переиспользовать текущие модели, авторизацию, каталог и flow запуска игры; не добавлять зависимость без необходимости; оплату в эту задачу не включать — способ оплаты определить отдельно.
- Не входит: платёжный сервис, рейтинги, отзывы, корзина, промокоды и автоматические выплаты автору.
- Проверка:
cd evening_detective_server && go test ./...;cd evening_detective_frontend && npm run type-check && npm run lint && npm run lint:css. - Ручная проверка: отправить сценарий на модерацию от автора, одобрить и отклонить его от администратора, проверить видимость в каталоге и на странице игры, выдать игроку доступ вручную и запустить игру.
- Следующий шаг: изучить текущие модели и API сценариев, каталог, авторизацию, модерацию и выдачу доступа к игре, затем выбрать минимальную модель магазина и точки интеграции.
ED-022 — Вход через Яндекс ID
- Статус:
TODO - Приоритет:
P1 - Репозитории:
evening_detective_server,evening_detective_frontend - Цель: дать всем пользователям возможность регистрироваться и входить через Яндекс ID.
- Решение: добавить OAuth-вход через Яндекс; при новой регистрации получать только email и запрашивать позывной отдельной формой; сохранить существующий способ входа; если email уже есть в системе, отправлять ссылку для подтверждения привязки Яндекс ID к аккаунту.
- Критерии: новый пользователь регистрируется через Яндекс; позывной вводится пользователем; существующий аккаунт связывается с Яндекс ID после подтверждения ссылки; после связывания доступны оба способа входа; обычная регистрация и вход не ломаются; используются только email и идентификатор Яндекс ID, без аватара и других данных.
- Ограничения: использовать существующую авторизацию, пользователей и email-flow; OAuth client ID, secret и callback URL хранить в переменных окружения; не добавлять новый платёжный или внешний сервис без необходимости; ручную проверку выполняет пользователь.
- Не входит: отключение обычного входа, получение аватара, импорт других данных профиля и восстановление доступа через Яндекс сверх стандартного OAuth-flow.
- Проверка: ручная проверка пользователем регистрации, входа, привязки по ссылке и сохранения обычного входа; после реализации — релевантные backend- и frontend-проверки по изменённым репозиториям.
- Следующий шаг: изучить текущие модели пользователей, авторизацию, email-подтверждения и frontend-flow входа, затем выбрать минимальные точки интеграции Яндекс OAuth.
ED-014 — Периодическое сохранение сценариев в Git
- Статус:
TODO - Приоритет:
P2 - Репозиторий:
evening_detective_server - Цель: автоматически сохранять все сценарии в отдельный Git-репозиторий после изменений.
- Решение: после изменения сценария запускать отложенное сохранение с ограничением не чаще одного раза в 5 минут; экспортировать сценарии в текущем экспортном формате, выполнять commit и push на сервере. Адрес репозитория, ветка и учётные данные задаются через переменные окружения. Ошибку commit/push показывать в панели администратора.
- Критерии: изменение сценария приводит к его появлению в отдельном репозитории; частые изменения не создают операции чаще одного раза в 5 минут; commit и push выполняются автоматически; ошибка синхронизации видна администратору; все сценарии экспортируются без потери данных.
- Ограничения: использовать серверный flow сохранения сценария; не хранить URL, ключи и пароли в коде или Git; не добавлять новую инфраструктуру и зависимости без необходимости; не выполнять commit или push в текущих репозиториях проекта.
- Не входит: ручной UI для редактирования Git, восстановление сценария из Git и ручная проверка пользователем.
- Проверка: ручная проверка пользователем — изменить сценарий, убедиться в появлении commit и push в отдельном репозитории, проверить ограничение частоты и отображение ошибки при недоступном push.
- Следующий шаг: изучить серверный flow изменения сценариев, экспортный формат, текущие фоновые механизмы и конфигурацию окружения, затем выбрать минимальную точку запуска отложенной Git-синхронизации.
ED-017 — Демо-игра из каталога
- Статус:
TODO - Приоритет:
P1 - Репозитории:
evening_detective_server,evening_detective_frontend - Цель: дать зарегистрированному пользователю возможность один раз пройти выбранную администратором демо-игру из каталога.
- Контекст: демо использует один конкретный сценарий; каждая попытка пользователя создаёт отдельную обычную игру с одной командой.
- Решение: в админ-панели администратор выбирает игру из каталога и назначает её демо-игрой, а также задаёт используемый сценарий. Пользователь запускает демо обычным игровым flow; незавершённую игру можно продолжить. После завершения повторный запуск запрещён, вместо него показывается сообщение о прохождении и предлагаются другие игры каталога.
- Критерии: администратор может назначить и настроить демо-игру; зарегистрированный пользователь видит её в каталоге; при запуске создаётся отдельная игра с одной командой; выбранный сценарий используется без подмены; незавершённая игра возобновляется; завершивший пользователь не может создать вторую демо-игру и видит альтернативы каталога.
- Ограничения: переиспользовать существующие каталог, авторизацию, создание игры, игровые состояния и результаты; не добавлять отдельный игровой flow или зависимость без необходимости; не ломать обычные игры.
- Не входит: несколько сценариев в одной демо-игре, повторное прохождение одним пользователем, анонимный доступ и отдельная система прогресса.
- Проверка:
cd evening_detective_server && go test ./...;cd evening_detective_frontend && npm run type-check && npm run lint && npm run lint:css. - Ручная проверка: назначить игру демо и выбрать сценарий, запустить её двумя пользователями, продолжить незавершённую игру, завершить одну и проверить запрет повторного запуска и показ других игр каталога.
- Следующий шаг: изучить модель каталога, админ-панель, создание игр и проверку завершённых игр пользователя, затем выбрать минимальную модель настройки демо и точку запуска из каталога.
ED-013 — Просмотр ответов перед окончательным завершением игры
- Статус:
TODO - Приоритет:
P1 - Репозитории:
evening_detective_server,evening_detective_frontend - Цель: дать команде возможность после завершения игрового этапа посмотреть свои ответы и правильные ответы, затем автоматически окончательно закрыть игру через 15 минут.
- Контекст: в таких играх одна игра соответствует одной команде; любой игрок команды может открыть просмотр ответов.
- Решение: после обычного завершения переводить игру в отдельный статус просмотра ответов; при первом открытии просмотра сохранять время начала 15-минутного периода; по истечении периода переводить игру в финальный статус с фиксацией результата и отображением формы отзыва. Если просмотр не открыт, игра остаётся в статусе просмотра ответов.
- Критерии: любой игрок команды видит ответы команды вместе с правильными ответами; первый просмотр запускает общий для игры таймер; время хранится на сервере и не сбрасывается обновлением страницы; до истечения 15 минут игровые действия недоступны; после истечения игра окончательно завершена, результат доступен, форма отзыва показывается; повторные открытия не продлевают период; доступ к ответам и переходы статусов проверяются на сервере.
- Ограничения: переиспользовать существующие endpoint, авторизацию, сервисы и форму отзыва; не добавлять отдельный сервис или зависимость без необходимости; не ломать текущие сценарии
draft/run/pause/finish; сгенерированные protobuf-файлы менять только через существующую генерацию. - Не входит: отдельный таймер для команды, так как одна игра содержит одну команду; изменение состава или подсчёта результата; редизайн формы отзыва.
- Проверка:
cd evening_detective_server && go test ./...;cd evening_detective_frontend && npm run type-check && npm run lint && npm run lint:css. - Ручная проверка: завершить игру, открыть просмотр ответов, обновить страницу и убедиться, что отсчёт продолжается; проверить недоступность игровых действий, автоматическое финальное завершение через 15 минут, результат и форму отзыва.
- Следующий шаг: изучить текущие переходы статусов игры, авторизацию игрока, endpoint выдачи ответов и flow формы отзыва, затем выбрать минимальное серверное хранение времени первого просмотра и точку запуска финального завершения.
ED-009 — Оптимизировать изображения для web
- Статус:
TODO - Приоритет:
P1 - Репозиторий:
evening_detective_server - Цель: ускорить загрузку фотографий на сайте, сохраняя оригиналы для печати.
- Контекст: сейчас для просмотра на сайте используются оригинальные изображения, подготовленные для печати, поэтому страницы загружаются медленно.
- Решение: при загрузке фотографии сохранять оригинал и создавать облегчённую web-версию; сайт должен получать web-версию, а оригинал оставаться доступным для печати. Для уже загруженных фотографий предусмотреть отдельную безопасную пакетную обработку с созданием web-версий без удаления оригиналов.
- Следующий шаг: изучить текущий flow загрузки, хранения и выдачи фотографий, проверить объём уже загруженных файлов, затем выбрать минимальный способ генерации web-версий и запуска обработки без новой инфраструктуры.
- Критерии: оригинал не теряется; web-версия создаётся автоматически для новых файлов; web-версии создаются для уже загруженных фотографий; endpoint сайта выдаёт web-версию; размер и время загрузки заметно уменьшены; ошибки обработки не приводят к потере оригинала; повторный запуск обработки безопасен.
- Ограничения: не менять оригиналы; не добавлять зависимость или отдельный сервис без необходимости; не менять API шире требуемого для переключения выдачи.
- Не входит: изменение качества оригиналов; полноценный CDN.
- Проверка:
cd evening_detective_server && go test ./... - Ручная проверка: загрузить фото, убедиться в наличии оригинала и web-версии, открыть страницу сайта и проверить, что выдаётся облегчённый файл.
ED-010 — Расширить MCP функциями автора сценария
- Статус:
TODO - Приоритет:
P2 - Репозиторий:
evening_detective_server - Цель: дать автору сценария возможность работать со сценарием через существующий MCP.
- Контекст: текущий MCP нужно дополнить авторскими операциями, чтобы сценарий можно было просматривать и редактировать без обходных ручных действий.
- Решение: изучить существующий MCP и добавить минимальный набор авторских функций для просмотра сценария, добавления и редактирования точек, а также связанных сущностей и операций, необходимых для полноценного авторского flow.
- Следующий шаг: инвентаризировать текущие MCP-инструменты, модели и сервисы сценариев, затем зафиксировать точный набор операций и права доступа автора.
- Критерии: автор может получить структуру и содержимое сценария; добавлять точки; редактировать точки; выполнять необходимые связанные операции через MCP; ошибки и недоступные операции возвращаются предсказуемо; существующие MCP-инструменты не ломаются.
- Ограничения: переиспользовать существующие сервисы и правила доступа; не дублировать бизнес-логику в MCP; не менять сгенерированный API без необходимости.
- Не входит: отдельный новый MCP-сервер; полноценный визуальный редактор; изменение сценарной модели без подтверждённой необходимости.
- Проверка:
cd evening_detective_server && go test ./... - Ручная проверка: подключиться к MCP от имени автора, просмотреть сценарий, добавить точку, изменить её и проверить результат в редакторе/хранилище.
ED-002 — Rate-limit публичной регистрации команды
- Статус:
TODO - Приоритет:
P1 - Репозиторий:
evening_detective_server - Цель: ограничить спам-регистрации и расход SMTP-квоты.
- Контекст: публичный
POST /api/games/{id}/registrationsне требует авторизации и вызывает отправку email. - Решение: ограничить регистрации как минимум по
(IP, game), а повторную отправку — по email; лимиты должны быть согласованы до реализации. - Следующий шаг: определить лимиты и выбрать место хранения счётчика без зависимости от production-базы.
- Критерии: превышение лимита отклоняется предсказуемой ошибкой; нормальная регистрация не ломается; есть тесты на границы лимита.
- Ограничения: не добавлять внешнюю инфраструктуру без необходимости; не блокировать легитимные регистрации организатора.
- Не входит: полноценная CAPTCHA и общая защита всех публичных endpoint.
- Проверка:
cd evening_detective_server && go test ./... - Ручная проверка: отправить несколько регистраций с одного IP и проверить ответ после достижения лимита.
ED-003 — Очистка персональных данных регистраций
- Статус:
TODO - Приоритет:
P1 - Репозиторий:
evening_detective_server - Цель: удалять персональные данные завершённых игр по утверждённому сроку хранения.
- Контекст:
contact_emailи связанные данные регистрации остаются в БД после завершения игры. - Решение: очищать персональные поля команд завершённых игр, сохраняя данные, нужные для итогов; удалять истёкшие confirmation-токены.
- Следующий шаг: утвердить срок хранения и точный список полей, затем спроектировать job.
- Критерии: срок хранения зафиксирован в политике; job идемпотентен; игровые итоги не ломаются; есть тест на очистку.
- Ограничения: не удалять команды и данные, необходимые для итоговой таблицы; не запускать очистку без утверждённого срока хранения.
- Не входит: изменение всей политики хранения данных приложения.
- Проверка:
cd evening_detective_server && go test ./... - Ручная проверка: проверить завершённую игру после запуска job и убедиться, что итоги доступны без персональных полей.
ED-004 — Просмотр графа сценария
- Статус:
TODO - Приоритет:
P2 - Репозиторий:
evening_detective_frontend - Цель: показывать граф переходов сценария в редакторе.
- Решения: граф открывается из редактора в полноэкранной модалке; узлы — вступление, точки и вопросы; двери и текстовые маркеры — рёбра;
[Код]и([Код])равнозначны. - Реализация: чистый построитель графа, иерархическая раскладка сверху вниз, динамический импорт
vis-network, подсветка связей выбранного узла. - Следующий шаг: сверить актуальное состояние редактора и реализовать построитель, модалку и интеграцию без изменения сгенерированного API.
- Критерии: отображаются скрытые точки и вопросы; ненайденные коды видны отдельно; выбор узла подсвечивает входящие/исходящие связи; граф работает на мобильной ширине.
- Ограничения: не менять
src/api/generated/**; не добавлять новую библиотеку, если текущего frontend-стека достаточно. - Не входит: редактирование сценария через граф и автоматическое исправление ненайденных ссылок.
- Проверка:
cd evening_detective_frontend && npm run type-check && npm run lint && npm run lint:css && npm run build - Ручная проверка: открыть граф сценария с дверями, текстовыми маркерами, скрытой точкой и ненайденным кодом.
Правила обновления
- Перед началом работы перевести выбранную задачу в
IN_PROGRESS. - Не держать больше одной задачи в
IN_PROGRESS, если работа не разделена явно. - При блокировке записать конкретную причину и следующий внешний шаг.
- После проверки обновить результат, перевести задачу в
DONEи перенести её вCOMPLETED_TASKS.md. - Устойчивое знание записывать в будущую базу знаний отдельно, а не раздувать этот список.