Home / Case studies / PlainSight
Capstone Project · S1 2026

PlainSight

A local AI triage layer for Wazuh that turns noisy alert batches into readable summaries and management-ready reports, without sending client data outside the network.

What the project solved

The sponsor had one Level 1 admin responsible for a FortiGate 60E, a FortiSwitch 424E, and a Ruckus R650 AP. There was no central place to look. Triage meant logging into three vendor consoles and reading raw syslog, and by the sponsor's estimate it took 45 to 60 minutes to work through a single batch.

The hard constraint was that the gear sat on a live client network. Anything that touched real telemetry had to stay on-prem. No cloud LLM API, no SaaS SIEM, nothing that called out to the internet for analysis.

PlainSight became the single pane that sat in front of all of that. Telemetry came in, got normalised, got scored, got summarised by a local model, and got presented in a form a Level 1 could actually act on. A one-click PDF on the way out covers management reporting.

Outcome: Triage time dropped from 45 to 60 minutes down to under 10 seconds for AI-summarised batches in lab testing. The number that matters more to me is that the dashboard gives you a starting point that is not "go read all the logs".

Architecture and implementation

01
Telemetry pipeline
Two ingestion paths feed into the same operational store. Wazuh on Ubuntu Server (virtualised on ESXi) pulls syslog from the FortiGate, the FortiSwitch, and the Ruckus AP, and PlainSight polls the Wazuh Indexer on an interval. A second path is a local file watcher that handles Fortinet key-value logs, Ruckus tarballs, and APC UPS event codes when Wazuh is not the source. Everything lands in a SQLite database running in WAL mode. SQLite is not what the proposal called for. I switched to it once it became obvious I needed shared operational state between the dashboard and a background triage service, and the Wazuh Indexer alone was not a clean place to keep analyst workflow data like triage status or incident records.
Wazuh Ubuntu Server VMware ESXi SQLite (WAL) Custom Ingestion Syslog
02
Local AI ("SoMi")
The assistant is called SoMi. It runs llama3.2:3b through Ollama on a Lenovo ThinkCentre (i5-8500T, 16 GB RAM, no GPU). The proposal had phi3:mini and I tested both; llama3.2:3b followed instructions more reliably at a similar latency tier, which mattered more than raw speed for the kind of "here are 8 alerts, summarise and give next steps" prompts I was running. The piece I am genuinely happy with is that most user-facing questions hit a fast deterministic path against SQLite before the model gets called. "How many critical alerts today" does not need a 3-billion-parameter model. A separate background service does AI triage on stored alerts and waits when interactive SoMi is busy, so the two never fight over the same Ollama instance.
Ollama llama3.2:3b Local Inference ThinkCentre i5-8500T Zero Cloud
03
Dashboard and analyst workflow
The frontend is Streamlit. Pages cover the global overview, threat timeline, per-device scorecards, search, the SoMi chat panel, threat intel, MITRE ATT&CK mapping, an incidents view, and a system admin page. This is the part of the build that grew the most. The proposal stopped at "live feed plus AI summaries plus MITRE". The shipped version also carries triage status with an audit trail, an incident object that links back to source alerts, suppression rules for noisy patterns, saved searches, an IOC watchlist, public threat-intel feed enrichment, behavioural baselines per device per hour, correlation rules for things like brute force and off-hours criticals, and a retention engine that archives by severity before deletion. None of that was in the original scope. All of it turned out to be needed once an actual analyst session sat down with the dashboard for an hour.
Streamlit Python MITRE ATT&CK Threat Intel Incidents PDF Export

What it looks like