/** * This file was auto-generated by openapi-typescript. * Do not make direct changes to the file. */ export interface paths { "/api/v1/health": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** Liveness-проба */ get: operations["getHealth"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/ready": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** Readiness-проба (готовность агента и зависимостей) */ get: operations["getReady"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/metrics": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** Метрики в формате Prometheus text exposition */ get: operations["getPrometheusMetrics"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/status": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** Сводный статус шлюза, туннеля и GeoIP */ get: operations["getStatus"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/config": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** Текущая конфигурация (без секретов) */ get: operations["getConfig"]; /** Атомарное применение конфигурации (validate → staging → apply → rollback) */ put: operations["putConfig"]; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/config/validate": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; get?: never; put?: never; /** Сухая валидация конфигурации без применения */ post: operations["validateConfig"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/routing/rules": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** Список правил маршрутизации */ get: operations["listRoutingRules"]; put?: never; /** Создать правило маршрутизации */ post: operations["createRoutingRule"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/routing/rules/{rule_id}": { parameters: { query?: never; header?: never; path: { /** @description Идентификатор правила */ rule_id: components["parameters"]["RuleId"]; }; cookie?: never; }; /** Правило по идентификатору */ get: operations["getRoutingRule"]; /** Изменить правило */ put: operations["updateRoutingRule"]; post?: never; /** Удалить правило */ delete: operations["deleteRoutingRule"]; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/routing/mode": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; get?: never; /** Переключить режим split-tunnel */ put: operations["putRoutingMode"]; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/routing/geoip/update": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; get?: never; put?: never; /** Обновить снапшот GeoIP (RIPE Stat → локальный кэш) */ post: operations["updateGeoIp"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/routing/import": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; get?: never; put?: never; /** Импорт .conf / JSON (пиры и правила) */ post: operations["importRoutingConfig"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/metrics/stream": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** * WebSocket-поток метрик и статуса * @description WebSocket-апгрейд на том же пути. Клиент передаёт токен либо заголовком * `Authorization: Bearer `, либо query-параметром `token`. * Сервер отправляет текстовые JSON-кадры схемы `WsFrame`; при `type=metrics` * поле `data` соответствует `MetricsSample`, при `type=status` — `StatusResponse`, * при `type=error` — `Error`. */ get: operations["streamMetrics"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/devices": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** Устройства за шлюзом */ get: operations["listDevices"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/logs": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** Журнал событий */ get: operations["listLogs"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/auth/login": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; get?: never; put?: never; /** Аутентификация (сессия UI + токен API) */ post: operations["login"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/auth/logout": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; get?: never; put?: never; /** Завершить сессию */ post: operations["logout"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/api/v1/auth/session": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** Текущая сессия и CSRF-токен */ get: operations["getAuthSession"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; } export type webhooks = Record; export interface components { schemas: { /** * @description Машиночитаемый код ошибки * @enum {string} */ ErrorCode: "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "upstream_unavailable" | "agent_unavailable" | "internal_error"; /** @description Единый формат ошибки для всех не-2xx ответов */ Error: { code: components["schemas"]["ErrorCode"]; /** @description Человекочитаемое описание */ message: string; /** * @description Машиночитаемые детали (для validation_failed — список issues) * @default null */ details: { [key: string]: unknown; } | null; }; Check: { name: string; ok: boolean; detail?: string | null; }; HealthResponse: { /** @enum {string} */ status: "ok" | "degraded" | "down"; version: string; uptime_s: number; checks: components["schemas"]["Check"][]; }; ReadyResponse: { ready: boolean; checks: components["schemas"]["Check"][]; }; /** * @description Режим split-tunnel * @enum {string} */ RoutingMode: "geoip" | "dns" | "all-vpn" | "direct-only"; /** @enum {string} */ RuleKind: "domain" | "cidr" | "geoip" | "asn"; /** @enum {string} */ RuleAction: "vpn" | "direct"; /** @enum {string} */ LogLevel: "debug" | "info" | "warning" | "error"; /** @enum {string} */ TunnelState: "up" | "down" | "error"; TunnelStatus: { /** @example awg0 */ interface: string; state: components["schemas"]["TunnelState"]; handshake_age_s: number | null; rx_bytes: number; tx_bytes: number; endpoint: string | null; /** Format: date-time */ last_handshake_at: string | null; }; /** @enum {string} */ GeoIpSource: "ripe-stat" | "cache" | "none"; GeoIpStatus: { source: components["schemas"]["GeoIpSource"]; prefix_count: number; /** Format: date-time */ updated_at: string | null; }; StatusResponse: { version: string; uptime_s: number; mode: components["schemas"]["RoutingMode"]; tunnel: components["schemas"]["TunnelStatus"]; geoip: components["schemas"]["GeoIpStatus"]; kill_switch: boolean; dns_leak_protection: boolean; }; TunnelConfig: { /** * @description Адрес интерфейса в CIDR * @example 10.8.0.2/32 */ address: string; listen_port: number; mtu: number; /** @description Приватный ключ интерфейса; только запись, в ответах отсутствует */ private_key: string; dns?: string[]; }; PeerConfig: { public_key: string; /** @description Preshared key; только запись, в ответах отсутствует */ preshared_key?: string; endpoint: string; allowed_ips: string[]; persistent_keepalive?: number | null; }; DnsConfig: { /** @enum {string} */ mode: "internal" | "external"; servers: string[]; }; /** @enum {string} */ Ipv6Policy: "direct" | "tunnel" | "block"; RoutingConfig: { mode: components["schemas"]["RoutingMode"]; kill_switch: boolean; mtu_clamping: boolean; ipv6: components["schemas"]["Ipv6Policy"]; geoip: components["schemas"]["GeoIpStatus"]; }; ConfigResponse: { tunnel: components["schemas"]["TunnelConfig"]; peers: components["schemas"]["PeerConfig"][]; dns: components["schemas"]["DnsConfig"]; routing: components["schemas"]["RoutingConfig"]; /** Format: date-time */ updated_at: string; }; /** @description Частичное обновление конфигурации (merge в текущее состояние) */ ConfigUpdateRequest: { tunnel?: components["schemas"]["TunnelConfig"]; peers?: components["schemas"]["PeerConfig"][]; dns?: components["schemas"]["DnsConfig"]; routing?: components["schemas"]["RoutingConfig"]; }; ValidationIssue: { /** @description JSON Pointer до проблемного поля */ path: string; code: string; message: string; /** @enum {string} */ severity: "error" | "warning"; }; ValidateResponse: { valid: boolean; errors: components["schemas"]["ValidationIssue"][]; warnings: components["schemas"]["ValidationIssue"][]; }; RoutingRule: { /** Format: uuid */ id: string; name: string; kind: components["schemas"]["RuleKind"]; value: string; action: components["schemas"]["RuleAction"]; enabled: boolean; priority: number; comment: string | null; /** Format: date-time */ created_at: string; /** Format: date-time */ updated_at: string; }; RoutingRuleCreate: { name: string; kind: components["schemas"]["RuleKind"]; value: string; action: components["schemas"]["RuleAction"]; /** @default true */ enabled: boolean; /** @default 100 */ priority: number; comment?: string | null; }; RoutingRuleUpdate: { name?: string; kind?: components["schemas"]["RuleKind"]; value?: string; action?: components["schemas"]["RuleAction"]; enabled?: boolean; priority?: number; comment?: string | null; }; RoutingRuleList: { items: components["schemas"]["RoutingRule"][]; total: number; }; ModeUpdateRequest: { mode: components["schemas"]["RoutingMode"]; }; ModeUpdateResponse: { mode: components["schemas"]["RoutingMode"]; /** Format: date-time */ applied_at: string; /** Format: uuid */ reconcile_id: string; }; GeoIpUpdateRequest: { /** * @description Игнорировать локальный кэш и обновить из RIPE Stat * @default false */ force: boolean; }; GeoIpUpdateResponse: { /** @enum {string} */ status: "updated" | "cached" | "failed"; source: components["schemas"]["GeoIpSource"]; prefix_count: number; /** Format: date-time */ updated_at: string; duration_ms: number; }; ImportRequest: { /** @enum {string} */ format: "amneziawg-conf" | "wireguard-conf" | "json"; content: string; /** * @description Применить импорт сразу, а не только вернуть разбор * @default false */ apply: boolean; }; ImportResponse: { imported_peers: number; imported_rules: number; warnings: string[]; }; Device: { name: string; ip: string; mac: string | null; vpn: boolean; ipsets: string[]; /** Format: date-time */ last_seen_at: string | null; }; DeviceList: { items: components["schemas"]["Device"][]; total: number; }; LogEntry: { /** Format: date-time */ ts: string; level: components["schemas"]["LogLevel"]; logger: string; message: string; fields: { [key: string]: unknown; }; }; LogList: { items: components["schemas"]["LogEntry"][]; total: number; next_cursor: string | null; }; AuthLoginRequest: { username: string; password: string; }; AuthSession: { authenticated: boolean; username: string | null; /** Format: date-time */ expires_at: string | null; csrf_token: string | null; }; MetricsSample: { rx_bytes: number; tx_bytes: number; rx_rate_bps: number; tx_rate_bps: number; handshake_age_s: number | null; active_peers: number; }; WsFrame: { /** @enum {string} */ type: "metrics" | "status" | "error"; /** Format: date-time */ ts: string; /** * @description MetricsSample при type=metrics, StatusResponse при type=status, * Error при type=error. */ data: { [key: string]: unknown; }; }; }; responses: { /** @description Некорректный запрос */ BadRequest: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description Отсутствует или недействителен токен доступа */ Unauthorized: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description Недостаточно прав */ Forbidden: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description Объект не найден */ NotFound: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description Конфликт состояния (например, apply уже выполняется) */ Conflict: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description Тело запроса не соответствует схеме */ ValidationFailed: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description Превышен лимит запросов */ RateLimited: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description Внешний источник (RIPE Stat) недоступен */ UpstreamUnavailable: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description Агент шлюза недоступен (unix-socket не отвечает) */ AgentUnavailable: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description Внутренняя ошибка */ InternalError: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; }; parameters: { /** @description Идентификатор правила */ RuleId: string; }; requestBodies: never; headers: never; pathItems: never; } export type $defs = Record; export interface operations { getHealth: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description Процесс жив */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["HealthResponse"]; }; }; 500: components["responses"]["InternalError"]; }; }; getReady: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description Состояние готовности (в том числе при ready=false) */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["ReadyResponse"]; }; }; 500: components["responses"]["InternalError"]; 503: components["responses"]["AgentUnavailable"]; }; }; getPrometheusMetrics: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description Текстовый экспорт метрик */ 200: { headers: { [name: string]: unknown; }; content: { "text/plain": string; }; }; }; }; getStatus: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description Статус */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["StatusResponse"]; }; }; 401: components["responses"]["Unauthorized"]; 500: components["responses"]["InternalError"]; 503: components["responses"]["AgentUnavailable"]; }; }; getConfig: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description Конфигурация; секретные поля отсутствуют */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["ConfigResponse"]; }; }; 401: components["responses"]["Unauthorized"]; 500: components["responses"]["InternalError"]; }; }; putConfig: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["ConfigUpdateRequest"]; }; }; responses: { /** @description Конфигурация применена */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["ConfigResponse"]; }; }; 400: components["responses"]["BadRequest"]; 401: components["responses"]["Unauthorized"]; 409: components["responses"]["Conflict"]; 422: components["responses"]["ValidationFailed"]; 500: components["responses"]["InternalError"]; }; }; validateConfig: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["ConfigUpdateRequest"]; }; }; responses: { /** @description Результат валидации (в том числе при valid=false) */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["ValidateResponse"]; }; }; 401: components["responses"]["Unauthorized"]; 422: components["responses"]["ValidationFailed"]; 500: components["responses"]["InternalError"]; }; }; listRoutingRules: { parameters: { query?: { /** @description Фильтр по признаку включённости */ enabled?: boolean; kind?: components["schemas"]["RuleKind"]; }; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description Список правил */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["RoutingRuleList"]; }; }; 401: components["responses"]["Unauthorized"]; 500: components["responses"]["InternalError"]; }; }; createRoutingRule: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["RoutingRuleCreate"]; }; }; responses: { /** @description Правило создано */ 201: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["RoutingRule"]; }; }; 400: components["responses"]["BadRequest"]; 401: components["responses"]["Unauthorized"]; 409: components["responses"]["Conflict"]; 422: components["responses"]["ValidationFailed"]; 500: components["responses"]["InternalError"]; }; }; getRoutingRule: { parameters: { query?: never; header?: never; path: { /** @description Идентификатор правила */ rule_id: components["parameters"]["RuleId"]; }; cookie?: never; }; requestBody?: never; responses: { /** @description Правило */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["RoutingRule"]; }; }; 401: components["responses"]["Unauthorized"]; 404: components["responses"]["NotFound"]; 500: components["responses"]["InternalError"]; }; }; updateRoutingRule: { parameters: { query?: never; header?: never; path: { /** @description Идентификатор правила */ rule_id: components["parameters"]["RuleId"]; }; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["RoutingRuleUpdate"]; }; }; responses: { /** @description Обновлённое правило */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["RoutingRule"]; }; }; 400: components["responses"]["BadRequest"]; 401: components["responses"]["Unauthorized"]; 404: components["responses"]["NotFound"]; 422: components["responses"]["ValidationFailed"]; 500: components["responses"]["InternalError"]; }; }; deleteRoutingRule: { parameters: { query?: never; header?: never; path: { /** @description Идентификатор правила */ rule_id: components["parameters"]["RuleId"]; }; cookie?: never; }; requestBody?: never; responses: { /** @description Правило удалено */ 204: { headers: { [name: string]: unknown; }; content?: never; }; 401: components["responses"]["Unauthorized"]; 404: components["responses"]["NotFound"]; 500: components["responses"]["InternalError"]; }; }; putRoutingMode: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["ModeUpdateRequest"]; }; }; responses: { /** @description Режим применён */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["ModeUpdateResponse"]; }; }; 400: components["responses"]["BadRequest"]; 401: components["responses"]["Unauthorized"]; 422: components["responses"]["ValidationFailed"]; 500: components["responses"]["InternalError"]; 503: components["responses"]["AgentUnavailable"]; }; }; updateGeoIp: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: { content: { "application/json": components["schemas"]["GeoIpUpdateRequest"]; }; }; responses: { /** @description Обновление выполнено (или взято из кэша) */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["GeoIpUpdateResponse"]; }; }; 401: components["responses"]["Unauthorized"]; 422: components["responses"]["ValidationFailed"]; 500: components["responses"]["InternalError"]; 503: components["responses"]["UpstreamUnavailable"]; }; }; importRoutingConfig: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["ImportRequest"]; }; }; responses: { /** @description Результат импорта */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["ImportResponse"]; }; }; 400: components["responses"]["BadRequest"]; 401: components["responses"]["Unauthorized"]; 422: components["responses"]["ValidationFailed"]; 500: components["responses"]["InternalError"]; }; }; streamMetrics: { parameters: { query?: { /** @description Токен доступа для сред, где нельзя задать заголовок */ token?: string; /** @description Период отправки кадров, мс */ interval_ms?: number; }; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description Переключение протокола на WebSocket */ 101: { headers: { [name: string]: unknown; }; content?: never; }; 401: components["responses"]["Unauthorized"]; 500: components["responses"]["InternalError"]; }; }; listDevices: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description Список устройств */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["DeviceList"]; }; }; 401: components["responses"]["Unauthorized"]; 500: components["responses"]["InternalError"]; }; }; listLogs: { parameters: { query?: { limit?: number; /** @description Курсор пагинации из предыдущего ответа (`next_cursor`) */ cursor?: string; level?: components["schemas"]["LogLevel"]; /** @description Подстрока поиска по сообщению */ q?: string; }; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description Страница журнала */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["LogList"]; }; }; 401: components["responses"]["Unauthorized"]; 422: components["responses"]["ValidationFailed"]; 500: components["responses"]["InternalError"]; }; }; login: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["AuthLoginRequest"]; }; }; responses: { /** @description Сессия создана */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AuthSession"]; }; }; 401: components["responses"]["Unauthorized"]; 422: components["responses"]["ValidationFailed"]; 429: components["responses"]["RateLimited"]; 500: components["responses"]["InternalError"]; }; }; logout: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description Сессия завершена */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AuthSession"]; }; }; 401: components["responses"]["Unauthorized"]; 500: components["responses"]["InternalError"]; }; }; getAuthSession: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description Состояние сессии */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AuthSession"]; }; }; 401: components["responses"]["Unauthorized"]; 500: components["responses"]["InternalError"]; }; }; }