# Заголовки входа отладочного запуска подставляет сам сервис, а не второй процесс - **Дата:** 2026-08-23 - **Источник:** [../../openspec/changes/archive/2026-08-23-config-test-headers-login/design.md](../../openspec/changes/archive/2026-08-23-config-test-headers-login/design.md), решения 1, 6, 7 и 10 ## Решение Заголовки входа на машине разработчика ставит сам сервис — отдельным слоем цепочки корня приложения, а не вспомогательным процессом рядом: > отдельный слой цепочки корня приложения, стоящий **перед** > `TrustedHeaderIdentity` и **после** ограничителя частоты. Он правит заголовки > запроса и ничего больше не делает: учётной записи не заводит, отказов не > выдаёт, в контекст не пишет. Включают слой два новых ключа настроек — предохранитель `[server] debug` и секция значений `[auth.test_headers]`. Прежний вспомогательный процесс уходит: > **Решено** владельцем на чекпоинте: подкоманда удаляется. Назначения у неё не > остаётся — всё, ради чего её поднимали, делает сам сервис, — и второго способа > входить локально не остаётся тоже. Имена заголовков служат именами ключей секции, но набор принимаемых имён порождают константы транспорта: дом у имён остаётся один, а ключ, не совпавший ни с одним из них, роняет старт. ## Почему Владелец назвал желаемое: один бинарник, различия между запусками — в конфиге. Дизайн записал это целью: > Локальный запуск идёт одним процессом и одной командой; **вход** — то, кем > назвался пришедший, — отличает тестовый прогон от боевого содержимым файла > настроек, и ничем больше. Довод в пользу слоя перед узнаванием, а не внутри него: > Отлаживается **та же** ветка кода, что работает в бою: подставленный заголовок > неотличим от пришедшего от Caddy к моменту, когда его читает узнавание. Отвергнуты три очевидных подхода, и у каждого названа цена. **Подстановка внутри `TrustedHeaderIdentity`** — «узнавание получило бы второй источник значений и ветку, которой в бою нет. Отлаживалась бы не боевая ветка, а её отладочный двойник». **Произвольная карта имён заголовков в конфиге** — «опечатка `Remote-Usr` даёт „сервис меня не узнаёт“ без единого следа». **Вырезать подстановку из боевой сборки тегом сборки:** > сборка образа в гейте не проверяется вовсе (`CLAUDE.md`, «Гейт»), и тег, > забытый в одной ступени, дал бы ровно ту тишину, которой избегает пункт 3. ## Почему это ADR Триггер сработал дважды. **Дорогой откат:** решение заводит два имени ключа настроек, а имя ключа конфига `CLAUDE.md` называет необратимым; вернуться к вспомогательному процессу значит поднять удалённую подкоманду, убрать оба ключа из настроек и переписать рецепт локального запуска, разошедшийся по образцу конфига, `README.md`, `CLAUDE.md` и конвенции настроек. **Намеренный отказ:** вырезать отладочный код из боевой сборки тегом сборки — то, что делают по умолчанию, и отказ от этого объясняется один раз здесь, а не на каждом вопросе «почему подстановка вообще есть в боевом бинарнике». ## Последствия - `+` Локальный запуск идёт одним процессом и одной командой; приложение открывают по адресу сервиса, второго порта нет. - `+` Отлаживается боевая ветка узнавания: подставленный заголовок неотличим от пришедшего от прокси к моменту, когда его читают. - `+` Второго способа входить локально не остаётся, и документация перестаёт каждый раз говорить, какой из способов чей. - `+` Имена заголовков остаются с одним домом — константами транспорта; ключ, не совпавший ни с одним из них, роняет старт и называет принимаемые имена. - `−` **Местный инструмент больше не воспроизводит поломки контура.** Цена названа в источнике прямо: два значения `Remote-User`, заголовок с недоверенного адреса, цепочка `X-Forwarded-For` — всё это теперь воспроизводит только автотест, ставящий заголовок сам. - `−` В боевом бинарнике появляется код, называющий пришедшего без провайдера. Что его держит и чего у него нет — [ADR-2026-08-23-no-address-guard-for-debug-login](ADR-2026-08-23-no-address-guard-for-debug-login.md). - `−` У ключа `[server] debug` закрытый перечень следствий, и держать его придётся руками: новое поведение привязывается к ключу только отдельным решением владельца и получает своё требование спеки [access](../../openspec/specs/access/spec.md). Ключ с открытым перечнем следствий обрастает ими молча. - `−` Каждый новый логин имитации заводит учётную запись, а удалять их сервис не умеет. Локальная база ронится и пересоздаётся свободно, в бою подстановка выключена — но лишние записи копятся.