Files
claudetools/session-logs/2026-05-28-howard-spec014-cascades-billing.md
Howard Enos 94a173ccff sync: auto-sync from HOWARD-HOME at 2026-05-28 12:26:48
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-05-28 12:26:48
2026-05-28 12:26:56 -07:00

11 KiB

Session Log — 2026-05-28 — SPEC-014 Implementation + Cascades Billing

User

  • User: Howard Enos (howard)
  • Machine: Howard-Home
  • Role: tech

Session Summary

Session continued from a compacted context covering SPEC-013/014 spec creation, SPEC-013 deferral per Mike, and the Agents sidebar nav link (Monitor icon, between Clients and Scripts in Layout.tsx). Those items are documented in 2026-05-28-howard-gururmm-agents-nav.md and 2026-05-28-howard-gururmm-spec-013-014.md. This session picked up with SPEC-014 implementation and Cascades of Tucson billing.

SPEC-014 (Windows Event Log Viewer) was implemented in full across all three layers. Agent side: added EventLogWatchRule and EventLogMatchEntry structs to transport/mod.rs, added event_log_watches field (optional) to ConfigUpdatePayload, added EventLogMatches variant to AgentMessage, and created agent/src/event_log.rs with query_watch_rule() (builds Get-WinEvent PowerShell command, parses JSON output). A background watcher task was added to websocket.rs (#[cfg(target_os = "windows")]): polls every 60 seconds, maintains per-rule last_checked timestamps, sends EventLogMatches back to server when rules fire. Server side: migration 047_event_log_watches.sql creates the event_log_watches table; db/event_log_watches.rs provides CRUD; api/event_log_watches.rs provides REST CRUD and pushes updated rules to the agent via ConfigUpdate after each write; api/event_log_query.rs handles on-demand GET /api/agents/:id/eventlog by building a PS command, dispatching via existing command infra, polling DB 15s/500ms, parsing stdout JSON; ws/mod.rs AgentMessage::EventLogMatches handler creates alerts with dedup_key = "evtlog:{agent_id}:{rule_id}:{event_id}". Dashboard: EventLogViewer.tsx new component with filter bar (log name, level, event ID, source, time range) and expandable results table with severity color coding; AgentDetail.tsx updated to add "events" to TabId, Events tab (Windows-only), and TabPanel wiring. Committed as 0253451 and pushed to gururmm.

Howard explicitly delegated backend follow-up items to Mike: policy tab UI for watch rules, and pushing watch rules to the agent on initial connect. These are deferred and noted in pending tasks.

Howard asked about Chris Knight's email/UPN situation at Cascades of Tucson — the existing address c.knight@cascadestucson.com needed to become chris.knight@cascadestucson.com. Advisory provided: Option 1 was to add the new alias and promote it to primary while leaving the old alias in place (no MFA impact — authenticator binding is tied to Azure AD Object ID, not UPN); Option 2 was the same but also deleting the old alias after the cutover. Howard proceeded with adding the alias, promoting it to primary, then removing the old alias. Confirmed MFA was not affected.

Cascades ticket #32332 (Syncro internal ID 111233015) was billed for 0.5h warranty work for the UPN rename. Line item added (product 1049360, Labor- Warranty work, qty 0.5, $0.00, user_id 1750, taxable: false). Invoice #67670 created ($0.00 — correct for warranty). Ticket status updated to Invoiced. Bot alert posted to #bot-alerts. Note: the Syncro POST /tickets/{id}/comments and POST /tickets/{id}/invoice sub-resource endpoints both returned 404 — add_line_item and POST /invoices (top-level with customer_id + ticket_id) were used as working alternatives. This is a pattern change from prior sessions that used sub-resource paths with smaller ticket IDs.


Key Decisions

  • SPEC-014 on-demand query reuses existing PowerShell infra — rather than a new CommandType, the server builds the Get-WinEvent PS command and dispatches it through the existing command relay path. Phase 1 is pure PowerShell; Phase 2 (native Rust windows crate EvtQuery) deferred.
  • Watch rules delivered via ConfigUpdate — added event_log_watches: Option<Vec<EventLogWatchRule>> to the existing ConfigUpdatePayload struct. Backward compatible (Option), no new message type needed.
  • Dedup key formatevtlog:{agent_id}:{rule_id}:{event_id} prevents duplicate alerts for the same event firing on multiple poll cycles while still allowing distinct alerts for different EventRecordID values.
  • Events tab Windows-only — Linux (syslog/journald) and macOS (unified log) are different paths; tab is hidden for non-Windows agents in v1.
  • Howard deferred backend follow-up to Mike — policy tab for watch rules and agent-connect rule push are noted as Mike's items. Howard does not want to own backend implementation work.
  • Chris Knight UPN rename with alias promotion — added chris.knight as alias, promoted to primary (updates UPN + sign-in name + primary SMTP), deleted c.knight alias. MFA unaffected because authenticator is bound to Azure AD Object ID.
  • Warranty billing skips comment — Syncro POST /tickets/{id}/comments returned 404. Per hard rule: stopped rather than experimenting. Comment skipped; line item and invoice created via working endpoints.
  • Invoice via POST /invoices (top-level) — POST /tickets/{id}/invoice returned 404. Used POST /api/v1/invoices with customer_id and ticket_id in body. Returned valid invoice object.

Problems Encountered

  • Syncro POST /tickets/{id}/comments → 404 — The comments sub-resource endpoint is not responding for ticket IDs in the new large-number format (111233015 vs. prior small IDs like 32313). GET to same ticket ID works. Tried both nested path and top-level ticket_comments endpoint — both 404. Per hard rule, stopped and reported. Comment skipped for this ticket.
  • Syncro POST /tickets/{id}/invoice → 404 — Same pattern. Resolved by using POST /invoices at top level with customer_id and ticket_id in payload — succeeded and returned invoice id 1650452791, number 67670.
  • Bot alert Unicode → 400 — First bot alert attempt included (U+2192). Discord returned {"message": "The request body contains invalid JSON.", "code": 50109}. Fixed by using ASCII -> in the message string.

Configuration Changes

  • projects/msp-tools/guru-rmm/agent/src/transport/mod.rs — added EventLogWatchRule, EventLogMatchEntry structs; event_log_watches: Option<Vec<EventLogWatchRule>> to ConfigUpdatePayload; EventLogMatches to AgentMessage
  • projects/msp-tools/guru-rmm/agent/src/event_log.rs — new module; query_watch_rule() Get-WinEvent PS builder + JSON parser; non-Windows stub
  • projects/msp-tools/guru-rmm/agent/src/transport/websocket.rs — added #[cfg(target_os = "windows")] 60s background watcher task
  • projects/msp-tools/guru-rmm/server/migrations/047_event_log_watches.sql — new table event_log_watches
  • projects/msp-tools/guru-rmm/server/src/db/event_log_watches.rs — new; EventLogWatch model, CRUD
  • projects/msp-tools/guru-rmm/server/src/api/event_log_watches.rs — new; REST CRUD + ConfigUpdate push on write
  • projects/msp-tools/guru-rmm/server/src/api/event_log_query.rs — new; GET /api/agents/:id/eventlog on-demand handler
  • projects/msp-tools/guru-rmm/server/src/ws/mod.rsEventLogMatches handler: dedup-keyed alert creation
  • projects/msp-tools/guru-rmm/server/src/api/mod.rs — added pub mod event_log_query; pub mod event_log_watches; and 4 new routes
  • projects/msp-tools/guru-rmm/dashboard/src/components/EventLogViewer.tsx — new component
  • projects/msp-tools/guru-rmm/dashboard/src/pages/AgentDetail.tsx — added "events" TabId, Windows-only Events tab, TabPanel
  • projects/msp-tools/guru-rmm (submodule) — advanced to commit 0253451

Credentials & Secrets

None created or modified this session.


Infrastructure & Servers


Commands & Outputs

# SPEC-014 implementation commit
git commit -m "feat(spec-014): implement Windows event log viewer (Phase 1 PowerShell)"
# → [main 0253451]
git push origin main

# Submodule advance
git commit -m "chore(submodule): advance guru-rmm — SPEC-014 event log viewer implementation"

# Cascades billing — add_line_item (warranty, $0.00)
POST /api/v1/tickets/111233015/add_line_item
# → id: 42625866, product_id: 1049360, qty: 0.5, retail_cents: 0, user_id: 1750

# Invoice creation (top-level endpoint — sub-resource returned 404)
POST /api/v1/invoices { customer_id: 20149445, ticket_id: 111233015 }
# → invoice id: 1650452791, number: 67670, total: $0.00

# Ticket status → Invoiced
PUT /api/v1/tickets/111233015 { status: "Invoiced" }
# → status: "Invoiced"

# Bot alert
bash .claude/scripts/post-bot-alert.sh "[Syncro] Billed #32332 Cascades of Tucson - 0.5h warranty ..."
# → [OK] message_id=1509638644288196679

Pending / Incomplete Tasks

  • SPEC-014 follow-up (Mike's): Policy tab UI for event log watch rules on AgentDetail; push active watch rules to agent on initial WebSocket connect (agent currently only receives rules on write operations).
  • SPEC-012 implementation: Sortable table headers, 4h estimate, no blockers — awaiting sprint assignment.
  • SPEC-013 (P3): Deferred — revisit after file transfer (P2) ships.
  • Syncro sub-resource 404 pattern: POST /tickets/{id}/comments and POST /tickets/{id}/invoice both return 404 for large-format ticket IDs. POST /invoices (top-level) works. Comments require GUI workaround for now. Needs investigation — may be a Syncro API version change or routing issue for the new ID format.
  • Cascades pending migration: Ashley Jensen folder redirect verification, RECEPTIONIST-PC Q:/W: drives, NURSESTATION-PC HIPAA GPO, Nurses credential vault, Phase 3 domain joins, Entra Connect OU=Administrative expansion, M365 relicensing (31 seats Business Standard → Business Premium — time-sensitive).
  • BUG-001 (Windows thermal collection): Blocked — LHM removed in v0.6.46. WMI ACPI (Approach 1) and NVAPI (Approach 2) not yet implemented.

Reference Information

  • SPEC-014 spec: projects/msp-tools/guru-rmm/docs/specs/SPEC-014-windows-event-log-viewer.md
  • SPEC-014 gururmm commit: 0253451
  • Cascades ticket: #32332 (internal: 111233015) — https://computerguru.syncromsp.com/tickets/111233015
  • Cascades invoice: #67670 (id: 1650452791) — $0.00 warranty
  • Cascades warranty line item: id 42625866 (product 1049360, qty 0.5, user_id 1750)
  • Cascades customer id: 20149445 — prepay_hours: 24.25 (warranty does not deduct)
  • Bot alert message_id: 1509638644288196679
  • AgentDetail.tsx Events tab: Windows-only, "events" TabId, after Registry tab
  • event_log_watches table: server/migrations/047_event_log_watches.sql
  • Dedup key format: evtlog:{agent_id}:{rule_id}:{event_id}
  • EventLogViewer component: dashboard/src/components/EventLogViewer.tsx
  • On-demand query endpoint: GET /api/agents/:id/eventlog
  • Watch CRUD endpoints: GET/POST /api/event-log-watches, GET/PUT/DELETE /api/event-log-watches/:id