Add browser deploy recon backend with port scan, web crawl, and deploy lane recommendations.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

POST /api/v1/recon/scan probes fleet ports from the server host, crawls owned HTTP targets, maps findings to spread lanes, and records optional oath ledger rows.
This commit is contained in:
AetherForge
2026-06-07 11:23:10 -07:00
parent 483eafa9dd
commit f3e5a9a07d
40 changed files with 3091 additions and 4 deletions

View File

@@ -30,6 +30,7 @@ interface FmCommandResult {
interface Props {
activeTab: 'ops' | 'recon' | 'files' | 'spread' | 'tunnels';
spreadHostHint?: string;
selectedAgents: Agent[];
selectedCount: number;
singleSelectedAgent: Agent | null;
@@ -51,6 +52,7 @@ interface Props {
export default function CrucibleExpandedOps({
activeTab,
spreadHostHint = '',
selectedAgents,
selectedCount,
singleSelectedAgent,
@@ -777,6 +779,11 @@ export default function CrucibleExpandedOps({
if (activeTab === 'spread') {
return (
<div className={panelClass}>
{spreadHostHint ? (
<p className="crucible-spread-host-hint" data-testid="crucible-spread-host-hint">
Deploy Recon target: <strong>{spreadHostHint}</strong> select egress agents and run Spread Now or Probe &amp; Join.
</p>
) : null}
<CrucibleCollapsibleSection label="Lateral Movement" className="cop-agg" helpField="crucible_section_spread" defaultOpen>
<span style={{ display: 'inline-flex', alignItems: 'center', gap: '2px' }}>
<button type="button" className="button crucible-op-btn" disabled={aggDisabled('spread_now')} title={aggTitle('spread_now')} onClick={() => aggBulk('spread_now', {}, `Run lateral spread sweep on ${targets.length} node(s)?`)}>

View File

@@ -35,6 +35,7 @@ function operatorDeckId(pathname: string): string {
if (path.startsWith('/forge') || path.startsWith('/builder')) return 'forge';
if (path.startsWith('/crucible')) return 'crucible';
if (path.startsWith('/emberwake') || path.startsWith('/spread')) return 'emberwake';
if (path.startsWith('/deploy-recon') || path.startsWith('/browser-spread')) return 'deploy-recon';
if (path.startsWith('/builds')) return 'builds';
if (path.startsWith('/settings')) return 'settings';
if (path.startsWith('/pathtracer')) return 'pathtracer';
@@ -58,6 +59,7 @@ const NAV_BASE: readonly NavItem[] = [
{ to: '/mission-deck', label: 'Mission Deck', icon: 'mission', glow: true },
{ to: '/builds', label: 'Builds', icon: 'builds' },
{ to: '/emberwake', label: 'Emberwake', icon: 'ember' },
{ to: '/deploy-recon', label: 'Deploy Recon', icon: 'recon' },
{ to: '/settings', label: 'Calibrate', icon: 'gear' },
];
@@ -158,6 +160,14 @@ function NavIcon({ type }: { type: string }) {
<path d="M8 21h8" />
</svg>
);
case 'recon':
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5">
<circle cx="11" cy="11" r="7" />
<path d="M20 20l-3.5-3.5" />
<path d="M8 11h6M11 8v6" strokeOpacity="0.45" />
</svg>
);
case 'trace':
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5">