Известные ограничения
Описание
Список того, что в текущей реализации онбординг-бота осознанно отложено, с причиной и тем, что уже готово на стороне бота (чтобы включение в будущем было минимальным изменением). Ни один из пунктов не является багом — затронутая функциональность либо не активирована намеренно, либо требует отдельного решения вне скоупа этой задачи.
1. Reactivation / struct_overtake — backend-эмиссия не включена
Бот полностью готов принимать и обрабатывать события reactivation и
struct_overtake из outbox (EventHandlersService.onReactivation,
onStructOvertake, apps/onboarding-bot/src/outbox/event-handlers.service.ts)
— DM пользователю уже реализован и покрыт тестами. BotEventType содержит
оба значения на обеих сторонах контракта.
Backend их не эмитит. Точка эмиссии завязана на закомментированный блок
распределения наград StructPartnerUpReward в
apps/backend/src/.../distributionsStats.job.ts (финансовый код начисления
наград при обгоне структуры) — включать его нужно осознанным решением
команды, а не как побочный эффект доработки бота: раскомментирование
затрагивает не только уведомление, а саму логику начисления
вознаграждений.
Что нужно, чтобы включить: раскомментировать/реализовать эмиссию
BotOutboxService-события в соответствующей точке job'а начисления наград
(без изменения самой логики распределения) — на стороне бота
дорабатывать ничего не требуется.
2. Сегментация «неактивные» — по бот-активности, не по веб-сессии
AdminService.filterInactive / сегмент bc:seg:inactive:<N> в мастере
рассылки и pt:list:stuck в списке партнёров используют
bot_users.lastActivityAt — момент последнего взаимодействия с ботом
(FunnelService.advanceStage обновляет её на каждый переход этапа).
Пользователь, который активно пользуется веб-кабинетом Magnet, но не
заходит в Telegram, будет ошибочно попадать в сегмент «неактивные» — сейчас
бот не видит sessions.timeActive (веб-активность) основного backend'а.
Что нужно, чтобы включить: синхронизация веб-времени активности в
bot_users (либо через outbox-событие на каждую веб-сессию, либо через
периодический батч-синк GET /bot/user/state → timeActive, поле уже
возвращается этим эндпоинтом, но в bot_users не сохраняется). Отложено как
краевое уточнение — основной путь (бот-активность) уже отражает вовлечённость
в воронку.
3. Детект «ушёл к другому лидеру B» — только для wallet-регистрации
EventHandlersService.onRegistered сравнивает payload.submitted_link
(сырую реф-ссылку, с которой юзер регистрировался) с
botUser.leaderLink (first-touch реф-ссылка лидера A из бота) — расхождение
триггерит notifyLeaderLeft (DM лидеру A «Ваш партнёр зарегистрировался у
лидера B»). Это работает, потому что кошелёк-регистрация
(processRegistrationInProgramsEvent, ончейн-синк) эмитит registered с
заполненным submitted_link.
Социальная/email-регистрация (registerSocialWallet, off-chain путь) не
эмитит бот-событие registered вообще — вся эмиссия событий registered
привязана к sync.service (ончейн-синк). Соответственно уход партнёра к
другому лидеру через соц./email-регистрацию бот не детектит и лидера A не
уведомляет.
Что нужно, чтобы включить: протянуть эмиссию registered (или
эквивалентного события с submitted_link) из off-chain пути регистрации —
отдельная задача на стороне auth/sync, не затрагивающая бота.
4. Frontend: рендер уведомлений PartnerLeftToLeader/NewPartnerViaBot не добавлен
Пассивный фоллбэк POST /bot/notification (когда DM недоступен, 403 — нет
активного диалога с ботом) пишет генерическую запись в
NotificationService.addNotification веб-кабинета основного backend'а, но
фронтенд (apps/frontend) не добавляет специфичный рендер для типов события
бота (type: 'bot_event' и т.п.) — такие уведомления в веб-кабинете
отобразятся как есть (или не отобразятся специфично оформленными), без
кастомной иконки/текста под конкретный сценарий.
Низкий приоритет: основной канал доставки таких уведомлений — DM в боте;
веб-фоллбэк срабатывает только когда у адресата нет активного диалога с
ботом (не начинал /start или заблокировал бота).
5. Известный технический долг (не риск, но стоит знать)
AdminService.createBroadcast/runBroadcast— более ранняя (глобальна я, без per-recipient леджера/rate-limit/resume) реализация рассылок, вытесненнаяBroadcastUpdate+BroadcastSenderService. Код не удалён и не вызывается ни одним пользовательским путём — кандидат на чистку в будущем рефакторинге, не влияет на текущее поведение.BonusService/bot_bonus_grants— сущность и сервис стартовых бонусов существуют в кодовой базе, но провайдер не зарегистрирован вAppModule(сознательно откреплён на раннем этапе доработки бота, до решения продукта по механике бонусов). Таблицаbot_bonus_grantsсоздаётся миграцией, но не используется.- In-memory telegraf-сессия (
ctx.session) — состояние мастера рассылки и кэшViewerживут в памяти процесса. При строгом соблюдении «1 реплика» (см. «Архитектура») это не проблема; при рестарте процесса открытый мастер рассылки теряется (пользователь просто начинает заново черезbc:new) — приемлемо для короткоживущего мастера. Redis-backed session — потенциальное будущее улучшение для многоинстансной раскатки, не требуется для v1. - Пресеты расписания рассылки — только «через 1 час» и «завтра в 10:00»; произвольный ввод даты/времени текстом не реализован (см. «Меню-навигация»).