iac/apps/system-log/openapi.yaml

428 lines
18 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

openapi: 3.0.3
info:
title: system-log API
version: "1.0.0"
description: |
REST API сервиса **system-log** (`platform/system-log`) — приём и выборка
записей журнала системных событий (кто, над чем и какое действие совершил).
Сервис написан на Go (фреймворк **Fiber v2**). Роутинг собирается в
`internal/controller/http/v0`: базовая группа `/api` → подгруппа `v0` →
ресурс `/system_log`. Плюс служебный эндпоинт `/ping`.
### Аутентификация
Аутентификация на уровне приложения не настроена — эндпоинты доступны без
авторизации. Ограничение доступа обеспечивается сетевым слоем (ClusterIP /
Istio), а не самим сервисом.
### Пагинация
Списочные ответы возвращают объект `{ count, limit, offset, next, prev, result }`.
Управление — параметрами `limit` и `offset`. Значения по умолчанию:
`limit = 100`, `offset = 0` (константы `_defaultLimit` / `_defaultOffset`
в `internal/controller/http/v0/systemlog/controller.go`). Ссылки `next`/`prev`
формируются в `pkg/pagination`. У эндпоинта поиска (`POST /search`) полей
`next`/`prev` нет.
### Фильтрация
Массивные фильтры (`actor_ids`, `event_names`, `model_names`, `instance_ids`,
`target_ids`, `company_ids`, `statuses`, `message`) в GET-запросе передаются
списком значений через запятую и парсятся Fiber `QueryParser`. Поля
`instance_uuids` и `resource_uuids` разбираются вручную (`strings.Split` +
`uuid.Parse`) — при невалидном UUID возвращается `400`.
### Замечания (расхождения кода)
- `metadata` в фильтре объявлено как `map[string]interface{}` с query-тегом,
но при передаче в query-строке Fiber не восстановит вложенный объект —
фильтрация по `metadata` практически применима через тело `POST /search`.
- Поле `is_processed_by_worker` присутствует в фильтре, но отдаётся в выборку
наравне с остальными; используется воркером обогащения.
- Ответ `POST /system_log/` при успехе — простая строка `"OK"` (не объект).
servers:
- url: https://api.sarex.io
description: Production (ingress)
- url: https://stage-api.sarex.io
description: Stage (ingress)
- url: http://backend-svc.system-log.svc.cluster.local
description: Внутрикластерный адрес (ClusterIP, порт 80 → 8000)
- url: http://localhost:8888
description: Локальный запуск (config.env)
tags:
- name: system_log
description: Записи журнала системных событий
- name: service
description: Служебные эндпоинты
paths:
# ==========================================================================
# Service
# ==========================================================================
/ping:
get:
tags: [service]
summary: Проверка живости
description: Liveness/readiness-проба (используется в probes деплоймента). Всегда `200 OK` без тела.
operationId: ping
security: []
responses:
'200':
description: OK
# ==========================================================================
# System log
# ==========================================================================
/api/v0/system_log/:
get:
tags: [system_log]
summary: Список записей журнала (с фильтрами)
description: |
Возвращает отфильтрованные записи журнала с пагинацией.
Массивные параметры принимают список значений через запятую.
operationId: getSystemLogRecords
parameters:
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Offset'
- name: actor_ids
in: query
description: ID авторов событий; список значений через запятую
example: "1,2,3"
schema: { type: string }
- name: event_names
in: query
description: Названия событий (напр. create, edit, delete, transfer); через запятую
example: "create,edit,delete"
schema: { type: string }
- name: model_names
in: query
description: Названия моделей (напр. document, bundle, project); через запятую
example: "document,bundle"
schema: { type: string }
- name: instance_ids
in: query
description: ID сущностей; список значений через запятую
example: "1,2,3"
schema: { type: string }
- name: instance_uuids
in: query
description: UUID сущностей; список значений через запятую (валидируются как UUID)
example: "3fa85f64-5717-4562-b3fc-2c963f66afa6"
schema: { type: string }
- name: resource_uuids
in: query
description: UUID ресурсов; список значений через запятую (валидируются как UUID)
schema: { type: string }
- name: registered_at_gte
in: query
description: Нижняя граница времени регистрации (>=)
example: "2025-02-16T15:04:05Z"
schema: { type: string, format: date-time }
- name: registered_at_lte
in: query
description: Верхняя граница времени регистрации (<=)
example: "2025-02-16T15:04:05Z"
schema: { type: string, format: date-time }
- name: instance_path
in: query
description: Путь сущности (ltree), точное совпадение
example: "1.79899.80131"
schema: { type: string }
- name: target_ids
in: query
description: ID целей; список значений через запятую
example: "1,2,3"
schema: { type: string }
- name: target_path
in: query
description: Путь цели (ltree), точное совпадение
example: "4.3.2.1"
schema: { type: string }
- name: company_ids
in: query
description: ID компаний; список значений через запятую
example: "1,2,3"
schema: { type: string }
- name: statuses
in: query
description: Подстатусы события; список значений через запятую
example: "add_bundle,delete_bundle,rename_document"
schema: { type: string }
- name: message
in: query
description: Сообщения; список значений через запятую
schema: { type: string }
- name: is_processed_by_worker
in: query
description: Признак обработки записи воркером обогащения
schema: { type: boolean }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/SystemLogListResponse' }
'400':
$ref: '#/components/responses/BadRequest'
'500':
$ref: '#/components/responses/InternalError'
post:
tags: [system_log]
summary: Создать записи журнала
description: |
Принимает пакет записей в поле `system_logs`. Для каждой записи должно
быть задано **ровно одно** из `instance_id` / `instance_uuid`
(не оба и не ни одного — иначе `400`). Обязательны `event_name` и
`model_name`. При успехе возвращается строка `"OK"`.
operationId: createSystemLogRecords
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SystemLogCreateRequest' }
responses:
'200':
description: Записи созданы
content:
application/json:
schema:
type: string
example: "OK"
'400':
$ref: '#/components/responses/BadRequest'
'500':
$ref: '#/components/responses/InternalError'
/api/v0/system_log/search:
post:
tags: [system_log]
summary: Поиск записей журнала (фильтры в теле)
description: |
Аналог GET-выборки, но фильтры передаются в теле запроса
(`filters`). Позволяет использовать сложные фильтры (в т.ч. `metadata`),
которые неудобно кодировать в query-строке. В ответе нет `next`/`prev`.
operationId: searchSystemLogs
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SystemLogSearchRequest' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/SystemLogSearchResponse' }
'400':
$ref: '#/components/responses/BadRequest'
'500':
$ref: '#/components/responses/InternalError'
# ============================================================================
components:
parameters:
Limit:
name: limit
in: query
description: Кол-во записей на странице
schema: { type: integer, format: uint64, default: 100 }
Offset:
name: offset
in: query
description: Смещение от начала выборки
schema: { type: integer, format: uint64, default: 0, minimum: 0 }
responses:
BadRequest:
description: Ошибка разбора/валидации запроса
content:
application/json:
schema: { $ref: '#/components/schemas/ControllerError' }
InternalError:
description: Внутренняя ошибка сервиса
content:
application/json:
schema: { $ref: '#/components/schemas/ControllerError' }
schemas:
# ---- Общие ----
ControllerError:
type: object
description: Формат ошибки (`internal/controller/errors.go`, `ErrorToResponse`).
properties:
message: { type: string, example: "error parse body" }
status_code: { type: integer, example: 400 }
# ---- Доменная запись ----
SystemLog:
type: object
description: Запись журнала системных событий (`internal/entity/system_log.go`).
properties:
actor_id:
type: integer
format: uint64
description: ID автора события
example: 1023
event_name:
type: string
description: Название события (напр. edit, create, copy)
example: "edit"
model_name:
type: string
description: Над какой сущностью произошло событие (напр. document, inspection)
example: "document"
instance_id:
type: integer
format: uint64
nullable: true
description: ID сущности (для моделей с числовым ключом)
example: 80131
instance_uuid:
type: string
format: uuid
nullable: true
description: UUID сущности (для моделей с UUID-ключом)
registered_at:
type: string
format: date-time
nullable: true
description: Время регистрации события
example: "2023-05-04T08:09:53.852916Z"
instance_path:
type: string
nullable: true
description: Путь сущности (ltree)
example: "1.79899.80131"
target_id:
type: integer
format: uint64
nullable: true
description: ID цели события
company_id:
type: integer
format: uint64
nullable: true
description: ID компании (может обогащаться воркером)
example: 1
metadata:
type: object
additionalProperties: true
description: Произвольные дополнительные данные о событии
example: { "document_name": "КСГ.pdf", "count_bundle": 3 }
message:
type: string
nullable: true
description: Произвольное сообщение
example: "bundle was deleted from document"
status:
type: string
nullable: true
description: Подстатус события
example: "delete_bundle"
resource_uuid:
type: string
format: uuid
nullable: true
description: UUID связанного ресурса
target_path:
type: string
nullable: true
description: Путь цели (ltree)
required: [event_name, model_name]
# ---- Запросы ----
SystemLogCreateRequest:
type: object
description: >
Пакет записей для создания. Для каждой записи обязательно ровно одно из
instance_id / instance_uuid.
properties:
system_logs:
type: array
minItems: 1
items: { $ref: '#/components/schemas/SystemLog' }
required: [system_logs]
SystemLogFilter:
type: object
description: Набор фильтров выборки (`entity.SystemLogFilter`).
properties:
limit: { type: integer, format: uint64, default: 100 }
offset: { type: integer, format: uint64, default: 0 }
actor_ids:
type: array
items: { type: integer, format: uint64 }
event_names:
type: array
items: { type: string }
model_names:
type: array
items: { type: string }
instance_ids:
type: array
items: { type: integer, format: uint64 }
instance_uuids:
type: array
items: { type: string, format: uuid }
registered_at_gte: { type: string, format: date-time, nullable: true }
registered_at_lte: { type: string, format: date-time, nullable: true }
instance_path: { type: string, nullable: true }
target_ids:
type: array
items: { type: integer, format: uint64 }
target_path: { type: string, nullable: true }
company_ids:
type: array
items: { type: integer, format: uint64 }
statuses:
type: array
items: { type: string }
message: { type: string, nullable: true }
metadata:
type: object
additionalProperties: true
resource_uuids:
type: array
items: { type: string, format: uuid }
is_processed_by_worker: { type: boolean, nullable: true }
SystemLogSearchRequest:
type: object
description: Тело запроса поиска (`SearchParams` в `dto.go`).
properties:
limit: { type: integer, format: uint64, default: 100 }
offset: { type: integer, format: uint64, default: 0 }
filters: { $ref: '#/components/schemas/SystemLogFilter' }
# ---- Ответы ----
SystemLogListResponse:
type: object
description: Ответ списочной выборки (`entity.SystemLogRecordsRequest`).
properties:
count: { type: integer, format: uint64, example: 1226 }
limit: { type: integer, format: uint64, nullable: true, example: 100 }
offset: { type: integer, format: uint64, nullable: true, example: 0 }
next:
type: string
nullable: true
example: "http://localhost:8888/api/v0/system_log?limit=100&offset=100"
prev:
type: string
nullable: true
result:
type: array
items: { $ref: '#/components/schemas/SystemLog' }
required: [count, result]
SystemLogSearchResponse:
type: object
description: Ответ поиска (`entity.SystemLogRecordsSearch`) — без next/prev.
properties:
count: { type: integer, format: uint64, example: 1226 }
limit: { type: integer, format: uint64, nullable: true, example: 100 }
offset: { type: integer, format: uint64, nullable: true, example: 0 }
result:
type: array
items: { $ref: '#/components/schemas/SystemLog' }
required: [count, result]