5.3 KiB
ADR-001: Подавление Telegram link-preview в низкоуровневых примитивах нотификаций
Статус
Accepted
Контекст
С ORCH-067 карточка трекера и notify-сообщения несут кликабельный номер задачи
<a href="https://plane.mva154.duckdns.org/.../issues/<id>/">ORCH-NNN</a>. Telegram
Bot API по умолчанию (при отсутствии ключа disable_web_page_preview) разворачивает
web-page-preview для первой ссылки в сообщении — под каждым сообщением трекера
раскрывается баннер «Plane — Modern project management». В дефолтном режиме bump
(ORCH-067) карточка пересоздаётся на каждом переходе, поэтому баннер дублируется на
каждой задаче и каждом обновлении, засоряя ленту (жалоба Owner, 08.06).
Код-аудит (src/notifications.py) подтвердил причину: JSON-payload обоих
низкоуровневых примитивов — send_telegram() (POST /sendMessage, стр. 55-60) и
edit_telegram() (POST /editMessageText, стр. 168-173) — не содержит ключ
disable_web_page_preview. Все вышестоящие нотификации (update_task_tracker в обоих
режимах, notify_approve_requested, notify_error, alert'ы стадий из
launcher/stage_engine) проходят через эти два примитива.
Решение
Добавить "disable_web_page_preview": True в JSON-payload httpx.post обоих примитивов:
send_telegram() и edit_telegram(). Изменение — на уровне низкоуровневого
примитива, а не на уровне каждого вызова, потому что:
- Единая точка — все исходящие сообщения трекера/нотификаций идут через эти две
функции; правка двух строк гасит баннер у ВСЕХ потребителей (карточка
bump/edit, notify-хелперы, alert'ы) без изменения их кода. - Безусловно, без флага — превью Plane не нужно никому (это не данные, а навигация по ссылке, которая остаётся кликабельной). Kill-switch не вводится: риск регрессии нулевой, правка обратима одной строкой. Это согласуется с принципом «минимум зависимостей/конфигурации».
- Top-level флаг, а не
link_preview_options.is_disabled— top-leveldisable_web_page_previewостаётся валиден и обратносовместим в Bot API; это минимальная правка без введения вложенной структуры.
parse_mode: "HTML" сохраняется в обоих payload (иначе <a href> перестанет
рендериться — ссылка должна остаться кликабельной). disable_notification,
bump/edit-логика, repoint tracker_message_id, delete-семантика, контракты возврата
(send_telegram → message_id|None, edit_telegram → EDIT_*) — не затрагиваются.
Последствия
Плюсы:
- Баннер link-preview исчезает под карточкой трекера (оба режима) и под всеми notify/alert-сообщениями — одна правда в двух примитивах.
- Ссылка на задачу остаётся кликабельной (HTML сохранён).
- Нулевой риск: ключ аддитивный, контракты примитивов и инвариант «одна карточка на
задачу» не меняются;
never-raise(try/except) сохранён.
Минусы / ограничения:
- Поведение безусловное — нет конфигурации «вернуть превью». Сознательный выбор: превью трекера не имеет ценности, флаг был бы лишней поверхностью.
Не затрагивается: STAGE_TRANSITIONS, реестр QG_CHECKS, схема БД, parse_mode,
disable_notification, транспортные хелперы delete_telegram/repoint-логика. Глобальный
ADR не требуется — решение локально для src/notifications.py, не сквозное.
Self-hosting
Изменение не требует немедленного рестарта прод-контейнера и не меняет топологию.
Деплой — штатный через staging (8501) → Confirm Deploy (ORCH-059). По ORCH-026
(сериализация merge одного репо) задача мержится после освобождения конвейера
orchestrator (координация с ORCH-074 — см. BRD §7).