generated from VLADIMIR/template
55 lines
4.9 KiB
Markdown
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 заменён тестовой реализацией;
|
|
реальным капитанам тесты ничего не отправляют.
|