## Why

Веб уже показывает, с какой именно записью метабазы сматчилась загрузка:
страница `/download/{id}` и экран ревью выводят provider, id и — если URL
строится — ссылку на страницу записи (`internal/httpapi`: `matchURL`/
`providerURL`, шаблон `download_main.html`). В Telegram матч показан беднее:
карточка ревью (`internal/tgbot/render.go`, `baseLine`) выводит только
`provider id` из **сырого** распознавания и **без ссылки**, а уведомление о
готовности матч не показывает вовсе. Из-за этого ошибочную привязку (не тот
фильм/сезон) из бота не видно — приходится открывать веб.

## What Changes

- **Карточка подтверждения (review)** в боте показывает матч со **ссылкой** на
  запись метабазы (когда URL строится) — как веб: `provider id ↗`. Без URL —
  тем же текстом, что и раньше.
- **Уведомление о готовности** (`renderDone`) показывает строку матча (provider,
  id, ссылка) — чтобы ошибочную привязку было видно и в финальном пинге.
- **Provider/id берутся эффективные** (`ReviewData.Provider`/`ProviderID`, с
  учётом ручных правок), консистентно с веб-страницей и экраном ревью, а не из
  сырого распознавания.
- **Единый билдер URL:** канонический `providerURL` и выбор ссылки матча
  `matchURL` переезжают из `internal/httpapi` в ядро `internal/worker`
  (`worker.ProviderURL` + метод `(*ReviewData).MatchURL()`), чтобы оба
  транспорта (веб и Telegram) строили ссылку одинаково. httpapi делегирует туда.
- **Экранирование:** provider, id и URL — недоверенные, экранируются перед
  вставкой в HTML-сообщение (инвариант «выход LLM недоверенный»); ссылка
  рисуется только при непустом URL. URL — в контексте атрибута `href`: помимо
  `<`/`>`/`&` экранируется и кавычка (иначе изготовленный id разорвёт атрибут и
  Telegram отклонит сообщение).

## Capabilities

### New Capabilities

Нет.

### Modified Capabilities

- `notifications`: добавляется требование к **содержанию** уведомлений/
  подтверждений — показ записи матча метабазы (provider, id, ссылка) в карточке
  ревью и уведомлении о готовности, эффективным провайдером, с экранированием.
  Условия и события доставки (падение, review, готовность, рассинхрон) без
  изменений.

## Impact

- **Спеки:** дельта `notifications` — ADDED «Показ записи матча метабазы» +
  MODIFIED «Экранирование внешнего текста» (в перечень добавлены id матча и URL,
  экранирование учитывает контекст `href`/кавычку).
- **Код:** `internal/worker/review.go` (новые `ProviderURL` + метод `MatchURL`),
  `internal/httpapi/review.go`/`download.go` (делегируют в worker; локальные
  `providerURL`/`matchURL` удаляются, `sourceMatchURL` зовёт `worker.ProviderURL`),
  `internal/tgbot/render.go` (`baseLine` по `ReviewData` со ссылкой; строка матча
  в `renderDone`).
- **Тесты:** тесты `providerURL`/`matchURL` переезжают в `internal/worker`;
  `internal/tgbot` — проверка ссылки и экранирования в строке матча.
- **Миграции БД:** нет (данные матча уже в БД).
