Files
evening_detective_server/docs/PARTICIPATION.md
T
2026-09-16 02:57:00 +07:00

55 lines
4.9 KiB
Markdown

# Подтверждение участия
Для всех форматов игр за 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,
а не прочтение письма или гарантированное попадание во входящие.
## Проверка
```sh
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 заменён тестовой реализацией;
реальным капитанам тесты ничего не отправляют.