API: контракт, права и проверяемый результат
Преобразуем контракт в набор запросов и ловим неверные ожидания в сгенерированных проверках.
- Разделить схему, бизнес-правило и право на объект.
- Подготовить разные сессии и ожидаемые эффекты.
- Проверить негативные сценарии без использования реальных секретов.
От запроса к оракулу
Ассистент быстро предложит тело POST и список HTTP-кодов. Но корректный JSON и ответ 200 ещё не доказывают правильность API. Сначала зафиксируйте допустимые поля, действующего пользователя, объект, исходное состояние и ожидаемый эффект. Учебный контракт OD-API-1 специально мал: каждое ожидание можно независимо проверить по его тексту. Приведённые пути не являются работающим сервисом QA Orbit.
Для своего проекта замените их endpoint согласованного стенда и уточните политику ответов. Не передавайте помощнику реальные токены, cookie и клиентские карточки. Обозначения session_A и session_B описывают роли в сценарии; секреты подставляются локально разрешённым инструментом. До отправки запроса вы должны знать автора задачи и команду каждого участника.
Полная спецификация упражнения
Учебный контракт OrbitDesk OD-API-1. Это спецификация для упражнений, не действующий удалённый сервис.
Объект: {id, title, description, authorId, teamId, state: "draft" | "published"}.
POST /api/lab/tasks: нужна сессия. Тело: {title: string, description?: string}; description по умолчанию "". Title: 1–80 кодовых точек Unicode; description: 0–2000. Сохранение не обрезает пробелы. Сервер назначает authorId и teamId из сессии, state=draft. Поля authorId, teamId, state в клиентском теле отклоняются с 422. Успех: 201 и объект; ошибка типа или длины: 422.
GET /api/lab/tasks/{id}: без сессии — 401. Неизвестный объект, чужая команда или чужой draft — 404 без содержимого задачи. Собственный draft или published своей команды — 200 и объект. Editor не получает право читать чужой draft.
POST /api/lab/tasks/{id}/publish: пустое тело. Порядок проверки: 401 (нет сессии) → 404 (нет объекта или чужая команда) → 403 (не автор и не editor) → 409 (уже published) → 422 (title.trim() пуст) → 200. Роль editor разрешает отдельное действие publish для своей команды. Trim соответствует JavaScript String.prototype.trim. Успех меняет только state.
Ошибки: JSON {error:{code,message}}; code — машинный идентификатор, текст message может меняться. Любой отказ не изменяет существующие объекты и не создаёт новую задачу. Дублирование создания, редактирование, архивирование и повтор при потерянном ответе не специфицированы.Различайте действие и объект
Анна создала t1 как draft. Её чтение возвращает 200. Борис с ролью user получает 404 без содержимого, хотя состоит в той же команде. У Веры с ролью editor есть отдельное право publish, но нет права читать чужой draft. После публикации Борис может прочитать тот же объект. Если выполнять все запросы с сессией Анны, проверка чужого доступа не состоится. Случайный UUID тоже не заменяет авторизацию.
Рассмотрим подмену authorId при создании. По OD-API-1 такое поле в клиентском теле отклоняется с 422. Ожидание не ограничивается надписью на форме: объект не должен появиться у чужого владельца. Сервер определяет владельца по проверенной сессии. У разных продуктов запрещённые поля могут обрабатываться иначе; здесь выбран явный отказ, чтобы не оставлять двусмысленности.
Три слоя проверки
На уровне протокола проверьте статус и формат JSON. На уровне структуры — необходимые поля и их типы. На уровне бизнеса — автора из сессии, состояние draft после создания и изменение только state при публикации. Для отказов сравните объект до и после разрешённым чтением. В проверке чужого draft отдельно убедитесь, что тело ответа не раскрывает title и description. Правильный код с утечкой данных остаётся провалом.
При нескольких ошибках важен порядок. Нет сессии и плохой title дают 401, а не 422. Неавтор-user с пробельным title получает 403 до валидации. Модель может верно перечислить оба кода, но неправильно связать их с конкретным запросом. Ревьюируйте таблицу с акторами и фикстурами, а не наличие знакомых слов.
Доказательство вместо впечатления
Сохраните минимальный безопасный запрос, ответ и наблюдение состояния. Если publish вернул 403, но задача стала published, тест должен провалиться по побочному эффекту. Если ожидается 200, повторно прочитайте объект другим разрешённым участником и сравните идентичность. Точную изменяемую фразу message обычно проверять не нужно; наличие и тип машинного code и бизнес-эффект важнее. Конкретные значения code в OD-API-1 не перечислены: не придумывайте их и не приравнивайте к HTTP-статусу. Для точной проверки enum нужен дополнительный контракт.
Без стенда можно завершить анализ и отредактировать набор, но нельзя объявлять динамическую проверку пройденной. В практике ниже вы именно проектируете запросы. Доступ к платной модели не требуется: уже предоставлен ошибочный ответ, который нужно разобрать по контракту.
ЗАДАЧА
Спроектируй проверки API с акцентом на права и эффекты.
КОНТЕКСТ
Учебный OD-API-1; все сессии и данные синтетические.
ВХОДНЫЕ ДАННЫЕ
Учебный контракт OrbitDesk OD-API-1. Это спецификация для упражнений, не действующий удалённый сервис.
Объект: {id, title, description, authorId, teamId, state: "draft" | "published"}.
POST /api/lab/tasks: нужна сессия. Тело: {title: string, description?: string}; description по умолчанию "". Title: 1–80 кодовых точек Unicode; description: 0–2000. Сохранение не обрезает пробелы. Сервер назначает authorId и teamId из сессии, state=draft. Поля authorId, teamId, state в клиентском теле отклоняются с 422. Успех: 201 и объект; ошибка типа или длины: 422.
GET /api/lab/tasks/{id}: без сессии — 401. Неизвестный объект, чужая команда или чужой draft — 404 без содержимого задачи. Собственный draft или published своей команды — 200 и объект. Editor не получает право читать чужой draft.
POST /api/lab/tasks/{id}/publish: пустое тело. Порядок проверки: 401 (нет сессии) → 404 (нет объекта или чужая команда) → 403 (не автор и не editor) → 409 (уже published) → 422 (title.trim() пуст) → 200. Роль editor разрешает отдельное действие publish для своей команды. Trim соответствует JavaScript String.prototype.trim. Успех меняет только state.
Ошибки: JSON {error:{code,message}}; code — машинный идентификатор, текст message может меняться. Любой отказ не изменяет существующие объекты и не создаёт новую задачу. Дублирование создания, редактирование, архивирование и повтор при потерянном ответе не специфицированы.
Акторы OD-API-1: Анна — user, автор t1, команда A; Борис — user, не автор t1, команда A; Вера — editor, не автор t1, команда A; Глеб — editor, команда B. Если не сказано иное, t1 — draft с title="Проверить экспорт" и description="". Для независимого кейса исходное состояние восстанавливается. t1 — псевдоним фактического ID. Актора API-кейса нельзя автоматически отождествлять с автором задачи из отдельной SQL-фикстуры: OD-DATA-1 служит только упражнениям по данным.
ОГРАНИЧЕНИЯ
Не выдумывай endpoint. Не выполняй запросы и не проси секреты. Разделяй код, поля ответа и изменение объекта.
ОЖИДАЕМЫЙ ФОРМАТ
Таблица: актор, состояние, запрос, ожидаемый код, тело, эффект, основание. Вопросы отдельно.Используйте разрешённый ИИ-сервис. Не отправляйте рабочие секреты и персональные данные.
Источники и проверка фактов
OWASP API1: Broken Object Level AuthorizationПрава нужно проверять для конкретного объекта и действия на сервере; скрытая кнопка не является проверкой доступа.Авторский учебный материал · Редакция QA Orbit · версия 2026-10-28.1