# Разбор TOML: незнакомый ключ и незнакомая секция не отказ, а тишина

Отвечает на вопрос, возникший по ходу задачи `config-test-headers-login`: что
делает декодер настроек с ключом и секцией, которых структура не знает, и виден
ли этот случай хоть чем-нибудь. Наблюдение понадобилось потому, что ревью нашло
опечатку в имени новой секции `[auth.test_headers]`, проходящую молча, и без
разреза нельзя было сказать, где кончается предмет задачи и начинается свойство
самой библиотеки.

Соседняя записка о той же библиотеке — [toml-decode-errors.md](toml-decode-errors.md)
— разбирает семейства **отказов**; здесь предмет обратный: случай, отказа не
дающий.

## Как снималось

Прогонами на зависимости, зафиксированной в `go.mod`:
`github.com/BurntSushi/toml` версии **v1.5.0**. Оба уровня снял триаж ревью
2026-08-23, отчёт —
[triage-2026-08-23.md](../../openspec/changes/archive/2026-08-23-config-test-headers-login/review/triage-2026-08-23.md),
находка 2 и факт, подтверждённый разбором прохода `operations`. Временные файлы
прогонов удалены, бинарник поднимался в каталог вне репозитория, не в `data/`.

- **Модульный.** Вход
  `[server]\ndebug = true\n[auth]\n[auth.test_headrs]\n"Remote-User" = "dev"` —
  опечатка в имени секции.
- **Сквозной.** Настоящий бинарник на конфиге с той же опечаткой, порт 18099,
  каталог данных вне репозитория; проба `curl /app/me`.

## Что выяснилось

- **Незнакомая секция и незнакомый ключ отказа не дают: `decode err=<nil>`.**
  Разбор проходит целиком, поля структуры остаются нулевыми, и отличить «в файле
  этого нет» от «в файле это написано с опечаткой» по результату разбора нельзя.
  В прогоне: `Server.Debug=true len(TestHeaders)=0`.
- **Потерянное называет только `MetaData.Undecoded()`.** Он возвращает перечень
  путей, которых структура не знала: `[auth.test_headrs
  auth.test_headrs.Remote-User]`. Значение это в проекте не читает никто — ни
  загрузка настроек, ни проверки старта.
- **Контроль показывает, что дело в уровне, а не в разборе вообще.** Ту же
  опечатку **внутри** известной секции (`Remote-Usr` вместо `Remote-User`)
  ловит проверка старта — `auth: секция [auth.test_headers] называет
  заголовок, которого сервис не читает: Remote-Usr`, — потому что судит её код
  проекта, а не библиотека. Ошибка в имени самой секции до этого кода не
  доходит.
- **Сквозной прогон следа не оставляет вовсе.** Бинарник поднимается без
  предупреждения, `curl /app/me` отвечает `401`, а в журнале стоит только
  `INFO "Incoming request" … http.status_code=401`.
- **Отсюда направление отката бинарника безопасно.** Прежний образ, получивший
  конфиг с ключами, которых его структура ещё не знает, эти ключи игнорирует и
  поднимается. Свойство держится ровно на тишине выше: перечень
  `MetaData.Undecoded()` никто не судит.

## Что из этого следует для кода

Свойство сегодня используется, а не терпится: правило выкладки «конфиг после
образа» опирается именно на него, и его дом — [../architecture.md](../architecture.md),
«Эксплуатация». Здесь записано, чем свойство обеспечено и как проверено, а не
надо ли его менять.

Отсюда же цена любой будущей проверки `MetaData.Undecoded()`: непонятый ключ,
роняющий старт, закрывает опечатки во всех секциях разом — и тем же движением
снимает безопасность отката, потому что прежний образ перестанет поднимать
конфиг новее себя. Разменивать одно на другое — отдельное решение владельца,
а не попутная правка.

**Наблюдение привязано к версии.** Версия, начавшая судить незнакомые ключи
сама, сменит оба следствия разом — молчаливую опечатку и безопасный откат.
