- шаг схемы закрывает поверхность, которую хранилище приносит открытой: собственную регистрацию, вход по паролю и одноразовый код — без этого закрытие приёма обходилось двумя запросами - продление сессии выключено, срок семь суток: иначе отзыв доступа у провайдера до сервиса не доходит никогда - файл записи отдаётся вошедшему по токену файла — пересмотр ADR-2026-08-12-file-link-open-but-not-logged
5.4 KiB
✨ Пускать в приложение только после входа через OIDC
- Тип: feature
- Категория: Очередь
- Зачем: HTTP API открыт наружу без аутентификации: любой из интернета заводит задачи за наши деньги и читает чужие расшифровки по идентификатору.
- Теги: goal:multi-user
Двигает пункты 1 и 3 «Завершения» цели: неаутентифицированный запрос к записям не проходит ни к странице, ни к API; вход идёт через OIDC у Authelia, а выход из сессии работает.
Провайдер — Authelia по OIDC. Своей регистрации и своих паролей не делаем, это
граница из паспорта. Разграничения записей по владельцу
здесь ещё нет: после входа видно всё, что видно сейчас, — этим занимается
record-ownership.
Ответ провайдера разбирает PocketBase, а не наш код — решено 2026-08-11
(adr).
У её коллекции пользователей настраивается провайдер oidc с адресами Authelia,
и учётные записи заводятся сами; проверено на версии 0.39.10,
docs/research/pocketbase.md. Отсюда порядок:
задача идёт после pocketbase-storage, до неё настраивать нечего.
Затрагивает
- настройка провайдера
oidcу коллекции пользователей PocketBase: адреса Authelia, идентификатор клиента, секрет, соответствие полей учётной записи; - эндпоинты входа и выхода, которые PocketBase приносит своими;
POST /api/audioиGET /api/status/:id— оба уходят за аутентификацию;GET /healthиGET /metrics— остаются открытыми и сессии не требуют;- хранение сессии: её ведёт PocketBase, и решить надо, чем она предъявляется приложению;
- секция конфигурации под провайдера: адрес, идентификатор клиента, секрет;
docs/security.md— периметр меняется, и первая его строка перестаёт быть верной;config.dist.tomlиinternal/config.
Критерии приёмки
- Запрос к
POST /api/audioиGET /api/status/:idбез сессии получает отказ, а не заводит задачу и не отдаёт текст. Оракул — тест на обоих эндпоинтах без куки: код ответа 401 либо 302 на вход, тело без данных задачи. Тот же тест проверяет вторую сторону границы:GET /healthиGET /metricsбез куки отвечают 200. - Сессия переживает перезапуск приложения. Оракул — тест: запрос с прежней кукой после пересоздания сервера проходит.
- Выход из сессии закрывает доступ. Оракул — тест: после выхода тот же запрос получает отказ.
- Секрет провайдера не попадает ни в лог, ни в ответ. Оракул — тест на отсутствие значения секрета в записанном выводе логгера.
- Первая строка
docs/security.mdописывает новый периметр. Оракул —task gate, шагdocs.py check.
Рамки
Владельца у записи здесь не заводим и выборку не сужаем: после входа видно
столько же, сколько сейчас. Инвариант «бот отвечает только тем, кто в белом
списке» не трогаем — он живёт до telegram-account-link. Панель администратора
тоже не трогаем: наружу её закрывает Authelia на обратном прокси, а это работа
выкладки.
GET /health и GET /metrics за аутентификацию не уходят — решено 2026-08-12.
Сессии нет ни у пробы здоровья, ни у сборщика Prometheus, и вход по личным
токенам эта задача не заводит. Наружу их закрывает то же правило обратного
прокси, что и панель администратора, — работа выкладки. Пока правило не
поставлено, /metrics отдаёт наружу объёмы работы сервиса: число задач, размеры
и длительности записей; содержимого расшифровок в них нет.