Repository navigation
v2.0.0
v2.0.0
New dashboard
The dashboard has been rebuilt. Everything the collector gathers is unchanged —
same 33 event IDs, same wire format, same database — but the page that shows it
is new, and it answers a different first question.
The headline is a share, not a count
"4,000 NTLM events" means nothing without knowing what it is 4,000 out of. The
page now opens with "Still 26 % of all logons go through NTLM", computed
against Kerberos in the same period, with the direction of travel underneath.
The API gained krb_ev so the share can be computed at all.
Below it the handover bar splits the estate three ways — insecure, outdated,
target state. The bar is geometrically exact; hovering a segment raises a card
with the name, count and share, and clicking one filters the event list to it.
Exact figures sit in a readout beneath, which always lists all three including a
zero, because a category that silently vanishes reads as a rendering fault.
Everything is a way in
The three charts are drill-downs. Click a day in the trend, a cell in the
heatmap, a cause in "Why NTLM", or a segment of the handover bar, and the event
list filters to exactly those events. The filters run server-side using the same
SQL predicates the charts are counted with — a day three weeks back is not in
the list the page happens to be holding, and a filter built from a slightly
different expression would return a different number than the bar it came from.
Verified row by row against every panel.
Clicking an event opens the raw record as Windows reported it: every field
grouped and labelled, an explanation of what that event ID means, and what a
failure code implies. Buttons jump to everything from the same account, program
or machine.
New panels
- Most-used targets — which server absorbs the most NTLM
- Accounts already using Kerberos — the healthy side, by account
- Agents by OS — a ring counting reporting machines by Windows build, amber
for anything predating Server 2019, which cannot produce the 40xx events at all - Domain and forest functional level, read from rootDSE
Layout and readability
Full width with a fixed column count — two on anything up to a 1440p desktop, a
third only past 2900 px, because auto-fitting packed four abreast and read as a
wall. Type is larger throughout, surfaces are lighter, and the contrast of the
faintest text against a panel went from 3.31:1 to 4.69:1 — clearing WCAG AA for
the first time. Table headers are their own band; secondary cells carry real
content and sit at 7.53:1 rather than 4.69:1.
Fixed along the way
Several of these had shipped unnoticed and were only found by rendering the
running page in a real browser rather than reasoning about the code:
- The heatmap was one day off. The server stores the grid Monday-first, the
page read it Sunday-first, so every row showed the following day's data and
the "peak" line named the wrong day. Three places shared the mistake. - The trend chart drew nothing. Correct percentage heights inside a
container whose columns had no definite height, so they collapsed to zero.
Invisible to any test that does not lay the page out. - The events panel reported its own cap as the result — "300 / 300" no
matter how many matched. It now reads "300 / 2,431 – newest 300 loaded". - No way to log out when a dashboard password was configured.
- A placeholder printed literally in the machines panel. Every translation
string is now checked against its call site. - Dropdown lists were rendered light on a dark page (
color-schemewas missing). - Account lists ran together without spaces.
Security
The rebuilt dashboard was re-audited rather than assumed safe. Six payload
classes were injected into twenty attacker-influenced fields via the real ingest
API, the page was rendered against the result and every detail drawer opened:
zero executable payloads in 107,717 characters of generated HTML, with a
counter-check confirming the payloads arrived and were escaped. Five security
headers including a default-src 'none' CSP, login enforced on every endpoint,
no state-changing GET, CSV export proof against all eight injection and
delimiter attacks.
Unchanged and still worth doing before an enterprise rollout: TLS between
agent and collector, restricted network access to the dashboard, and running
with --password.
Upgrade notes
- Collector only for the dashboard. Replace the file, restart, hard-refresh
with Ctrl+F5 — without it the browser serves the old page from cache. - Existing databases gain two columns automatically at startup.
- Agents keep working unchanged. The functional-level fields stay empty until
agents are updated; nothing else depends on them. - Item status ("done") set in the old dashboard survives — it lives in the
database.