Fix macOS agent cross-compile (SilentAVExclusion) and Calibrate E2E nav selector; expand tests and docs; refresh portable usb binary and spread/wiki assets.
29 KiB
Open medium / by design
| Issue | Notes |
|-------|-------|
| bof_execute disabled | Agent returns explicit error in-memory BOF execution disabled for safety (client.go). |
| Process hollowing AMSI/ETW | Relocation patching done; Defender/ETW detection causes ~50% failure bypass not implemented (hollow_windows.go). |
| Cloudflared on Linux server | In-process tunnel start is Windows-only; Linux/macOS builds use no-op stub use external connector (AF_TUNNEL_EXTERNAL) or add cross-platform launcher. |
| macOS camera / GPU miner | Stubs return "not supported"; Linux has V4L2 + nvidia-smi path. |
| Agent WireGuard auto-download | Windows ensureWGExe() downloads WireGuard on first Path Tracer use heavy side effect; pre-install recommended. |
| Non-Windows Path Tracer agent parity | pathtracer_stub.go returns error on wg_setup; Linux/macOS agents cannot join WireGuard chains. |
| KEV heuristics | Non-Windows agents return catalog with Status: n/a Windows-only CVE matching.
Open large / deferred
| Issue | Notes |
|-------|-------|
| Non-Windows agent parity | pathtracer_stub.go returns error JSON on wg_setup; Linux/macOS cannot join chains. UI filters platform; server does not validate platform field. |
| In-memory sessions only | TraceSession map in handler RAM server restart loses session state while agents may still hold tunnels; no DB persistence or startup sweep. |
| WireGuard auto-download | Windows ensureWGExe() silently downloads/installs WireGuard on first use heavy, needs admin, no progress UI. |
| No PathTracerPage Vitest | Page logic (polling, chain selection, QR modal) untested; only uiHelp.test.ts covers help keys. |
| No agent-side pathtracer tests | pathtracer_windows.go / stub have zero Go tests. |
| NAT / symmetric UDP | UPnP + DB IP fallback may still yield unreachable endpoints; no STUN/TURN or connectivity probe after configure. |
| Fixed listen port 51820 | All hops use same UDP port multiple agents behind one NAT may conflict; no per-hop port allocation. |
| Agent display name vs hostname | WS auth UpsertAgent overwrites name with hostname on every connect operator-renamed fleet labels may not appear in Path Tracer unless re-saved after connect. |
Open medium / UX
| Issue | Notes |
|-------|-------|
| Visual island (green vs deck) | Page uses #00ffaa WireGuard chrome while data-operator-deck='pathtracer' sets blue accent (operatorDeck.css); intentional branding split (see DV-07). |
| Status polling only | UI polls /status every 2s no WebSocket push for hop progress; acceptable latency but stale during orchestration. |
| Error path leaves tracing UI | On status.error, tracing clears but session remains server-side until operator clicks End or TTL hops show failed state in chain panel. |
Open large / deferred
| Issue | Notes |
|-------|-------|
| No CI-automated HTTP forge | scripts/e2e-validate.ps1 -ForgeAgent still manual (multipart fusion, long compile). Live compile gated behind LIVE_FORGE=1 + -tags liveforge. |
| PathForge test gaps | Only TestPathForgePlacedExcludesHintFile; no skipped-counter, lock-original, or frontend UI tests. |
| Forge cancellation / batch races | Cancel token API tested in isolation; concurrent batch forge + mid-compile cancel not covered. |
| Non-Windows forge host limits | PE disguise (disguise_stub.go) and Windows signing (sign_stub.go / osslsigncode) are platform-constrained by design. |
| Mac PathForge runtime dependency | .command launchers curl /api/download/agent-mac at runtime requires reachable server_url and pre-placed agent binary. |
Open low
| Issue | Notes |
|-------|-------|
| pathforge_test.go dead loop | Lines 6672 iterate entry.Files but assert nothing harmless test noise. |
Open (document-only / deferred)
| Issue | Notes |
|-------|--------|
| Dual storage without sync policy | Complex cross-tab sync session preferred over local; aetherforge-auth event on logout |
| Flaky progress simulation vs. real compile time | Cosmetic stage timeline caps at 94% until server responds (45 min client timeout) |
| Path Forge / batch fusion test gaps | Cancellation, partial batch failure, cancel-token races needs dedicated tests |
| DashboardPage tests emit ECONNREFUSED stderr | Failure-path tests; happy-dom hits localhost:3000; tests pass |
| DownloadButton mock aliasing pattern | Document for new download helpers shared mock fn already in components.test.tsx |
--
Open (2026-06-06 audit LARGE)
-
tunnel_streamnot implemented server-side TCP reverse relay documented as future work (README.md). -
Server
cloudflaredlauncher no-op on non-Windows Linux server deploy cannot auto-launch tunnels (cloudflared/launcher_stub.go).
Low (open)
mergeConfigpartial-PUTUseTLSlegacy behavior omitted keys may not reset bools; seeconfig_test.go.
High (open)
- Non-Windows Path Tracer agent parity
pathtracer_stub.goreturns error onwg_setup; Linux/macOS agents cannot join WireGuard chains.
Medium (open)
-
Agent WireGuard auto-download: Windows agent
ensureWGExe()downloads and silently installs WireGuard fromdownload.wireguard.comon first Path Tracer use if not already present (agent/client/pathtracer_windows.go). Heavy side effect; no server-side fix operator should pre-install WireGuard on fleet hosts or accept first-run download latency. -
Mac PathForge
.commandstill depends onserver_url+/api/download/agent-macat runtime (now validated at forge time).
| Op | Command | Notes |
|----|---------|-------|
| SMB share enumeration | smb_shares | Windows + Remote Aggressive; ARP/subnet hosts ? net view JSON |
| Spread status | spread_status | In-memory last sweep (deploy/spread_status.go); read-only |
| Credential names | credential_vault_list | Win Credential Manager / macOS Keychain / Linux secret-tool + ~/.ssh paths names only |
| Secure wipe | secure_wipe | Overwrite-then-delete folder; system-root guards; confirm in UI |
| Port-forward matrix | tunnel_ssh_forward × N | CruciblePortForwardMatrix multi-row grid on selected Windows nodes |
UI: Phase C controls in CrucibleExpandedOps.tsx Fleet Maintenance (replaces coming soon stubs).
Linux / macOS parity
| Area | Status |
|------|--------|
| Mining + hashrate | RandomX pure-Go engine works on Linux/macOS; stats loop sends hashrate_15s/1m/15m + shares over WS. |
| Idle schedule guard | Fixed SystemCPUPercent was always 0 on Unix (reporter_unix.go), blocking idle-mode mining; Linux uses /proc/stat, macOS uses sysctl kern.cp_time. |
| Screenshot | Linux: scrot / ImageMagick import / gnome-screenshot. macOS: screencapture. |
| Camera | Linux V4L2 via ffmpeg/fswebcam (camera_linux.go). macOS: stub. |
| File ops | Cross-platform (file_ops_unix.go / file_ops_windows.go). |
| Posture | Unix collectors return firewall/AV/patch data (posture_unix.go), not all n/a. |
| Spread | SSH path on Linux/macOS (autospread_unix.go); SMB/WinRM Windows-only by design. |
| Firewall ops | Linux ufw/iptables (firewall_linux_ops.go); macOS pf + socketfilterfw (firewall_darwin_ops.go); other Unix stubs. |
| GPU miner | Windows-only T-Rex path; Linux/macOS stub with detect-only. |
| Docker E2E | docker/docker-compose.yml isolated agent + server; see docker/README.md. |
Open
-
Client: WebSocket/beacon paths integration-only in CI (Docker Tier 2 closes Linux slice).
-
macOS: camera, GPU miner stubs or partial; firewall aggressive ops implemented (see Backend BE-04).
-
Linux screenshot: headless containers need
xvfb+ scrot or customcommandfield. -
bof_executepermanently disabled handler always fails (client.go); product/safety decision. -
Linux/macOS GPU RVN mining broken
detectGPU()may find NVIDIA, butspec()downloads Windows.exeminers (gpu_miner.go,gpu_detect_stub.go). -
Mesh P2P without
-tags p2p default build reports 0 peers; UI exposesmesh_statuswith re-forge hint (mesh_p2p_stub.go). -
Process hollowing AMSI/ETW bypass not implemented documented ~50% failure rate (
hollow_windows.go). -
KEV exposure scan non-Windows all CVEs marked
n/a(cve_scan_stub.go). -
Unknown Unix CPU stats stub returns 0 can break idle-mining guard on exotic platforms (
cpu_stub.go).
Open (document-only / deferred)
| Issue | Notes |
|-------|--------|
| Dual storage without sync policy | Complex cross-tab sync session preferred over local; aetherforge-auth event on logout |
| Flaky progress simulation vs. real compile time | Cosmetic stage timeline caps at 94% until server responds (45 min client timeout) |
| Path Forge / batch fusion test gaps | Cancellation, partial batch failure, cancel-token races needs dedicated tests |
| DashboardPage tests emit ECONNREFUSED stderr | Failure-path tests; happy-dom hits localhost:3000; tests pass |
| DownloadButton mock aliasing pattern | Document for new download helpers shared mock fn already in components.test.tsx |
| server/webroot not auto-synced on npm run build | Manual step via devrun.bat or copy; stale webroot served old hashed assets |
| Vitest stderr noise | FleetTopologyMap three.js tags warn in happy-dom tests pass |
Open (needs product copy or broader pass)
| ID | Issue | Notes |
|----|-------|-------|
| UH-01 | Crucible expanded ops (spread/tunnels/recon buttons) | 40+ buttons still rely on title= only no HelpTip on each CrucibleExpandedOps action |
| UH-02 | Fleet Roster / Agents page bulk toolbar | Filter chips and bulk actions lack inline help |
| UH-03 | Emberwake / War Room campaign widgets | Funnel stages need HelpTip parity with Command Deck funnel |
| UH-04 | Mission Deck | Page has minimal operator guidance |
| UH-05 | Builder mission wizard chips | Inline blurbs exist on chips; not all advanced forge sections have HelpTip (see docAnchors.test gap list) |
| UH-06 | Settings tabs beyond Calibrate/Forge | Alerts, webhooks, desktop push sections partially covered |
Open (visual / UX debt)
| ID | Issue | Files / notes |
|----|-------|----------------|
| DV-01 | Neon cyan fragmentation canonical token is --neon-cyan: #00e8f5 but components hard-code #00f5ff, #00e5ff, and #0ff fallbacks | AgentRemoteActions.css, HashrateChart.tsx, BuildManagerPage.tsx, ProtocolTunnelPanel.css, FileManager.css (fixed), sacred geometry SVGs |
| DV-02 | Page header patterns diverge most pages use deck-hero + eyebrow; Build Manager uses bm-header / bm-title; Path Tracer uses green .pt-title (#00ffaa); Forge says The Forge vs nav Forge | BuildManagerPage.tsx/css, PathTracerPage.css, BuilderPage.tsx, Layout.tsx NAV |
| DV-03 | SacredPageHeader unused component + .page-header--sacred CSS exist but no page imports it; dead design path | SacredPageHeader.tsx, sacred-geometry.css |
| DV-04 | Pages.css duplicate / conflicting rules two .empty-state blocks (L192 vs L1078); second .page-header h1 block overrides visual-polish gradient when page CSS loads after global polish | Pages.css; load order via per-page imports |
| DV-05 | Default dashboard subtitle out-of-box copy is security is just an emotion until Calibrate overrides dashboard_subtitle; reads as placeholder to new operators | DashboardPage.tsx L70; SettingsPage.tsx L131 |
| DV-06 | Path Tracer buried in nav desktop sidebar lists it last; mobile hides it under More while Crucible/Forge are primary tabs | Layout.tsx MOBILE_PRIMARY vs MOBILE_MORE |
| DV-07 | Path Tracer visual island green WireGuard aesthetic (#00ffaa) does not use operator-deck page classes or brass/neon deck chrome | PathTracerPage.css, PathTracerPage.tsx (missing operator-deck-page) |
| DV-08 | Chart lazy-load placeholder is invisible ChartPlaceholder is an empty div at 35% opacity; advanced charts pop in with layout shift | DashboardPage.tsx L5153 |
| DV-09 | Dead chart badge styles .chart-live.sample / .blend in wealth-deck CSS; resolveChartSeries no longer emits sample mode | wealth-deck.css; chartSampleData.ts |
| DV-10 | Docs vs in-app naming drift wiki says Calibrate (Settings), Command Deck, Forge / Builder; nav uses Calibrate, Command Deck, Forge; Emberwake route was /spread redirect | public/docs/index.html, Layout.tsx, App.tsx |
| DV-11 | Public spread landing vs Emberwake /spread/ static kit uses aether.css deck tokens (good) but typography/spacing differs slightly from in-app Emberwake cards | public/spread/assets/aether.css, EmberwakePage.css |
| DV-12 | Emoji in status bar / actions ?? DOCS pill, agent action buttons (?? ? ?) inconsistent with otherwise SVG-icon nav | SystemStatusBar.tsx, AgentRemoteActions.tsx |
| DV-13 | No light theme entire product is dark-only; docs wiki matches but no prefers-color-scheme path | global styles |
| DV-14 | Sidebar version hard-coded footer shows v0.0.1 regardless of server build | Layout.tsx L321 |
| DV-15 | Mission Deck formatting source file has excessive blank lines (likely formatter artifact); harder to maintain, no runtime impact | MissionDeckPage.tsx |
Remaining doc gaps (need product copy / user input)
| Topic | Notes |
|-------|-------|
| Default dashboard subtitle | security is just an emotion until Calibrate override marketing copy decision (DV-05) |
| SocGholish / fake-update lander | Documented in spread playbook #third-party tab; no shipped branded HTML template |
| OAuth redirect abuse playbook | Research only no Entra app wizard in Emberwake |
| Earnings USD quote | TEST_RESULTS.md notes low priority; not wired |
| Screenshot placeholders in wiki | [Screenshot:
] divs need real captures from operator deck |
| Sidebar version v0.0.1 | Hard-coded in Layout.tsx should read server build version (DV-14) |
| Light theme | Dark-only documented; no prefers-color-scheme path (DV-13) |
Deferred needs refactor, heavy mocks, or external deps
| Area | Why deferred |
|------|--------------|
| agent/cmd/mine-validate | Standalone CLI (main package); exercises RandomX + live Stratum; run manually or in mining CI |
| Cloudflared Start with real token | Spawns/downloads binary + network; only empty-token path covered |
| FleetScheduler.Start loop | 1-minute ticker; logic covered via direct tickInterval/tickCron in same-package tests |
| CruciblePage full integration | Large page; helpers + CrucibleExpandedOps + FileManager tested separately |
| Fleet panel widgets | Partially covered via components.test.tsx; full panel flows need WS mocks |
| Path Forge / batch fusion cancel races | Needs dedicated cancel-token harness |
| Playwright E2E (server/web/e2e/) | Phase 8 of test-suite; requires build + temp server |
| Docker mining E2E | .github/workflows/ci-docker-mining.yml separate tier |
| Mesh P2P | Requires -tags p2p build tag |
| Platform-specific fusion launchers | OS-gated; crypto path covered in media_crypto_test.go |
| Suite | Result | Notes |
|-------|--------|-------|
| go test ./... (repo root) | N/A | No root go.mod; use per-module dirs (documented in Integration audit). |
| agent/ | PASS | All packages ok (client ~3s). |
| server/ | PASS | internal/api ~69s, internal/builder ~32s. |
| fusion/ | PASS | Includes media_crypto_test.go (untracked in git at time of pass). |
| server/web Vitest | PASS | 66 files / 587 tests (3 consecutive full runs). |
| Item | Notes |
|------|-------|
| Vitest stderr ECONNREFUSED 127.0.0.1:3000 | Failure-path / bulk-command tests in DashboardPage, AgentsPage, etc. (see Dashboard section). |
| FleetTopologyMap three.js ref warnings | happy-dom; cosmetic stderr. |
| Vite build chunk size warnings | three / vendor bundles > 500 kB; not a test failure. |
Bugs Builder/Security (Bug Team 4 audit, 2026-06-06)
Scope: server/internal/builder/, fusion/, server/config.go, cross-cutting API input validation and auth edge cases.
Fixed in this pass
| ID | Fix |
|----|-----|
| BLD-01 | PowerShell injection in uninstaller processName and persistenceKey were embedded in single-quoted PS1 strings without escaping apostrophes. A WorkerName like foo'; Invoke-Expression
; ' would break out of the string. Now uses strings.ReplaceAll(
, "'", "''") for both fields, consistent with how installRel was already escaped (uninstall.go). |
| BLD-02 | JSON build request body unbounded non-multipart POST /builder/build decoded r.Body without a size limit; a 1 GiB JSON body would buffer entirely. Fixed: http.MaxBytesReader capped to 512 KiB before json.Decode (handler.go). |
| BLD-03 | Unbounded backup pool/URL arrays BackupServerURLs, BackupPools, and RVNBackupPools from user input are concatenated verbatim into the generated Go source (generateBuiltinConfig). A request with 10 000 entries would produce a multi-MB .go file, slowing or crashing go build. Fixed: arrays truncated to 10 entries each in normalizeRequest (handler.go). |
| BLD-04 | Partial build dir not cleaned on failure when compileWorker, buildFusionFromRequest, writeUninstallScript, or MkdirAll fail mid-build, the entire builds/<uuid>/ tree (containing a copy of agent source + uploaded fusion payload) was left on disk. Added cleanupBuild() closure that calls os.RemoveAll(buildDir) on each failure return path (handler.go). |
| BLD-05 | Weak random password entropy generateRandomPassword() used only 4 random bytes (8 hex chars, 32-bit entropy), guessable in ~4 billion attempts. Increased to 8 bytes (16 hex chars, 64-bit entropy) (router.go). Test updated. |
| BLD-06 | Malformed config.json silently ignored json.Unmarshal failure was swallowed; operator saw no indication their config was rejected and defaults were running instead. Added fmt.Fprintf(os.Stderr,
) warning on parse failure (config.go). |
Deferred / large
| ID | Severity | Location | Description |
|----|----------|----------|-------------|
| BLD-D1 | High | server/internal/builder/pathforge.go | No server-side restriction on root_path. PathForgeRequest.RootPath is passed directly to filepath.WalkDir without any whitelist or prefix check. An authenticated operator (or compromised session) can supply any absolute path (e.g. C:\Windows\System32, /etc/) and the server will (a) enumerate every matching file and (b) write .exe, .bat, and .command companion files next to them. Fix: validate RootPath against an operator-configured allow-list (e.g. specific USB/NAS mount points), or at minimum reject absolute paths that escape a configured data_dir. |
| BLD-D2 | Medium | server/internal/builder/pathforge.go batContent / macContent | Filename injection in generated scripts. d.Name() (raw filesystem filename) is interpolated into .bat and .command scripts via fmt.Sprintf. On Windows, a filename containing %VAR% expands the BAT variable; a filename with " breaks the quoted argument. On macOS/Linux, a filename with ' breaks single-quoted shell strings, and a server_url containing ' would allow shell command injection in the generated curl line. Fix: escape " and % for BAT content; escape ' ? '\'' for shell content. |
| BLD-D3 | Low | server/internal/builder/handler.go buildUniversalAgent | No partial build cleanup for universal builds. The cleanupBuild fix (BLD-04) covers single-platform buildAgent. The corresponding buildUniversalAgent / finishSpreadKit / finishUniversalFusion do not clean up buildDir on internal failures. Extend the same pattern. |
Bugs Server (Bug Team 1 audit, 2026-06-06)
Deferred / large
| ID | Severity | Location | Description |
|----|----------|----------|-------------|
| SRV-B1 | High | server/main.go | No graceful shutdown on SIGINT/SIGTERM. Fixed. http.ListenAndServe replaced with http.Server + goroutine; signal.NotifyContext(syscall.SIGINT, syscall.SIGTERM) drives a srv.Shutdown(ctx) with 10 s timeout on signal, allowing all defer calls (cloudflared.Stop(), database.Close(), maintenance.StopRetentionJobs(), fleetSched.Stop()) to run cleanly. |
| SRV-B2 | Medium | server/internal/db/sqlite.go | SQLite max-connections not configured. Fixed. db.SetMaxOpenConns(1) added immediately after sql.Open; the single-connection pool eliminates concurrent-writer WAL-lock contention and SQLITE_BUSY errors under load. |
| SRV-B3 | Medium | server/internal/scheduler/fleet_scheduler.go | O(tasks × agents) DB queries per minute. Fixed. BulkLastFleetTaskRuns added to the db package; tickInterval now pre-fetches all relevant fleet_task_runs rows in a single query and checks an in-memory map[string]time.Time (keyed "agentID:taskID") in the nested loop — 1 query per tick instead of tasks × agents. |
| SRV-B4 | Medium | server/internal/api/websocket.go broadcastDashboard | Stale-conn cleanup races with Fixed. HandleDashboardWS teardown.broadcastDashboard no longer spawns a goroutine to delete the dashboard map entry on write failure. It only closes the connection; HandleDashboardWS already owns all map cleanup via its existing defer, so the double-delete and the spurious presence_update{online:false} are eliminated. |
| SRV-B5 | Low | server/internal/api/agent_ws_limiter.go | Rate-limiter map never purges zero-entry keys. Fixed. delete(agentWSRateLim.attempts, clientIP) called when len(filtered) == 0 after the expiry sweep; map keys are reclaimed as IP addresses churn out of the window. |
Backend
db.New/MkdirAll: Already returns error on failure (server/internal/db/sqlite.go); remove stale Low (open) note in Server API section when editing that doc block.
Frontend
-
RemoteDirBrowserremoval: No broken imports. UI logic lives inFileManager.tsx+src/help/remoteDirBrowser.ts;remoteDirBrowser.test.tscovers helpers. DeletedRemoteDirBrowser.tsx/.cssare not referenced elsewhere. -
FileManager.test.tsx: Untracked but picked up by Vitest (src/**/*.test.{ts,tsx}); 10 tests pass add to git when committing Fleet work. -
Download test mocks: Prefer separate
vi.fn()per export when mockingapi/download(real module aliasesdownloadApiFiletodownloadAuthedFile; shared mock caused order-dependent flakes).
Open large / architecture
| Issue | Notes |
|-------|-------|
| Monolithic WebSocket context | Every useWebSocket() consumer re-renders on any WS state change. Split into FleetContext / EventsContext or selector hook (useAgents()) for true isolation. |
| CruciblePage size (~2k lines) | Single component owns terminal, fleet list, tabs, file manager hard to memoize subtrees; consider section components + React.memo boundaries. |
| Per-agent stats_update broadcast | Backend sends one dashboard message per agent stats tick; no batching/coalescing in websocket.go. Fleet of N agents ? N JSON parses/frame on client. |
| SystemStatusBar REST poll duplicates WS | Polls listAgents every 15s though fleet already streams via WebSocket wire readout to WS or drop agent poll. |
| Vite chunk size | three (~600 kB) and vendor bundles trigger build warnings; FleetTopologyMap loads three on Dashboard already lazy but still heavy first open. |
| No terminal virtualization | DOM cap at 400 lines helps; full virtual list (react-window) needed for 2000-line scrollback without mount cost. |
| MatrixRain always mounted in Layout | Runs on every route including mobile (hidden sidebar but component still mounts on desktop). Consider content-visibility or route-gated mount. |
| Path Tracer 2s REST poll | No WS push for hop progress; acceptable but adds load during orchestration. |
Open medium
| Issue | Notes |
|-------|-------|
| Emberwake war room double feed | 15s client poll + 30s server runWarRoomBroadcast redundant; prefer WS-only with poll fallback. |
| CursorFire + SacredGeometry on all routes | Desktop-only effects still mount with Layout; gate on VisualEffectsContext or route. |
| Earnings estimate on every hashrate change | Dashboard debounces via totalHashrate effect could share chart sampler interval. |
Deferred large / complex
| Issue | Location | Notes |
|-------|----------|-------|
| WebSocketProvider async race | context/WebSocketProvider.tsx | Fixed (2026-06-06). Added openingRef (useRef(false)) in-flight guard -- a second connect() call while a ticket fetch is in progress returns early. Added AbortController (ticketAbortRef) to cancel any prior in-flight fetch; aborted invocations bail before creating a WebSocket. openingRef is always reset in a finally block. |
| | useVisibleInterval calls fn on every dep changehooks/usePageVisible.ts | Fixed (2026-06-06). fn is now stored in a fnRef (useRef). The effect depends only on ms, enabled, and visible -- an unstable fn reference no longer re-runs the effect or triggers an extra immediate call. The interval always invokes fnRef.current() so callers always see the latest fn without extra renders. |
Deferred large / medium
| ID | Issue | Location | Notes |
|----|-------|----------|-------|
| BA-03 | | write() has no write deadlineclient/client.go — write() | Fixed. c.conn.SetWriteDeadline(time.Now().Add(15*time.Second)) is now called immediately before WriteJSON (and cleared afterward), so a stalled TCP socket cannot hold c.mu indefinitely and deadlock share submission, stats, and command-result goroutines. |
| BA-04 | SSH/SCP spread commands have no overall timeout | deploy/autospread_unix.go attemptSSHSpread() | ConnectTimeout=3 limits only the TCP handshake; after a successful connection, scp.Run() and ssh
start.Run() have no deadline. A slow or unresponsive host stalls the goroutine indefinitely, holding a slot in spreadSem (16 total). With 16 such hangs in flight, all future spread goroutines block waiting on the semaphore. Fix: use exec.CommandContext with a ~30 s deadline wrapping the whole SCP + SSH sequence. Fixed: exec.CommandContext with context.WithTimeout(30s) wraps the full SCP + SSH sequence; a hung host releases its semaphore slot after 30 s. |
| BA-05 | GPU miner binary download has no HTTP timeout or body-size cap | client/gpu_miner.go downloadAndExtract() | http.Get(url) with no timeout and io.ReadAll(resp.Body) with no size limit. A slow redirect or a response that trickles bytes forever will hang the goroutine; a gigabyte-scale response could OOM the agent. Fix: use an http.Client with a 5-min overall timeout, and wrap the body in io.LimitReader(resp.Body, 512<<20). Fixed: http.Client{Timeout: 5*time.Minute} + io.LimitReader(resp.Body, 512<<20). |
| BA-06 | CollectFullSysCheck blocks for 45+ s on empty subnets | client/syscheck.go CollectFullSysCheck() | Calls deploy.ScanLocalSubnet(56) synchronously in the command handler goroutine. ScanLocalSubnet probes up to 56 hosts × ~0.8 s timeout = ~45 s on an empty /24. During this time the agent cannot process incoming WebSocket messages (it is running in a command goroutine, but the read loop is separate; however if the server has a short reply timeout the session may drop). Consider running the subnet scan in a background goroutine and returning a "pending" token, or reducing the default maxHosts for syscheck. |
Infrastructure
-
Root
fix.py,fix3.py,fix4.py: Untracked one-off Python string/regex editors targetingCruciblePage.tsx(ProtocolTunnelonDispatch, GPU hashrate label). Intended changes appear already applied inCruciblePage.tsx. Safe to delete after review; not run in CI do not rely on them for builds. -
CI: Only
.github/workflows/ci-docker-mining.yml(Docker mining); no root Makefile test target found. -
data/login-credentials.json,data/users.json: Untracked; do not commit (secrets/local data).