Skip to content

UI

Three files:

File Content
socrates.html HTML shell (repo root)
static/socrates.css All styles
static/socrates.js All JavaScript

socrates.html loads the CSS and JS via <link> and <script src> tags. D3 and d3-sankey are vendored in static/ for offline use.

UI States

Welcome Screen (no analysis loaded)
  ├── URL input + file upload
  └── Previous analyses list

Analysis View (analysis loaded)
  ├── Header (back button, name, path, date range)
  ├── Visualizations bar (Diagram toggle, Aggregation toggle)
  ├── Filter Bar (active search and filters as removable chips)
  ├── Stats Grid (clickable event-type cards, shows the filtered count alone when a filter is active - see `buildStats()` in filtering.md)
  ├── Sankey Diagram (diagram mode — Source IP → Dest IP → Dest Port, reflects current filters)
  ├── Aggregations (frequency counts per column)
  └── Data Sections (tabbed tables)

JavaScript Architecture

Global state:

let allEvents = [];          // Loaded for "All Events" tab
let eventTypes = [];         // available types for current analysis
var currentMd5 = '';         // current analysis MD5 (var, not let - see below)
var currentFileName = '';    // display name (var, not let - see below)
var currentNotes = '';       // per-analysis freeform notes (var, not let - see below)
var currentFilters = {};     // {columnName: value} — global, flat (var, not let - see below)
let currentSearch = [];      // server-side full-text search terms (array)
let baseEventStats = {};     // unfiltered totals for stats card denominator
var advancedMode = false;    // advanced toggle state (var, not let - see below)
let tabDataCache = {};       // cached event data per type

currentMd5/currentFileName/currentNotes/currentFilters/advancedMode (and a couple of others, e.g. truncatedTypes) are deliberately declared with var rather than let/const - the JSDOM test harness (tests/jsdom_helper.py) assigns/reads them via separate window.eval() invocations, and only var/function declarations attach to the actual global object persistently across those separate evaluations.

Key function groups:

Group Functions Purpose
Navigation showWelcome(), loadAnalysis(), showTab(), showWelcomeUI(), showAnalysisUI() Screen/tab switching
Keyboard Navigation navigateStatTabs(), activeColumnStatCards(), navigateSampleCards(), navigateVertical(), seedVerticalNavSelectionIfStale(), navigateFilterBarItems(), focusNewestFilterChip(), focusFilterBarOrFirstCard(), navigateThemeTiles(), activateKeyboardSelection(), isNavigableKeyContext() Arrow-key/Enter navigation (see Usage)
Command Palette AUTOCOMPLETE_COMMANDS, openAutocompleteModal(), filterAutocomplete(), autocompleteMatchesQuery(), autocompleteMatchScore(), activateAutocompleteSelection() Type-anywhere command list (see Usage)
Data Loading loadTabData(), loadFromUrl(), uploadPcap(), checkStatus() Fetch data from API
Rendering buildStats(), buildSections(), buildSection(), buildAllEvents(), buildRowForEvent(), updateSankeyDiagram() Build HTML
Aggregation buildAggregationTablesCore(), buildAggregationTables(), buildAggregationTablesAll(), buildAggregationsSection(), buildAggregationsSectionAll() Frequency grids
Search performSearch(), clearSearchTerm(), refreshAnalysisData() Full-text search via server
Filtering applyFilter(), applyFilters(), clearFilter(), clearAllFilters(), getFilteredEvents(), getSankeyEvents(), refreshCurrentView() Column filter management
Streams downloadPcap(), loadAsciiTranscript(), loadHexdumpData(), switchStreamView(), togglePacket(), toggleRow() Stream analysis
Modals closeAllModals(), showNotesModal(), closeNotesModal(), saveAnalysisNotes(), openAnalysisNotesFromList(), showRulesModal(), closeRulesModal(), triggerRulesetUpdate(), isRulesetStale() Notes editing and Rules-modal management, shared modal cleanup
Utilities escapeHtml(), formatEvent(), extractValue(), extractAllValue(), getColumnsForType(), clearAnalysisContainers() Helpers

Column System

Each event type has its own column set. The "All Events" view uses a unified column set.

Shared columns (all types): Time, Protocol, Source IP, Source Port, Dest IP, Dest Port

Per-type columns: e.g. Alert/Category/Severity (alerts), Query/Type (DNS), Method/Host/URL/Status (HTTP). Every event type on the Event Types page has its own set - 30+ types by now - defined in getColumnsForType() (static/socrates.js), which is the source of truth; this doc intentionally doesn't enumerate all of them; a full list here would just drift out of sync with every new protocol added (the same problem already found and fixed once in filtering.md's old "Column Overlap" table).

All-events columns: Type (event type), Detail (type-specific summary)

Filtering Design

Filters are global - currentFilters is a flat {columnName: value} object. When switching tabs, filters for columns that don't exist in the new view are silently skipped (the column lookup returns -1 and the filter is ignored).

See filtering.md for full details.