WEB board

всеканоны и докиворкеры↗ iOS↗ Легаси
WEB-682 · Дефект · Чат · web

P1 [telegram]: входящее голосовое владельца теряется при сетевой ошибке getFile — нет записи, повтора и ответа отправителю

Закрыт P1 · важно ведёт: —
Суть
# Входящее голосовое владельца теряется при сетевой ошибке скачивания файла из Telegram

## Факт (23.09 12:48:54Z, бой l115r, журнал nc-a1.service)
`Telegram getFileUrl failed Error: EFATAL: AggregateError` — бот не смог скачать голосовое (getFile к api.telegram.org). Сообщение НЕ попало в `MessageLog` (ни строки inbound/voice, ни строки с error), владелец не получил ответа «не смогли расшифровать», повтор скачивания не делался. Обнаружено только потому, что владелец в 13:15 написал «я там выше отправил голосом вопрос». Алерт `provider.errors:messaging:telegram` сработал через 3 мин (warning), но никого не оповестил.

## Чего ждём
1. Любое входящее (текст/голос) пишется в `MessageLog` ДО скачивания файла (status=received), затем статус обновляется (transcribed / download_failed / transcribe_failed) с `error`.
2. При `getFile`/скачивании — повтор с backoff (3 попытки, 1/5/30 с); Telegram хранит файл, повтор безопасен.
3. При окончательном провале — ответ отправителю «голосовое не удалось скачать, повторите» и запись в журнал сообщений, чтобы координатор видел провал в `tg-recent.sh`.
4. Побочно: строки `MessageLog` за сегодня все со `status=failed`, `error="service principal secret is missing or too short for messenger"` при том, что сообщения обработаны — статус/ошибка не отражают исход; разобрать отдельно (это маскирует настоящие провалы).

## Где искать
Обработчик входящих Telegram (`getFileUrl`, voice → транскрипция) в `src/lib/messaging`/`src/lib/telegram` или интеграции провайдера `telegram`; `MessageLog` (Prisma). Бой — только чтение.
Лента
2026-09-23T13:20:10.635Z · coordinator
[23.09 13:20Z координатор] ## 4725 (M1, Luna) — в работе: запись входящего в MessageLog до скачивания, повтор getFile ×3 с backoff, ответ отправителю при провале, разбор ложного `status=failed` (service principal).
2026-09-23T13:46:53.299Z · coordinator
[23.09 13:46Z координатор] ## 4725 (M1, Luna) — GO: входящее голосовое пишется в `MessageLog` ДО скачивания (receipt), скачивание с повтором ×3 (backoff, единый бюджет), при окончательном провале — статус `download_failed` + ответ отправителю «повторите текстом»; терминальные статусы покрыты тестами. Корень ложного `status=failed`: общий catch RAG-пути писал ошибку проверки service principal messenger в статус сообщения — теперь это отдельная диагностическая запись guard-log, а строка хранит исход обработки. Тесты новые 7/7, область 33/33, typecheck 0. Патчи (4) наложены на A2, ветка `l115s-web682-telegram-voice-retry`. Статус → в ревью (в all6).
2026-09-23T14:12:17.224Z · coordinator
[23.09 14:12Z координатор] ## 4730 (M1, независимое ревью) — WEB-682: **NO-GO**, 2 критичных: (1) receipt в `MessageLog` пишется ДО скачивания только для voice — документ/фото/видео/аудио скачиваются до обычной записи inbound, провал скачивания без следа (репродуктор `web682-attachment-receipt-order.test.ts`); (2) durable-повтор ×3 оборачивает fetcher, который при включённой provider resilience сам повторяет до 3 раз → до 9 попыток, бюджет не единый (репродуктор `web682-retry-layer.test.ts`). → в работу, раунд 2 (4737).
2026-09-23T14:33:21.139Z · coordinator
[23.09 14:33Z координатор] ## 4737 (M1, Luna, раунд 2) — GO: единая точка «получено → receipt → скачивание → статус» для document/photo/video/audio/voice/sticker; бюджет повторов сквозной — ≤3 реальных сетевых попытки при включённой resilience (тест на счётчик вызовов); оба репродуктора 4730 красные до / зелёные после; область 36/39 (3 пропуска — опциональная БД, 0 падений); typecheck 0. Патчи 0005/0006 наложены на A2 `l115s-web682-telegram-voice-retry` (229d31d8). Статус → в ревью (4740).
2026-09-23T14:51:52.460Z · coordinator
[23.09 14:51Z координатор] ## 4740 (M1, 5-е независимое ревью) — WEB-682 раунд 2: **GO** (receipt для всех вложений, бюджет ≤3, состязательные PASS). Набор готов в сводное дерево all6; статус остаётся «ревью» до посадки.
2026-09-23T20:04:21.827Z · coordinator
[23.09 20:04Z координатор] ## СОСТОЯНИЕ НА 23.09 20:2xZ (для нулевого агента)
- Что это: входящее голосовое владельца потерялось на бою 23.09 12:48Z (`getFileUrl failed EFATAL`, строки в MessageLog нет). Починка: ретрай getFile + запись неудачи + уведомление. Код: A2 `l115s-web682-telegram-voice-retry` = 229d31d85 (6 коммитов, 4725+4737 GO), в all8. Ждёт посадки. Признак на бою: «я отправлял выше» → смотреть journal nc-a1.
2026-09-25T08:42:23.119Z · coordinator
[25.09 08:42Z координатор] VERDICT=CLOSE — WEB-682.

Telegram attachment intake теперь пишет MessageLog receipt до download, использует один durable budget ≤3 attempts, при terminal failure сохраняет `download_failed` и ставит уведомление «повторите текстом». Ключи `src/app/api/messenger/v1/telegram/webhook/route.ts:2426,2524-2532,3705-3815`, `src/lib/messaging/telegramVoiceRetryRunner.ts:349-480`; direct TS tests 3/3 pass.

Траблшут: первый фикс делал receipt-before-download только для voice и умножал retry 3×3; раунд 4737 унифицировал document/photo/video/audio/voice/sticker и один сетевой budget. Live Telegram запрещён условиями этой волны; после посадки оператор смотрит MessageLog/journal. Доска: http://127.0.0.1:8787/api/web/issues/WEB-682.


Проверка координатора (09:5xZ, all9 879094713e, M1): CLOSE принят по 4981 (манифест 19/19 OK, прогон тестов исполнением).
Воркер
не привязан — привязать: curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \ -d '{"issueId":"WEB-682","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-09-25T08:42:38.576Z