Improve fleet control, Crucible ops, and multi-machine identity.
Use hostname-first agent names so the same forged binary on many machines stays distinct at scale. Add WebSocket RTT latency on the roster and Crucible, fleet delete and uninstall flows, live alert config reload, and non-blocking pool setup. Fix Crucible phantom agents after delete, posture scan targeting, and USB portability (config data_dir, LAUNCH sync).
This commit is contained in:
@@ -6,21 +6,31 @@ const API_BASE = '/api/v1';
|
||||
// Agent-only REST (/agent/decide, /agent/report, /agent/heartbeat) is intentionally
|
||||
// omitted here — forged agents call those with X-Fleet-Secret, not dashboard Basic Auth.
|
||||
|
||||
async function fetchJSON<T>(url: string, options?: RequestInit): Promise<T> {
|
||||
const { headers: extraHeaders, ...rest } = options ?? {};
|
||||
const res = await fetch(`${API_BASE}${url}`, {
|
||||
...rest,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...authHeaders(),
|
||||
...(extraHeaders as Record<string, string> | undefined),
|
||||
},
|
||||
});
|
||||
if (!res.ok) {
|
||||
const err = await res.text();
|
||||
throw new Error(`API error ${res.status}: ${err}`);
|
||||
async function fetchJSON<T>(url: string, options?: RequestInit, timeoutMs = 10000): Promise<T> {
|
||||
const { headers: extraHeaders, signal: callerSignal, ...rest } = options ?? {} as RequestInit & { signal?: AbortSignal };
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
||||
if (callerSignal) {
|
||||
callerSignal.addEventListener('abort', () => controller.abort());
|
||||
}
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}${url}`, {
|
||||
...rest,
|
||||
signal: controller.signal,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...authHeaders(),
|
||||
...(extraHeaders as Record<string, string> | undefined),
|
||||
},
|
||||
});
|
||||
if (!res.ok) {
|
||||
const err = await res.text();
|
||||
throw new Error(`API error ${res.status}: ${err}`);
|
||||
}
|
||||
return res.json();
|
||||
} finally {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export const api = {
|
||||
@@ -154,6 +164,15 @@ export const api = {
|
||||
body: JSON.stringify({ agent_ids: agentIds, action }),
|
||||
}),
|
||||
|
||||
deleteAgent: (id: string) =>
|
||||
fetchJSON<{ success: boolean }>(`/agents/${id}`, { method: 'DELETE' }),
|
||||
|
||||
bulkDeleteAgents: (ids: string[]) =>
|
||||
fetchJSON<{ success: boolean; deleted: number }>('/agents/bulk-delete', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ ids }),
|
||||
}),
|
||||
|
||||
createUser: (username: string, password: string) =>
|
||||
fetchJSON<{ success: boolean }>('/users', {
|
||||
method: 'POST',
|
||||
|
||||
Reference in New Issue
Block a user