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

@@ -65,15 +65,22 @@ vi.mock('../context/ForgeContext', () => ({
useForge: vi.fn(() => ({ forging: false, stage: '' })),
}));
vi.mock('../api/download', () => ({
downloadApiFile: vi.fn(),
downloadAuthedFile: vi.fn(),
}));
vi.mock('../api/download', () => {
const downloadAuthedFile = vi.fn();
return {
downloadAuthedFile,
downloadApiFile: downloadAuthedFile,
};
});
vi.mock('../api/auth', () => ({
getStoredAuth: vi.fn(),
setStoredAuth: vi.fn(),
}));
vi.mock('../api/auth', async (importOriginal) => {
const actual = await importOriginal<typeof import('../api/auth')>();
return {
...actual,
getStoredAuth: vi.fn(),
setStoredAuth: vi.fn(),
};
});
vi.mock('qrcode', () => ({
default: {
@@ -174,9 +181,7 @@ describe('DownloadButton', () => {
);
const btn = screen.getByRole('button', { name: 'Save' });
await userEvent.setup().click(btn);
await waitFor(() => {
expect(screen.getByRole('button', { name: 'Downloading…' })).toBeDisabled();
});
expect(screen.getByRole('button', { name: 'Downloading…' })).toBeDisabled();
await waitFor(() => expect(downloadApiFileMock).toHaveBeenCalledWith('/api/x', 'a.bin'));
});
@@ -283,7 +288,7 @@ describe('SessionGate', () => {
it('renders children when stored auth validates', async () => {
getStoredAuthMock.mockReturnValue('dGVzdA==');
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: true }));
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: true, status: 200 }));
render(
<SessionGate>
<div>protected</div>
@@ -291,6 +296,18 @@ describe('SessionGate', () => {
);
await waitFor(() => expect(screen.getByText('protected')).toBeInTheDocument());
});
it('keeps session on network blip during startup validation', async () => {
getStoredAuthMock.mockReturnValue('dGVzdA==');
vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new Error('ECONNREFUSED')));
render(
<SessionGate>
<div>protected</div>
</SessionGate>
);
await waitFor(() => expect(screen.getByText('protected')).toBeInTheDocument());
expect(screen.getByRole('status')).toHaveTextContent(/Cannot reach server/i);
});
});
describe('GaugeRing', () => {
@@ -320,7 +337,7 @@ describe('HashrateChart', () => {
it('shows empty state when data is empty', () => {
render(<HashrateChart data={[]} title="Fleet Hash" />);
expect(screen.getByText('Fleet Hash')).toBeInTheDocument();
expect(screen.getByText(/Calibrating chart telemetry/i)).toBeInTheDocument();
expect(screen.getByText(/No live data yet/i)).toBeInTheDocument();
});
it('renders chart with validated sample series', () => {
@@ -329,14 +346,14 @@ describe('HashrateChart', () => {
render(
<HashrateChart
data={sample}
displayMode="sample"
displayMode="live"
title="Fleet Hash"
color="#00f5ff"
unit="H/s"
/>
);
expect(screen.getByText(/PEAK/)).toBeInTheDocument();
expect(screen.getByText(/PROJECTION/)).toBeInTheDocument();
expect(screen.getByText(/LIVE/)).toBeInTheDocument();
});
it('renders chart with data points', () => {