- колонка `owner` связью с `users` в обеих коллекциях новым шагом схемы `202608140001`; чтение задачи сужено владельцем, и чужая, ничья и несуществующая дают один ответ; правило просмотра файлов сужено им же - приём по HTTP берёт владельца из сессии, а предъявителя без учётной записи пользователя отвергает до чтения тела: позже пришлось бы убирать уложенный файл, а уборки файлов сервис не умеет. Выборка воркера владельцем не сужается - удаление учётной записи с записями отвергается стражем, и вешает его сама сборка хранилища: сборка, забывшая его позвать, теряла защиту молча
4.8 KiB
Why
Сегодня знание идентификатора задачи и есть право её читать: всякий вошедший видит любую расшифровку по её идентификатору — свою, соседа, чью угодно. Паспорт обещает приглашённому пользователю обратное: «каждый видит только свои записи».
Разграничение стоит первым в очереди не само по себе. На владельце записи стоят список записей, дедупликация, удаление, учёт расхода и квота — всё, что проект собирается делать дальше. Заводить их поверх общей кучи записей значит переделать каждое из них потом.
What Changes
- У записи появляется владелец — учётная запись, от имени которой её завели. Назначается он один раз, при приёме, и больше не меняется.
- Опрос готовности отдаёт только свои записи. Чужая запись по её идентификатору отвечает «не найдено» — тем же ответом, что и несуществующая. Отдельного «доступ запрещён» нет намеренно: по нему перебирается список заведённых задач.
- Приём по HTTP заводит владельца из предъявленной сессии. Приём без сессии отказывал и раньше, и это не меняется.
- Конвейер владельцем не сужается: расшифровка идёт для всех записей подряд, как и прежде. Владелец решает, кому запись показывать, а не кому её считать.
- BREAKING для содержимого базы: колонка владельца добавляется шагом схемы, и записи, заведённые до него, владельца не получают. Данные не переносим — проект заводится с чистого листа, так решено рамками задачи.
Записи, пришедшие ботом, владельца здесь не получают: связи чата Telegram с учётной записью приложения ещё нет, её заводит следующая задача. Что это значит для обязательности колонки — развилка, вынесенная в design.md и на чекпоинт.
Capabilities
New Capabilities
Новых нет: разграничение доступа — это поведение уже заведённой access, а не
новый домен.
Modified Capabilities
access: появляется владелец записи и правило «чужая запись неотличима от несуществующей». Сегодня спека прямо говорит обратное — «разграничения записей по владельцу здесь нет».intake: приём назначает владельца принятой записи, опрос готовности сужается владельцем. Обе строки спеки, обещающие обратное, снимаются.pipeline: записывается то, что до сих пор было умолчанием, — выборка задачи воркером владельцем не сужается.storage: у задачи в схеме появляется колонка владельца, и заводится она без умолчания.
Impact
- схема хранилища: новый шаг с колонкой владельца в таблице задач;
docs/database.md; internal/entity,internal/contract: у задачи появляется владелец, чтение сужается им;internal/adapter/repo/pocketbase: четыре места правки колонок очереди —applyToRecord,recordToJob,acquireColumns,acquiredRow;internal/service: оба метода заведения задачи;internal/controller/http: опрос готовности и приём;- публичный контракт
GET /api/status/{id}: чужая запись начинает отвечать404там, где прежде отдавала содержимое. Форма ответа не меняется.