tgbot: выбор кандидата метабазы inline-кнопками в карточке ревью
Когда для распознавания сохранены кандидаты метабазы, карточка подтверждения бота показывает кнопку «🗂 База (N)». По ней двухшагово (как delete/dismiss) разворачивается список кандидатов inline-кнопками; выбор пиннит источник через worker.ChooseCandidate (ручной матч, без авто-раскладки) и обновляет карточку. Веб остаётся точкой точных правок (ручной ввод id/URL, «без базы»). Безопасность границы: id кандидата из callback_data валидируется как ULID (ident.Parse) до доменного вызова, как в вебе. Текст inline-кнопок Telegram не парсится как HTML — название кандидата в подписи не экранируется. SDD: change telegram-vybor-nahodok — дельта notifications (ADDED «Выбор кандидата метабазы из карточки подтверждения бота») + review (MODIFIED «Разделение труда транспортов»: быстрый выбор кандидата — Telegram-действие). Влито в specs, change заархивирован. Миграций БД нет (кандидаты уже в БД). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+58
@@ -0,0 +1,58 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Выбор кандидата метабазы из карточки подтверждения бота
|
||||
|
||||
Карточка подтверждения бота SHALL предлагать выбрать источник из сохранённых
|
||||
кандидатов метабазы inline-кнопками, когда для распознавания загрузки есть хотя
|
||||
бы один такой кандидат (типичный триггер ревью — несколько подходящих записей без
|
||||
единичного сильного матча), а не молча оставлять загрузку с первым/лучшим или без
|
||||
базы. Когда сохранённых кандидатов нет, карточка кнопку выбора базы показывать
|
||||
SHALL NOT. Выбор SHALL быть двухшаговым: кнопка выбора базы разворачивает список
|
||||
кандидатов (по кнопке на кандидата, выбранный помечен), а нажатие кандидата
|
||||
пиннит его как источник и обновляет карточку. Отдельная кнопка SHALL возвращать
|
||||
карточку без изменений.
|
||||
|
||||
Выбор кандидата из бота — **ручной матч** (пиннинг источника): он SHALL NOT
|
||||
запускать авто-раскладку; раскладка выполняется отдельным подтверждением
|
||||
(«Применить»). Бот SHALL оставаться быстрым выбором из готового короткого списка
|
||||
кандидатов, тогда как точные правки (ручной ввод id/URL, «без базы») — на веб-
|
||||
поверхности.
|
||||
|
||||
Id кандидата приходит в `callback_data` и является недоверенным входом: перед
|
||||
доменным вызовом выбора система MUST валидировать его как ULID на границе
|
||||
транспорта; невалидный id MUST отклоняться без изменения состояния загрузки.
|
||||
Текст inline-кнопок Telegram не интерпретируется как разметка, поэтому название
|
||||
кандидата в подписи кнопки инъекции разметки не создаёт.
|
||||
|
||||
#### Scenario: Карточка с кандидатами предлагает выбор базы
|
||||
|
||||
- **GIVEN** загрузка в `review`, для распознавания которой сохранены кандидаты метабазы
|
||||
- **WHEN** бот рендерит карточку подтверждения
|
||||
- **THEN** карточка содержит кнопку выбора базы, ведущую к списку кандидатов inline-кнопками
|
||||
|
||||
#### Scenario: Выбор кандидата пиннит источник без авто-раскладки
|
||||
|
||||
- **GIVEN** развёрнутый в карточке список кандидатов метабазы
|
||||
- **WHEN** пользователь нажимает кнопку кандидата
|
||||
- **THEN** этот кандидат закрепляется как источник (ручной матч), карточка
|
||||
обновляется на месте, а авто-раскладка не запускается — для раскладки нужно
|
||||
явное «Применить»
|
||||
|
||||
#### Scenario: Id кандидата из callback валидируется на границе
|
||||
|
||||
- **GIVEN** callback выбора кандидата, где значение id кандидата недоверенное/невалидное
|
||||
- **WHEN** бот обрабатывает callback
|
||||
- **THEN** id кандидата валидируется как ULID до доменного вызова, а невалидное
|
||||
значение отклоняется без изменения состояния загрузки
|
||||
|
||||
#### Scenario: Возврат из списка не меняет состояние
|
||||
|
||||
- **GIVEN** развёрнутый в карточке список кандидатов
|
||||
- **WHEN** пользователь нажимает кнопку возврата
|
||||
- **THEN** бот возвращает исходную карточку подтверждения, не меняя выбранный источник
|
||||
|
||||
#### Scenario: Без кандидатов кнопки выбора базы нет
|
||||
|
||||
- **GIVEN** загрузка в `review`, для распознавания которой кандидаты метабазы не сохранены
|
||||
- **WHEN** бот рендерит карточку подтверждения
|
||||
- **THEN** карточка не содержит кнопку выбора базы
|
||||
Reference in New Issue
Block a user