# Ревью кода — telegram-enabled-flag Метка `medium`, режим по графу. Состав: `autotests`, `specs`, `code`, `basics`, `triage`. Проходы `adversary`, `ops`, `architecture` не запускались — живут с метки `large`. ## План с исходом по каждой теме | Тема | Дом | Глубина | Кто закрывает | Исход | | --- | --- | --- | --- | --- | | requirements | `openspec/specs/intake/spec.md` + дельта | разбор | specs | закрыта, 3 находки | | autotests | `CLAUDE.md`, «Гейт» | — | autotests | закрыта, 3 находки | | conventions | `docs/conventions/config.md` | разбор | code | закрыта, 3 находки | | architecture | `docs/architecture.md`, «Компоненты», «Единые точки» | разбор | basics | закрыта, находок нет | | security | `docs/security.md` | разбор | basics | закрыта, находок нет | | operations | `docs/architecture.md`, «Эксплуатация» | разбор | basics | закрыта, 2 находки | Тем без отчёта нет, тем без дома нет, своих тем проекта нет. ## Состояние гейта Зелёные: `build`, `vet`, `gofmt`, `tests` (`-race`, флака нет при `-count=1` трижды), `golangci-lint` (0 issues), `shell`, `dockerfile`, `go-version`, `migrations`, `openspec`, `vulns`. Красные: `docs` и `tasks` — «проект приведён к раскладке версии 3, текущая — 4». Краснота **унаследована**: проход `autotests` воспроизвёл её в отдельном рабочем дереве на чистом `903941f` без диффа. Чинится операцией `upgrade` скилла `av-dev:canon` и к этой работе не относится. `vulns`: единственная уязвимость `GO-2026-5932` в `golang.org/x/crypto/openpgp` недостижима из кода и уже названа в `CLAUDE.md`. ## Находки и что с ними сделано 15 сырых находок, после дедупликации по причине — 8 живых. | № | Находка | Severity | Исход | | --- | --- | --- | --- | | — | `telegramFromConfig` не прогонялся с включённым входом (покрытие `2 0`) | major | починено до остальных проходов: два теста на связку «собрать клиента → разобрать исход» | | — | Ветка `decodeError` с пустым последним ключом не покрыта (`1 0`) | major | починено: тест на опечатку «незакрытая скобка секции» | | 1 | Раздел «Эксплуатация» предписывает обратный порядок выкладки — по нему сервис не поднимется вовсе | major | **принята**, `docs/architecture.md` переписан: порядок задаётся по ключу, а не по файлу, плюс два случая отката | | 2 | Сторож инварианта «секрет не покидает конфиг» зелен по построению | major | **принята**, проверка переписана честно; оракул триажа — мутация `Validate()` на утечку оставляла её зелёной | | 3 | Шапки `ErrEmptyToken` и `AbsentMessageSender` защищают снятое поведение | minor | **принята**, обе переписаны под новый разрез | | 4 | Признак поднятости входа не держится ни одной проверкой | minor | **принята**, утверждение о нуле добавлено в тест выключенного входа | | 5 | Новый абзац конвенции снимает с учёта непроверяемую границу `update_timeout` | minor | **принята**, утверждение сужено до двух ключей | | 6 | Норма «отказ разбора не несёт значения» живёт вне спек, дом не назначен | minor | **принята как развилка (а)**: дом назначен явно в `design.md` — инвариант плюс конвенция | | — | Смена версии библиотеки разбора могла бы вернуть утечку | гипотеза | действия не требует: ловится добавленными проверками, подтверждено мутацией | | — | Третий случай отката: образ старше 2026-08-13 | гипотеза | свёрнуто в находку 1, записано вопросом владельцу | Проход `security` находок не дал: починку утечки он проверил по исходникам библиотеки независимо и признал разрез верным. ## Сигнал о заниженной метке `review-code` подал сигнал: изменение вводит обязательный ключ настроек без умолчания, уже выложенный файл после этого не грузится, а имя ключа конфига проект числит необратимым. На метке `large` порядок выкладки и откат закрывал бы отдельный проход `ops`. Сигнал материализовался находкой 1 — её нашёл `basics` попутно, а не проход, для неё предназначенный. `review-basics` возражений по метке не подавал. Метка прогона не пересматривалась: правило запрещает. ## Границы покрытия - **Три прохода не запускались** — `adversary`, `ops`, `architecture`. Уносят с собой враждебный разбор входов, отдельный разбор выкладки и отката, и независимый разбор архитектурного решения. - **Ни один из четырёх проходов не сообщил свой потолок и остаток за срезом.** Это находка о самом прогоне: без такой строки «находок больше нет» неотличимо от «больше не поместилось». У `basics` риск выше прочих — одна квота на три темы. - **Решения проекта не сверялись**: `docs/adr/` — процессный документ, прогон его не открывает. Расхождение с `ADR-2026-08-13-telegram-outage-does-not-block-startup`, который это изменение частично отменяет, ловит не ревью, а сверка документации. - **Записанные наблюдения не использовались**: `docs/research/` не открывался. - **Поимённая сверка с руководствами по стилю Go не задавалась никем** — в частности, для шва-параметра вместо интерфейса. - **Альтернативной реализации, с которой можно сдиффить решения, у конвейера нет** — проход независимой реализации снят по стоимости. - **Живьём проверяемо не всё.** Подъём, отказ старта, маршруты и остановка — проверены. Приём из Telegram, расшифровка и заливка — нет: боевым токеном запускаться запрещено, ключи Yandex выдуманы, распознавание подменяется в коде. Новый разрез при включённом входе с настоящим ботом не проверялся ничем, кроме подставной сборки клиента. - Шаблон настроек в `pet-project-server` лежит в чужом репозитории и во вход не входил ни одному проходу.