14 KiB
GuruRMM — Role-Aware Offline Alerting + Alert Ignore/Mute (+ MSP360 API probe, Jupiter VM diag)
User
- User: Mike Swanson (mike)
- Machine: GURU-5070
- Role: admin
Session Summary
Shipped two GuruRMM alerting features end-to-end and investigated an MSP360 API
capability question, then diagnosed an unrelated Unraid VM network fault. After the
morning backup-alert cleanup (separate log), Mike asked whether the MSP360 API could
delete plans / trigger backups / configure storage for the three console follow-ups.
Probed api.mspbackups.com with the vaulted Provider token: it is monitoring-only
(Companies/Users/Monitoring, GET; every management path 404s; OPTIONS confirms
read-only). The agent-CLI fallback also failed -- the white-labeled MSP360 agent on
SERVER has no cbb.exe at any standard path. Concluded the three items stay
MSP360-console tasks and filed them as coord todos for Mike.
Built role-aware offline alerting + correlated mass-offline detection (spec
role-aware-offline-alerting). Servers offline are incidents; workstations offline
are routine. Implemented server-side (Tasks 1-5): migration 054 role_override
column + a shared agent_role classifier delegating to the canonical
agent_is_server; OfflineAlertingConfig in the policy JSONB; a new scheduled
offline-sweep evaluator generating server-only agent_offline alerts plus site
(>=50% + >=3) and fleet (>=10) mass_offline_* aggregates; a warm-up restart guard;
and PUT /api/agents/:id/role-override. Code Review REJECTED the first cut for a
CRITICAL defect in the spec's own restart guard (last_seen < started_at
permanently disabled detection in steady state because last_seen advances on every
heartbeat); fixed by making the warm-up window the sole guard. Re-review APPROVED.
Then the dashboard unit (Tasks 6-7): role-aware triage (offline servers individual +
elevated; offline workstations collapsed into a quiet "N workstations offline"
roll-up) and the role-override control on the agent detail page; plus a small server
DTO fix so GET /api/agents/:id returns role_override. Verified live: a real
offline server (WIN-TG2STMODJG8, "Windows Server 2019 Standard Evaluation",
auto-classified via os_name) fired agent_offline; zero false mass-offline despite
~55 chronically-offline agents; restart guard held across deploys.
Built alert ignore/mute (perma-silence) (spec alert-mute). Distinct from
ack/resolve, which only quiet the current cycle: a mute keyed on dedup_key
suppresses a recurring condition until un-ignored, with a required reason. Server
unit (Tasks 1-4): migration 055 alert_mutes table + muted status; an
is_dedup_muted gate inserted into the universal create_or_update_alert AND the
one create_check_alert bypass so muted conditions write status='muted' (never
active, never email); transactional mute_condition/unmute_condition;
POST /api/alerts/:id/mute (reason required -> 400) and /unmute. Code Review
APPROVED (the muted gate is a top-of-function early return, so the active path is
byte-for-byte unchanged for normal alerts). Verified live against WIN-TG2STMODJG8's
re-firing agent_offline: mute -> muted, survived a full offline sweep without
re-firing, unmute -> active. The dashboard unit (Task 5) is NOT yet built.
Finally, diagnosed an Unraid VM network fault on Jupiter (172.16.3.20): the libvirt
domain "Windows Server 2016" (guest hostname ACG-DWP-X-BB) had no LAN. Found the
host side healthy (vnet8 bridged to br0, forwarding, receiving LAN broadcast), and
the guest holding APIPA 169.254.157.152 with no gateway -- its single e1000 NIC is
DHCP-enabled but not getting a lease from pfSense (172.16.0.1). Paused for Mike's
call on DHCP-vs-static before changing the guest.
Key Decisions
- Offline classification = auto (
os_product_type2/3, elseos_name/os_version~/server/i) + a manualrole_overridecolumn.os_product_typeis populated on only 16/168 agents, soos_nameis the workhorse signal; inventory-less offline servers (SIF-SERVER, Server2013) auto-classify as workstations and need the manual override -- Mike held on tagging them. - Mass/aggregate alerts pin to a representative offline agent with a site/fleet
dedup_keyrather than makingalerts.agent_idnullable (avoids a rippling migration across every alert path). - Restart guard = warm-up window only (max grace after boot). Dropped the broken
last_seen < started_atclause. Individual server alerts fire independently of the site-outage alert (so a still-down server keeps paging after an outage clears). - Alert mute keyed on
dedup_key(universal recurring-condition id, always set); permanent until un-ignored; stays muted on severity escalation. Gate placed at the two creation choke points so it is universal across every alert type. - MSP360 console items stay manual: the Provider API token is monitoring-tier only; no REST path for plan delete / run / storage config at our access level.
Problems Encountered
- CRITICAL restart-guard defect (my spec error):
last_seen < started_atsilently disabled offline detection in steady state. Caught in Code Review; fixed to warm-up-only and re-reviewed. The bug-enshrining unit test was rewritten. - Split-brain classifier: the new
agent_rolediverged from the existingagent_is_server. Unified by delegating to the canonical fn (threadedos_version). GET /api/agents/:idomittedrole_override(returnsAgentResponse, notAgentWithDetails), so the override card rendered blind. Fixed by adding the field to the baseAgent/AgentResponseDTOs (allAgentSELECTs useSELECT *).- Orphaned offline alerts + per-agent policy N+1 in the sweep: replaced scattered resolves with one authoritative resolve-except pass; read per-agent grace only for servers; mass membership uses global grace/window.
- MSP360 white-label: no
cbb.exeon SERVER, so the agent-CLI automation route for the backup console tasks was not viable without per-box fingerprinting. - Submodule gitlink: detached to the pinned commit before
/saveso the session-log commit does not fold a gitlink bump.
Configuration Changes
GuruRMM submodule (azcomputerguru/gururmm), all merged to main:
server/migrations/054_agent_role_override.sql(new) --role_overridecolumn.server/migrations/055_alert_mutes.sql(new) --alert_mutestable + partial unique indexON dedup_key WHERE active.server/src/alerts/offline.rs(new) -- offline sweep + mass detection.server/src/db/alerts.rs--AlertStatus::Muted;is_dedup_muted/mute_condition/unmute_condition; muted gate increate_or_update_alert;create_or_update_alerttitle/message/severity refresh (from morning).server/src/alerts/check_alerts.rs-- mute gate + notify suppression.server/src/db/agents.rs--role_overrideonAgent/AgentResponse/AgentWithDetails;agent_role+set_agent_role_override.server/src/db/policies.rs,server/src/policy/{effective,merge}.rs--OfflineAlertingConfig+ merge.server/src/main.rs-- offline-sweep spawn (60s).server/src/api/{alerts,agents,mod}.rs-- mute/unmute + role-override endpoints.dashboard/src/lib/agentRole.ts(new),dashboard/src/components/ExceptionStream.tsx,dashboard/src/pages/AgentDetail.tsx,dashboard/src/api/client.ts-- triage + override control.- specs/
role-aware-offline-alerting/and specs/alert-mute/(new spec folders).
Credentials & Secrets
No new secrets. MSP360 Provider API: vault msp-tools/msp360-api.sops.yaml
(credentials.login / credentials.password); base https://api.mspbackups.com,
POST /api/Provider/Login -> access_token; monitoring-only tier. GuruRMM API:
vault infrastructure/gururmm-server.sops.yaml. Jupiter: vault
infrastructure/jupiter-unraid-primary.sops.yaml (root@172.16.3.20:22, key auth
works from GURU-5070).
Infrastructure & Servers
- GuruRMM API/server: 172.16.3.30:3001 (Linux VM on Jupiter). Dashboards rmm-beta / rmm.azcomputerguru.com (shared API serves both).
- Jupiter Unraid: 172.16.3.20, root:22, Unraid 6.12.85. VMs via virsh; bridge
br0(uplink eth2),172.16.3.20/22. VM "Windows Server 2016" = guestACG-DWP-X-BB, vnet8/br0/e1000, MAC 52:54:00:d4:8e:59, APIPA 169.254.157.152 (no DHCP lease). - Office LAN 172.16.0.0/22; pfSense 172.16.0.1 (router + DNS + DHCP).
Commands & Outputs
- Offline alerting commits:
f1cdf5d,30e4f23(fix),21d63bd(DTO),3eedf91(dashboard). Alert-mute:29c405e(spec),a120e71(server). - Live mute verify: empty-reason 400; mute -> status=muted; after a 60s sweep the muted alert did NOT re-fire active (count=0); unmute -> active.
- Jupiter diag:
virsh domiflist 9(vnet8/br0/e1000);virsh domifaddr 9 --source agent-> 169.254.157.152; guest-execipconfig /all-> DHCP Enabled: Yes, APIPA, no gateway.
Pending / Incomplete Tasks
- alert-mute dashboard (Task 5) -- NOT started. Ignore button + required-reason prompt + Muted filter + Un-ignore, on the alerts page AND the agent Alerts tab; muted rows show Un-ignore instead of Ack/Resolve. (Mike: "then continue" -> do this next.) Plus alert-mute Task 6 (roadmap) + Task 7 (final doc).
- offline alerting -- Task 8 (roadmap entry) outstanding; classification gap: tag SIF-SERVER / Server2013 (and WIN-TG2STMODJG8 if it should be a workstation) via role_override -- held for Mike.
- Jupiter VM -- decide DHCP vs static for ACG-DWP-X-BB; if DHCP, run
ipconfig /renewvia guest agent; if static, set the intended IP. Paused for Mike. - MSP360 console (Mike-side todos): delete SERVER's Nov-2024 plan; AD1 full backup for retention; LAB-Becky storage-or-delete.
Reference Information
- Commits (main):
f1cdf5d,30e4f23,21d63bd,3eedf91,29c405e,a120e71. - Specs:
projects/msp-tools/guru-rmm/specs/role-aware-offline-alerting/,.../specs/alert-mute/. - MSP360 PlanType map: 3=Files,7=SQL,8=Restore,11=Image,13=Consistency,16=HyperV.
- New alert types:
agent_offline,mass_offline_site,mass_offline_fleet; new statusmuted; new tablesalert_mutes; new columnsagents.role_override. - Test box: WIN-TG2STMODJG8 agent id b6c715df-09fe-4e97-b09a-82a1b535f041 (offline eval server, used for live verification).
Update: 00:44 PT — alert-mute dashboard shipped, beta->prod promotion, MSI dedup cleanup, parked design
Completed since the initial save
- Alert ignore/mute dashboard (Task 5) — shipped + deployed (commit
63d7c5d). Reused the existing Radix Dialog for the required-reason prompt; sharedAlertRowso both the alerts page and the agent Alerts tab get Ignore/Un-ignore + the Muted filter; muted rows show Un-ignore (not Ack/Resolve) + reason/who/when; status badge labelsmutedas "Ignored". Code Review APPROVED;npm run buildclean. The alert-mute feature is now complete end-to-end (servera120e71+ dashboard63d7c5d). - Roadmap entries (commit
5f1d9f0): both offline alerting and alert ignore/mute added to FEATURE_ROADMAP.md Alerting section; specs' roadmap tasks marked DONE. - Dashboard beta -> production promotion. Prod (
/var/www/gururmm/dashboard, rmm.azcomputerguru.com) was stuck at the 2026-06-04 build. Ransudo /opt/gururmm/promote-dashboard.sh --confirmon 172.16.3.30 (the sanctioned promote: backs up prod first, keeps 10 backups, rsync beta->prod,--rollbackto undo). Backupdashboard-20260608-000926; prod now byte-identical to beta. This shipped ALL accumulated beta work to prod: this session's offline triage + role-override + alert mute UI, plus other sessions' credential-inheritance mgmt + clickable alert badges. Coord component gururmm/dashboard -> deployed. - MSI BSOD duplicate cleanup. MSI (Safesite/Glendale, agent a685af29...) had 4 BSOD VIDEO_TDR_FAILURE (0x116) alerts, all with
dedup_key = NULL(legacy, from the early-June BSOD implementation before the dedup key was added). Mike had muted one; the other 3 active duplicates could not be spanned by the mute (NULL key falls back to single-row). Resolved the 3 duplicates (final: 0 active, 1 muted "Client to replace unit", 3 resolved). Two resolve calls hit transient HTTP 000; retried clean.
Parked design conversation (NOT approved — captured for later)
A stream-of-thought design discussion produced two parked features, captured in
projects/msp-tools/guru-rmm/docs/PARKED_alert-lifecycle-and-telemetry-cadence.md
(commit 82a7b14) + two coord todos (eb14a4d2, bacc4f12):
- Stateful alert lifecycle + occurrence history (server): one alert per dedup_key spanning all statuses; re-fire reopens only when "substantively different" (severity escalation or re-fire after clear; not per-1%); occurrence count+first/last on the row, dated history via existing agent_events (no new table); ack reopens on substantive change, mute is absolute; server-side per-condition cooldown (~15min default, escalations bypass, recovery always prompt); subsumes BSOD per-bugcheck dedup + mute-across-refire + legacy null-key cleanup. Root cause it fixes: dedup currently matches only status='active', so ack/resolve breaks dedup and spawns duplicates.
- Tiered agent telemetry cadence (agent): per-collector collection intervals (live/on-demand ~5-10s only when watched; standard ~30-60s; slow ~5-15min; daily). Disk consumption (slow) vs disk I/O (fast) are different collectors; fast diagnostics as on-demand/live mode; cadence config in policy, server-pushed; cross-platform scheduler. Larger, separate agent-side feature.
Saved a feedback memory (.claude/memory/feedback_stream_of_thought_design.md): Mike
prefers free-form design conversations; Claude sharpens as a design partner but does
not build until an explicit go, then decomposes into specs.
Still open / parked
- Jupiter VM
ACG-DWP-X-BBno-DHCP (diagnosed, paused for Mike's DHCP-vs-static call; see wiki/systems/jupiter.md). - Offline classification overrides (SIF-SERVER/Server2013/WIN-TG2STMODJG8) — taggable from the agent detail role-override control; held.
- The two parked design features above; MSP360 console todos (3) from the morning.