The console
wakeweb is where an operator meets the mesh. It receives
scored entities from every edge and gives an analyst the three things a
decision needs: what fired, what the entity has been doing, and what
this asset is supposed to be doing. There is a free-form log explorer
too, but the index it searches lives on each edge: the console fans a
query out across per-edge DuckDB stores rather than holding a central
lake.
The loop, not the dashboard
A dashboard ends at the screen. Some of what an analyst decides here travels back down to the edges and changes what they do next. Not all of it, and the difference matters: see what actually travels below.
Triage
The queue is chronological, newest first, with sortable columns. It is the entities view, not this one, that is ordered by threat score. What does encode agreement is structural rather than cosmetic: an entity's source count is only incremented by remote reinforcement, never by its own edge's deposit, and an alert requires at least two sources. An alert therefore cannot fire from a single edge's evidence, whatever that edge saw.
| Entity | What fired | Score | Edges | State |
|---|---|---|---|---|
| 203.0.113.66 | credential pivot + slow scan | 8.7 | 5 | new |
| 198.51.100.23 | beaconing, 300s period | 6.4 | 3 | new |
| user:svc-backup | off-hours auth, role incongruence | 4.9 | 2 | acked |
| 192.0.2.140 | first-seen destination | 3.2 | 2 | acked |
| host:edge-04 | volume deviation vs EMA | 1.8 | 1 | dismissed |
What the analyst gets
- The verdict, with its lineage
- Which Sigma rules matched and their MITRE ATT&CK technique,
which behavioral detectors fired, and what CTI said. One caveat
worth stating: mmsigma does set a
remoteflag on a correlation fire built from a peer's partial, but nothing reads it back, so it is not surfaced here today. - The entity profile
- EMA classification per protocol and port against a weekly seasonal profile: 168 hour-of-week slots, so 09:00 Monday is compared with other Monday mornings rather than with a rolling average. Per-entity baselining is a separate mechanism (rolling 1h windows with mean plus k·sigma, and Welford population thresholds). See the profile panel on the pipeline page.
- Context, not just telemetry
- What the asset is for, who owns it, what it is expected to talk to. A backup account authenticating at 03:00 is either the whole finding or entirely uninteresting, and only context decides which.
- Threat intelligence
- CTI channels and their IOC coverage, so an analyst can see whether
a hit came from a feed they trust. Enrichment happens on the edge in
mmenrich; the console is where the sourcing is auditable. - Who is actually reporting
- SWIM liveness and per-node signal rates. An edge that stopped reporting is a detection gap, and it should be as visible as an alert.
Detection health
A ruleset degrades quietly. A rule that fires on everything trains
analysts to ignore it, and a rule that never fires looks exactly like
coverage you never had. Neither condition raises an alert, because
neither is an attack. So waked profiles its own Sigma
layer on a timer and writes the verdict where both an operator and
ordinary log-based alerting will find it.
That headline is the honest state of a detection layer: nothing is currently producing signal, and one rule is producing noise. It is the kind of thing a SOC usually discovers a quarter later, during a review.
How a rule gets called noisy
- The sample
- The profiler reads the tail of the enriched event stream, 50 MB by default, and counts hits per rule id. It does not re-run the matcher: the verdicts are already stamped on each event by mmsigma, so this is aggregation over a file rather than a second detection pass. That is what makes it cheap enough to run on an edge.
- The ratio
- The denominator is every event in that window, matched or not. A rule matching more than 2% of everything the collector saw is classed FP-suspect and reported as noisy. The guidance text calls that traffic benign, which is an assumption: the sample is live production traffic, not a curated clean corpus. On a host actually under attack, read the number accordingly.
- Silent rules
- Reported separately, as a coverage question rather than a noise problem: either the log source is not flowing, or the rule should be retired. Two qualifiers: the test is "produced no promoted signal", not "matched nothing", and it only covers rules that could promote (correlations, and single-event rules whose verdict is escalate). An ordinary alert-tier rule that never escalates is expected to be quiet here and is deliberately not listed.
- Active detections
- The headline count is the number of distinct Sigma rules and correlations that produced at least one promoted signal in the last 24 hours, excluding the noisy ones. It counts rules, not alerts, so a single loud rule cannot inflate it.
The check runs on edge nodes with the behavioral engine enabled, first
a few minutes after startup and then every six hours. The console
surfaces the same data on demand as a Detection Health
panel on the rules page, grouped into noisy, active, and silent, with
an edge selector; waked also exposes it as a
sigma.health call so a collector can ask any edge
directly.
Decisions that travel
Three console actions change what an edge does. They do not go through
fleet: wakeweb never dials out, collectors connect
to it on port 7949, and policy rides WAKE's own asset
distribution channel over TLS, landing with a SIGHUP to rsyslog.
analyst action (console)
|
+-- whitelist entity ---+
+-- context tag ---+--> custom_cti -> binary overlay
| |
| v
| collector RPC :7949 (edge dials in)
| |
| v
| asset distribution (TLS) -> SIGHUP rsyslog
| |
| +-- mmenrich overlay checked BEFORE the
| | .thrt DB: whitelist skips CTI
| | and GeoIP; a tag sets $!tags
| +-- mmwake score clamped to 0.01, below
| the 0.3 OCSF projection floor
|
+-- profile suppression --> self.configure RPC -> CONFIG_PUSH
-> waked behavioral engine rewrites
the signal to severity=info
What does not travel
Acknowledge, dismiss and watchlist are console state. Dismiss deletes one signal row on the one edge that owns it, because signal ids are edge-local; it does not recompute any score, there or anywhere else. Triage state lives in the console's own SQLite table and no edge reads it. The watchlist is a display list in the same database.
So there are two levers, and picking the wrong one is the common mistake:
- Whitelist
- The CTI lever. Stops an indicator being treated as a threat-intel hit. Behaviour is still observed, still scored behaviourally, and still gossiped.
- Profile suppression
- The behavioural lever. Pushed to every edge over the same channel,
it rewrites matching signals to informational severity with
suppressed_by: profile_matrix. This is the one to reach for when a signal type is simply not interesting for a class of asset.
Access
The console does not hold its own user database. It delegates
authentication to fleet over the local fleetd broker
socket, so operator accounts are managed in exactly one place and there
are no per-app service tokens to rotate. That socket carries login and
tenant topology only; it is not how policy reaches an edge. A broker
outage fails closed.
Authorization today is tenant scoping, not a read/write split: a session is clamped to its tenant, and within that scope any authenticated session can whitelist, suppress or dismiss. A viewer-style role exists in the UI but is not yet enforced as read-only, so treat console access as operator access. Mutations are recorded in the console's own audit table.
Where it runs
The soc-console
platform is the reference deployment: a Linux host running rsyslog with
the WAKE modules, two waked instances (an edge on
7948 and a collector on 7949), wakeweb, and
fleetd. It aggregates from every edge in the fleet.
For an existing SOC, the alternative is no console at all: have your
SIEM pull waked's /ocsf feed, a token-gated
NDJSON endpoint served over GET. Note the direction, since
it is the opposite of most integrations: waked ships
nothing outbound and the collector does not dial your SIEM. It binds to
loopback by default, so exposing it is a deliberate act.