вход переехал на доверенный заголовок Authelia вместо собственного OIDC
- пришедшего называет заголовок Remote-User от прокси, и верят ему только с адреса из перечня trusted_proxies; своего входа у сервиса не осталось — ни корня /auth, ни кук, ни срока сессии, ни секрета клиента в конфиге и в базе - учётная запись заводится первым обращением: EnsureUser в пакете хранилища, шаг схемы 202608220001 с колонкой provider_login и снятыми правилами users - cmd/oidcstub заменён на cmd/devtools с подкомандой proxy; заодно закрыт унаследованный DL3066 — пользователь образа назван числом
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Неизвестный путь вне корней открывает приложение
|
||||
|
||||
Сервис SHALL отдавать разметку приложения на всяком пути, который не принадлежит
|
||||
ни одному корню сервиса и не совпадает с отдельным адресом наблюдения. Корни
|
||||
перечислены поимённо — `/api` у хранилища, `/app` у приложения, `/_` у панели, —
|
||||
отдельными адресами стоят `/health` и `/metrics`.
|
||||
|
||||
Корня `/auth` в перечне больше нет: собственного входа у сервиса не осталось, и
|
||||
адресов под этим корнем не существует. Прежние адреса входа поэтому отвечают тем
|
||||
же, чем отвечает всякий путь вне корней, — разметкой приложения. Резервировать имя
|
||||
за отказом сервис не берётся: имя, за которым ничего не стоит, ничем не отличается
|
||||
от любого другого свободного имени, а второй перечень «когда-то занятых корней»
|
||||
разошёлся бы с первым молча.
|
||||
|
||||
Путь принадлежит корню, когда **совпадает с ним точно либо начинается им вместе с
|
||||
косой чертой**. Оба условия обязательны: по одному лишь префиксу корню `/app`
|
||||
достался бы посторонний `/apple`, а по одному лишь префиксу с косой чертой голый
|
||||
`/api` не достался бы никому и уехал бы разметкой.
|
||||
|
||||
Путь, принадлежащий корню, MUST не проваливаться в приложение никогда: отказ
|
||||
контракта остаётся отказом контракта и уходит той формой, которой этот корень
|
||||
отвечает и сегодня. Иначе программа, ошибшаяся адресом под корнем приложения,
|
||||
получила бы разметку с кодом `200` вместо отказа с машиночитаемым кодом — и
|
||||
приняла бы её за ответ.
|
||||
|
||||
Путь **под каталогом ресурсов** — тем, который наполняет сборщик, — разметкой не
|
||||
подменяется: не совпавший с файлом, он MUST отвечать `404`. Иначе разметка
|
||||
прежней сборки, назвавшая ресурс, которого в новой сборке уже нет, получает на
|
||||
него `200` и разметку вместо ресурса: браузер отвергнет её по типу содержимого,
|
||||
человек увидит пустой экран, а в кодах ответов сервиса не останется ничего.
|
||||
|
||||
Открывающими страницу считаются `GET` и `HEAD`, и только они; прочие методы MUST
|
||||
отвечать `405`.
|
||||
|
||||
#### Scenario: Обновление страницы посреди приложения открывает тот же экран
|
||||
|
||||
- **GIVEN** приложение открыто на своём маршруте
|
||||
- **WHEN** браузер спрашивает этот путь заново
|
||||
- **THEN** ответ имеет код `200`
|
||||
- **AND** тело ответа — разметка приложения
|
||||
|
||||
#### Scenario: Голый корень разметкой не подменяется
|
||||
|
||||
- **WHEN** запрос приходит на путь, совпадающий с корнем сервиса точно и без
|
||||
косой черты
|
||||
- **THEN** тело ответа — не разметка приложения
|
||||
|
||||
#### Scenario: Посторонний путь, начинающийся именем корня, открывает приложение
|
||||
|
||||
- **WHEN** запрос приходит на путь, который начинается именем корня, но не
|
||||
отделён от него косой чертой
|
||||
- **THEN** ответ имеет код `200`
|
||||
- **AND** тело ответа — разметка приложения
|
||||
|
||||
#### Scenario: Прежний адрес входа открывает приложение
|
||||
|
||||
- **WHEN** запрос приходит на путь под прежним корнем входа
|
||||
- **THEN** ответ имеет код `200`
|
||||
- **AND** тело ответа — разметка приложения
|
||||
|
||||
#### Scenario: Неизвестный путь под корнем приложения отвечает отказом
|
||||
|
||||
- **GIVEN** запрос идёт с заголовком, поставленным прокси
|
||||
- **WHEN** он спрашивает неизвестный путь под корнем приложения
|
||||
- **THEN** ответ имеет код `404`
|
||||
- **AND** тело ответа — отказ приложения с машиночитаемым кодом, а не разметка
|
||||
|
||||
#### Scenario: Неизвестный путь под корнем приложения неузнанному отвечает как все прочие его адреса
|
||||
|
||||
- **WHEN** запрос приходит на неизвестный путь под корнем приложения без
|
||||
заголовка
|
||||
- **THEN** ответ имеет код `401`
|
||||
- **AND** тело ответа — не разметка приложения
|
||||
|
||||
#### Scenario: Неизвестный путь под корнем хранилища отвечает отказом
|
||||
|
||||
- **WHEN** запрос приходит на неизвестный путь под корнем хранилища
|
||||
- **THEN** тело ответа — не разметка приложения
|
||||
|
||||
#### Scenario: Несуществующий ресурс отвечает отсутствием, а не разметкой
|
||||
|
||||
- **WHEN** браузер спрашивает под каталогом ресурсов файл, которого в сборке нет
|
||||
- **THEN** ответ имеет код `404`
|
||||
- **AND** тело ответа — не разметка приложения
|
||||
|
||||
### Requirement: Открытое приложение показывает вошедшего
|
||||
|
||||
Приложение SHALL спрашивать сервис, кто пришёл, и показывать его имя. Отказ
|
||||
`401` MUST показываться строкой о том, что сервис его не узнал, и MUST никуда не
|
||||
уводить: своего входа у сервиса нет, а вести человека некуда — заголовок ставит
|
||||
обратный прокси, и человек, которого прокси не назвал, до приложения дошёл бы
|
||||
только мимо него.
|
||||
|
||||
Всякий **иной** отказ и сорванный запрос MUST показываться строкой о неудаче.
|
||||
Разделять их приложение обязано: «сервис вас не узнал» и «сервис не отвечает» —
|
||||
разные состояния, и человек по ним делает разное. Прежде отказ `401` уводил ко
|
||||
входу; уводить стало некуда, и различие сохраняется ради текста, а не ради
|
||||
перехода.
|
||||
|
||||
Имя пришедшего берётся ответом сервиса, а не заголовком запроса: заголовок ставит
|
||||
прокси, и приложение его не видит вовсе. Имени в ответе может не быть — тогда
|
||||
приложение MUST показать, что человек узнан, и MUST не подставлять вместо имени
|
||||
адрес почты: его в ответе нет по норме `access`.
|
||||
|
||||
#### Scenario: Узнанный виден
|
||||
|
||||
- **GIVEN** запрос приложения идёт с заголовком, поставленным прокси
|
||||
- **WHEN** он открывает приложение
|
||||
- **THEN** приложение показывает его имя
|
||||
|
||||
#### Scenario: Неузнанному показывают, что его не узнали
|
||||
|
||||
- **GIVEN** сервис отвечает на вопрос о пришедшем кодом `401`
|
||||
- **WHEN** человек открывает приложение
|
||||
- **THEN** приложение показывает строку о том, что его не узнали
|
||||
- **AND** никуда его не уводит
|
||||
|
||||
#### Scenario: Отказ сервиса от неузнавания отличается
|
||||
|
||||
- **GIVEN** сервис отвечает на вопрос о пришедшем отказом, который не является
|
||||
неузнаванием
|
||||
- **WHEN** человек открывает приложение
|
||||
- **THEN** приложение показывает строку о неудаче
|
||||
- **AND** эта строка не та, которой оно сообщает о неузнавании
|
||||
Reference in New Issue
Block a user