Files
jellybit/openspec/changes/archive/2026-07-18-telegram-download-id-code/specs/notifications/spec.md
T
avandClaude Opus 4.8 4a58b0bda0 tgbot: download id моноширинным (code) для tap-to-copy
Включён 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>
2026-07-18 15:17:26 +03:00

47 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## ADDED Requirements
### Requirement: Download id в уведомлениях моноширинным для tap-to-copy
Уведомления, содержащие download id, система SHALL отображать id моноширинным
блоком (в Telegram — `<code>`), чтобы в клиенте работало tap-to-copy: id можно
скопировать одним касанием для перехода на `/download/{id}` или диагностики по
логам. Визуальный префикс (`#` / `download_id=`) SHALL оставаться вне
моноширинного блока, чтобы копировался чистый id без лишних символов.
#### Scenario: Id карточки review копируется одним касанием
- **GIVEN** уведомление о входе загрузки в `review` с download id
- **WHEN** бот рендерит сообщение
- **THEN** download id выводится моноширинным блоком (tap-to-copy), а префикс `#`
остаётся обычным текстом вне блока
#### Scenario: Id в сообщении об ошибке копируется
- **GIVEN** сообщение об отказе операции с `download_id`
- **WHEN** бот рендерит сообщение
- **THEN** значение download id выводится моноширинным блоком для копирования
### Requirement: Экранирование внешнего текста при форматированных уведомлениях
При включённом форматировании исходящих сообщений (parse mode) система MUST
экранировать все внешние/недоверенные фрагменты перед вставкой в размеченное
сообщение: display name, распознанное название, источник/контекст, целевой путь,
причины распознавания, provider, код и текст ошибки. Это защищает от того, что
спецсимволы разметки сломают сообщение или что разметка будет инъектирована из
недоверенного источника (инвариант «выход LLM недоверенный»). Секреты
(токены/ключи/пароли) MUST NOT попадать в текст уведомлений и логи.
#### Scenario: Спецсимволы в названии не ломают разметку
- **GIVEN** уведомление, где display name или распознанное название содержит
символы разметки (`<`, `>`, `&`)
- **WHEN** бот рендерит форматированное сообщение
- **THEN** эти символы экранируются, сообщение доставляется корректно, а разметка
из недоверенного текста не интерпретируется
#### Scenario: Внешний путь и причины экранируются
- **GIVEN** уведомление с целевым путём плана и причинами распознавания
- **WHEN** бот рендерит форматированное сообщение
- **THEN** символы разметки в пути и причинах экранируются перед вставкой