Files
transcriber/docs/adr/ADR-2026-08-13-telegram-intent-declared-not-inferred.md
T
av 8f7c3a057a удалён вход Telegram, владелец записи стал обязателен в схеме
- убраны клиент бота, транспорт обновлений, отправитель сообщений, сборка
  входа при старте, секция настроек и зависимость go-telegram-bot-api; из
  конвейера ушла доставка ответа отправителю — исход виден опросом готовности.
  Колонки адресата и значение источника остались в схеме: применённые шаги не
  переписываются
- шаг 202608140003 запрещает пустого владельца у аудиозаписи и у файла;
  существующие строки он не проверяет, и это принято сознательно — искать их
  надо запросом до выкладки
- ревью нашло два пред-существующих дефекта, оба закрыты: пустой второй ответ
  распознавателя стирал сохранённую расшифровку, а пустая расшифровка перестала
  быть заметной вместе с убранной доставкой. Попутно поднят golang.org/x/image
  до v0.45.0 — красный шаг vulns, воспроизводился и на чистом master
2026-08-15 07:24:35 +03:00

68 lines
5.9 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.
# Намерение объявляется признаком, а не выводится из ключа доступа
- **Дата:** 2026-08-13
- **Источник:** openspec/changes/archive/2026-08-13-telegram-enabled-flag/design.md
- **Статус:** устарело — вход Telegram убран решением [ADR-2026-08-15-telegram-intake-removed-temporarily](ADR-2026-08-15-telegram-intake-removed-temporarily.md); довод устоял и понадобится возврату входа
## Решение
Вход Telegram включается отдельным признаком `telegram.enabled`, а `bot_token`
означает только доступ. Признак **обязателен**: умолчания у него нет, и файл
настроек без него негоден — сервис выходит с ошибкой настройки, назвав
недостающий ключ.
## Почему
Прежде пустой ключ доступа значил разом две вещи — «вход выключен намеренно» и
«ключа нет», — и сервис поднимался без бота в обоих случаях. Цена расхождения
падала на выкладку: файл настроек собирает Ansible, и потерянный при сборке ключ
выглядел для сервиса как решение владельца.
Умолчания у признака нет, и это **намеренный отказ от очевидного подхода**
булев ключ обычно заводят с умолчанием. Цитата из источника:
> умолчание — это угаданное намерение, а признак заводится ровно затем, чтобы
> намерение объявляли. Файл, где его забыли, одинаково плохо читается в обе
> стороны, и любое умолчание делает одну из двух ошибок тихой.
Отвергнуты оба умолчания. «Включён» — файл без признака работал бы «как-нибудь»,
и разница между объявленным и угаданным намерением исчезала бы ровно там, где её
завели. «Выключен» — первый же подъём после выкладки выключил бы бота молча, то
есть дал бы исход, против которого написано само требование.
Отсутствие ключа судит **разбор**, а не значение: `toml.MetaData.IsDefined`
отличает «не задан» от «задан ложным», тогда как нулевое значение `bool` у обоих
одинаковое. Форма поля с указателем отвергнута: указатель пережил бы проверку и
уехал к потребителям, где `nil` уже невозможен, но выглядит возможным.
Тем же решением закрыт разрез текста отказа при разборе файла настроек. Цитата
из источника:
> Пересказывать библиотеку нельзя: она собирает текст отказа из разбираемого
> куска файла, и оборванная строка секретного ключа уехала бы в журнал вместе со
> значением.
Норму держит инвариант «Секрет не покидает конфиг», а форму записи — конвенция
настроек. Спеки загрузку настроек не нормируют, и это назначено явно: загрузка
не принадлежит ни одной заведённой capability.
## Последствия
- `+` потерянный при сборке файла ключ доступа роняет старт вслух, а не оставляет
сервис работать в половину силы;
- `+` выключенный вход перестал быть поводом для предупреждения: решение
владельца сообщается записью «к сведению», а предупреждение осталось за тем,
чего владелец не выбирал, — недоступностью Telegram;
- `+` оборванная строка секретного ключа больше не уносит значение в журнал
контейнера;
- `` **порядок выкладки стал обязательным**: шаблон настроек обязан получить
признак раньше накатки образа, иначе сервис не поднимется вовсе. Правило живёт
в [architecture.md](../architecture.md), раздел «Эксплуатация», и задаётся там
по ключу, а не по файлу целиком;
- `` один путь молчаливой потери бота остался: признак, ошибочно собранный
как «выключен», отличим от решения владельца только записью журнала. Признак
поднятости входа тут не помощник — он равен нулю и при недоступности Telegram;
- `` отказ разбора файла настроек стал беднее на текст библиотеки: место и ключ
названы, а что именно в строке не так — нет. Плата принята ради инварианта,
помеченного необратимым.