From e0e3dd0d8253164ef5764249b424192e5a773da5 Mon Sep 17 00:00:00 2001 From: Howard Enos Date: Fri, 3 Jul 2026 17:00:47 -0700 Subject: [PATCH] sync: auto-sync from HOWARD-HOME at 2026-07-03 17:00:12 Author: Howard Enos Machine: HOWARD-HOME Timestamp: 2026-07-03 17:00:12 --- .claude/memory/MEMORY.md | 2 + ...project_av_migration_bitdefender_to_edr.md | 24 +++ .../reference_rmm_deploy_via_screenconnect.md | 30 +++ .claude/scripts/gps-rmm-progress-check.sh | 63 +++++++ errorlog.md | 10 + ...026-07-03-howard-gps-rmm-coverage-audit.md | 73 ++++++++ projects/gps-rmm-audit/targets.json | 37 ++++ projects/gps-rmm-audit/tracker.md | 174 ++++++++++++++++++ wiki/clients/arizona-medical-transit.md | 65 +++++++ 9 files changed, 478 insertions(+) create mode 100644 .claude/memory/project_av_migration_bitdefender_to_edr.md create mode 100644 .claude/memory/reference_rmm_deploy_via_screenconnect.md create mode 100644 .claude/scripts/gps-rmm-progress-check.sh create mode 100644 projects/gps-rmm-audit/session-logs/2026-07/2026-07-03-howard-gps-rmm-coverage-audit.md create mode 100644 projects/gps-rmm-audit/targets.json create mode 100644 projects/gps-rmm-audit/tracker.md create mode 100644 wiki/clients/arizona-medical-transit.md diff --git a/.claude/memory/MEMORY.md b/.claude/memory/MEMORY.md index e2631253..0d3b6675 100644 --- a/.claude/memory/MEMORY.md +++ b/.claude/memory/MEMORY.md @@ -206,3 +206,5 @@ - [Windows won't-boot / offline DISM repair playbook](windows-offline-dism-repair-gotchas.md) — Automatic Repair loop = boot-critical fault (disk/registry/wedged update), NOT shell/appx store corruption (that's a symptom); `FaultyPackageInProgress` + 100s of Install/Uninstall-Pending packages = wedged CU -> RevertPendingActions or clean install. Offline DISM rejects `wim:` source (0x800f082e) -> MOUNT the wim, source `\Windows`. Ventoy breaks WIM mount (0xc1420134) -> use Rufus. 25H2(26200)=24H2(26100)+enablement, so match 26100 media. First hit: Four Paws AvImark #32447. - [365 app suite — authoritative map + consent-drift fix](reference_365_app_suite.md) — full map in `.claude/skills/remediation-tool/references/app-suite.md`; per-tenant consent is NOT uniform (VWP had the app but no SharePoint role). Run `consent-audit.sh ` to detect gaps; fix via adminconsent URL or direct appRoleAssignment grant. - [Remediation-tool has full M365 access (incl. SharePoint)](reference_remediation_tool_365_access.md) — the app suite covers Graph/EXO/Defender/SharePoint; don't declare "no access" on an accessDenied. SharePoint app-only needs a CERT (secret = "Unsupported app only token"); use get-token.sh `sharepoint`/`sharepoint-admin` tiers + CSOM admin API (Graph /admin/sharepoint/settings scope not held). Full map: skill references/app-permissions-and-sharepoint.md. +- [AV migration: Bitdefender -> Datto EDR](project_av_migration_bitdefender_to_edr.md) — retire Bitdefender fleet-wide except Dataforth; end-state per machine = GuruRMM + Datto EDR +- [RMM deploy via ScreenConnect](reference_rmm_deploy_via_screenconnect.md) — push GuruRMM agent to client workstations via SC send-command (SYSTEM), not DC remote-exec (DCOM/schtasks blocked on Win11 clients) diff --git a/.claude/memory/project_av_migration_bitdefender_to_edr.md b/.claude/memory/project_av_migration_bitdefender_to_edr.md new file mode 100644 index 00000000..c7b917fe --- /dev/null +++ b/.claude/memory/project_av_migration_bitdefender_to_edr.md @@ -0,0 +1,24 @@ +--- +name: project_av_migration_bitdefender_to_edr +description: AV strategy — migrate all clients from Bitdefender to Datto EDR, except Glaztech and Dataforth +metadata: + type: project +--- + +Standing AV direction (set by Howard 2026-07-03): ACG is moving endpoint AV/security +from **Bitdefender GravityZone -> Datto EDR** for **all clients EXCEPT Glaztech Industries +and Dataforth Corp** (those two stay on Bitdefender / handled separately). + +**Why:** consolidate on Datto EDR as the security plane; Bitdefender is being retired +fleet-wide (Glaztech + Dataforth are the two exceptions — both have large established +Bitdefender footprints: Glaztech ~242 endpoints, Dataforth managed separately). + +**How to apply:** whenever setting up or reconciling a client's endpoints (e.g. the +GPS->GuruRMM coverage audit), the target end-state per machine is: GuruRMM agent + +Datto EDR agent, and Bitdefender **removed**. Do NOT deploy new Bitdefender coverage. +Use existing Bitdefender inventory only as a discovery source for which machines exist +(its company names carry the Syncro CID `_NNNNN`, handy for mapping). Deploy Datto EDR +via `[[datto-edr]]` (create-group -> mint-key -> deploy-cmd, pushed through `/rmm`). + +Related: GPS->RMM audit tracker `projects/gps-rmm-audit/tracker.md`. Exceptions = Glaztech + +Dataforth (leave their existing AV alone; do not migrate them to EDR in this effort). diff --git a/.claude/memory/reference_rmm_deploy_via_screenconnect.md b/.claude/memory/reference_rmm_deploy_via_screenconnect.md new file mode 100644 index 00000000..fae5ae97 --- /dev/null +++ b/.claude/memory/reference_rmm_deploy_via_screenconnect.md @@ -0,0 +1,30 @@ +--- +name: reference_rmm_deploy_via_screenconnect +description: Best channel to mass-deploy the GuruRMM agent to client workstations = ScreenConnect send-command (not DC remote-exec) +metadata: + type: reference +--- + +**To push the GuruRMM agent onto a client's existing machines, the reliable channel is +ScreenConnect `send-command` (Backstage), NOT remote-exec from the domain controller.** + +Discovered 2026-07-03 deploying to Instrumental Music Center (see +`projects/gps-rmm-audit/tracker.md`). Remote-exec FROM the DC to Win10/11 workstations +fails on default client settings: +- WMI/`Win32_Process` over **DCOM** -> "RPC server unavailable" (DCOM firewalled on clients) +- `schtasks /S` -> connects over SMB but Win11 **rejects the task definition** from an older + (Server 2016) DC ("The request is not supported") +- `New-PSDrive`/`sc.exe` admin-share from SYSTEM context -> access/parse failures +- WinRM is off by default on workstations + +**What works cleanly:** ScreenConnect. ACG endpoints already run the SC agent, and +`send-command` runs on the guest **as SYSTEM** — no credentials, no firewall fight, no +DA-password-in-logs concern. Pattern (via the `[[screenconnect]]` skill): +1. `GetSessionsByName` with the EXACT hostname -> sessionID (no list-all method; must query by exact name). +2. Build the site installer one-liner: `irm 'https://rmm.azcomputerguru.com/install//windows'|iex` (site code from the client's vault `gururmm-site-*.sops.yaml`). +3. Encode it: `powershell -NoProfile -ExecutionPolicy Bypass -EncodedCommand ` (avoids all quoting; no /TR length limit like schtasks). +4. `send-command --session --command "" --confirm`. Online guests install + enroll in ~1-3 min; offline guests QUEUE in SC and install on reconnect. +5. Verify via GuruRMM `/api/agents` (hostname appears under the client, status online). + +Note `iconv` is absent in this Git-Bash — compute the base64 with `py -c "import base64; ..."`. +Related: `[[project_av_migration_bitdefender_to_edr]]` (same channel can push the Datto EDR agent + remove Bitdefender once RMM is on). diff --git a/.claude/scripts/gps-rmm-progress-check.sh b/.claude/scripts/gps-rmm-progress-check.sh new file mode 100644 index 00000000..47b33cd2 --- /dev/null +++ b/.claude/scripts/gps-rmm-progress-check.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# gps-rmm-progress-check.sh — daily GPS->GuruRMM enrollment progress check. +# +# Reads projects/gps-rmm-audit/targets.json (GPS device target per client), +# pulls live GuruRMM /api/agents, computes per-client enrollment gaps, and DMs +# Howard a one-message summary. When every tracked client has met its target it +# reports "COMPLETE" so the scheduled task can be retired. +# +# Usage: +# bash gps-rmm-progress-check.sh # check + DM Howard +# bash gps-rmm-progress-check.sh --dry-run # check + print, no Discord +# +# Registered as a daily Windows scheduled task. Read-only against RMM. +set -u +ROOT="${CLAUDETOOLS_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}" +TARGETS="$ROOT/projects/gps-rmm-audit/targets.json" +DRY=0; [ "${1:-}" = "--dry-run" ] && DRY=1 + +[ -f "$TARGETS" ] || { echo "[ERROR] targets.json not found at $TARGETS" >&2; exit 1; } + +# --- auth + fetch agents --- +eval "$(bash "$ROOT/.claude/scripts/rmm-auth.sh" 2>/dev/null)" >/dev/null +if [ -z "${TOKEN:-}" ] || [ -z "${RMM:-}" ]; then + echo "[ERROR] RMM auth failed" >&2 + bash "$ROOT/.claude/scripts/log-skill-error.sh" "gps-rmm-progress-check" "RMM auth failed" >/dev/null 2>&1 + exit 1 +fi +AGENTS=$(curl -s "$RMM/api/agents" -H "Authorization: Bearer $TOKEN" | tr -d '\000-\037') +[ "${AGENTS:0:1}" = "[" ] || { echo "[ERROR] /api/agents not an array: ${AGENTS:0:100}" >&2; \ + bash "$ROOT/.claude/scripts/log-skill-error.sh" "gps-rmm-progress-check" "GET /api/agents non-array" >/dev/null 2>&1; exit 1; } + +# --- per-client live agent counts (unique hostnames, to ignore dup agent rows) --- +COUNTS=$(echo "$AGENTS" | jq -r '[.[] | {c:.client_name, h:(.hostname|ascii_downcase)}] + | group_by(.c) | map({client:.[0].c, n:( [.[].h] | unique | length )}) | .[] | "\(.n)\t\(.client)"') + +# --- compare targets vs live --- +REPORT=""; DONE_ALL=1; TOTAL_TARGET=0; TOTAL_HAVE=0; GAP_CLIENTS=0 +while IFS=$'\t' read -r TGT NAME BUCKET; do + [ -z "$NAME" ] && continue + HAVE=$(echo "$COUNTS" | awk -F'\t' -v n="$NAME" '$2==n{print $1; found=1} END{if(!found)print 0}' | head -1) + HAVE=${HAVE:-0} + TOTAL_TARGET=$((TOTAL_TARGET + TGT)) + TOTAL_HAVE=$((TOTAL_HAVE + HAVE)) + if [ "$HAVE" -lt "$TGT" ]; then + DONE_ALL=0; GAP_CLIENTS=$((GAP_CLIENTS+1)) + GAP=$((TGT - HAVE)) + STATE=$([ "$HAVE" -eq 0 ] && echo "NO ORG/AGENTS" || echo "short") + REPORT="${REPORT} - ${NAME}: ${HAVE}/${TGT} in RMM (${STATE}, gap ${GAP}) [${BUCKET}]\n" + fi +done < <(jq -r '.clients[] | "\(.target)\t\(.client)\t\(.bucket)"' "$TARGETS") + +DATE=$(date +%Y-%m-%d) +if [ "$DONE_ALL" -eq 1 ]; then + MSG="**GPS->RMM enrollment: COMPLETE (${DATE})** All tracked GPS clients meet their RMM device target (${TOTAL_HAVE}/${TOTAL_TARGET}). You can retire the daily check task (schtasks /Delete /TN GPS-RMM-Progress)." +else + MSG="**GPS->RMM enrollment check ${DATE}** — ${TOTAL_HAVE}/${TOTAL_TARGET} devices in RMM; ${GAP_CLIENTS} clients still short:\n${REPORT}(Glaz-Tech excluded pending billing review. Source: projects/gps-rmm-audit/targets.json)" +fi + +if [ "$DRY" -eq 1 ]; then + echo -e "$MSG" + exit 0 +fi +echo -e "$MSG" | bash "$ROOT/.claude/scripts/discord-dm.sh" howard diff --git a/errorlog.md b/errorlog.md index a095673a..1a40d18e 100644 --- a/errorlog.md +++ b/errorlog.md @@ -29,6 +29,16 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure · 2026-07-03 | GURU-5070 | agy | gemini returned no response (empty after 3 attempts) [ctx: mode=review err= at process.processTicksAndRejections (node:internal/process/task_queues:104:] (x2) +2026-07-03 | Howard-Home | rmm-search/gps-audit | [correction] RMM org 'Russo, Steve' was mis-named at setup — it IS Russo Law Firm (Steve Russo = owner, Shannon Trionfo = main contact), not a separate resident. Renamed org to 'Russo Law Firm' via PUT /api/clients/:id. Lesson: an RMM org named after a person may be a mislabeled business; verify owner/contact against Syncro before treating as residential. Root cause: client created without a skill/standard naming step. + +2026-07-03 | Howard-Home | rmm/av-removal | [friction] step1 PS timed out at 180s (avastclear download + mb5uns -Wait); split into async download + separate MB uninstall [ctx: host=DESKTOP-5JK4EGI] + +2026-07-03 | Howard-Home | ps-encoded | encode produced empty output [ctx: src=.claude/skills/_tmp_win_recon.ps1] + +2026-07-03 | Howard-Home | rmm/onboarding-diagnostic | probe timed out (240s, exit -1) on slow VM endpoint DESKTOP-5JK4EGI; fell back to lean targeted recon [ctx: host=DESKTOP-5JK4EGI kind=VM] + +2026-07-03 | Howard-Home | rmm-diagnose | could not extract valid diagnostic JSON from probe output [ctx: host=DESKTOP-5JK4EGI status=failed exit=-1] + 2026-07-03 | Howard-Home | remediation-tool/graph | [friction] auditLogs/signIns $filter (userId/UPN) hangs HTTP000 on Cascades tenant; large $top also hangs. Fix: small unfiltered $top=50, filter client-side 2026-07-03 | Howard-Home | rmm/ps-encoded | [friction] iconv missing in Git Bash so ps-encoded.sh cannot build UTF-16LE -EncodedCommand. Fix: py -c base64.b64encode(text.encode('utf-16-le')) diff --git a/projects/gps-rmm-audit/session-logs/2026-07/2026-07-03-howard-gps-rmm-coverage-audit.md b/projects/gps-rmm-audit/session-logs/2026-07/2026-07-03-howard-gps-rmm-coverage-audit.md new file mode 100644 index 00000000..85a46481 --- /dev/null +++ b/projects/gps-rmm-audit/session-logs/2026-07/2026-07-03-howard-gps-rmm-coverage-audit.md @@ -0,0 +1,73 @@ +## User +- **User:** Howard Enos (howard) +- **Machine:** Howard-Home +- **Role:** tech + +## Session Summary + +Ran a full audit of every Syncro business paying for GPS (Guru Protection Service) and reconciled it against GuruRMM coverage. Started by identifying the 44 GPS clients (40 active, 4 paused) from Syncro recurring schedules, then built a machine-readable reconciliation: Syncro billed GPS device counts (the "should have") vs live GuruRMM `/api/agents` (the reality), cross-checked against Datto EDR and Bitdefender for AV/backup context. Produced a durable tracker at `projects/gps-rmm-audit/tracker.md` splitting clients into Bucket A (7 count-match), Bucket B (8 present-but-short), and Bucket C (25 with no RMM org). + +Bucket A was verified end-to-end across all layers: machine reconciliation, backups (B2/MSP360), AV (Datto EDR + Bitdefender — coverage is split across both tools), vault entries, and wiki (created the missing Arizona Medical Transit article). Surfaced several findings: Dataforth +8 machines over billed, Cascades duplicate agent + unbilled backup bucket, Len's LAB-SVR offline since Jun 18, AMT billed backup with no B2 destination. Backup billing mismatches were flagged and held for Winter per Howard's instruction (an early DM to Winter was retracted via the bot). + +Fixed a data error in RMM: the org "Russo, Steve" was mislabeled — it is Russo Law Firm (Steve Russo owner, Shannon Trionfo main contact); renamed via `PUT /api/clients/:id`. Captured a standing AV strategy: migrate Bitdefender -> Datto EDR for all clients except Glaztech and Dataforth. + +Bucket B reconciled with a RMM-vs-Datto-vs-Bitdefender coverage matrix, cleanly splitting into real deploy gaps (IMC, Safesite, Horseshoe, Grabb, QWM) and billing flags (Jimmy, Stamback, Glaz-Tech). Built and registered a daily Windows scheduled task (GPS-RMM-Progress, 8:07am) that compares live RMM counts to GPS targets and DMs Howard the remaining gaps until complete; verified working (baseline 46/189 devices, 32 clients short). + +Executed the IMC deploy as the template. Determined the true fleet (~22 active AD/Bitdefender machines vs 1 in RMM). Remote-exec from the DC failed on Win10/11 client defaults (DCOM firewalled, schtasks version-rejected by Win11, WinRM off, SYSTEM can't create GPOs, SSH route not up). The working channel was ScreenConnect send-command (runs as SYSTEM on the guest). Pushed the site installer to 20 of 21 targets; RMM IMC agents climbed from 1 to 12 (online now, offline queued in SC). Saved the deploy pattern as reusable memory. + +## Key Decisions +- Built a machine-readable `targets.json` rather than parsing the markdown tracker daily (fragile). +- AV coverage must be checked in BOTH Datto EDR and Bitdefender before declaring a gap — coverage is split (Datto for big clients, Bitdefender for small). +- Bitdefender inventory is now a discovery source only (which machines exist), not a coverage target, given the Bitdefender->Datto EDR migration (except Glaztech + Dataforth). +- Daily reminder implemented as a LOCAL Windows scheduled task (has vault/RMM/Discord creds) rather than a cloud routine (which lacks vault access). +- IMC deploy via ScreenConnect, not GPO — GPO's only advantage (no stored cred) evaporated once SYSTEM proved unable to create GPOs, and ScreenConnect send-command runs as SYSTEM with no creds at all. +- Any DA-password use through the RMM channel was immediately scrubbed via `DELETE /api/commands/:id`. + +## Problems Encountered +- RMM org "Russo, Steve" mislabeled -> renamed to Russo Law Firm (owner/contact confirmed by Howard). +- Winter DM sent before Howard said "hold until verified" -> deleted from her DM channel via the bot (HTTP 204). +- Remote agent deploy from the DC failed across four methods (New-PSDrive, WMI/DCOM, schtasks/S, sc.exe) due to Win11 client firewall/version defaults -> pivoted to ScreenConnect send-command, which worked. +- `iconv` absent in Git-Bash -> computed base64 (UTF-16LE) for the encoded command via `py -c`. +- `schtasks /TR` has a 261-char cap -> used bare `powershell -enc` instead of the full inline command. + +## Configuration Changes +- Created `projects/gps-rmm-audit/tracker.md` — master audit tracker/checklist. +- Created `projects/gps-rmm-audit/targets.json` — machine-readable enrollment targets. +- Created `.claude/scripts/gps-rmm-progress-check.sh` — daily progress check + Discord DM. +- Created `wiki/clients/arizona-medical-transit.md` — new client wiki article. +- Created `.claude/memory/project_av_migration_bitdefender_to_edr.md` + `.claude/memory/reference_rmm_deploy_via_screenconnect.md` (+ MEMORY.md index lines). +- Registered Windows scheduled task `GPS-RMM-Progress` (daily 8:07am, Howard-Home). +- RMM: renamed client `b83b0c29-81e6-4ce4-98ec-74639998d2ce` "Russo, Steve" -> "Russo Law Firm". +- RMM: enrolled ~11 new IMC agents (deploy in progress). +- errorlog.md: one [correction] entry (Russo). + +## Credentials & Secrets +- No new credentials created. Used existing vault entries: `clients/imc/imc1.sops.yaml` (IMC\guru Domain Admin — used transiently for DC deploy attempts, scrubbed from RMM logs), `clients/imc/gururmm-site-main.sops.yaml` (site code INNER-BRIDGE-8354). +- Note: IMC1 SSH `password-fallback` is stored in `clients/imc/imc1.sops.yaml` (vault) — not reproduced here. + +## Infrastructure & Servers +- GuruRMM API: http://172.16.3.30:3001 (auth via vault `infrastructure/gururmm-server.sops.yaml`). +- IMC1 = Primary DC, domain IMC.local, 192.168.0.2, Server 2016. GuruRMM client_id 4fb591e7-... / agent 88cbf7c0-abfa-4f12-846c-96274f718bff. IMC RMM site IMCMain / INNER-BRIDGE-8354. +- IMC reachable only via Tailscale subnet router pfsense-2 (100.119.153.74) advertising 192.168.0.0/24 — route not currently accepted on Howard-Home. +- ScreenConnect: https://computerguru.screenconnect.com (RESTful API Manager ext) — deploy channel for IMC. +- Datto EDR orgs: Instrumental Music Center not a distinct org (agents land in Default RMM Org); Dataforth 51, Cascades 34, Safesite 48, Horseshoe 6, Glaztech 5. + +## Commands & Outputs +- Deploy one-liner (per client, site-coded): `irm 'https://rmm.azcomputerguru.com/install//windows'|iex` — pushed via ScreenConnect send-command as `powershell -NoProfile -ExecutionPolicy Bypass -EncodedCommand `. +- Daily check: `bash .claude/scripts/gps-rmm-progress-check.sh [--dry-run]`. Baseline: 46/189 devices in RMM, 32 clients short. +- RMM command scrub: `DELETE /api/commands/:id` -> HTTP 204. + +## Pending / Incomplete Tasks +- IMC: ~8 offline machines queued in SC (install on reconnect); IMC-L1-GRAPHICS has no SC session (stale, handle separately). Verify final 20/20 via daily check. +- Bucket B remaining real-deploy clients: Safesite (~6+), Horseshoe (~5-8), Grabb & Durando (~3), Quantum Wealth (~1) — same ScreenConnect channel. +- Bucket B billing flags (Jimmy, Stamback, Glaz-Tech) — document for Winter/Mike, no action. +- Bucket C: 25 clients with no RMM org — onboard + deploy. +- AV migration (Bitdefender -> Datto EDR, except Glaztech + Dataforth) — after RMM everywhere. +- Backup billing flags (AMT/Cascades/Len's) — send Winter the full verified list once complete. +- Task #4: confirm Glaz-Tech 159 GPS billing anomaly with Mike. + +## Reference Information +- Tracker: `projects/gps-rmm-audit/tracker.md`; targets: `projects/gps-rmm-audit/targets.json`. +- Memory: `project_av_migration_bitdefender_to_edr`, `reference_rmm_deploy_via_screenconnect`. +- Syncro base: https://computerguru.syncromsp.com/api/v1. GuruRMM install page: https://rmm.azcomputerguru.com/install/. +- Scheduled task: `GPS-RMM-Progress` (daily 8:07am Howard-Home). diff --git a/projects/gps-rmm-audit/targets.json b/projects/gps-rmm-audit/targets.json new file mode 100644 index 00000000..a76e5187 --- /dev/null +++ b/projects/gps-rmm-audit/targets.json @@ -0,0 +1,37 @@ +{ + "_comment": "GPS->RMM enrollment targets. Daily check compares live GuruRMM agent count per client_name to 'target' (GPS devices billed). client = expected RMM client_name (set at onboarding for bucket C). Glaz-Tech excluded (159 billing anomaly, pending Mike). Updated 2026-07-03.", + "clients": [ + {"client": "Instrumental Music Center", "cid": 7088508, "target": 20, "bucket": "B"}, + {"client": "Safesite", "cid": 26563106, "target": 37, "bucket": "B"}, + {"client": "Horseshoe Management", "cid": 625269, "target": 9, "bucket": "B"}, + {"client": "Grabb & Durando Law Office", "cid": 14232794, "target": 12, "bucket": "B"}, + {"client": "Quantum Wealth Management", "cid": 7088747, "target": 3, "bucket": "B"}, + {"client": "Jimmy Company", "cid": 18560272, "target": 12, "bucket": "B-flag"}, + {"client": "Stamback Septic", "cid": 11513046, "target": 8, "bucket": "B-flag"}, + {"client": "Reliant Well Drilling and Pump Corporate", "cid": 10736261, "target": 9, "bucket": "C"}, + {"client": "Zeus Nestora", "cid": 1196974, "target": 8, "bucket": "C"}, + {"client": "Little Hearts Little Hands", "cid": 1144233, "target": 8, "bucket": "C"}, + {"client": "PUTT LAND SURVEYING, INC.", "cid": 7180175, "target": 7, "bucket": "C"}, + {"client": "Curtis Plumbing", "cid": 416585, "target": 6, "bucket": "C"}, + {"client": "The Prairie Schooner", "cid": 3664974, "target": 5, "bucket": "C"}, + {"client": "Mineralogical Record", "cid": 207770, "target": 5, "bucket": "C"}, + {"client": "T & C Sorensen", "cid": 344886, "target": 4, "bucket": "C"}, + {"client": "MVAN Enterprises Inc", "cid": 29462761, "target": 4, "bucket": "C"}, + {"client": "Ridgetop Group", "cid": 9413367, "target": 3, "bucket": "C"}, + {"client": "Multicultural Counseling Center", "cid": 35483539, "target": 3, "bucket": "C"}, + {"client": "Brett Interiors", "cid": 15726057, "target": 3, "bucket": "C"}, + {"client": "Heieck, Sheila", "cid": 12045942, "target": 3, "bucket": "C"}, + {"client": "The Marc Group", "cid": 869073, "target": 2, "bucket": "C"}, + {"client": "Residential and Renovation Engineering", "cid": 7088403, "target": 2, "bucket": "C"}, + {"client": "Bill Tedards", "cid": 487887, "target": 2, "bucket": "C"}, + {"client": "Janet Altschuler", "cid": 457710, "target": 2, "bucket": "C"}, + {"client": "Business Services of Tucson LLC", "cid": 29338800, "target": 2, "bucket": "C"}, + {"client": "Andy's Mobile Fuel", "cid": 27364453, "target": 2, "bucket": "C"}, + {"client": "Design and Brand Envoys", "cid": 26747288, "target": 2, "bucket": "C"}, + {"client": "Pro-Tech Services", "cid": 23702122, "target": 2, "bucket": "C"}, + {"client": "Inside Track Productions", "cid": 3021358, "target": 1, "bucket": "C"}, + {"client": "Gary A Hartman LLC", "cid": 29038261, "target": 1, "bucket": "C"}, + {"client": "Robyn Pittman", "cid": 17031534, "target": 1, "bucket": "C"}, + {"client": "Marty Ryan", "cid": 140717, "target": 1, "bucket": "C"} + ] +} diff --git a/projects/gps-rmm-audit/tracker.md b/projects/gps-rmm-audit/tracker.md new file mode 100644 index 00000000..1953eecc --- /dev/null +++ b/projects/gps-rmm-audit/tracker.md @@ -0,0 +1,174 @@ +# GPS -> GuruRMM Coverage Audit + +**Goal:** For every business/client paying for GPS (Guru Protection Service), verify that +GuruRMM is set up correctly — the org/account exists, the machines they pay for are all +enrolled and reporting, and the services they pay for (backups, AV, email) are actually +configured and working. Where the client wiki is missing host/login/provider info, fill +those gaps as we go (credentials -> SOPS vault via `/vault`). + +**Source of truth for "should have":** Syncro active recurring schedules (device counts + +service line items). **Reality:** GuruRMM `/api/agents`, plus backup/AV/email tooling. + +- Started: 2026-07-03 (Howard) +- **AV STRATEGY (Howard 2026-07-03):** migrate **Bitdefender -> Datto EDR for ALL clients except Glaztech and Dataforth** (those two keep Bitdefender). Target end-state per machine (non-exempt) = GuruRMM agent + Datto EDR + Bitdefender removed. Bitdefender inventory is now only a discovery source (which machines exist), not a coverage target. See memory `project_av_migration_bitdefender_to_edr`. +- Scope: 40 **active** GPS clients (4 paused clients excluded: Marcia Ashton, Tucson Mountain Motors, Richard Pittman, Brenda Lopez) +- GPS device count = sum of GPS workstation + server SKUs (excludes AntiVirus add-on, discounts, setup) + +## Per-client verification checklist (each client) + +- [ ] 1. RMM org/account exists and is named correctly +- [ ] 2. Machine count in RMM matches GPS devices billed (reconcile every host) +- [ ] 3. Services billed are actually configured + working: Backup / AV / Email / VoIP +- [ ] 4. Client wiki has: host/provider (email, DNS, web — and whether ACG-managed), admin logins (-> vault), key contacts +- [ ] 5. Discrepancies logged + remediation started + +Legend: `MATCH` RMM >= billed · `SHORT (n)` RMM under billed by n · `MISSING` no RMM org · +`?` needs investigation. Svc flags from billing: B=Backup A=AV E=Email V=VoIP. + +--- + +## A. Present in RMM — counts match (verify services + wiki) — 7 + +| done | Client | Syncro CID | GPS billed | RMM machines | Status | Svc | Notes | +|------|--------|-----------|-----------:|-------------:|--------|-----|-------| +| [ ] | Dataforth Corp | 578095 | 43 | 51 | MATCH (RMM+8) | B A E | RMM has more than billed — reconcile extras | +| [ ] | Cascades of Tucson | 20149445 | 29 | 33 | MATCH (RMM+4) | A E V | | +| [ ] | Valley Wide Plastering | 31694734 | 29 | 28 | MATCH (~) | B | short 1, within reason | +| [ ] | Len's Auto Brokerage | 3289131 | 8 | 8 | MATCH | E | | +| [ ] | Arizona Medical Transit | 7088349 | 1 | 2 | MATCH (RMM+1) | B E V | | +| [ ] | AT Trebesch | 238740 | 1 | 1 | MATCH | - | | +| [ ] | Russo Law Firm | 23331699 | 3 | 3 | MATCH | A E V | Renamed 2026-07-03 from mislabeled "Russo, Steve" (Steve Russo owner, Shannon Trionfo contact) | + +### Bucket A findings (discovery 2026-07-03) + +- **Dataforth Corp** — 51 agents vs 43 billed GPS (**+8**). Possible under-billing / uncounted machines — several look like personal boxes (DESKTOP-*, LAPTOP-RD47E88A, Test01). Reconcile host-by-host with Mike; confirm which are billable. Wiki: `dataforth.md` exists. +- **Cascades of Tucson** — 33 agents vs 29 billed (**+4**). `RECEPTIONIST-PC` appears **twice** in RMM — likely a duplicate/stale agent record to clean up. Wiki: `cascades-tucson.md` exists. +- **Valley Wide Plastering** — 28 agents vs 29 billed (short 1). Effectively reconciled. Wiki: `valleywide.md` exists. +- **Len's Auto Brokerage** — 8 agents = 8 billed (MATCH). **FLAG: LAB-SVR (production Server 2019) agent offline since 2026-06-18** (~2 wks) — verify box/agent health. Email = 1x M365 Apps for Business; **email host/provider not documented** in wiki (gap). Wiki: `lens-auto-brokerage.md` thorough. +- **Arizona Medical Transit** — 2 agents (AMT-HYPERV + AMT-PC) vs 1 billed. **No wiki article exists** — create one (host/provider, logins -> vault). +- **AT Trebesch** — 1 agent = 1 billed (MATCH). Wiki: `attrebesch.md` exists. +- **Russo Law Firm** — 3 agents = 3 billed (MATCH). Org rename applied today. Sites: Main (has all 3) + empty "Shannon" site — consider moving STRIONFO to the Shannon site. Wiki: `russo-law.md` exists. + +**Still to verify per client (services + wiki):** backups (none billed for most of A except Dataforth/VWP/AMT), AV coverage vs billed AV seats, email host documented, admin logins in vault. + +#### Backup layer (B2/MSP360) findings +- **Dataforth** — `ACG-Dataforth` bucket present w/ data (billed B) [OK dest exists] +- **Valley Wide** — `VWP-Backup` bucket present w/ data (billed B) [OK dest exists] +- **Arizona Medical Transit** — **billed Data Backup but NO dedicated B2 bucket** — destination unknown (Datto? shared bucket?). VERIFY where AMT backup lands. +- **Cascades** — `ACG-Cascades` bucket present w/ data **but no Data Backup line item billed** — possible unbilled backup / revenue leak, or legacy. Confirm w/ Mike. +- **Len's Auto** — `ACG-Lens` bucket present w/ data **but backup not billed** (Svc=E only) — same question as Cascades. +- Caveat: bucket file lists are name-ordered, not time-ordered — "backup ran today" freshness must be confirmed in the MSP360 console; bucket presence only proves a destination is configured. +- Other buckets not tied to a bucket-A client: ACG-BST, ACG-Brett, ACG-GLAZTECH, ACG-IX, ACG-PST, ACG-REDNOUR, ACG-Rohrbach, ACG-TCA, Horseshoe, ACG-Internal, MSPBackups20200311 (stale — 2021, ex-client FSG). + +#### AV layer findings (AV split across TWO tools — Datto AV is primary for big clients, Bitdefender for smaller) +- **Dataforth** — billed 43 AV. **Datto EDR: 51 agents** (org 4a2664bf) — covered [OK]. (Bitdefender also has 5 — legacy/partial; Datto is primary.) +- **Cascades** — billed 29 AV. **Datto EDR: 34 agents** (org 2d5ea96e) — covered [OK]. Bitdefender company exists but 0 endpoints — Cascades AV lives entirely in Datto. +- **Russo Law Firm** — billed ~5 AV. **Bitdefender: 6 endpoints** (company 60abfa4c) — covered [OK], but STRIONFO listed **twice** in Bitdefender (dedupe stale record). Not the primary in Datto. +- Lesson for the audit: AV coverage is NOT single-tool — must check BOTH Datto EDR and Bitdefender before declaring an AV gap. Bitdefender company names carry the Syncro CID suffix (`_NNNNN`) which makes mapping exact. +- Datto "Default RMM Org" (35 agents, 23 sites) is a catch-all — small clients' Datto agents may sit there unsegmented; relevant when we reach buckets B/C. + +#### Email + vault findings +- **Vault:** all 7 A clients have entries. **Dupes to consolidate:** `russo` + `russo-law`, and `valleywide` + `vwp`. AMT had a vault entry (RMM keys) but no wiki (now created). +- **Email hosts (from billing — several need the actual mail host documented):** + - Dataforth — Pax8 M365 (Exchange Online P1 + M365 Business Std): ACG-managed M365 [OK] + - Cascades — 45 M365 Business Premium **+ 235 "Exchange Hosted Email"**: large hosted-Exchange footprint, **host not documented** [GAP] + - Len's Auto — only 1 M365 *Apps for Business* (no mailbox license): actual **email host unknown** [GAP] + - Arizona Medical Transit — 5 "Exchange Hosted Email": **host not documented** [GAP] + - Russo Law — 5 "Exchange Hosted Email": **host not documented** [GAP] + - AT Trebesch — no email billed +- "Exchange Hosted Email" is a recurring unknown across A (and likely B/C) — one host to identify (ACG-hosted Exchange vs a third party). Resolve once, apply everywhere. + +#### Bucket A verification rollup (2026-07-03) +- **Machines:** reconciled 7/7 (findings above). **Backups:** mapped 7/7 (3 billing flags held for Winter). **AV:** verified 3/3 AV-billed clients covered (Datto + Bitdefender). **Vault:** present 7/7. **Wiki:** 6 existed + AMT created = 7/7. +- **Remaining open (documentation, not coverage gaps):** email host for Cascades/Len's/AMT/Russo; Dataforth +8 billing reconcile; Cascades dup agent + Bitdefender dup (STRIONFO); Len's LAB-SVR offline; vault dupe consolidation. All logged; nothing outbound to Winter until the full list is verified. + +## B. Present in RMM — SHORT (missing agents to deploy) — 8 + +| done | Client | Syncro CID | GPS billed | RMM machines | Gap | Svc | Notes | +|------|--------|-----------|-----------:|-------------:|----:|-----|-------| +| [ ] | Glaz-Tech Industries | 143932 | 159 | 5 | 154 | B A E | ANOMALY — 149x GPS basic + 10x GPS Pro Server billed; verify billing is real vs legacy before treating as 154 missing | +| [ ] | Instrumental Music Center | 7088508 | 20 | 1 | 19 | A E V | | +| [ ] | Jimmy Company | 18560272 | 12 | 1 | 11 | B A | | +| [ ] | Horseshoe Management | 625269 | 9 | 1 | 8 | B E | | +| [ ] | Safesite LLC | 26563106 | 37 | 31 | 6 | A E | | +| [ ] | Stamback Septic | 11513046 | 8 | 3 | 5 | V | | +| [ ] | Grabb & Durando Law Office | 14232794 | 12 | 9 | 3 | B A E | | +| [ ] | Quantum Wealth Management | 7088747 | 3 | 2 | 1 | B E V | | + +### Bucket B coverage matrix (RMM vs Datto AV vs Bitdefender, 2026-07-03) + +| Client | GPS billed | RMM | Datto | Bitdef | Read | +|--------|----------:|----:|------:|-------:|------| +| Glaz-Tech Industries | 159 | 5 (all servers) | 5 | 242 | **ANOMALY** — RMM+Datto = 5 real infra boxes; Bitdefender 242 is years of stale enrollments; 149 GPS-basic billing not backed by real machines. HUMAN review (Mike). | +| Instrumental Music Center | 20 | 1 | 0 | 22 | **Real gap** — ~22 workstations exist (Bitdefender AV) but only IMC1 in RMM. Deploy ~19 RMM agents. | +| Horseshoe Management | 9 | 1 | 6 | 7 | **Real gap** — 6-7 machines exist (Datto+BD), only HSM-NewServer in RMM. Deploy ~5-8 agents. | +| Safesite LLC | 37 | 31 | 48 | 16 | **Real gap** — 48 in Datto, RMM 31. Machines exist; RMM short ~6+. Dedupe RMM `MSI` (listed twice). | +| Grabb & Durando | 12 | 9 | 0 | 15 | **Real gap** — 15 in Bitdefender, RMM 9. Deploy ~3-6 agents. | +| Quantum Wealth Mgmt | 3 | 2 | 0 | 4 | **Small gap** — BD 4, RMM 2. Add ~1-2 agents. | +| Jimmy Company | 12 | 1 | 0 | 1 | **BILLING FLAG** — only 1 machine managed anywhere (RMM Blaster2 / BD 1). Billed 12 -> either stale billing OR 11 unmanaged+unprotected machines. Investigate. | +| Stamback Septic | 8 | 3 (2 uniq) | 0 | 2 | **BILLING FLAG** — 2-3 machines managed anywhere, billed 8. Same question as Jimmy. RMM `DESKTOP-BTR2AM3` listed twice (dedupe). | + +**Split:** Real RMM-deploy gaps -> IMC, Horseshoe, Safesite, Grabb, QWM (~34-52 agents to push where the box already runs Datto/BD AV). Billing/coverage review (for Winter/Mike, document only) -> Glaz-Tech, Jimmy, Stamback. RMM dedupes -> Safesite `MSI` x2, Stamback `DESKTOP-BTR2AM3` x2. +Bitdefender companies exist for ALL bucket-B (and nearly all bucket-C) clients with the Syncro CID in the name — AV is broadly deployed even where RMM is not. + +#### IMC deep-dive (template client for the deploy pattern, 2026-07-03) +- **IMC1 = Primary DC** for domain `IMC.local` (192.168.0.2), already in RMM; Domain Admin cred `IMC\guru` vaulted (`clients/imc/imc1.sops.yaml`). RMM site: **IMCMain / INNER-BRIDGE-8354**. +- **True active fleet ~22** (AD objects with 2026 logons == Bitdefender's 22). Billed 20 GPS — legit. +- **RMM has only IMC1** -> **21 active domain machines need the agent.** +- Deploy vehicle: push GuruRMM site MSI (INNER-BRIDGE-8354) from the DC to domain members using the vaulted Domain Admin cred (Invoke-Command or a software-install GPO). This is the reusable pattern for any **domain** client (DC already in RMM -> AD is the authoritative list -> push from DC). +- **AD hygiene finding:** ~24 stale computer objects in IMC.local (Windows 7, last logon 2015-2019) never removed — separate cleanup task. +- Deploy targets (in Bitdefender, active, not IMC1): IMC-M-EDSERVICE, IMC-SVCSTR, IMC-L1-STATION9, IMC-MINI, IMC-LESSONS, IMC-STATION2, IMC-STATION1, PURCHASINGCOMP, IMC-L1-GRAPHICS, LAPTOP-DCHQ3F92, LAPTOP-PNVA9G51, PHIL2021LAPTOP, IMC-LUIS, DESKTOP-GHG12G3, DESKTOP-JQ0D38J, DESKTOP-URV3UGR, C2B, IMC-PRINTSERVER, DESKTOP-44L80C0, DESKTOP-MR3ALTK, REPAIRADMIN (21). + +#### IMC DEPLOY EXECUTED 2026-07-03 — via ScreenConnect (channel finding: see memory `reference_rmm_deploy_via_screenconnect`) +- **DC remote-exec is a dead end** on IMC's Win10/11 clients: DCOM firewalled (WMI "RPC unavailable"), schtasks/S rejected by Win11 from the 2016 DC ("request not supported"), WinRM off. SYSTEM on the DC also can't create GPOs; SSH to IMC1 blocked (Tailscale route not accepting 192.168.0.0/24 + no local key). +- **Working channel = ScreenConnect send-command** (runs as SYSTEM on the guest, no creds, no firewall issue). Every IMC machine has an SC agent. +- Pushed `powershell -enc /windows'|iex>` to 20 of 21 targets (2 test + 18 rollout). **IMC-L1-GRAPHICS** has NO SC session (stale 2025 box — handle separately). +- Result: **RMM IMC agents 1 -> 12 and climbing** (online machines enrolled in ~1-3 min; offline ones queued in SC, install on reconnect). Daily check task tracks to completion. +- DA-password attempts via RMM were scrubbed (`DELETE /api/commands/:id`, HTTP 204) — no credential persisted. No partial installs from the failed methods. + +## C. MISSING from RMM entirely (no org found) — 25 + +| done | Client | Syncro CID | GPS billed | Svc | Notes / verify not under an alias | +|------|--------|-----------|-----------:|-----|-------| +| [ ] | Reliant Well Drilling and Pump | 10736261 | 9 | B V | | +| [ ] | Zeus Nestora | 1196974 | 8 | - | | +| [ ] | Little Hearts Little Hands | 1144233 | 8 | E | | +| [ ] | PUTT Land Surveying | 7180175 | 7 | A E | | +| [ ] | Curtis Plumbing | 416585 | 6 | B A E | | +| [ ] | The Prairie Schooner | 3664974 | 5 | B E V | | +| [ ] | Mineralogical Record | 207770 | 5 | B A V | | +| [ ] | T & C Sorensen | 344886 | 4 | B E | | +| [ ] | MVAN Enterprises Inc | 29462761 | 4 | A E | | +| [ ] | Ridgetop Group | 9413367 | 3 | B | | +| [ ] | Multicultural Counseling Center | 35483539 | 3 | A E | | +| [ ] | Brett Interiors | 15726057 | 3 | B | | +| [ ] | Heieck, Sheila | 12045942 | 3 | E | individual-named account | +| [ ] | The Marc Group | 869073 | 2 | E | | +| [ ] | Residential and Renovation Engineering | 7088403 | 2 | A V | | +| [ ] | Bill Tedards | 487887 | 2 | B E V | | +| [ ] | Janet Altschuler | 457710 | 2 | B | individual-named account | +| [ ] | Business Services of Tucson LLC | 29338800 | 2 | B | | +| [ ] | Andy's Mobile Fuel | 27364453 | 2 | E | | +| [ ] | Design and Brand Envoys | 26747288 | 2 | B A E | | +| [ ] | Pro-Tech Services | 23702122 | 2 | A | | +| [ ] | Inside Track Productions | 3021358 | 1 | - | | +| [ ] | Gary A Hartman LLC | 29038261 | 1 | B | | +| [ ] | Robyn Pittman | 17031534 | 1 | - | individual-named account | +| [ ] | Marty Ryan | 140717 | 1 | A E | individual-named account | + +--- + +## Daily progress check (automated) +- Windows scheduled task **GPS-RMM-Progress** runs daily 8:07am (Howard-Home), script `.claude/scripts/gps-rmm-progress-check.sh`, targets `projects/gps-rmm-audit/targets.json`. Compares live RMM agent counts (unique hostnames) to GPS device targets and DMs Howard the remaining gaps; reports COMPLETE when all met (then retire via `schtasks /Delete /TN GPS-RMM-Progress`). Baseline 2026-07-03: **46/189 devices in RMM, 32 clients short.** Glaz-Tech excluded pending billing review. + +## Rollup + +- **7** clients match on machine count (still need service + wiki verification). +- **8** clients present but short — ~50 agents to deploy (excl. Glaz-Tech anomaly). +- **25** clients with **no RMM org** — ~86 GPS devices billed, zero RMM presence (some may be under an alias / not yet deployed — verify per client). +- **Biggest single flag:** Glaz-Tech Industries billed 159 GPS but only 5 RMM agents — confirm the billing is current before acting. + +## Method notes +- GPS SKUs matched: GPS basic/monthly, GPS pro/monthly, GPS Workstation, GPS Server, GPS Pro Server (+ variants). Excluded: GPS AntiVirus Add-on, GPS addon, GPS Discount, GPS Set-up, GPS trial. +- RMM counts from `GET /api/agents` grouped by `client_name`, 2026-07-03. +- "MISSING" = no `client_name` match in RMM; each must be double-checked for an alias (person name / DBA) before onboarding a duplicate. diff --git a/wiki/clients/arizona-medical-transit.md b/wiki/clients/arizona-medical-transit.md new file mode 100644 index 00000000..af29825e --- /dev/null +++ b/wiki/clients/arizona-medical-transit.md @@ -0,0 +1,65 @@ +--- +type: client +name: arizona-medical-transit +display_name: Arizona Medical Transit +last_compiled: 2026-07-03 +compiled_by: HOWARD-HOME/claude-main +sources: + - Syncro recurring schedule (customer 7088349) + - GuruRMM /api/agents + vault clients/arizona-medical-transit/* + - projects/gps-rmm-audit/tracker.md +backlinks: [] +--- + +# Arizona Medical Transit + +Non-emergency medical transport, Tucson AZ. Small managed client on GPS (Guru Protection +Service). Owner runs a multi-location setup — a main office plus two home offices — each +stood up as its own GuruRMM site. Created here 2026-07-03 during the GPS->RMM coverage +audit; several fields are verified-from-systems, others flagged as gaps to fill. + +## Profile +- **Syncro customer ID:** 7088349 +- **Contract type:** Managed — GPS monthly + services (backup, email, VoIP) +- **Paying for (Syncro recurring):** 1x GPS basic/monthly · 1x Service - Data Backup · + 5x Email - Exchange Hosted Email · 1x Email - Spam filtering · PacketDial VOIP 500 + + 3x Phone Extension + E911 · small ad-hoc labor +- **Key contacts:** (GAP — capture names/phone/email) + +## Infrastructure + +### GuruRMM sites & agents +- **GuruRMM client_id:** `4fb591e7-2660-4c2d-9bc6-6f42bf107b17` +- Three provisioned sites (enrollment keys in vault, see Access): + +| Site | site_code | Agents enrolled | +|---|---|---| +| Main | GREEN-FORGE-3000 | AMT-HYPERV (online) | +| Home-M | SILVER-FALCON-1975 | AMT-PC (online) | +| Home-B | DARK-BRIDGE-5305 | none yet | + +- **AMT-HYPERV** (Main) — Hyper-V host, Windows, online. +- **AMT-PC** (Home-M) — workstation, Windows, online. +- 2 agents online vs 1 GPS device billed — reconcile which devices are billable with Mike. + +### Services (audit 2026-07-03) +- **Backup:** billed 1x Service - Data Backup, but **NO Backblaze B2 bucket exists for AMT** + — backup destination unconfirmed (Datto? another target? not running?). VERIFY. [FLAG] +- **AV:** none billed. (Not in scope; small client.) +- **Email:** 5x "Exchange Hosted Email" + spam filtering — **host not documented** (ACG-hosted + Exchange vs third party). Document the actual mail host + admin portal. [GAP] +- **VoIP:** PacketDial / OITVOIP — VOIP 500 + 3 extensions + E911. Manage via `/packetdial`. + +## Access +- **GuruRMM enrollment keys:** vault `clients/arizona-medical-transit/gururmm-site-{main,home-m,home-b}.sops.yaml` +- **Other admin logins (M365/email, network, etc.):** (GAP — capture and store via `/vault`) +- **Vault path:** `clients/arizona-medical-transit/` + +## Open items (from GPS->RMM audit) +1. Confirm backup destination for the billed Data Backup line (no B2 bucket found). [FLAG — Winter/billing] +2. Document email host + admin portal for the 5 hosted mailboxes. +3. Capture key contact name(s) + primary admin credentials -> vault. +4. Reconcile 2 RMM agents vs 1 GPS device billed. + +## Backlinks +*(none yet)*