ADR-008: Абстракция channel service
- Статус: Принято
- Дата: 16 апреля 2026
- Автор: CTO Agent (KALA-151)
Контекст
Плагины Telegram и WhatsApp изначально читали env-переменные напрямую. Для одного Telegram-бота и одного WhatsApp-номера это работает, но не масштабируется на multi-tenant или multi-namespace деплой, где у разных отделов может быть разная конфигурация канала.
Уровню каналов нужен стабильный контракт, чтобы будущие web, Slack, email и DB-backed канальные записи можно было добавлять без переписывания каждого плагина.
Решение
Ввести интерфейс ChannelService:
export interface ChannelService {
getActiveChannel(type: ChannelType): Promise<ChannelConfig | null>;
listActive(type?: ChannelType): Promise<ChannelConfig[]>;
findByRoutingKey?(key: string): Promise<ChannelConfig | null>;
}
Текущий EnvChannelService читает существующий config-объект и возвращает один активный Telegram-канал и один активный WhatsApp-канал. Неподдерживаемые типы возвращают null или пустой список.
Fastify даёт сервис как app.channelService, поэтому плагины зависят от интерфейса, а не читают env напрямую.
Рассмотренные альтернативы
Оставить чтение env в плагинах
Отклонено. Упрощает первый деплой, но усложняет multi-channel маршрутизацию и тестирование.
Сразу перейти на DB-backed каналы
Пока отклонено. Продукту сначала нужна абстракция; DB-модель и management UI можно добавить позже без смены plugin-контрактов.
Свой service у каждого плагина
Отклонено. У Telegram и WhatsApp должна быть одна и та же форма: type, id, department, namespace, enabled flag и config map.
Последствия
Плюсы
- Channel-плагины полагаются на стабильный интерфейс.
- Тесты могут инстанциировать
EnvChannelServiceс маленьким config-стабом. - Будущая DB-backed маршрутизация сможет поддерживать несколько каналов каждого типа.
- Department и namespace scope — first-class поля в
ChannelConfig.
Минусы
- Env-backed реализация пока отдаёт только один канал каждого типа.
- Секреты живут в process-конфиге, пока не добавится DB-backed хранилище секретов.
findByRoutingKey()остаётся опциональным до момента, когда понадобится для inbound-маршрутизации.
Заметки по реализации
src/lib/channels/channel-service.tsопределяет интерфейс и env-backed реализацию.- Сейчас сервис поддерживает
telegramиwhatsapp. ChannelTypeуже включаетslack,emailиwebдля будущих реализаций.