feat(web): patching API client, status vocabulary and navigation
This commit is contained in:
+153
-2
@@ -417,6 +417,99 @@ export interface WorkflowRun {
|
||||
server_runs: ServerRun[];
|
||||
}
|
||||
|
||||
export type PatchScope = "all" | "security";
|
||||
export type PatchReboot = "never" | "if_required";
|
||||
export type PatchRunStatus = "running" | "succeeded" | "partial" | "failed" | "cancelled";
|
||||
export type PatchServerStatus =
|
||||
| "queued"
|
||||
| "waiting_offline"
|
||||
| "patching"
|
||||
| "rebooting"
|
||||
| "succeeded"
|
||||
| "failed"
|
||||
| "unsupported"
|
||||
| "agent_too_old"
|
||||
| "missed_offline"
|
||||
| "window_closed"
|
||||
| "cancelled";
|
||||
|
||||
export interface MaintenanceWindow {
|
||||
window_id: string;
|
||||
name: string;
|
||||
cron: string;
|
||||
tz: string;
|
||||
duration_minutes: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface MaintenanceWindowInput {
|
||||
name: string;
|
||||
cron: string;
|
||||
tz: string;
|
||||
duration_minutes: number;
|
||||
}
|
||||
|
||||
export interface WindowSpan {
|
||||
start: string;
|
||||
end: string;
|
||||
}
|
||||
|
||||
export interface PatchPolicy {
|
||||
policy_id: string;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
window_id: string;
|
||||
target_server_ids: string[];
|
||||
target_tags?: Record<string, string>;
|
||||
scope: PatchScope;
|
||||
reboot: PatchReboot;
|
||||
max_concurrent: number;
|
||||
notify_channel_ids?: string[];
|
||||
next_run_at?: string;
|
||||
last_run_at?: string;
|
||||
last_skipped?: Skip;
|
||||
disabled_reason?: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export type PatchPolicyInput = Pick<
|
||||
PatchPolicy,
|
||||
"name" | "enabled" | "window_id" | "target_server_ids" | "target_tags" | "scope" | "reboot" | "max_concurrent" | "notify_channel_ids"
|
||||
>;
|
||||
|
||||
export interface PatchServerRun {
|
||||
server_id: string;
|
||||
hostname: string;
|
||||
status: PatchServerStatus;
|
||||
pending_before: number;
|
||||
pending_after?: number;
|
||||
rebooted_at?: string;
|
||||
verified_at?: string;
|
||||
output?: string;
|
||||
error?: string;
|
||||
started_at?: string;
|
||||
finished_at?: string;
|
||||
}
|
||||
|
||||
export interface PatchRun {
|
||||
run_id: string;
|
||||
policy_id?: string;
|
||||
policy_name?: string;
|
||||
triggered_by: string;
|
||||
source: "schedule" | "run_now" | "server" | "vulnerabilities" | "mcp";
|
||||
scope: PatchScope;
|
||||
reboot: PatchReboot;
|
||||
max_concurrent: number;
|
||||
window_end?: string;
|
||||
status: PatchRunStatus;
|
||||
cancelled_at?: string;
|
||||
started_at: string;
|
||||
finished_at?: string;
|
||||
servers: PatchServerRun[];
|
||||
}
|
||||
|
||||
export type Role = "owner" | "admin" | "member";
|
||||
|
||||
/** The session as returned by GET /auth/me mirrors auth.Session on the server. */
|
||||
@@ -842,12 +935,70 @@ export const api = {
|
||||
});
|
||||
},
|
||||
|
||||
applyUpdates(serverId: string): Promise<{ message: string }> {
|
||||
return request<{ message: string }>(`/servers/${serverId}/apply-updates`, {
|
||||
applyUpdates(serverId: string, source?: "vulnerabilities"): Promise<{ message: string; run_id?: string }> {
|
||||
const qs = source ? `?source=${source}` : "";
|
||||
return request<{ message: string; run_id?: string }>(`/servers/${serverId}/apply-updates${qs}`, {
|
||||
method: "POST",
|
||||
});
|
||||
},
|
||||
|
||||
listMaintenanceWindows(): Promise<MaintenanceWindow[]> {
|
||||
return request<MaintenanceWindow[]>("/maintenance-windows");
|
||||
},
|
||||
|
||||
createMaintenanceWindow(input: MaintenanceWindowInput): Promise<MaintenanceWindow> {
|
||||
return request<MaintenanceWindow>("/maintenance-windows", { method: "POST", body: JSON.stringify(input) });
|
||||
},
|
||||
|
||||
updateMaintenanceWindow(windowId: string, input: MaintenanceWindowInput): Promise<MaintenanceWindow> {
|
||||
return request<MaintenanceWindow>(`/maintenance-windows/${windowId}`, { method: "PUT", body: JSON.stringify(input) });
|
||||
},
|
||||
|
||||
deleteMaintenanceWindow(windowId: string): Promise<void> {
|
||||
return request<void>(`/maintenance-windows/${windowId}`, { method: "DELETE" });
|
||||
},
|
||||
|
||||
previewMaintenanceWindow(input: Omit<MaintenanceWindowInput, "name">): Promise<WindowSpan[]> {
|
||||
return request<WindowSpan[]>("/maintenance-windows/preview", { method: "POST", body: JSON.stringify(input) });
|
||||
},
|
||||
|
||||
listPatchPolicies(): Promise<PatchPolicy[]> {
|
||||
return request<PatchPolicy[]>("/patch-policies");
|
||||
},
|
||||
|
||||
createPatchPolicy(input: PatchPolicyInput): Promise<PatchPolicy> {
|
||||
return request<PatchPolicy>("/patch-policies", { method: "POST", body: JSON.stringify(input) });
|
||||
},
|
||||
|
||||
updatePatchPolicy(policyId: string, input: PatchPolicyInput): Promise<PatchPolicy> {
|
||||
return request<PatchPolicy>(`/patch-policies/${policyId}`, { method: "PUT", body: JSON.stringify(input) });
|
||||
},
|
||||
|
||||
deletePatchPolicy(policyId: string): Promise<void> {
|
||||
return request<void>(`/patch-policies/${policyId}`, { method: "DELETE" });
|
||||
},
|
||||
|
||||
runPatchPolicyNow(policyId: string): Promise<PatchRun> {
|
||||
return request<PatchRun>(`/patch-policies/${policyId}/run-now`, { method: "POST" });
|
||||
},
|
||||
|
||||
listPatchRuns(params: { policy_id?: string; server_id?: string; limit?: number } = {}): Promise<PatchRun[]> {
|
||||
const qs = new URLSearchParams();
|
||||
if (params.policy_id) qs.set("policy_id", params.policy_id);
|
||||
if (params.server_id) qs.set("server_id", params.server_id);
|
||||
if (params.limit) qs.set("limit", String(params.limit));
|
||||
const suffix = qs.toString();
|
||||
return request<PatchRun[]>(`/patch-runs${suffix ? `?${suffix}` : ""}`);
|
||||
},
|
||||
|
||||
getPatchRun(runId: string): Promise<PatchRun> {
|
||||
return request<PatchRun>(`/patch-runs/${runId}`);
|
||||
},
|
||||
|
||||
cancelPatchRun(runId: string): Promise<void> {
|
||||
return request<void>(`/patch-runs/${runId}/cancel`, { method: "POST" });
|
||||
},
|
||||
|
||||
listAuditEvents(params: AuditQuery = {}): Promise<AuditPage> {
|
||||
const qs = new URLSearchParams();
|
||||
if (params.q) qs.set("q", params.q);
|
||||
|
||||
Reference in New Issue
Block a user