у записи появился владелец: чужую больше не отдают
- колонка `owner` связью с `users` в обеих коллекциях новым шагом схемы `202608140001`; чтение задачи сужено владельцем, и чужая, ничья и несуществующая дают один ответ; правило просмотра файлов сужено им же - приём по HTTP берёт владельца из сессии, а предъявителя без учётной записи пользователя отвергает до чтения тела: позже пришлось бы убирать уложенный файл, а уборки файлов сервис не умеет. Выборка воркера владельцем не сужается - удаление учётной записи с записями отвергается стражем, и вешает его сама сборка хранилища: сборка, забывшая его позвать, теряла защиту молча
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: У записи есть владелец, и чужую ей не отдают
|
||||
|
||||
Сервис SHALL заводить у каждой записи, принятой **по HTTP**, — владельца, то
|
||||
есть учётную запись, от имени которой запись принята, — и MUST отдавать данные
|
||||
такой записи только её владельцу. Владелец назначается один раз, при приёме, и
|
||||
MUST не меняться у записи, у которой владелец есть: совместного доступа, ролей и
|
||||
передачи записи другому сервис не знает. Оговорка не случайна — назначить
|
||||
владельца записи, у которой его нет, вправе задача, заводящая связь чата
|
||||
Telegram с учётной записью.
|
||||
|
||||
Владелец MUST браться из предъявленной сессии и ниоткуда больше. Владелец,
|
||||
пришедший полем запроса, дал бы всякому вошедшему право завести запись на чужое
|
||||
имя.
|
||||
|
||||
Обращение к чужой записи MUST быть неотличимо от обращения к несуществующей.
|
||||
Отдельный отказ «доступ запрещён» превращает опрос в перебор — по разнице
|
||||
ответов считывается, какие записи заведены, а идентификатор записи и есть то,
|
||||
что разграничение прячет. Каким именно ответом это выражено, нормирует
|
||||
capability `intake`: там живёт адрес опроса, и держатель нормы обязан быть один.
|
||||
|
||||
Пустой владелец MUST не совпадать ни с одной записью — ни со своей, ни с чужой,
|
||||
ни с ничьей. Правило записано со стороны **спрашивающего**, а не со стороны
|
||||
записи: обязательность владельца, которую держит одна лишь подпись метода, пустую
|
||||
строку пропускает, и первый же вызывающий без учётной записи получил бы ровно
|
||||
множество записей без владельца, то есть все записи бота.
|
||||
|
||||
Записи, принятые из Telegram, владельца не имеют: связи чата с учётной записью
|
||||
приложения сервис не ведёт. Такая запись MUST не доставаться по API никому —
|
||||
ответ на неё тот же, что и на несуществующую, — а её расшифровка уезжает
|
||||
отправителю в чат, как и прежде.
|
||||
|
||||
#### Scenario: Своя запись доступна
|
||||
|
||||
- **GIVEN** человек вошёл и принял запись
|
||||
- **WHEN** он спрашивает состояние этой записи своей сессией
|
||||
- **THEN** ответ несёт состояние записи
|
||||
|
||||
#### Scenario: Чужая запись неотличима от несуществующей
|
||||
|
||||
- **GIVEN** запись принята одним вошедшим
|
||||
- **WHEN** её состояние спрашивает другой вошедший
|
||||
- **THEN** ответ тот же, что и на неизвестный идентификатор, — и кодом, и телом
|
||||
|
||||
#### Scenario: Владельца не задают запросом
|
||||
|
||||
- **WHEN** запрос на приём записи несёт своё значение владельца
|
||||
- **THEN** владельцем принятой записи становится предъявитель сессии
|
||||
|
||||
#### Scenario: Запись из Telegram не достаётся по API
|
||||
|
||||
- **GIVEN** запись принята ботом
|
||||
- **WHEN** её состояние спрашивает вошедший человек
|
||||
- **THEN** ответ тот же, что и на неизвестный идентификатор
|
||||
|
||||
#### Scenario: Пустой владелец не открывает ничего
|
||||
|
||||
- **GIVEN** заведены три задачи: своя, чужая и принятая ботом
|
||||
- **WHEN** состояние каждой спрашивают с пустым владельцем
|
||||
- **THEN** ответ на все три тот же, что и на неизвестный идентификатор
|
||||
Reference in New Issue
Block a user