feat(ui): frontend polish sweep — 8 UX fixes

- DeckyFleet: card click opens inspect side-drawer instead of
  auto-filtering (localSearch filter behavior removed)
- Dashboard: LIVE FEED / DECKIES UNDER SIEGE / TOP ATTACKERS panels
  now have fixed max-height with overflow scroll instead of growing
- parseEventBody: defensive RFC 5424 header strip so raw syslog lines
  from the collector render as k=v pills instead of raw text
- Attackers: search placeholder updated; activity (Active/Passive/
  Inactive) and country chip filters added on top of existing IP search
- Credentials + Bounty: sortable column headers (click to asc/desc/clear)
- SwarmHosts + RemoteUpdates: icon extracted from <h1> into flex div
  with violet-accent class, matching site-wide Identities pattern
- Swarm.css: fix --panel-border undefined variable → --border so the
  title border-bottom line is visible on SwarmHosts and RemoteUpdates
This commit is contained in:
2026-04-29 23:56:38 -04:00
parent a322d88b3c
commit 9adee07d21
10 changed files with 318 additions and 37 deletions

View File

@@ -11,11 +11,16 @@ export interface ParsedBody {
tail: string | null;
}
// RFC 5424: <PRI>VERSION TIMESTAMP HOSTNAME APPNAME PROCID MSGID SD MSG
// Matches both framed (<135>1 ...) and unframed (bare timestamp) variants.
const rfc5424Re = /^(?:<\d+>\d\s+)?\d{4}-\d{2}-\d{2}T[\d:.+-]+\s+\S+\s+\S+\s+\S+\s+\S+\s+(?:-|\[.*?\])\s*/;
export function parseEventBody(msg: string | null | undefined): ParsedBody {
const empty: ParsedBody = { head: null, fields: {}, tail: null };
if (!msg) return empty;
const body = msg.trim();
let body = msg.trim();
if (!body || body === '-') return empty;
body = body.replace(rfc5424Re, '');
const keyRe = /([A-Za-z_][A-Za-z0-9_]*)=/g;
const firstKv = body.search(/(^|\s)[A-Za-z_][A-Za-z0-9_]*=/);