4.9 KiB
Подтверждение участия
Для всех форматов игр за 24 часа до start_at сервер отправляет письмо капитану.
Проверка запускается при старте сервера, затем раз в минуту. Отправка последовательная:
большая рассылка занимает дополнительное время. Команды без email видны организатору,
но письмо им отправить невозможно.
Правила
pending— ожидает ответа; команда сохраняет право участвовать.confirmed— подтверждено капитаном, первым ходом команды (first_action) или автоматически при регистрации менее чем за сутки.cancelled— отменено; команда остаётся в истории организатора, но исключается из игры, ответов организатору, результатов, карты и PDF с QR-кодами.- Ровно за 24 часа автоматического подтверждения нет.
- Ответ окончательный: повтор того же ответа успешен, противоположный отклоняется.
- После планового начала или выхода игры из
draftновые ответы не принимаются. - Перенос игры и повторный сбор подтверждений не поддерживаются.
Правило поздней регистрации вычисляется в сервисе перед созданием команды для формы и ручного добавления.
Существующие команды миграция не изменяет: они остаются в статусе pending.
Даты без часового пояса в существующих games.start_at и teams.created_at считаются UTC.
Запуск
- Применить миграцию
20260915120000_add_team_participation.sqlчерез обычныйgoose up. - Обновить сервер и фронтенд вместе: фронтенд должен обслуживать
/participation. - Проверить существующие SMTP-настройки,
APP_BASE_URL,PARTICIPATION_SECRET.GAME_TIMEZONEзадаёт часовой пояс письма, по умолчаниюAsia/Barnaul.
Рассылка запускается автоматически. Если APP_BASE_URL, PARTICIPATION_SECRET или часовой пояс
некорректны, сервер пишет причину отключения рассылки в журнал.
Не менять PARTICIPATION_SECRET между попытками отправки: HMAC-токен привязан к команде и этому секрету.
В БД хранится только SHA-256 токена. Уже отправленные ссылки проверяются по сохранённому хешу.
Токен передаётся в URL-фрагменте и теле API-запроса, не в query string.
Не включать тела запросов /api/participation/* в access-логи.
Неудачные попытки повторяются через пять минут автоматически, максимум восемь раз на команду.
После восьмой неудачи новые попытки не запускаются; ошибка остаётся видна организатору.
Пятиминутная аренда задания защищает от одновременной обработки серверами и восстанавливается
после падения. Одна попытка ограничена минутой. Ошибки сохранения результата записываются в журнал.
SMTP не обеспечивает ровно одну доставку: если письмо принято, а результат не сохранён,
возможен дубль с той же ссылкой. participation_sent_at означает принятие письма SMTP,
а не прочтение письма или гарантированное попадание во входящие.
Проверка
go test ./...
TEST_DATABASE_URL='host=localhost port=5432 user=test dbname=test sslmode=disable' \
go test ./internal/repos/teams_repo ./internal/services/game_service -count=1
Интеграционные тесты создают и удаляют собственные схемы. SMTP заменён тестовой реализацией; реальным капитанам тесты ничего не отправляют.