capitalize headings

This commit is contained in:
thesabear committed 2026-09-01 17:59:02 +03:00
1 parent 4c1b23a69c
commit f20ed10632
16 files changed
+65 -65

No files matched your search

+5 -5
View File
@@ -47,7 +47,7 @@ for n in data:
Build SOC Board HTML -> 104443 chars
```
## Why one function instead of native Dashy widgets
## Why One Function Instead of Native Dashy Widgets
Dashy's own built-in widget types cover simple cases well, but none of them can join data across sources the way this board needs to — a per-host tile that combines Wazuh findings, Prometheus resource usage, and Slack alert history into one expandable panel isn't expressible as a single native widget config. Building it as one Node-RED function that does the aggregation server-side, then hands the dashboard pre-joined data, was the tradeoff made: a large, custom function to maintain, in exchange for a board that actually reflects cross-system state instead of fourteen disconnected tiles a human has to mentally correlate themselves.
@@ -66,7 +66,7 @@ Clicking through to one of those "folded-in specialty widgets" — the Vault sea
> [!TIP]
> **Deliberately scoped**: security/error/warning signal only. Per-app uptime is handled separately by Dashy's own native status checks on individual tiles — the only up/down signal inside this board is *infrastructure-tier* reachability from Prometheus, not per-app availability. Keeping the scope narrow — resisting the temptation to also make this the uptime dashboard — is what keeps the board actually scannable instead of turning into a second copy of Grafana.
## Every finding ships with a copy-ready incident summary
## Every Finding Ships With a Copy-ready Incident Summary
Each finding's expanded row has a "Copy Debug Prompt" button, not just an acknowledge control. Clicking it builds a fully-formed summary from that specific finding's own host, severity, title, and detail, and copies it straight to the clipboard — a complete, structured starting point for triage without manually re-gathering context from the board itself. This is the real template:
@@ -80,7 +80,7 @@ Detail: {meta}
```
## Acknowledge mechanism: client-side, no backend
## Acknowledge Mechanism: client-side, no backend
![A finding's stable key (hostId::group::title) gets acknowledged into the browser's localStorage as a flat map, which live re-derives the host tile badge, the Active Issues strip, and any open detail panel's gauges — and never touches Wazuh, Slack, or any other upstream source](../assets/dashy-soc-board-acknowledge.svg)
@@ -95,7 +95,7 @@ localStorage.getItem("socAckedV2")
> [!IMPORTANT]
> Acknowledging a finding is a **display filter only** — it never writes back to Wazuh, Slack, or any upstream source described elsewhere in this repo, is scoped per-browser rather than fleet-wide, and a full data set for every host is always kept in memory (in inert template elements, not just whichever panel is currently open) so the recompute has everything it needs regardless of which panel happens to be open. A reload in a different browser shows the finding again. This was a deliberate tradeoff favoring simplicity — no backend state to build, secure, or back up — over persistence, made because the board's job is triage visibility, not an audit trail of who acknowledged what (that's what Wazuh's own alert log in [`docs/security-monitoring.md`](security-monitoring.md) is for).
## Real integration gotchas hit building this
## Real Integration Gotchas Hit Building This
> [!WARNING]
> A few non-obvious lessons from actually building this, in case they save someone else the debugging time:
@@ -105,7 +105,7 @@ localStorage.getItem("socAckedV2")
> - Node-RED's Mustache templating in a core node's URL field is scoped to `msg` directly, not `msg.msg` — the correct reference is `{{{url}}}`, not `{{{msg.url}}}`, and it needs the triple-brace form specifically for values containing characters like `&` that the double-brace form would HTML-escape. Get either wrong and the request silently goes to an empty or mangled URL instead of erroring.
> - Replacing a bind-mounted config file's content doesn't get picked up by a plain container restart — the container keeps watching the old inode; a full recreate is required, the same gotcha that shows up in [`docs/registry-and-build.md`](registry-and-build.md)'s redeploy path.
## Widget design: shape follows data, not one template everywhere
## Widget Design: shape follows data, not one template everywhere
Every widget's visual style is chosen to match the *shape* of the data it shows, not a single card/badge component reused everywhere — the same design instinct behind this repo's own docs, honestly: