fix: 2026-06-04 audit pass — README, USB pack, multi-area fixes
WS ticket dashboard auth, builder universal signing/size limits/fusion obfuscation/dropper bundles, Path Tracer WireGuard topology, SessionGate degraded mode and download timeouts, server bootstrap (data dir, cloudflared dedupe, config port precedence), agent mesh/miner/spread fixes. README refreshed; usb bundle repacked; PROBLEMS.md audit log updated.
This commit is contained in:
@@ -9,7 +9,7 @@ import type {
|
||||
import type { Agent, Share, FleetAlert, PoolStatus, AIActivityEntry, WSMessage } from '../types';
|
||||
import { WebSocketContext } from './WebSocketContext';
|
||||
import type { SeqCommandResult } from './WebSocketContext';
|
||||
import { getStoredAuth } from '../api/auth';
|
||||
import { authHeaders, getStoredAuth } from '../api/auth';
|
||||
|
||||
/**
|
||||
* WebSocketProvider mounts a SINGLE WebSocket connection for the whole app.
|
||||
@@ -54,25 +54,44 @@ export function WebSocketProvider({ children }: { children: React.ReactNode }) {
|
||||
|
||||
const existing = wsRef.current;
|
||||
if (existing && (existing.readyState === WebSocket.OPEN || existing.readyState === WebSocket.CONNECTING)) {
|
||||
existing.onclose = null;
|
||||
existing.close();
|
||||
}
|
||||
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const wsUrl = `${protocol}//${window.location.host}/ws/dashboard?token=${encodeURIComponent(token)}`;
|
||||
const ws = new WebSocket(wsUrl);
|
||||
wsRef.current = ws;
|
||||
|
||||
ws.onopen = () => { if (!unmounted.current) setIsConnected(true); };
|
||||
|
||||
ws.onclose = () => {
|
||||
const openSocket = async () => {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
let wsQuery = `token=${encodeURIComponent(token)}`;
|
||||
try {
|
||||
const resp = await fetch('/api/v1/auth/ws-ticket', {
|
||||
method: 'POST',
|
||||
headers: authHeaders(),
|
||||
});
|
||||
if (resp.ok) {
|
||||
const data = (await resp.json()) as { ticket?: string };
|
||||
if (data.ticket) {
|
||||
wsQuery = `ticket=${encodeURIComponent(data.ticket)}`;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* fall back to legacy token query param */
|
||||
}
|
||||
if (unmounted.current) return;
|
||||
setIsConnected(false);
|
||||
if (reconnectTimer.current) clearTimeout(reconnectTimer.current);
|
||||
if (!getStoredAuth()) return;
|
||||
reconnectTimer.current = setTimeout(connect, 3000);
|
||||
};
|
||||
|
||||
ws.onerror = () => { ws.close(); };
|
||||
const wsUrl = `${protocol}//${window.location.host}/ws/dashboard?${wsQuery}`;
|
||||
const ws = new WebSocket(wsUrl);
|
||||
wsRef.current = ws;
|
||||
|
||||
ws.onopen = () => { if (!unmounted.current) setIsConnected(true); };
|
||||
|
||||
ws.onclose = () => {
|
||||
if (unmounted.current) return;
|
||||
setIsConnected(false);
|
||||
if (reconnectTimer.current) clearTimeout(reconnectTimer.current);
|
||||
if (!getStoredAuth()) return;
|
||||
reconnectTimer.current = setTimeout(connect, 3000);
|
||||
};
|
||||
|
||||
ws.onerror = () => { ws.close(); };
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
try {
|
||||
@@ -222,6 +241,9 @@ export function WebSocketProvider({ children }: { children: React.ReactNode }) {
|
||||
console.error('Failed to parse WebSocket message:', err);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void openSocket();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user