Sprint 0 / #19: OpenAPI 3.1 контракт API v1 + TS-клиент и контрактные тесты #57
Vendored
+281
@@ -309,4 +309,285 @@ export interface paths {
|
||||
};
|
||||
}
|
||||
export type webhooks = Record<string, never>;
|
||||
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__
|
||||
|
||||
Reference in New Issue
Block a user