20. OpenAPI-метаданные

20.1 Обязательно

  • R-OAS-1. Каждый эндпоинт имеет уникальный operationId в camelCase. Паттерн: действие + ресурс.

    /api/v1/orders:
      get:
        operationId: getOrders
      post:
        operationId: createOrder
    
    /api/v1/orders/{id}:
      get:
        operationId: getOrder
      put:
        operationId: updateOrder
      delete:
        operationId: deleteOrder
    
    /api/v1/orders/{id}/confirm:
      post:
        operationId: confirmOrder
    
    /api/v1/orders/search:
      post:
        operationId: searchOrders
    
  • R-OAS-2. Группировка эндпоинтов через tags. Один тег на ресурс, имя — множественное число с заглавной. Action-эндпоинты относятся к тегу родительского ресурса (confirmOrders).

    tags:
      - name: Orders
        description: 'Управление заказами'
      - name: Users
        description: 'Управление пользователями'
    
    /api/v1/orders:
      get:
        tags: [Orders]
      post:
        tags: [Orders]
    
    /api/v1/orders/{id}/confirm:
      post:
        tags: [Orders]
    
  • R-OAS-3. Параметры пути в OpenAPI именуются уникально по контексту: {orderId}, {itemId}. В дизайн-документации (см. R-NEST-4 в URL и ресурсы) используется {id} — контекст устраняет неоднозначность; в OpenAPI это требование инструмента (Swagger/Redoc не работают с одинаковыми именами параметров).

    /api/v1/orders/{orderId}/items/{itemId}:
      get:
        parameters:
          - name: orderId
            in: path
            required: true
            schema:
              type: string
              format: uuid
          - name: itemId
            in: path
            required: true
            schema:
              type: string
              format: uuid
    
  • R-OAS-4. Каждый эндпоинт имеет summary (короткая фраза, до 80 символов). description — по необходимости, если логика неочевидна.

    /api/v1/orders/{id}/confirm:
      post:
        summary: 'Подтвердить заказ'
        description: |
          Переводит заказ из статуса CREATED в CONFIRMED.
          Заказ должен содержать хотя бы одну позицию.
          После подтверждения изменение состава заказа невозможно.
    

21. Антипаттерны

Сводка ссылок на запрещающие правила (X-коды) — единая точка для быстрой проверки контракта.

АнтипаттернПравилоКорректно
Глагол в URL для CRUDR-URL-X4POST /api/v1/orders
CamelCase в путиR-URL-X1/order-items
snake_case в путиR-URL-X1/order-items
Завершающий слешR-URL-X2/api/v1/orders
Расширение файла в путиR-URL-X3/api/v1/orders
ID в теле вместо путиR-NEST-X2PUT /orders/{id}
Глубокая вложенностьR-NEST-X1/comments?itemId={id}
Множественное/единственное число вперемешкуR-RES-X2/orders/{id}/items
GET с побочным эффектомR-MTH-X1POST /orders/{id}/cancel
Версия в queryR-VER-X2/api/v1/orders
Минорная версия в путиR-VER-X1/api/v1/...
Бизнес-логика в queryR-QRY-X4POST /orders/{id}/cancel
Comma-separated массивы в queryR-QRY-X3повтор параметра
page=0 в публичном контрактеR-QRY-X2page=1
Префикс X- в заголовкахR-HDR-X1доменный префикс (Shop-)
Envelope-обёрткаR-RSP-X4плоский ресурс
null в успешном ответеR-RSP-X1отсутствие поля
nullable: true в OpenAPIR-RSP-X3required или отсутствие
application/json для ошибокR-ERR-X1application/problem+json
type: "about:blank" в ошибкахR-ERR-X2URN urn:problem:<service>:<code>
Stack traces в теле 500R-ERR-X4code + общий detail
Rate limiting без заголовковR-RATE-X1Retry-After + RateLimit-*
Deprecation без SunsetR-DEP-X1заголовок Sunset с датой
me для собственных ресурсовR-ALIAS-X1контекст из токена
HATEOAS-ссылки в телеR-PRIN-X1OpenAPI-описание навигации
Любой метод кроме POST для actionR-ACT-X2POST /orders/{id}/confirm

Финальная сводка: правил «Обязательно» — около 75, «Запрещено» — около 35. На любое нарушение ревью цитирует конкретный код (R-URL-3, R-ERR-X2, R-MTH-X1), чтобы автор PR мог быстро найти контекст.