APIСтандартизация
тема 1
Открыть слайдами →

76Команда должна формально записать свои правила

API Style Guide — внутренний стандарт проекта, файл docs/API_STYLE_GUIDE.md.

примеры правил
URI MUST use nouns.

GET MUST NOT change business state.

Public operations MUST define operationId.

Errors SHOULD use application/problem+json.

Collections MUST support pagination
when their size is unbounded.
API_STYLE_GUIDE.md
├─ URI
├─ HTTP
├─ JSON
├─ Errors
├─ Versioning
└─ Security

В учебном проекте после каждого правила указано, чем оно проверяется автоматически: правилом Spectral или тестом.

77У правил должна быть сила требования

В инженерных спецификациях сила требования обозначается ключевыми словами из RFC 2119.

MUSTобязательно; MUST NOT — обязательно не делать
SHOULDрекомендуется; отступление нужно обосновать
MAYдопускается по выбору команды
Every operation MUST have operationId.

Endpoints SHOULD provide examples.

Clients MAY request up to 100 items.

Так документ становится менее двусмысленным: «желательно добавить пример» и «нужно добавить operationId» больше не читаются одинаково.

Zalando и adidas используют этот подход в своих API guidelines.

78Style Guide недостаточно просто написать

Если в компании 100 API, человек не сможет вручную проверять каждую строку каждого OpenAPI.

Правило, которое проверяют только на review, рано или поздно пропустят. Поэтому часть правил переводится в форму, понятную программе.

Один из популярных инструментов — Spectral.

  1. API STYLE GUIDE.md для людей
  2. MACHINE RULES.yaml для программы
  3. LINTERпроверяет каждый коммит

79Linter для OpenAPI

Spectral анализирует описания API в YAML и JSON и сообщает о нарушениях правил.

У Spectral есть встроенный ruleset для OpenAPI:

.spectral.yaml
extends:
  - spectral:oas

Он проверяет корректность документа и базовые рекомендации. Поверх него команда добавляет собственные правила.

запуск
npx @stoplight/spectral-cli lint openapi/openapi.yaml
github.com · stoplightio/spectralСКРИНШОТ · 15.09.2026
Репозиторий Spectral: описание «JSON/YAML linter … with baked in support for OpenAPI». Клик — увеличить.

80Часть правил переносим в код

Файл .spectral.yaml учебного проекта: встроенные правила с повышенной строгостью и три собственных.

.spectral.yaml (сокращено)
extends:
  - spectral:oas

rules:
  info-contact: error
  info-description: error
  operation-operationId: error
  operation-tags: error
  path-params: error

  paths-no-verbs:
    description: URI MUST описывать ресурс
      существительным, а не действием.
    severity: error
    given: "$.paths"
    then:
      field: "@key"
      function: pattern
      functionOptions:
        notMatch: "/(get|create|update|delete...)"
вывод Spectral на плохом контракте (фрагмент)
 2:6    error  info-contact           Info object must have "contact" object.
10:22   error  paths-no-verbs         URI MUST описывать ресурс существительным
11:9    error  operation-operationId  Operation must have "operationId".
36:19   error  error-responses-use-problem-json
47:19   error  json-properties-snake-case

✖ 9 problems (7 errors, 2 warnings)

Отсутствие operationId теперь не рекомендация преподавателя, а автоматически обнаруживаемая проблема.

API_STYLE_GUIDE.md→.spectral.yaml→openapi.yaml

81Контракт можно проверять обычным тестом

app.openapi() возвращает контракт как словарь Python, и тест проверяет его, как любые другие данные.

tests/test_contract.py
from app.main import app


def test_openapi_contract_has_required_metadata():
    schema = app.openapi()

    assert schema["info"]["title"]
    assert schema["info"]["version"]
    assert schema["info"]["description"]
    assert schema["info"]["contact"]["name"]
  1. CODE
  2. app.openapi()
  3. TEST ASSERTIONS

Если кто-то удалит contact из app/main.py, тест упадёт с указанием строки. Правило проверяется автоматически при каждом запуске pytest.

82Каждый endpoint обязан иметь operationId

Тест проходит по всем операциям схемы и проверяет правило для каждой.

tests/test_contract.py
def test_every_operation_has_operation_id():
    schema = app.openapi()
    for path, method, operation in operations(schema):
        assert operation.get("operationId"), (
            f"{method.upper()} {path} has no operationId"
        )

Вспомогательная функция operations() в том же файле перебирает schema["paths"] и отбрасывает ключи, которые не являются HTTP-методами.

  1. OpenAPI paths
  2. for each operation
  3. CHECK

Так стандартизация превращается из просьбы «пожалуйста, не забудьте» в проверяемое требование. В учебном проекте девять таких тестов, включая сверку openapi/openapi.json с кодом.

83Проверка выполняется до объединения изменений

GitHub Actions запускает проверки на каждый push и pull request.

.github/workflows/ci.yml (сокращено)
name: API contract
on:
  push:
  pull_request:

jobs:
  contract:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install -r requirements.txt
      - run: pytest
      - run: python scripts/export_openapi.py --check
      - uses: actions/setup-node@v4
      - run: npx --yes @stoplight/spectral-cli@6.16.3 lint openapi/openapi.yaml
  1. Push / Pull request
  2. GitHub
  3. CI
  4. Tests · export --check · Spectral
  5. oasdiff · только в pull request
  6. PASS / FAIL

Ошибочный API contract обнаруживается ещё до deployment.

Доказательство: первый прогон в репозитории учебного проекта
github.com · MaximBytecamp/api-standard-templateСКРИНШОТ · 16.09.2026
Прогон ci.yml после push в main: job contract прошёл за 19 с, breaking-changes пропущен, потому что это не pull request. Логи шагов GitHub показывает только после входа. Клик — увеличить.

84Документация должна показывать, какие операции защищены

Недостаточно написать в README «нужен токен». OpenAPI формально описывает security scheme.

В нашем проекте write operations требуют Bearer token:

ТокенЧтениеЗапись
нетда401
demo-tokenдада
viewer-tokenда403
  1. Swagger UI · Authorize
  2. Bearer token
  3. Protected operation

В production реальный механизм может использовать OAuth 2.0 / OpenID Connect: токен выдаёт сервер авторизации, а сервис проверяет его подпись и срок действия.

Swagger UI · AuthorizeСКРИНШОТ · 15.09.2026
Окно Available authorizations: схема BearerAuth (http, Bearer) и поле для токена. Операции записи отмечены замком. Клик — увеличить.

85Правильный Swagger ещё не делает API безопасным

OWASP API Security Top 10 описывает риски, характерные именно для API.

РискКак выглядит в Service Desk
Broken Object Level Authorizationсотрудник подставляет чужой ticket_id и читает чужое обращение
Broken Authenticationсервер принимает просроченный или поддельный токен
Broken Object Property Level Authorizationклиент меняет поле, которое ему менять нельзя

Наличие /docs и OpenAPI schema не является доказательством безопасности API.

github.com · OWASP/API-SecurityСКРИНШОТ · 15.09.2026
OWASP Top 10 API Security Risks – 2023: первый риск — API1:2023 Broken Object Level Authorization. Клик — увеличить.

86Теперь документация становится частью разработки

Итоговая цепочка: каждое звено проверяет предыдущее.

  1. API STYLE GUIDE
  2. FASTAPI CODE
  3. OPENAPI SCHEMA
  4. SWAGGER UI / REDOC
  5. LINTER
  6. CONTRACT TESTS
  7. CI

Style guide задаёт правила. Код реализует контракт, из кода получается схема. По схеме строится документация, её проверяют линтер и тесты, а CI не даёт объединить изменение, которое нарушает правила.

API больше не является только набором функций Python.

Кадр крупным планом