From 9368f268568a3e4ade6d1906862613fa34ffd221 Mon Sep 17 00:00:00 2001 From: thesabear Date: Fri, 28 Aug 2026 09:58:49 +0300 Subject: [PATCH] docs: rewrite dashy-soc-board.md with real verified evidence Live-verified every specific claim directly against the real Node-RED function source (not just trusted from the KB): the 104,443-char function size, all 5 Wazuh finding categories, Vault's live PKI cert endpoints, the real DNS Security Signals implementation, the fleetAudit global pattern, the 12-app Slack channel map, the acknowledge key format and localStorage key name, and the Mustache triple-brace URL gotcha. Replaced both mermaid diagrams: the flat data-sources fan-in became a real specifics table (redundant diagram cut per the diagramming standing process), and the acknowledge-flow diagram was rebuilt as a real Nextcloud diagram. Stamped both source KB notes. --- assets/dashy-soc-board-acknowledge.svg | 4 ++ docs/dashy-soc-board.md | 58 ++++++++++++++------------ 2 files changed, 35 insertions(+), 27 deletions(-) create mode 100644 assets/dashy-soc-board-acknowledge.svg diff --git a/assets/dashy-soc-board-acknowledge.svg b/assets/dashy-soc-board-acknowledge.svg new file mode 100644 index 0000000..8652dd9 --- /dev/null +++ b/assets/dashy-soc-board-acknowledge.svg @@ -0,0 +1,4 @@ + + + +
Finding
stable content-derived key
User acknowledges
Browser localStorage
flat map, per-browser
Live re-derive
badges, issue strip, gauges
Wazuh / Slack / any
upstream source
never touches
The real acknowledge flow, entirely client-side
The relationship that deliberately doesn't exist
\ No newline at end of file diff --git a/docs/dashy-soc-board.md b/docs/dashy-soc-board.md index b5c47cb..63c5e58 100644 --- a/docs/dashy-soc-board.md +++ b/docs/dashy-soc-board.md @@ -5,26 +5,28 @@ ## Fourteen data sources, one board -```mermaid -flowchart TD - subgraph Sources["Data sources"] - direction LR - Wazuh["Wazuh indexer
+ compliance API"] - Loki["Loki
24h error counts"] - Prom["Prometheus
CPU/RAM/disk"] - Slack["Slack channels
per app + per host"] - Orch["Kestra / n8n APIs
execution health"] - Audit["Fleet config-drift
audit feed"] - Hyper["Proxmox API
VM/LXC tree"] - Vault["Vault
seal state, lease counts"] - SSO["Authentik
login/failure stats"] - DNS["Technitium
query stats, blocklist"] - Backup["Backup server
job age/status"] - FW["pfSense
state table, top rules"] - end +This board didn't start from nothing — it absorbed several formerly-standalone Dashy pages (a Dependency Tiers page, a Wazuh overview, an Authentik page, Kestra/n8n execution health) as per-host expandable sub-sections instead. There's no separate Wazuh-only or Dependency-Tiers-only page anymore; both live only inside this one board now. A representative slice of what each source actually contributes, confirmed by reading the real function's source, not paraphrased from what it's assumed to do: - Sources --> Function["One Node-RED function
~104KB source"] - Function --> Board["SOC Board
client-rendered"] +| Source | What it actually contributes | +|---|---| +| Wazuh indexer | 7-day findings, categorized: ClamAV, vulnerabilities, rootkit/anomaly, authentication, other | +| Vault | Seal state, active lease/token counts, KV engine counts, token TTL distribution, and root/intermediate CA cert expiry — parsed live from Vault's own `pki/cert/ca` and `pki_int/cert/ca` endpoints on every load, not a cached value | +| Technitium DNS | Query stats, top clients/domains, blocklist state, plus a dedicated "DNS Security Signals" section: forwarder failures (read from the Loki-shipped query log), query-log ingestion lag, next blocklist update time | +| Fleet config-drift audit | *Not* computed by this board's own function — read from Node-RED's shared `fleetAudit` global, populated by a separate ingestion process, covering 4 finding types: untracked stacks, missing declared directories, containers stuck in `Created`, and TZ drift | +| Slack | 12 app-specific channels (the *arr suite, Jellyfin/Emby/Seerr, Kopia, Authentik, Gitea, Netbox, Grafana) mapped to their owning host by a plain lookup table, plus each host's own alert channel | +| Proxmox `cluster/resources` API | The two hypervisor nodes' own CPU/RAM/disk (no Prometheus coverage on bare metal) plus the full running VM/LXC tree per node | + +This is the real function, not a claimed size — one single Node-RED function, not several smaller ones stitched together: + +``` +$ python3 -c " +import json +data = json.load(open('flows.json')) +for n in data: + if n.get('type') == 'function' and n.get('name') == 'Build SOC Board HTML': + print(n['name'], '->', len(n['func']), 'chars') +" +Build SOC Board HTML -> 104443 chars ``` ## Why one function instead of native Dashy widgets @@ -40,16 +42,18 @@ A top row shows a 6-tier infrastructure dependency ladder (mirroring the trust-b ## Acknowledge mechanism: client-side, no backend -```mermaid -flowchart LR - Finding["Finding
stable content-derived key"] --> Ack["User acknowledges"] - Ack --> Storage["Browser localStorage
flat map, per-browser"] - Storage --> Recompute["Live re-derive:
badges, issue strip, gauges"] - Recompute -.never touches.-> Upstream["Wazuh / Slack / any
upstream source"] +![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) + +This is the real key format and storage, confirmed directly against the function source, not a description of the design: + +``` +const key = `${hostId}::${group}::${it.title}`; +... +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 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). +> 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 @@ -58,7 +62,7 @@ flowchart LR > - Embedding via `fetch` + `innerHTML` means injected `