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

@@ -59,15 +59,17 @@ function defaultsFromConfig(config: ServerConfig, serverInfo: ServerInfo, builds
return forgeDefaultsFromServerSmart(config, serverInfo, builds);
}
// Simulated stage timeline — (label, target% completed at this point, min ms from start)
// Simulated stage timeline — real compiles (garble/universal/fusion) often take 1030+ min.
// Cap below 95% until the server responds; finishForgeSuccess sets 100%.
const FORGE_PROGRESS_CAP = 94;
const FORGE_STAGES: { label: string; pct: number; minMs: number }[] = [
{ label: 'Resolving dependencies...', pct: 8, minMs: 0 },
{ label: 'Compiling agent source...', pct: 28, minMs: 800 },
{ label: 'Cross-compiling targets...', pct: 52, minMs: 2500 },
{ label: 'Applying obfuscation...', pct: 68, minMs: 5000 },
{ label: 'Packaging deliverable...', pct: 82, minMs: 8000 },
{ label: 'Signing & finalizing...', pct: 93, minMs: 11000 },
{ label: 'Almost done...', pct: 98, minMs: 15000 },
{ label: 'Resolving dependencies...', pct: 6, minMs: 0 },
{ label: 'Compiling agent source...', pct: 18, minMs: 20000 },
{ label: 'Cross-compiling targets...', pct: 36, minMs: 90000 },
{ label: 'Applying obfuscation...', pct: 52, minMs: 240000 },
{ label: 'Packaging deliverable...', pct: 68, minMs: 420000 },
{ label: 'Signing & finalizing...', pct: 82, minMs: 600000 },
{ label: 'Still forging (may take a while)...', pct: FORGE_PROGRESS_CAP, minMs: 900000 },
];
function ForgeProgressBar({ building, stage, progress }: { building: boolean; stage: string; progress: number }) {
@@ -153,6 +155,9 @@ export default function BuilderPage() {
const forgedThisSessionRef = useRef(false);
const [refreshingEndpoints, setRefreshingEndpoints] = useState(false);
const [simpleMode, setSimpleMode] = useState(loadSimpleMode);
const [pendingReforgeBuild, setPendingReforgeBuild] = useState<BuildRecord | null>(null);
const [highlightFusionPrep, setHighlightFusionPrep] = useState(false);
const fusionPrepRef = useRef<HTMLDivElement>(null);
// Drive simulated stage progress while a single build is running
useEffect(() => {
@@ -175,14 +180,14 @@ export default function BuilderPage() {
}
const s = FORGE_STAGES[next];
// Smoothly interpolate within this stage toward the next stage's target %
const nextPct = next + 1 < FORGE_STAGES.length ? FORGE_STAGES[next + 1].pct : 98;
const nextMs = next + 1 < FORGE_STAGES.length ? FORGE_STAGES[next + 1].minMs : 20000;
const nextPct = next + 1 < FORGE_STAGES.length ? FORGE_STAGES[next + 1].pct : FORGE_PROGRESS_CAP;
const nextMs = next + 1 < FORGE_STAGES.length ? FORGE_STAGES[next + 1].minMs : 1200000;
const stageElapsed = elapsed - s.minMs;
const stageDur = nextMs - s.minMs;
const frac = stageDur > 0 ? Math.min(1, stageElapsed / stageDur) : 0;
const pct = s.pct + (nextPct - s.pct) * frac;
if (next !== stageIdx) stageIdx = next;
setStage(s.label, Math.min(98, pct));
setStage(s.label, Math.min(FORGE_PROGRESS_CAP, pct));
forgeStageTimerRef.current = setTimeout(advance, 250);
};
advance();
@@ -238,8 +243,10 @@ export default function BuilderPage() {
setListenPort(config.port || 8989);
}
const candidates = info ? lanEndpointCandidates(info, config.port || info.port) : [];
const base = defaultsFromConfig(config, info ?? { port: config.port || 8989, host: '', local_ips: [], suggested_url: '', dashboard_url: '', websocket_url: '' }, builds as BuildRecord[]);
setForm(applySmartForgeDefaults(base, { builds: builds as BuildRecord[], endpointCandidates: candidates }));
const buildList = builds as BuildRecord[];
const base = defaultsFromConfig(config, info ?? { port: config.port || 8989, host: '', local_ips: [], suggested_url: '', dashboard_url: '', websocket_url: '' }, buildList);
setRecentBuilds(buildList);
setForm(applySmartForgeDefaults(base, { builds: buildList, endpointCandidates: candidates }));
})
.catch((err) => {
console.error(err);
@@ -257,17 +264,21 @@ export default function BuilderPage() {
}
};
// Handle ?reforge=<buildId> links from Build Manager page
// Handle ?reforge=<buildId> links from Build Manager — pre-fill only; user confirms before compile.
useEffect(() => {
const reforgeId = searchParams.get('reforge');
if (!reforgeId || recentBuilds.length === 0) return;
if (!reforgeId || !form || recentBuilds.length === 0) return;
const match = recentBuilds.find((b) => b.id === reforgeId);
if (match) {
reForgeFromBuild(match);
const merged = buildRequestFromRecord(match, form as unknown as Record<string, unknown>) as unknown as BuildRequest;
setForm(merged);
setPendingReforgeBuild(match);
setError('');
setLastBuild(null);
setSearchParams({}, { replace: true });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchParams, recentBuilds]);
}, [searchParams, recentBuilds, form]);
const finishForgeSuccess = async (result: BuildResponse) => {
setStage('Build complete!', 100);
@@ -355,6 +366,12 @@ export default function BuilderPage() {
}
};
const focusFusionPrepPicker = () => {
setHighlightFusionPrep(true);
fusionPrepRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' });
window.setTimeout(() => setHighlightFusionPrep(false), 6000);
};
const reForgeFromBuild = async (build: BuildRecord) => {
if (!form) return;
const merged = buildRequestFromRecord(build, form as unknown as Record<string, unknown>) as unknown as BuildRequest;
@@ -366,8 +383,9 @@ export default function BuilderPage() {
// server after a build completes (M15). Prompt the user to re-upload first.
if (merged.fusion_enabled && !fusionPrepFile) {
setError(
'This build used a Fusion payload. Re-upload the payload file in the Fusion section above, then click "Re-forge" again.'
'This build used a Fusion payload. Re-upload the payload file in the Fusion section below, then confirm Re-forge again.'
);
focusFusionPrepPicker();
return;
}
@@ -651,7 +669,16 @@ export default function BuilderPage() {
await finishForgeSuccess(result);
} catch (err: any) {
if (err.message !== 'build cancelled') {
setError(err.message || 'Build failed');
let msg = err?.message || 'Build failed';
const aborted =
err?.name === 'AbortError' ||
/abort|timed out|timeout/i.test(msg);
if (aborted) {
msg =
'Forge request ended early (browser or proxy timeout). The server may still be compiling — open Build Manager or refresh this page in a minute.';
}
setError(msg);
void loadRecentBuilds();
}
} finally {
cancelTokenRef.current = '';
@@ -702,7 +729,7 @@ export default function BuilderPage() {
[form, fusionPrepFile]
);
const preflightChecks = useMemo(
() => (form ? runForgePreflight(form, !!fusionPrepFile) : []),
() => (form ? runForgePreflight(normalizeForgeForm(form), !!fusionPrepFile) : []),
[form, fusionPrepFile]
);
const canForge = form ? !preflightHasErrors(preflightChecks) : false;
@@ -811,6 +838,39 @@ export default function BuilderPage() {
return (
<div className="page fade-in command-deck">
<SetupBanner status={setupStatus} />
{pendingReforgeBuild && (
<div className="reforge-confirm-banner form-error" role="alert">
<span></span>
<div style={{ flex: 1 }}>
<strong>Re-forge {pendingReforgeBuild.worker_name}?</strong>
<p className="form-hint" style={{ margin: '0.35rem 0 0', color: 'inherit' }}>
Settings were loaded from Build Manager. Confirm to start compiling this cannot be undone mid-forge.
</p>
</div>
<div style={{ display: 'flex', gap: '0.5rem', flexShrink: 0 }}>
<button
type="button"
className="btn btn-primary btn-sm"
disabled={building}
onClick={() => {
const build = pendingReforgeBuild;
setPendingReforgeBuild(null);
void reForgeFromBuild(build);
}}
>
Confirm Re-forge
</button>
<button
type="button"
className="btn btn-outline btn-sm"
disabled={building}
onClick={() => setPendingReforgeBuild(null)}
>
Cancel
</button>
</div>
</div>
)}
{/* Hidden file input for importing blueprint .json files */}
<input
type="file"
@@ -1867,7 +1927,10 @@ export default function BuilderPage() {
{form.fusion_enabled && (
<>
{/* Single-file pick (used when Forge button is clicked) */}
<div className={`form-group ${fieldMeta.fusion_prep?.disabled ? 'field-disabled' : ''}`}>
<div
ref={fusionPrepRef}
className={`form-group fusion-prep-picker${highlightFusionPrep ? ' fusion-prep-highlight' : ''}${fieldMeta.fusion_prep?.disabled ? ' field-disabled' : ''}`}
>
<div className="label-row">
<label className="label">
Drop any file to fuse <HelpTip field="fusion_prep" />
@@ -1880,6 +1943,7 @@ export default function BuilderPage() {
accept="*"
onChange={(e) => {
applyFusionFileSelection(e.target.files?.[0] || null);
setHighlightFusionPrep(false);
e.target.value = '';
}}
/>