diff --git a/ui/src/api/generated/schema.d.ts b/ui/src/api/generated/schema.d.ts index f1a6caf..3008c3f 100644 --- a/ui/src/api/generated/schema.d.ts +++ b/ui/src/api/generated/schema.d.ts @@ -309,4 +309,285 @@ export interface paths { }; } 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: { // __CHUNK__