openapi: 3.0.3

info:
  title: CDE Orchestration API
  version: "0.0.0"
  description: |
    HTTP API оркестратора **cde-orchestration-demo**
    (`gitlab.com/sarex-team/cde-orchestration-demo`) — управление процессами
    согласования/подписи документов в Camunda (Zeebe/Operate).

    Сервис написан на Go (**Fiber v3**), точка входа — `cmd/http/main.go`,
    сборка приложения — `internal/app/http/server.go`. Все ручки объявлены в
    `internal/controller/http/v0` и смонтированы под префиксом `/api`.

    ### Аутентификация
    Все эндпоинты проходят через middleware `pkg/http/middleware/auth.go`.
    Токен передаётся заголовком `Authorization: Bearer <jwt>`. Поддерживаются
    два режима:

    1. **Sarex** (по умолчанию) — подпись JWT проверяется RSA public key из
       переменной `PUBLIC_KEY`.
    2. **Zitadel** — если передан дополнительный заголовок
       `Identity: Bearer <jwt>`, полезная нагрузка берётся из метаданных
       этого токена (`urn:zitadel:iam:user:metadata`); подпись основным
       сервисом не проверяется.

    При отсутствии/некорректности заголовков middleware возвращает `401`.

    ### Замечания
    - Ручка `GET /api/process/{instance_key}` может вернуть `425 Too Early`,
      если процесс есть в кеше, но ещё не создан в Camunda (идёт обработка).
    - Тело ответов на запись (`process`, `sign`, `operate`) обычно пустое —
      значим только HTTP-статус.

  contact:
    name: cde-orchestration-demo
    url: https://gitlab.com/sarex-team/cde-orchestration-demo

servers:
  - url: http://localhost:8080/api
    description: Локальный запуск (Fiber, ADDRESS по умолчанию :8080)
  - url: http://cde-svc.cde.svc.cluster.local/api
    description: Внутрикластерный адрес (ClusterIP)

tags:
  - name: infra
    description: Служебные эндпоинты
  - name: process
    description: Процессы согласования/подписи
  - name: sign
    description: Отправка подписей в процесс
  - name: operate
    description: Управление определениями процессов (BPMN)

security:
  - bearerAuth: []

paths:
  /:
    get:
      tags: [infra]
      summary: Проверка доступности
      description: Возвращает 200 OK. Требует валидной авторизации (middleware).
      operationId: root
      responses:
        "200":
          description: OK
        "401":
          description: Не авторизован

  /process/:
    post:
      tags: [process]
      summary: Запустить процесс
      description: |
        Создаёт инстанс процесса согласования/подписи в Camunda по документам
        из `payload`. Если для `flow_id` уже есть активный инстанс — вернётся
        `400`.
      operationId: createProcess
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProcessCreateRequest"
      responses:
        "202":
          description: Процесс принят к обработке
        "400":
          description: Ошибка валидации или активный инстанс уже существует
        "401":
          description: Не авторизован
        "500":
          description: Внутренняя ошибка (ошибка создания инстанса в Camunda)

  /process/{instance_key}:
    get:
      tags: [process]
      summary: Получить состояние процесса
      description: |
        Возвращает текущее состояние процесса по `flow_id` (в пути — числовой
        ключ). Логика: если запись есть в кеше, но нет активного инстанса в
        Camunda — процесс ещё обрабатывается (`425`).
      operationId: getProcess
      parameters:
        - name: instance_key
          in: path
          required: true
          description: Числовой идентификатор (`flow_id`)
          schema:
            type: integer
            format: uint64
      responses:
        "200":
          description: Состояние процесса
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetProcessInstanceResponse"
        "401":
          description: Не авторизован
        "404":
          description: Процесс не найден
        "425":
          description: Too Early — процесс ещё обрабатывается
        "500":
          description: Внутренняя ошибка

  /sign/:
    post:
      tags: [sign]
      summary: Отправить подписи в процесс
      description: |
        Публикует сообщение `signRequest` в процесс Camunda с подписями из
        `payload`. Для элементов с `mrpa_id` предварительно проверяется доступ
        через sarex-backend.
      operationId: sign
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SignRequest"
      responses:
        "200":
          description: Подписи приняты, сообщение отправлено в процесс
        "401":
          description: Отсутствует токен авторизации
        "403":
          description: Нет прав на MRPA
        "422":
          description: MRPA не найдена
        "500":
          description: Внутренняя ошибка

  /operate/processes:
    post:
      tags: [operate]
      summary: Загрузить определение процесса (BPMN)
      description: |
        Принимает BPMN-файл (multipart, поле `definition`) и деплоит его в
        Zeebe.
      operationId: deployProcessDefinition
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required: [definition]
              properties:
                definition:
                  type: string
                  format: binary
                  description: BPMN-файл определения процесса
      responses:
        "200":
          description: Определение загружено
        "400":
          description: Файл не передан/некорректен
        "401":
          description: Не авторизован
        "500":
          description: Внутренняя ошибка деплоя

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        JWT Sarex (проверяется по `PUBLIC_KEY`). Для режима Zitadel
        дополнительно передаётся заголовок `Identity: Bearer <jwt>`.

  schemas:
    ProcessCreateRequest:
      type: object
      required: [flow_id, author_id]
      description: Запрос на старт процесса (`internal/dto/http.go`).
      properties:
        flow_id:
          type: integer
          format: uint64
          description: Внешний ID процесса (обязателен, != 0)
        author_id:
          type: integer
          format: uint64
          description: ID автора запроса (обязателен, != 0)
        company_id:
          type: integer
          format: uint64
        step_id:
          type: integer
          format: uint64
        metadata:
          type: object
          additionalProperties: true
        payload:
          type: array
          description: Документы для обработки (произвольные объекты)
          items:
            type: object
            additionalProperties: true
        overwrite_marks:
          type: boolean
        mode:
          type: string
          description: Режим работы ("original", "copy", "both")
        use_signature:
          type: boolean
        create_copy_on_finish:
          type: boolean
        comment:
          type: string
        is_last_signer:
          type: boolean

    GetProcessInstanceResponse:
      type: object
      description: Состояние инстанса процесса (`internal/dto/http.go`).
      properties:
        status:
          type: string
        use_signature:
          type: boolean
        is_finished:
          type: boolean
        is_ready_for_sign:
          type: boolean
        is_last_signer:
          type: boolean
        create_copy_on_finish:
          type: boolean
        comment:
          type: string
        payload:
          description: Полезная нагрузка процесса (структура зависит от процесса)
          nullable: true
        instance_key:
          type: integer
          format: uint64

    SignRequest:
      type: object
      required: [flow_id, payload]
      description: Запрос на подпись документов в процессе (`internal/dto/http.go`).
      properties:
        flow_id:
          type: integer
          format: uint64
        metadata:
          type: object
          additionalProperties: true
        payload:
          type: array
          items:
            $ref: "#/components/schemas/SignRequestPayloadElem"

    SignRequestPayloadElem:
      type: object
      properties:
        bundle_id:
          type: string
          format: uuid
        author_id:
          type: integer
          format: uint64
        signature:
          type: string
          description: Сгенерированная подпись (помещается в p7s)
        algorithm:
          type: string
        mrpa_id:
          type: string
          format: uuid
          nullable: true
          description: Если задан — проверяется доступ через sarex-backend
