Files
2026-09-16 02:57:00 +07:00

4.9 KiB

Подтверждение участия

Для всех форматов игр за 24 часа до start_at сервер отправляет письмо капитану. Проверка запускается при старте сервера, затем раз в минуту. Отправка последовательная: большая рассылка занимает дополнительное время. Команды без email видны организатору, но письмо им отправить невозможно.

Правила

  • pending — ожидает ответа; команда сохраняет право участвовать.
  • confirmed — подтверждено капитаном, первым ходом команды (first_action) или автоматически при регистрации менее чем за сутки.
  • cancelled — отменено; команда остаётся в истории организатора, но исключается из игры, ответов организатору, результатов, карты и PDF с QR-кодами.
  • Ровно за 24 часа автоматического подтверждения нет.
  • Ответ окончательный: повтор того же ответа успешен, противоположный отклоняется.
  • После планового начала или выхода игры из draft новые ответы не принимаются.
  • Перенос игры и повторный сбор подтверждений не поддерживаются.

Правило поздней регистрации вычисляется в сервисе перед созданием команды для формы и ручного добавления. Существующие команды миграция не изменяет: они остаются в статусе pending. Даты без часового пояса в существующих games.start_at и teams.created_at считаются UTC.

Запуск

  1. Применить миграцию 20260915120000_add_team_participation.sql через обычный goose up.
  2. Обновить сервер и фронтенд вместе: фронтенд должен обслуживать /participation.
  3. Проверить существующие 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 заменён тестовой реализацией; реальным капитанам тесты ничего не отправляют.