openapi: 3.0.3 info: title: Drawings API version: "0.0.1" description: | REST API сервиса **drawings-api** (`gitlab.com/sarex-team/rnd/drawings-api`) — управление разрезами (cross-sections) чертежей, их данными и экспортом в DWG через сервис workflows. Сервис написан на **Go** (gorilla/mux, go-pg). Роутер собирается в `cmd/drawings-api/bootstrap.go`. Помимо служебных эндпоинтов (`/ping`, `/metrics`) есть две группы бизнес-маршрутов с одинаковым набором операций: - `/api/v1/*` — публичный роутинг; - `/internal/v1/*` — внутренний роутинг (набор тот же плюс webhook экспорта, вызываемый воркером workflow). На все бизнес-маршруты навешены middleware: JSON-ответ (`rest.JSONResponse`), request-id (`reqid.Middleware`) и логирование. Явной аутентификации в коде сервиса нет — доступ ограничивается на уровне ingress/сети кластера. ### Экспорт в DWG `POST /exports` создаёт запись экспорта и запускает workflow из двух задач (парсинг cross-section в DWG + webhook-уведомление). По завершении workflow вызывает `POST /internal/v1/exports/{export_id}/webhook`, который переводит экспорт в статус `done`. servers: - url: /api/v1 description: Публичный префикс - url: /internal/v1 description: Внутренний префикс tags: - name: service description: Служебные эндпоинты - name: cross-sections description: Разрезы чертежей - name: exports description: Экспорт разрезов в DWG paths: /ping: get: tags: [service] summary: Healthcheck description: Возвращает статус готовности. Доступен в корне (без префикса). responses: "200": description: Сервис готов content: application/json: schema: type: object properties: status: type: string example: ready /metrics: get: tags: [service] summary: Prometheus-метрики description: Метрики в формате Prometheus. Доступен в корне (без префикса). responses: "200": description: Метрики content: text/plain: schema: type: string # ----- Публичные маршруты (/api/v1) и внутренние (/internal/v1) идентичны, # кроме webhook, который есть только на /internal/v1. Пути ниже указаны # относительно префикса из блока servers. ----- /cross-sections: post: tags: [cross-sections] summary: Создать разрез description: Создаёт cross-section вместе с его данными (`data.raw_data`). requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateCrossSectionRequest" responses: "200": description: Созданный разрез content: application/json: schema: $ref: "#/components/schemas/CrossSection" "400": $ref: "#/components/responses/BadRequest" "500": $ref: "#/components/responses/StorageError" get: tags: [cross-sections] summary: Список разрезов по instance_id parameters: - name: instance_id in: query required: true description: UUID инстанса (чертежа) schema: type: string format: uuid responses: "200": description: Массив разрезов (пустой, если ничего не найдено) content: application/json: schema: type: array items: $ref: "#/components/schemas/CrossSection" "400": $ref: "#/components/responses/BadRequest" "500": $ref: "#/components/responses/StorageError" /cross-sections/{cs_id}: delete: tags: [cross-sections] summary: Удалить разрез (soft-delete) parameters: - $ref: "#/components/parameters/CrossSectionId" responses: "200": $ref: "#/components/responses/OK" "400": $ref: "#/components/responses/BadRequest" "404": description: Разрез не найден (возможно, уже удалён) content: application/json: schema: $ref: "#/components/schemas/Error" "500": $ref: "#/components/responses/StorageError" /cross-sections/{cs_id}/data: get: tags: [cross-sections] summary: Данные разреза parameters: - $ref: "#/components/parameters/CrossSectionId" responses: "200": description: Данные разреза content: application/json: schema: $ref: "#/components/schemas/Data" "400": $ref: "#/components/responses/BadRequest" "500": $ref: "#/components/responses/StorageError" /exports: post: tags: [exports] summary: Создать экспорт разреза в DWG description: | Создаёт запись экспорта и запускает workflow экспорта в DWG. В ответе `workflow_status` = `running`. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateExportRequest" responses: "200": description: Созданный экспорт content: application/json: schema: $ref: "#/components/schemas/Export" "400": $ref: "#/components/responses/BadRequest" "500": $ref: "#/components/responses/StorageError" get: tags: [exports] summary: Список экспортов по фильтрам description: | Хотя бы один из фильтров должен быть задан, иначе `400`. Каждый параметр — список UUID/чисел через запятую. parameters: - name: cross_section_ids in: query required: false description: UUID разрезов через запятую schema: type: string - name: export_ids in: query required: false description: UUID экспортов через запятую schema: type: string - name: workflow_ids in: query required: false description: UUID workflow через запятую schema: type: string - name: attachment_ids in: query required: false description: ID вложений (целые) через запятую schema: type: string responses: "200": description: Массив экспортов (пустой, если ничего не найдено) content: application/json: schema: type: array items: $ref: "#/components/schemas/Export" "400": $ref: "#/components/responses/BadRequest" "500": $ref: "#/components/responses/StorageError" /exports/{export_id}: delete: tags: [exports] summary: Удалить экспорт parameters: - $ref: "#/components/parameters/ExportId" responses: "200": $ref: "#/components/responses/OK" "400": $ref: "#/components/responses/BadRequest" "500": $ref: "#/components/responses/StorageError" /exports/{export_id}/webhook: post: tags: [exports] summary: Webhook завершения экспорта (только /internal/v1) description: | Вызывается воркером workflow по завершении экспорта. Переводит экспорт в статус `done`. Доступен только по внутреннему префиксу `/internal/v1`. parameters: - $ref: "#/components/parameters/ExportId" responses: "200": $ref: "#/components/responses/OK" "400": $ref: "#/components/responses/BadRequest" "500": $ref: "#/components/responses/StorageError" components: parameters: CrossSectionId: name: cs_id in: path required: true description: UUID разреза schema: type: string format: uuid ExportId: name: export_id in: path required: true description: UUID экспорта schema: type: string format: uuid responses: OK: description: Успешно (тело — строка `"OK"`) content: application/json: schema: type: string example: OK BadRequest: description: Некорректный запрос content: application/json: schema: $ref: "#/components/schemas/Error" StorageError: description: Внутренняя ошибка (ошибка хранилища) content: application/json: schema: $ref: "#/components/schemas/Error" schemas: CrossSection: type: object properties: id: type: string format: uuid name: type: string created_at: type: string format: date-time deleted_at: type: string format: date-time instance_id: type: string format: uuid documents: type: object additionalProperties: $ref: "#/components/schemas/ConnectedDocument" exports: type: array items: $ref: "#/components/schemas/Export" ConnectedDocument: type: object properties: color: type: string name: type: string Data: type: object properties: cross_section_id: type: string format: uuid raw_data: type: string CreateCrossSectionRequest: type: object description: Разрез плюс его данные. Наследует поля CrossSection. allOf: - $ref: "#/components/schemas/CrossSection" - type: object properties: data: $ref: "#/components/schemas/Data" Author: type: object properties: id: type: integer format: int64 first_name: type: string last_name: type: string Export: type: object properties: id: type: string format: uuid name: type: string author: $ref: "#/components/schemas/Author" created_at: type: string format: date-time deleted_at: type: string format: date-time nullable: true cross_section_id: type: string format: uuid workflow_id: type: string format: uuid nullable: true workflow_status: type: string nullable: true enum: [done, running, error] file_type: type: string enum: [dwg] attachment_id: type: integer nullable: true CreateExportRequest: type: object required: [cross_section_id, author, file_type, company_id] properties: cross_section_id: type: string format: uuid author: $ref: "#/components/schemas/Author" file_type: type: string enum: [dwg] company_id: type: integer format: int64 Error: type: object description: Ответ об ошибке (gotools/httperror). properties: error: type: string