feat: Emberwake, Crucible phases, Linux agent, musical dashboard, e2e
Emberwake spread/waterhole UI, campaign DB, spread handler, spread-kit web publisher, and SPREAD_TECHNIQUES doc. Crucible Phase A-C: expanded ops, port-forward matrix, remote dir browser, crucible help/tests. Linux agent hardening: credential vault, persistence audit, firewall/defender deploy, SMB spread status, CPU stats, screenshots/crypt/file-ops split. Docker compose and agent/server images with e2e validation script and docs. Musical dashboard: ambient music player, hover SFX, SoundContext/AmbientMusicContext, steampunk polish. Public builds API, dropper handler updates, SessionGate and fleet UX. README and PROBLEMS.md refresh.
This commit is contained in:
@@ -42,6 +42,7 @@ import {
|
||||
defaultRunnerName,
|
||||
defaultEmbeddedName,
|
||||
} from '../help/fusionMedia';
|
||||
import { SPREAD_PROFILES, applySpreadProfile, type SpreadProfileId } from '../help/spreadProfiles';
|
||||
import './Pages.css';
|
||||
|
||||
export function formatBytes(n: number): string {
|
||||
@@ -158,6 +159,7 @@ export default function BuilderPage() {
|
||||
const [pendingReforgeBuild, setPendingReforgeBuild] = useState<BuildRecord | null>(null);
|
||||
const [highlightFusionPrep, setHighlightFusionPrep] = useState(false);
|
||||
const fusionPrepRef = useRef<HTMLDivElement>(null);
|
||||
const [spreadProfile, setSpreadProfile] = useState<SpreadProfileId | ''>('');
|
||||
|
||||
// Drive simulated stage progress while a single build is running
|
||||
useEffect(() => {
|
||||
@@ -1025,6 +1027,7 @@ export default function BuilderPage() {
|
||||
|
||||
<div className="card builder-form">
|
||||
{simpleMode ? (
|
||||
<>
|
||||
<div className="forge-simple-banner card">
|
||||
<p className="font-tech">RECOMMENDED DEFAULTS — AUTO-SELECTED</p>
|
||||
<p className="form-hint">{RECOMMENDED_DEFAULTS_BLURB}</p>
|
||||
@@ -1032,6 +1035,30 @@ export default function BuilderPage() {
|
||||
Reset to recommended defaults
|
||||
</button>
|
||||
</div>
|
||||
<div className="form-group" style={{ marginBottom: '1rem' }}>
|
||||
<label className="label">Spread profile presets</label>
|
||||
<div className="endpoint-chips" style={{ flexWrap: 'wrap' }}>
|
||||
{SPREAD_PROFILES.map((p) => (
|
||||
<button
|
||||
key={p.id}
|
||||
type="button"
|
||||
className={`endpoint-chip ${spreadProfile === p.id ? 'active' : ''}`}
|
||||
style={{ borderColor: spreadProfile === p.id ? p.color : undefined, color: spreadProfile === p.id ? p.color : undefined }}
|
||||
title={p.blurb}
|
||||
onClick={() => {
|
||||
setSpreadProfile(p.id);
|
||||
if (form) setForm(applySpreadProfile(form, p.id));
|
||||
}}
|
||||
>
|
||||
{p.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
{spreadProfile && (
|
||||
<p className="form-hint">{SPREAD_PROFILES.find((p) => p.id === spreadProfile)?.blurb}</p>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="forge-rules-banner">
|
||||
<h3 className="font-tech">FORGE RULES — READ THIS ONCE</h3>
|
||||
|
||||
Reference in New Issue
Block a user