config: включение Telegram разведено с ключом доступа
- в секции [telegram] заведён обязательный ключ enabled: умолчания у него нет, файл без него негоден; bot_token стал только ключом доступа и при enabled = false не читается вовсе, а пустой при enabled = true роняет старт - выключенный вход даёт подъём одним входом без единого обращения к Telegram и записью INFO вместо прежнего WARN: это выбор владельца, а не отклонение - отказ разбора файла настроек больше не пересказывает toml — её ParseError несёт в тексте разбираемое значение, и оборванная строка секретного ключа уносила его в журнал; теперь называются путь, строка, столбец и последний ключ
This commit is contained in:
@@ -102,6 +102,17 @@ Ansible из `pet-project-server`). Приложение просто читае
|
||||
- Загрузчик на старте проверяет, что обязательные секреты не пусты (ловит криво
|
||||
отрендеренный файл) — см. «Проверка и остановка на старте».
|
||||
- В логи секреты не попадают — см. [logging.md](logging.md), «Безопасность».
|
||||
- **Отказ загрузки настроек не несёт содержимого файла.** Текст такого отказа
|
||||
собирает библиотека разбора, и собирает она его из разбираемого куска:
|
||||
`toml.ParseError` кладёт в сообщение само значение («Invalid float value: %q»).
|
||||
Оборванная кавычка в строке секретного ключа — типовая поломка криво
|
||||
отрендеренного шаблона выкладки — уносит ключ в журнал контейнера целиком, а
|
||||
инвариант «секрет не покидает конфиг» помечен необратимым. Поэтому отказ
|
||||
разбора пересобирается своими словами: путь, строка, столбец и последний ключ,
|
||||
без сообщения библиотеки. Прочие отказы декодера (несовпадение типов,
|
||||
неподдерживаемый тип) собраны из имён ключей и типов, значений в них нет, и их
|
||||
текст остаётся как есть — иначе за разборчивость отказа платили бы там, где
|
||||
платить не за что.
|
||||
|
||||
## Проверка и остановка на старте
|
||||
|
||||
@@ -119,11 +130,16 @@ Ansible из `pet-project-server`). Приложение просто читае
|
||||
TOML. Пустые ключи Yandex ловятся в конструкторе распознавателя, и там процесс
|
||||
выходит с кодом 1. Единого места проверки нет.
|
||||
|
||||
Токен бота под это расхождение больше не подпадает: он судится при сборке
|
||||
клиента, до подъёма сервера, и разрез у него объявленный — пустое значение
|
||||
означает отказ от входа и даёт подъём без Telegram, непустое негодное роняет
|
||||
старт как ошибка настройки. Нормирует это `openspec/specs/intake`, «Недоступный
|
||||
или незаданный вход Telegram не мешает подъёму».
|
||||
Под это расхождение больше не подпадают два ключа секции `[telegram]` — признак
|
||||
включения и ключ доступа, — и проверок у них две. Третий ключ секции,
|
||||
`update_timeout`, границ по-прежнему не проверяет никто, и ноль в нём обращает
|
||||
длинный опрос в непрерывный. Обязательность признака включения судит загрузчик — только разбор отличает
|
||||
«ключ не задан» от «ключ задан ложным», потому что нулевое значение `bool` у
|
||||
обоих одинаковое. Заполненность ключа доступа судит `TelegramConfig.Validate()` из
|
||||
`main.go`, рядом с проверкой `[auth]`: пустой `bot_token` при `enabled = true` —
|
||||
ошибка настройки и отказ старта. Непустой негодный по-прежнему судится при сборке
|
||||
клиента, до подъёма сервера. Нормирует это `openspec/specs/intake`, «Признак
|
||||
включения решает, поднимается ли вход Telegram».
|
||||
|
||||
Секция `[auth]` — первая, у которой проверка своя и стоит на старте:
|
||||
`AuthConfig.Validate()` зовётся из `main.go` сразу после загрузки и роняет
|
||||
@@ -142,3 +158,11 @@ TOML. Пустые ключи Yandex ловятся в конструкторе
|
||||
([ADR](../adr/ADR-2026-08-12-single-data-dir-config-key.md)).
|
||||
- Умолчания задаются в `defaultConfig()`, файл их перекрывает. Новое поле
|
||||
требует правки обоих мест.
|
||||
- **Обязательное поле — поле, у которого умолчания нет намеренно.** Умолчание у
|
||||
такого поля было бы угаданным намерением, и одна из двух ошибок стала бы
|
||||
тихой. Форма записи: умолчания нет ни в `defaultConfig()` (причина — строкой
|
||||
комментария у самого поля), ни по нулевому значению типа; присутствие ключа
|
||||
судит **разбор** — `MetaData.IsDefined` из `toml.DecodeFile`, — потому что
|
||||
значение отличить «не задано» от «задано нулём» не позволяет. В
|
||||
`config.dist.toml` у поля стоит значение свежей установки. Первое такое поле —
|
||||
`telegram.enabled`.
|
||||
|
||||
Reference in New Issue
Block a user