Включён HTML parse mode у всех исходящих сообщений бота (send + edit-путь
refreshCard), download id выводится моноширинным <code> — в клиентах Telegram
по нему работает tap-to-copy (скопировать id для /download/{id} или диагностики).
Префикс # / download_id= остаётся вне <code>, чтобы копировался чистый id.
Parse mode делает разметку значимой для всех текстов, поэтому добавлен
escape-хелпер и экранированы все внешние/недоверенные фрагменты: display name,
распознанное название, источник/контекст, целевой путь, причины, provider,
error_code/error_msg (инвариант «выход LLM недоверенный»). esc применяется
последним шагом, после усечения, чтобы обрез не разрубил HTML-сущность.
Capability notifications: два ADDED-требования (формат id + экранирование).
Беклог: задача закрыта, зонтичный telegram-revyu-uvedomleniy обновлён.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
51 lines
3.5 KiB
Markdown
51 lines
3.5 KiB
Markdown
## Why
|
||
|
||
Download id в уведомлениях бота сейчас уходит обычным текстом с префиксом `#`
|
||
(`internal/tgbot/bot.go`, `render.go`). В клиентах Telegram по моноширинному
|
||
`<code>`-тексту работает tap-to-copy — удобно скопировать id для перехода на
|
||
`/download/{id}` или для диагностики по логам. Обычный текст так скопировать
|
||
нельзя.
|
||
|
||
Чтобы получить `<code>`, нужно включить у исходящих сообщений parse mode. Это
|
||
делает разметку значимой для **всех** текстов бота: спецсимволы (`<`, `>`, `&`)
|
||
в display name, путях, распознанных названиях, причинах и тексте ошибок сломают
|
||
сообщение или будут истолкованы как разметка. Escape-хелпера сейчас нет — его
|
||
надо ввести и аккуратно применить ко всем внешним фрагментам.
|
||
|
||
## What Changes
|
||
|
||
- **Download id выводится моноширинным** (`<code>{id}</code>`) во всех
|
||
уведомлениях бота — tap-to-copy. Визуальный префикс (`#` / `download_id=`)
|
||
остаётся вне `<code>`, чтобы копировался чистый id.
|
||
- **Включается HTML parse mode** у всех исходящих сообщений — как у `send()`, так
|
||
и у edit-пути обновления карточки (`refreshCard`).
|
||
- **Вводится escape-хелпер**; все внешние/недоверенные фрагменты (display name,
|
||
распознанное название, источник/контекст, путь плана, причины распознавания,
|
||
provider, `error_code`/`error_msg`) экранируются перед вставкой в размеченное
|
||
сообщение. Инвариант «выход LLM недоверенный» распространяется на разметку.
|
||
- Секреты по-прежнему не попадают в сообщения и логи (без изменений).
|
||
|
||
## Capabilities
|
||
|
||
### New Capabilities
|
||
|
||
Нет.
|
||
|
||
### Modified Capabilities
|
||
|
||
- `notifications`: добавляется требование к **формату** уведомлений — download id
|
||
моноширинным (tap-to-copy) и инвариант безопасного экранирования внешнего
|
||
текста при включённом форматировании. Условия и события доставки уведомлений
|
||
(падение, review, готовность, рассинхрон) без изменений.
|
||
|
||
## Impact
|
||
|
||
- **Спеки:** дельта `notifications` (два ADDED-требования: формат id и
|
||
экранирование).
|
||
- **Код:** `internal/tgbot/bot.go` (`send` — ParseMode HTML; `refreshCard` —
|
||
ParseMode HTML на edit; композиция id как `<code>`), `internal/tgbot/render.go`
|
||
(escape-хелпер + экранирование всех внешних фрагментов, id в `<code>`).
|
||
- **Тесты:** `internal/tgbot/bot_test.go` — обновить ожидания текста (id теперь в
|
||
`<code>`), добавить проверку экранирования спецсимволов во внешнем фрагменте.
|
||
- **Миграции БД:** нет.
|