Wiki
猫Table of Contents
- Framework Backlog
- Done
- [1.0.0]
- [1.0.0-rc.14] Модель выполнения webhook
- [1.0.0-rc.13] Модель наблюдаемости
- [1.0.0-rc.13] Модель авторизации и политик
- [1.0.0-rc.13] Модель пользовательских и внутренних ошибок
- [1.0.0-rc.13] Модель фиксации конфигурации
- [1.0.0-rc.13] Контракт схемы обновлений
- [1.0.0-rc.12] Conversation / Scene Model
- [1.0.0-rc.12] Typed Handler Input Model
- [1.0.0-rc.12] Request Context / Cancellation Model
- Ideas
Framework Backlog
Эта страница отслеживает список задач уровня фреймворка, связанных с отсутствующими концепциями в библиотеке, а не просто с нехваткой документации.
Done
[1.0.0]
Major — закрыто до тега 1.0.0
- M1.
BotPayloadType*былиvar, должны бытьconst. - M2. Асимметрия именования методов
Observer—OnReceiveUpdate→OnUpdateReceived;OnHandledUpdate→OnUpdateHandled. - M3. Uploader возвращал ad-hoc строку ошибки вместо
*ResponseError. - M4.
BotOptsFileJSONне сохранялPollTimeout— поле терялось при round-trip. - M5. Устаревший godoc
Bot.Updates— утверждал "30-second timeout" и "empty slice if none". - M6. Противоречивый godoc
NewRandomDraftProvider— говорил "cryptographically secure", но использовалmath/rand/v2. - M7. Godoc
Draft.Deleteговорил "internal method" — метод экспортирован. - M8. Русские комментарии в production-коде —
msg_handler.go,tgapi/uploader_api.go. - M9. Godoc
MessageContext.Errorссылался на неэкспортированный хелпер. - M10.
SceneиSceneSessionсмешивали экспортированные поля с setter-ами —Scene.PluginNameзакрыт,SceneSession.Dataзакрыт. - M11. Constant-time compare для webhook secret — использован
subtle.ConstantTimeCompare.
Minor — закрыто до тега 1.0.0
- Убраны godoc-комментарии с неэкспортированных функций.
- Godoc
Plugin.AddCommandссылался на.command. - Builder раннеров:
Onetime/Timeout→Every/Async;Once()удалён. - Опечатка в webhook: "must between" → "must be between".
- Inline
errors.New(...)в webhook →Err*sentinel-ы. - Добавлен godoc для
tgapi.UpdateTypeManagedBot,Bot.GetAPI,Bot.GetUploader,InlineKeyboard.GetMaxRow. - Godoc
Bot.L10nисправлен — возвращает ключ, а не пустую строку. - Panic в
Bot.handleтеперь эмитируетErrorEventчерез observer. - Выравнена логика plugin-logger в
handleCallbackиhandleMessage. - Godoc
SetCallbackDataуточняет поведение zeroBotPayloadType. commands.goпустойcase CommandValueAny:объединён сdefault.Bot.SetDebugне вызываетconfigMutable— задокументировано в godoc.
Тесты, добавленные после правок
- Round-trip
BotOptsFileJSONдляPollTimeout. - Uploader 4xx/429 возвращает
*tgapi.ResponseError. - Panic в
Bot.handle→ observer получаетErrorEvent. - Webhook
/statusс невернымSecretTokenвозвращает 404, smoke-тест constant-time compare. - Table-driven тесты
parseCommandдля/cmd@botname.
[1.0.0-rc.14] Модель выполнения webhook
Текущее состояние:
- В репозитории уже есть низкоуровневые API для настройки webhook на уровне
tgapi:SetWebhook(...),DeleteWebhook(...),GetWebhookInfo(...), а также поддержка загрузки сертификата через uploader. - Во фреймворке теперь есть полноценные bot-level точки входа webhook runtime:
RunWebhookWithContext(...)иRunWebhook(...). - Webhook-доставка теперь использует ту же внутреннюю очередь update-ов, тот же worker pool, тот же запуск runners и тот же single-use runtime contract, что и polling.
- Поведение webhook runtime, security-модель и правила перехода обратно на polling теперь описаны в основной документации и wiki.
Почему это важно:
- Одной только поддержки webhook-транспорта на уровне API-клиента было недостаточно; пользователю всё ещё нужен был framework-owned runtime path, сопоставимый с polling.
- Полноценный runtime mode выравнивает worker scheduling, lifecycle behavior, правила конфигурации и shutdown semantics между двумя ingress-моделями.
- Фреймворку также нужна явная история перехода с webhook-доставки обратно на polling deployment.
Что теперь есть:
BotWebhookOpts,NewBotWebhookOpts()и fluent helper-методы для webhook-конфигурации.RunWebhookWithContext(...)иRunWebhook(...)как bot-owned точки входа runtime.- Общая queued dispatch-модель, worker-pool обработка, запуск runners и single-use semantics для polling и webhook mode.
- Fallback webhook
AllowedUpdatesк bot-level конфигурации типов update. - Валидация webhook path и количества TLS-файлов до remote webhook setup.
- Явное удаление remote webhook через
CloseWebhook()или низкоуровневыйtgapi.DeleteWebhook(...)при переходе deployment с webhook-доставки обратно на polling. - Регрессионные тесты на queue delivery, запуск runners, single-use behavior, rejection слишком большого body, path/TLS validation и auth-поведение status endpoint.
Практическая цель:
- Считать webhook-доставку полноценным runtime mode фреймворка, а не оставлять её только низкоуровневой transport primitive из
tgapi.
[1.0.0-rc.13] Модель наблюдаемости
Текущее состояние:
- Во фреймворке теперь есть полноценная
Observer-модель с типизированными runtime-событиями и panic-safe dispatch через runtime бота. - Observer hooks теперь покрывают получение и завершение update-ов, command и payload handlers, generic update handlers, lifecycle сценовых обработчиков, scene transitions, policy checks, завершение runners, polling retries и централизованный error routing.
- Инструментирование остаётся best-effort и не создаёт второй execution pipeline, а также не требует протаскивать app data через observer callbacks.
Почему это важно:
- Одного логирования недостаточно, чтобы получить стабильный runtime-facing observability contract для метрик, tracing-адаптеров и структурированного сбора событий.
- Framework-owned hooks делают поведение runtime видимым без необходимости патчить внутренние пути маршрутизации или дублировать инструментирование вокруг команд, payload, сцен и polling.
- Типизированная event model остаётся понятной в godoc и тестах, при этом не перегружая интеграцию observer.
Что теперь есть:
Observerкак публичный интерфейс инструментирования.- Типизированные события для update, handler, scene, policy, runner, polling и error flows.
- Безопасный dispatch событий через
safeEmitEvent(...), включая recovery от panic. - Runtime emission в command, payload, generic update и scene flows.
- События проверки политик через
PolicyCheckedEvent. - Наблюдаемость runners и polling через
RunnerFinishedEvent,PollingRetryEventи observerErrorEvent. - Регрессионные тесты для observer configuration, lifecycle command/payload handlers, lifecycle и transitions сцен, ошибок update handlers, ошибок callback decode, завершения runners, polling retries и policy checks.
Практическая цель:
- Считать наблюдаемость полноценной возможностью фреймворка, а не оставлять инструментирование на уровне случайного логирования и внешних обёрток.
[1.0.0-rc.13] Модель авторизации и политик
Текущее состояние:
- Во фреймворке теперь есть
Policy[T]как явная переиспользуемая модель правила доступа, работающая поверх нормализованногоMessageContextи общих данных приложения. - Политики интегрируются в уже существующую модель выполнения через
RequirePolicy(...), поэтому авторизация остаётся на middleware-пути и не создаёт второй pipeline маршрутизации. - У бота и плагинов появились явные helpers для регистрации политик на уровне конфигурации.
Почему это важно:
- Проверки доступа почти всегда нужны Telegram-ботам, но одних ad-hoc middleware недостаточно, чтобы это стало стабильной framework concept.
- Переиспользуемые policy helpers делают ограничения по типу чата, правам администратора и callback-контексту видимыми и компонуемыми, вместо того чтобы размазывать их по внутренностям обработчиков.
- Сохранение выполнения политик в рамках существующего middleware-пути позволяет добавить отдельный язык авторизации, не ломая текущую runtime model.
Что теперь есть:
Policy[T]как публичная абстракция авторизации.RequirePolicy(...)для адаптации политик в блокирующие middleware.Bot.UsePolicy(...)иPlugin.UsePolicy(...)для удобной регистрации.- Встроенные Telegram-aware helpers:
RequirePrivateChat(...),RequireGroupChat(...),RequireSupergroupChat(...),RequireChatAdmin(...),RequireChatCreator(...),RequireBotAdmin(...)иRequireCallbackFromUser(...). - Комбинаторы
AllPolicies(...),AnyPolicy(...)иNotPolicy(...). - Расширенная нормализация
MessageContextдляChatиChatID, а также регрессионные тесты на поведение политик и нормализованного контекста.
Практическая цель:
- Считать правила доступа полноценной концепцией фреймворка, а не оставлять контроль доступа только на уровне случайного паттерна middleware.
[1.0.0-rc.13] Модель пользовательских и внутренних ошибок
Текущее состояние:
- У фреймворка по-прежнему один централизованный путь ошибок из обработчиков, но теперь он поддерживает явное разделение на пользовательские и внутренние ошибки.
- Неразмеченные возвращённые ошибки остаются пользовательскими ради обратной совместимости.
- Внутренние сбои теперь можно логировать без автоматической отправки их сырого текста пользователю.
Почему это важно:
- Единый поток ошибок полезен, но не каждая ошибка должна превращаться в ответ пользователю.
- Сбои инфраструктуры, нарушения внутренних инвариантов и ошибки маршрутизации часто важны для операторов, но только засоряют или портят пользовательский UX.
- Без такой классификации пользователю либо начинают утекать внутренние ошибки, либо приходится полностью обходить централизованный путь.
Что теперь есть:
AsUserError(...)иAsInternalError(...)для явной классификации возвращаемых ошибок.IsUserError(...)иIsInternalError(...)для проверки этой классификации на стороне фреймворка.- Обновлённое поведение
MessageContext.Error(...): все ошибки по-прежнему логируются, но для внутренних ошибок автоматический ответ пользователю подавляется. - Регрессионные тесты для message и callback потоков.
Практическая цель:
- Сохранить централизованный error flow, но сделать пользовательские и операторские ошибки действительно разными по поведению.
[1.0.0-rc.13] Модель фиксации конфигурации
Текущее состояние:
- Фреймворк теперь считает конфигурацию бота структурно завершённой после начала первого runtime entry point:
Run(),RunWithContext(...)илиRunWebhookWithContext(...). - Поздние bot-level попытки мутации больше не применяются частично после старта runtime.
- Границы между регистрацией плагинов, стартом runtime и фиксацией конфигурации теперь оформлены как явное поведение фреймворка и закреплены тестами.
Почему это важно:
- Runtime-мутация prefixes, middleware, payload policy, локализации, runners или общих зависимостей слишком трудно поддаётся безопасному пониманию.
- У фреймворка уже были реальные точки фиксации вроде
AddPlugins(...); теперь они оформлены как явный контракт, а не как скрытая деталь реализации.
Что теперь есть:
- Bot-level конфигурационные методы игнорируют поздние вызовы после старта runtime.
- Правила жизненного цикла и freeze-модели задокументированы как полноценная концепция.
- Регрессионные тесты закрепляют игнорирование поздних мутаций.
Практическая цель:
- Сделать старт, runtime и владение конфигурацией достаточно предсказуемыми для стабильного контракта фреймворка.
[1.0.0-rc.13] Контракт схемы обновлений
Текущее состояние:
- Нормализация обновлений уже существовала, но теперь она описана и протестирована как явный контракт уровня фреймворка.
- Категории маршрутизации и гарантии заполнения
MessageContextтеперь рассматриваются как полноценная часть публичной модели.
Почему это важно:
- Код обработчиков должен понимать, на какие поля
MessageContextможно безопасно опираться в каждом потоке обновлений. - Без явного контракта обработка обновлений остаётся понятной только через чтение реализации.
Что теперь есть:
- Задокументированная модель маршрутизации для command flow, payload flow и generic update handlers.
- Явные комментарии на полях
MessageContext, описывающие гарантии для update-backed, callback-backed и message-backed контекстов. - Table-driven регрессионные тесты для нормализованного update contract, включая callback target semantics и non-command update flows.
Практическая цель:
- Сделать маршрутизацию обновлений и гарантии
MessageContextдостаточно явными, чтобы на них можно было опираться как на стабильный контракт1.0.
[1.0.0-rc.12] Conversation / Scene Model
Текущее состояние:
- Фреймворк хорошо обрабатывает одно обновление через команды, данные callback, middleware и обработчики обновлений.
- В нём уже есть полезные низкоуровневые строительные блоки:
MessageContext, черновики, маршрутизация данных callback, плагины и обработчики обновлений. - Теперь в нём уже есть реализованная начальная модель сцен для долгоживущих интерактивных сценариев: сцены можно регистрировать в плагинах, запускать через
MessageContext, сохранять черезSessionStoreи маршрутизировать раньше обычной обработки команд.
Почему это важно:
- Многие Telegram-боты быстро перерастают из изолированных команд в многошаговые сценарии с сохранением состояния.
- Реальным ботам часто нужны концепции вроде "подождать следующее сообщение пользователя", "пользователь сейчас на шаге 3 из 5" или "нажатие кнопки переводит пользователя в следующее состояние сцены".
- Без модели сцен пользователи библиотеки начинают строить свой мини-фреймворк поверх Laniakea.
Что уже есть:
- Маршрутизация активной сцены раньше обычной маршрутизации команд.
- Области действия сессии на пользователя, чат и пару пользователь-чат.
- Явный вход и выход через
MessageContext. - Обработчики шагов, локальные команды сцены и
OnMessage(...). - Встроенное in-memory-хранилище по умолчанию и интерфейс
SessionStoreдля собственного постоянного хранения.
Что ещё отсутствует или не до конца определено:
- Локальная маршрутизация данных callback внутри сцены.
- Ясное решение о том, нужен ли вообще дополнительный публичный API для просмотра состояния сцен.
- Дальнейшие расширения поверх текущей модели сцен, ориентированной на сообщения.
Текущее направление API:
Scene,SceneContext,SceneSessionиSessionStore.Plugin.NewScene(...)иPlugin.AddScene(...).MessageContext.EnterScene(...),EnterSceneStep(...)иExitScene(...).SceneContext.Stay(),Next(...),Exit(),Pass(),BindData(...)иSaveData(...).- Состояние на пользователя или чат с хранением в
SessionStoreи чистым интерфейсом для собственного постоянного хранения.
Важные ограничения дизайна:
- Это должно быть опциональным и расширяющим текущую модель.
- Это не должно заменять плагины, команды или обработчики как обычные точки входа во фреймворк.
- Это должно работать поверх существующих middleware и
MessageContext, а не вводить вторую несовместимую модель выполнения.
Практическая цель:
- Расширять текущую полноценную модель сцен только там, где это реально добавляет ценность.
- Сохранять поддержку и пошаговых форм, и модальных чат-сценариев без необходимости строить пользовательские слои маршрутизации вокруг активных сессий.
[1.0.0-rc.12] Typed Handler Input Model
Текущее состояние:
- Команды и данные callback сейчас отдают разобранный текст через
ctx.Textиctx.Args. CommandArgдаёт базовую проверку аргументов и их формы.- Обработчики всё ещё делают большую часть нетривиального разбора вручную.
Почему это важно:
- По мере роста бота обработчики часто начинают с повторяющегося шаблонного кода для разбора
ctx.Args. - Логика валидации расползается по обработчикам вместо того, чтобы жить в одном предсказуемом слое привязки.
- Текущая модель проста и честна, но помогает недостаточно, когда команды становятся более структурированными.
Чего не хватает:
- Полноценный способ привязывать аргументы команды или данные callback к типизированному Go-значению.
- Паттерн уровня фреймворка для ошибок преобразования и ошибок валидации вместо чистой работы со строками.
- Низкопороговый путь перехода от позиционных аргументов к структурированному входному объекту.
Возможное направление API:
- Лёгкий API привязки вроде
ctx.BindArgs(&input). - Или явная регистрация типизированных команд вроде
NewCommandTyped(...). - Позиционное отображение в структуры, optional-поля, базовая поддержка преобразований и интеграция с текущим потоком валидации.
- Единые ошибки привязки и валидации, которые идут через существующий централизованный путь обработки ошибок.
Пример пользовательского кода, который это должно сделать удобным:
type BanInput struct {
UserID int
Reason string
}
func ban(ctx *laniakea.MessageContext, db *App) error {
var input BanInput
if err := ctx.BindArgs(&input); err != nil {
return err
}
return db.Ban(input.UserID, input.Reason)
}
Важные ограничения дизайна:
- Избегать тяжёлой зависимости от reflection и слишком "магической" подсистемы.
- Сохранять текущую модель
ctx.Argsкак минимальную базовую модель. - Относиться к типизированной привязке как к удобному слою поверх текущей модели команд, а не как к её замене.
Практическая цель:
- Убрать повторяющийся код разбора, сохранив явный и Go-подобный характер фреймворка.
[1.0.0-rc.12] Request Context / Cancellation Model
Текущее состояние:
RunWithContext(...)иRunWebhookWithContext(...)управляют жизненным циклом выполнения бота и корректным завершением.tgapiуже поддерживает методы, принимающиеcontext.Context.- Обычные обработчики не получают полноценный
context.Context, привязанный к обработке конкретного запроса.
Почему это важно:
- Бизнес-логика обработчиков часто требует вызовов базы данных, HTTP-вызовов или обращений к нижележащим сервисам с поддержкой отмены.
- У фреймворка уже есть хорошая история с отменой выполнения на уровне механизма выполнения, но она пока не доходит естественным образом до пользовательского кода внутри обработчиков.
- В современном Go API
context.Context— стандартная часть корректного управления выполнением.
Чего не хватает:
- Чистый
context.Context, который сопровождает каждое обновление через всё выполнение обработчика. - Стандартный способ для кода приложения остановить работу, когда бот завершает работу или когда контекст обработки обновления отменён.
- Прямой мост между управлением жизненным циклом бота и отменой в сервисном слое.
Возможное направление API:
- Предпочесть non-breaking подход и выдавать context через
MessageContext, напримерctx.Context(). - Строить context из жизненного цикла обработки обновления, чтобы он оставался полезным во время корректного завершения.
- Сделать естественной передачу этого context в методы базы данных, HTTP-клиенты и
tgapi.WithContext(...).
Почему это, скорее всего, не должно быть изменением сигнатуры:
- Изменение сигнатур обработчиков на прямой
context.Contextбыло бы публичным ломающим изменением. - Аксессор на
MessageContextсохраняет совместимость и при этом даёт обработчикам идиоматичный Go-путь для отмены выполнения.
Практическая цель:
- Позволить коду обработчиков естественно участвовать в отмене выполнения и корректном завершении, не заставляя пользователей строить собственную передачу
context.
Связанные страницы:
Ideas
Пункты в этом разделе намеренно остаются теоретическими. Они могут позже превратиться в реальные задачи беклога, а могут так и остаться design notes, если текущей модели фреймворка окажется достаточно.
Модель сервисного слоя и графа зависимостей
Текущее состояние:
SetAppData(...)уже даёт фреймворку простую модель общих зависимостей через generic-параметр типа бота.- Эта модель намеренно лёгкая и хорошо подходит ботам, которым нужен только небольшой набор долгоживущих общих зависимостей.
Почему это пока только идея:
- В репозитории сейчас нет достаточно сильных признаков того, что нужен более тяжёлый service container или scoped dependency model.
- Framework-owned граф зависимостей добавит сложность в API и lifecycle, поэтому такой пункт стоит переносить в активный backlog только тогда, когда повторяющееся реальное использование покажет, что
AppDataуже недостаточно.
Что это могло бы значить позже, если станет нужно:
- Полноценный service registry поверх одного общего значения
AppData. - Опциональную валидацию требуемых сервисов до старта runtime.
- Более явные lifecycle- или scope-правила для сервисов, которыми управляет сам фреймворк.
Контракт композиции плагинов
Текущее состояние:
- Плагины уже не являются просто "мешком команд": регистрация через
AddPlugins(...)делает snapshot plugin state, считает регистрацию точкой фиксации и документирует post-registration mutation как неподдерживаемую. - Это уже даёт фреймворку осмысленный базовый контракт вокруг владения конфигурацией плагина и его неизменяемости во время runtime.
Почему это пока только идея:
- Текущее состояние репозитория пока не показывает достаточно сильного давления в сторону более богатой framework-level модели зависимостей или capabilities между плагинами.
- Дополнительный composition contract увеличит API surface и число правил валидации, поэтому его стоит держать как опциональное направление дизайна, пока реальные сценарии повторяющихся взаимодействий между плагинами не покажут, что он действительно нужен.
Что это могло бы значить позже, если станет нужно:
- Явные зависимости между плагинами.
- Декларации общих возможностей или требований между плагинами.
- Модель композиции уровня фреймворка для валидации и координации отношений между плагинами.
Navigation
Start here
Runtime and Architecture
- Bot-Lifecycle
- Webhook-Runtime
- Middleware
- Runners
- Error-Handling
- Logging
- Update-Routing-Model
- Policies
- Scenes
Interaction and Telegram API
- Inline-Keyboards-and-Payloads
- Auto-Generated-Commands
- Drafts
- Rich-Messages
- Localization
- Rate-Limiting
- tgapi-Overview