feat(web): Persona Generation page under AUTOMATION
New dashboard surface for editing the global emailgen persona pool — the JSON file fleet (MACVLAN/IPVLAN) and SWARM-shard mail deckies pull from. MazeNET topology personas are out of scope here; they're configured per-topology in the topology editor. Backend: * GET/PUT /api/v1/emailgen/personas — admin-write, viewer-read. PUT validates with the same Pydantic schema the worker uses (parse_personas), drops invalid entries with a warning, returns 400 only when the entire payload fails. Path is operator-discoverable on every response so a CLI-driven backup workflow stays visible. Frontend: * PersonaGeneration.tsx + .css — table + add/edit modal with the full EmailPersona schema (name, email, role, tone, mannerisms list, language, signature, active hours, reply latency, uses_llms_heavily). Local edits are batched; explicit "SAVE CHANGES" writes back, with a dirty-indicator pill and a "DISCARD" reset. Email uniqueness is enforced client-side so the scheduler never picks the same persona as both sender + recipient. * Sidebar AUTOMATION group gains a "Persona Generation" entry next to Orchestrator; route registered at /persona-generation. The worker reads the same on-disk file the API writes — see decnet.orchestrator.emailgen.global_pool. The API resets the in-process cache on every read/write so the worker picks up dashboard edits within its next tick rather than waiting on mtime.
This commit is contained in:
@@ -3,7 +3,7 @@ import { NavLink, useLocation } from 'react-router-dom';
|
||||
import {
|
||||
Menu, X, Search, Activity, LayoutDashboard, Terminal, Settings, LogOut,
|
||||
Server, Archive, Package, Network, ChevronDown, ChevronRight, HardDrive,
|
||||
ShieldAlert, Bell, Webhook, Lock, Crosshair, Fingerprint, Zap, Cpu,
|
||||
ShieldAlert, Bell, Webhook, Lock, Crosshair, Fingerprint, Zap, Cpu, Mail,
|
||||
} from '../icons';
|
||||
import { prefetchRoute } from '../routePrefetch';
|
||||
import './Layout.css';
|
||||
@@ -34,6 +34,7 @@ const ROUTE_LABELS: Record<string, string> = {
|
||||
'/identities': 'IDENTITIES',
|
||||
'/campaigns': 'CAMPAIGNS',
|
||||
'/orchestrator': 'ORCHESTRATOR',
|
||||
'/persona-generation': 'PERSONA GENERATION',
|
||||
'/config': 'CONFIG',
|
||||
'/swarm-updates': 'REMOTE UPDATES',
|
||||
'/swarm/hosts': 'SWARM HOSTS',
|
||||
@@ -108,8 +109,10 @@ const Layout: React.FC<LayoutProps> = ({
|
||||
|
||||
<nav className="sidebar-nav">
|
||||
<NavItem to="/" icon={<LayoutDashboard size={20} />} label="Dashboard" open={sidebarOpen} />
|
||||
<NavItem to="/fleet" icon={<Server size={20} />} label="Decoy Fleet" open={sidebarOpen} />
|
||||
<NavItem to="/mazenet" icon={<Network size={20} />} label="MazeNET" open={sidebarOpen} />
|
||||
<NavGroup label="DEPLOY" icon={<Server size={20} />} open={sidebarOpen}>
|
||||
<NavItem to="/fleet" icon={<Server size={18} />} label="Decoy Fleet" open={sidebarOpen} indent />
|
||||
<NavItem to="/mazenet" icon={<Network size={18} />} label="MazeNET" open={sidebarOpen} indent />
|
||||
</NavGroup>
|
||||
<NavGroup label="ALERTS" icon={<Bell size={20} />} open={sidebarOpen}>
|
||||
<NavItem
|
||||
to="/live-logs"
|
||||
@@ -127,15 +130,16 @@ const Layout: React.FC<LayoutProps> = ({
|
||||
indent
|
||||
/>
|
||||
</NavGroup>
|
||||
<NavItem to="/bounty" icon={<Archive size={20} />} label="Bounty" open={sidebarOpen} />
|
||||
<NavItem to="/credentials" icon={<Lock size={20} />} label="Credentials" open={sidebarOpen} />
|
||||
<NavGroup label="THREAT DATA" icon={<Activity size={20} />} open={sidebarOpen}>
|
||||
<NavItem to="/attackers" icon={<Activity size={18} />} label="Attackers" open={sidebarOpen} indent />
|
||||
<NavItem to="/identities" icon={<Fingerprint size={18} />} label="Identities" open={sidebarOpen} indent />
|
||||
<NavItem to="/campaigns" icon={<Crosshair size={18} />} label="Campaigns" open={sidebarOpen} indent />
|
||||
<NavItem to="/credentials" icon={<Lock size={18} />} label="Credentials" open={sidebarOpen} indent />
|
||||
<NavItem to="/bounty" icon={<Archive size={18} />} label="Bounty" open={sidebarOpen} indent />
|
||||
</NavGroup>
|
||||
<NavGroup label="AUTOMATION" icon={<Zap size={20} />} open={sidebarOpen}>
|
||||
<NavItem to="/orchestrator" icon={<Cpu size={18} />} label="Orchestrator" open={sidebarOpen} indent />
|
||||
<NavItem to="/persona-generation" icon={<Mail size={18} />} label="Persona Generation" open={sidebarOpen} indent />
|
||||
</NavGroup>
|
||||
<NavGroup label="SWARM" icon={<Network size={20} />} open={sidebarOpen}>
|
||||
<NavItem to="/swarm/hosts" icon={<HardDrive size={18} />} label="SWARM Hosts" open={sidebarOpen} indent />
|
||||
|
||||
Reference in New Issue
Block a user