локальный вход задаётся конфигом: заголовки подставляет сам сервис

- в конфиг добавлены секция [auth.test_headers] и предохранитель [server] debug:
  заголовки входа подставляет слой транспорта, второго процесса локальный запуск
  больше не требует
- подкоманда devtools proxy удалена целиком: всё, ради чего её поднимали, делает
  сам сервис
- адресного предохранителя нет по решению владельца — цена названа в ADR и в
  модели угроз
This commit is contained in:
av
2026-08-23 13:12:47 +03:00
parent 75c6f0168a
commit 52fe31319a
35 changed files with 3548 additions and 144 deletions
@@ -0,0 +1,74 @@
## Why
Чтобы открыть приложение на своей машине, сегодня мало запустить сервис: рядом
надо поднять второй процесс — подставной обратный прокси из оснастки, — потому
что сервис узнаёт пришедшего по заголовку, а браузер заголовков не ставит. Два
процесса вместо одного, свой порт у каждого и правило «приложение открывают по
адресу прокси, а не по адресу сервиса» — всё это надо помнить и объяснять
каждому, кто пришёл в проект.
Владелец назвал желаемое прямо: один бинарник, а различия между запусками
задаются конфигом. Тестовый прогон должен подниматься тем же
`go run ./cmd/transcriber -c config.toml`, что и всякий другой, и отличаться от
боевого только содержимым файла настроек.
## What Changes
- В секцию `[auth]` добавляется подсекция `test_headers` — имитация заголовков,
которые сервису на сервере ставит обратный прокси. Ключи подсекции задают
значения, которыми сервис назовёт пришедшего сам, когда тот пришёл ни с чем.
- В секцию `[server]` добавляется предохранитель `debug` — признак отладочного
запуска со значением по умолчанию «выключено». Подстановка заголовков работает
только при включённом признаке.
- Старт получает новые правила отказа. Заполненная имитация при выключенном
предохранителе роняет сервис, а не игнорируется молча; имитация, при которой
узнавание не состоится ни при каком запросе — неизвестное имя заголовка,
отсутствующий или негодный `Remote-User`, — роняет его тоже.
- Владелец обязан видеть отладочный запуск в журнале сервиса — предупреждением
при старте и на каждом подставленном запросе.
- Подставной обратный прокси `go run ./cmd/devtools proxy` убирается целиком:
всё, ради чего его поднимали, делает сам сервис, и второго способа входить
локально не остаётся. Решение владельца на чекпоинте; цена — поломки контура
местным инструментом больше не воспроизводятся.
- Образец конфига и памятка описывают локальный вход через настройки вместо
запуска второго процесса.
## Capabilities
### New Capabilities
Новых capability изменение не заводит: предмет прежний — кто пришёл в сервис и
пускают ли его дальше.
### Modified Capabilities
- `access`: узнавание получает второй источник заголовков — настройки сервиса —
и правила, при которых этот источник законен. Требования: подстановка идёт
только при включённом предохранителе, только при отсутствии пришедшего
заголовка, только с адресов, которым сервис и так верит; заполненная имитация
без предохранителя роняет старт; отладочный запуск виден в журнале, а значения
подставленного заголовка в журнале по-прежнему нет.
## Impact
- Настройки: `internal/config` — структуры секций `[server]` и `[auth]`,
умолчания, проверки старта. Имя нового ключа конфига необратимо и решается
человеком.
- Вход: `internal/controller/http` — цепочка слоёв корня приложения и
узнавание по заголовку.
- Точка входа: `cmd/transcriber` — порядок проверок при старте и сборка
цепочки.
- Оснастка: `cmd/devtools` — подкоманда `proxy` удаляется вместе с флагами,
шапкой пакета и строкой `usage()`.
- Документы: `config.example.toml`, `CLAUDE.md`, `README.md`,
`docs/security.md`, `docs/conventions/config.md`, `docs/architecture.md`
везде, где локальный вход описан через второй процесс.
- Граница домена: `docs/passport.md`, «Управление учётными записями». Сегодня
он утверждает, что кто пришёл, сервис не решает никогда, и что исключений у
этого больше нет. Изменение заводит исключение, и паспорт обязан назвать его
одной строкой с границей — предохранитель `[server] debug`, выключенный по
умолчанию, — и ссылкой на спеку `access`.
- Периметр: изменение заводит настройку, которой сервис пускает кого угодно.
Машиной боевая поломка не исключена: сервис с включённым предохранителем и
заполненной имитацией поднимется на любом перечне доверенных адресов. Что
стоит между боевой выкладкой и открытым входом — в `design.md`, решение 4.