ADR 009: Quiz Open Access Strategy
Status
Accepted - 2026-03-04
Context
Вопрос
Нужно ли требовать подписку на Telegram-канал для ответа на квизы в discussion group?
Текущая архитектура
- Квизы публикуются в discussion group через Telegram Bot
- Ответы обрабатываются через
callback_query→telegram-quiz-answer.service.ts - Пользователь автоматически создаётся при первом ответе на квиз (phantom user)
- Для входа в TMA (Telegram Mini App) уже требуется подписка на канал
Анализ угроз
| Угроза | Риск | Существующая защита |
|---|---|---|
| Спам ботов | Низкий | Rate limiter: 50 req/sec global, 10 req/min per user |
| Подделка identity | Невозможно | Telegram гарантирует ctx.from.id в callback_query |
| DDoS через квизы | Низкий | 1 ответ на 1 квиз (duplicate check), rate limiter |
| Неподписанные зарабатывают scrap | Некритично | Scrap бесполезен без входа в TMA (требует подписку) |
| Забаненные голосуют | Некритично | Забаненные не могут войти в TMA, scrap бесполезен |
Decision
Не добавлять проверку подписки на канал для квизов. Оставить квизы открытыми для всех.
Rationale: Quiz как воронка, а не забор
Сценарий с проверкой подписки (отвергнут):
Человек видит квиз → нажимает → "Подпишись!" → не хочет → ушёл навсегда
Сценарий без проверки (текущий, принят):
Человек видит квиз → играет → выигрывает → радуется
→ хочет посмотреть награды → открывает TMA
→ TMA требует подписку → подписывается добровольно
→ видит накопленный scrap → вау-эффект → лояльный пользователь
Ключевые аргументы
-
Двойной забор не нужен. TMA уже требует подписку на канал. Ставить второй забор на квизах — убивать конверсию на верхнем этапе воронки.
-
Phantom users — фича, не баг. Пользователи, отвечающие на квизы без TMA, накапливают scrap. При первом входе в TMA они видят "бонус" — это повышает retention.
-
Scrap без TMA бесполезен. Даже если неподписанный отвечает на квизы — он не может потратить scrap, открыть кейс или получить предмет без входа в TMA.
-
Забаненные безвредны. Забаненные пользователи заблокированы в TMA. Их ответы на квизы не влияют на экономику — scrap нельзя реализовать.
-
Техническая простота. Не нужно: Telegram API вызовы (
getChatMember), кэширование подписок, обработка ошибок API, новые зависимости в handler.
Consequences
Positive
- ✅ Максимальная конверсия: нулевой барьер для участия в квизах
- ✅ Накопление scrap как мотиватор для входа в TMA и подписки
- ✅ Нулевая нагрузка на Telegram API (нет
getChatMemberвызовов) - ✅ Простота кода: не добавлены новые зависимости, кэши, edge cases
- ✅ Будущее: бот в чужих группах — пользователи играют, потом приходят в наш канал
Negative
- ⚠️ Неподписанные пользователи влияют на статистику квизов (correctAnswers, totalAttempts)
- ⚠️ Забаненные могут продолжать отвечать (но scrap бесполезен)
Accepted Risks
- Статистика квизов включает ответы неподписанных — некритично для бизнес-метрик
- Забаненные накапливают бесполезный scrap — нулевой impact
Alternatives Considered
| Option | Effort | Impact | Decision |
|---|---|---|---|
| Открытые квизы (без проверки) | None | Лучшая конверсия | ✅ ACCEPTED |
| Проверка подписки с кэшем 24ч | Medium | ~10k API calls/день | ❌ Избыточный контроль |
| Проверка подписки с кэшем 5мин | Medium | ~30k API calls/день | ❌ Перебор |
| Бан-проверка в processAnswer | Low | Блок единичных забаненных | ❌ Не оправдано (TMA блокирует) |
Re-evaluation Criteria
Пересмотреть решение если:
- Бот добавлен в чужие группы И нужна принудительная конверсия (не органическая)
- Обнаружена масштабная эксплуатация квизов ботами (>10% phantom users)
- Scrap станет реализуемым без TMA (новые каналы монетизации)