From 8389e64a02438e3789d4895edc85e9e1d6b5212f Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Thu, 4 Jun 2026 19:27:56 -0700 Subject: [PATCH] sync: auto-sync from GURU-5070 at 2026-06-04 19:27:51 Author: Mike Swanson Machine: GURU-5070 Timestamp: 2026-06-04 19:27:51 --- .../dataforth/migration-gap-diff-RESUME.md | 63 ++++++++++++++ .../session-logs/2026-06-04-session.md | 86 +++++++++++++++++++ session-logs/2026-06-04-session.md | 52 +++++++++++ 3 files changed, 201 insertions(+) create mode 100644 clients/dataforth/migration-gap-diff-RESUME.md create mode 100644 clients/dataforth/session-logs/2026-06-04-session.md diff --git a/clients/dataforth/migration-gap-diff-RESUME.md b/clients/dataforth/migration-gap-diff-RESUME.md new file mode 100644 index 0000000..bd2f3d0 --- /dev/null +++ b/clients/dataforth/migration-gap-diff-RESUME.md @@ -0,0 +1,63 @@ +# Dataforth Migration-Gap Diff — RESUME (parked 2026-06-04) + +**Status:** PARKED. Mike will run **approach A (WizTree on all servers)** tomorrow (2026-06-05). + +## Goal +The 2025 post-ransomware recovery restore (`Restore plan` ~10/1–10/2/2025, ~3.4M files) migrated each share from its old `D:\` location to the current `C:\Shares\...` layout and **silently dropped files** (proven by the SP1366 case — see ticket #32385). Find what else was dropped, per share. **Review-only catalog — NO automatic restore** (some deletions were intentional; the backup is additive-only). + +## Backup-side data (already captured) +- HGHAUBNER (Georg's machine) `D:` is a pre-attack backup of the DF shares. +- Full-drive WizTree CSV exported (2.3 GB) + zip (196 MB): **`AD2 C:\ClaudeTools\clients\dataforth\WizTree_20260604184904.zip`** (moved OFF the c-drive share — it's a sensitive file list). +- Local working copy also at `GURU-5070 C:\Users\guru\AppData\Local\Temp\wiztree.zip`. +- **Backup scale (the 7 mapped shares): ~8.7M files / ~5.7 TB** — too big for live enumeration via RMM, hence WizTree both sides. + +## Share → live-server mapping (HGH folders are named by SHARE, not server) +| HGH backup folder | Live target | Notes | +|---|---|---| +| `DF C-Drive` | AD2 `C:\Shares\c-drive` | SP1366 already restored | +| `DF E-Drive` | AD2 `C:\Shares\e-drive` | 2.29M files / 2.26 TB | +| `DF WebShare` | AD2 `C:\Shares\webshare` | | +| `DF Sage` | SAGE-SQL `C:\sage` | | +| `DF Server Sales` | FILES-D1 `E:\Shares\sales` | | +| `DF Server Archive` | FILES-D1 `E:\Shares\archive` | | +| `DF Server Engineering` | AD1 `C:\Engineering` | | +| `DF Staff` | — SKIP | Georg's personal profile backup | +| `Dataforth` | — SKIP | Georg's personal work-data backup | + +**Also flag:** the `staff` share is entirely **absent on FILES-D1** (only `archive` + `sales` exist) — separate issue, not in scope here. + +## Plan (approach A — WizTree both sides) +1. Push portable WizTree to the 4 live servers via RMM (AD2, FILES-D1, SAGE-SQL, AD1). +2. Export each relevant volume/share to CSV: `WizTree64.exe "" /export="" /admin=1`. **Treat CSVs as sensitive — keep them out of any share** (stage to a private dir, e.g. `C:\ClaudeTools\...`, transfer via SFTP off AD2 like we did the backup CSV). +3. Diff CSV-to-CSV per share (backup relative paths − live relative paths, case-insensitive) → files present in backup, missing live. +4. Write catalog → `clients/dataforth/migration-gap-catalog-2026-06-04.md` (per share: whole folders missing + individual files missing). + +## RMM agent IDs (GuruRMM, client "Dataforth Corp") +- AD2 `cfa93bb6-0cdc-4d4e-a29e-1609cda6f047` (has OpenSSH too: `sysadmin`, vault `clients/dataforth/ad2.sops.yaml`) +- AD1 `bf7bc5ee-4167-4a62-912a-c88b11a5943d` +- FILES-D1 `8566a19d-49a9-4f8b-9c6c-012cc934484b` +- SAGE-SQL `120ba7bf-8544-48a0-98a1-40ed5cdd3e1f` +- HGHAUBNER `2aefe0d5-2357-4bdd-965a-abfccb4767a5` (Georg logged in; user_session writes to mapped Q:/T:/V:/X: → AD2 shares) + +## Transfer trick (proven) +HGHAUBNER/server `user_session` can write to existing GPO-mapped drives (e.g. Q: → `\\ad2\c-drive`) but **cannot** open fresh UNC (WTS-impersonation has no network creds). So: copy to a mapped AD2 share → SFTP off AD2 (`sysadmin`) → process locally → delete the staged copy from the share. + +--- + +## Other Dataforth items PARKED 2026-06-04 (not started) + +### 1. AD1 Files backup — command READY, awaiting "run AD1" +AD1's shared data folders need a Files plan matching AD2's (NBF, daily 2 AM, 180-day retention, `ACG-Dataforth`). Shares: `Engineering`→`C:\Engineering`, `ITSvc`→`C:\Shares\ITSvc`. AD1 currently has only the `Image2025` image plan. Verified AD2 `Files` plan config: `SerializationSupportRetentionTime=180 days`, GFS off, synthetic full, compression, fast-NTFS. Run on AD1 via RMM (agent `bf7bc5ee…`): +``` +cbb.exe addBackupPlan -n "Files" -a "ACG-Dataforth" -nbf -syntheticFull yes -d "C:\Engineering" -d "C:\Shares\ITSvc" -c yes -fastNtfs yes -ntfs yes -every day -at "2:00 AM" -purge "180d" -notification errorOnly -dr yes +``` +(`cbb.exe` = `C:\Program Files\Arizona Computer Guru\Online Backup\cbb.exe`.) Optionally trigger an initial run after. Confirm with user before executing (production DC). + +### 2. AD2 Claude capability updates +AD2 runs its own Claude from **`C:\ClaudeTools`** (a git clone of the ClaudeTools repo; has `.claude/commands/` mirroring ours) + `C:\dataforth-ad2-context` (DOS-project workdir w/ its own CLAUDE.md). `~/.claude` (sysadmin) has no `commands/` and no `CLAUDE.md`. User wants the AD2 Claude to: **(a)** know how to use syncro + coord, **(b)** read/update the DF wiki, **(c)** have access to all Dataforth data in ClaudeTools. TODO: check whether `C:\ClaudeTools` remote == shared Gitea (so updates flow via repo + git pull) or is a diverged clone; then add the syncro/coord commands + a CLAUDE.md w/ DF context + ensure the DF wiki + `clients/dataforth` data are present, and that it can auth (vault/identity, coord API). + +### 3. Dataforth wiki fleet update +GuruRMM enrollment grew 13 → **45 agents** (40 online) incl. servers AD1, FILES-D1, SAGE-SQL, DF-HYPERV-B, DF-SVR-D2-Sync, eng-dev-server. Update `wiki/clients/dataforth.md` GuruRMM-enrollment section (currently lists only DF-GAGETRAK). + +### Housekeeping +- Sensitive backup-CSV copy on GURU-5070: `C:\Users\guru\AppData\Local\Temp\wiztree.zip` — delete after the diff is done (or now if not needed). diff --git a/clients/dataforth/session-logs/2026-06-04-session.md b/clients/dataforth/session-logs/2026-06-04-session.md new file mode 100644 index 0000000..03665b9 --- /dev/null +++ b/clients/dataforth/session-logs/2026-06-04-session.md @@ -0,0 +1,86 @@ +# Dataforth — Session Log 2026-06-04 + +## User +- **User:** Mike Swanson (mike) +- **Machine:** GURU-5070 +- **Role:** admin + +## Session Summary + +Recovered missing PCB manufacturing print files for the SP1366 MAQ20 Communications Module (revisions E, F, G, H), reported missing by John Lehman. The files live on AD2 (`Q:` → `\\ad2\c-drive` → `C:\Shares\c-drive`) under `DOCUMENT\DESIGN\SP\SP1366 MAQ20 Communications Module\{E,F,G,H}\PCB1366 REV PRINTOUTS FOR MANUFACTURING`. The PRINTOUTS folders existed but contained only a `TOP SIDE DRILL PANEL.PDF` each; the LAYERS/PASTE/AD/CD/DG exports were gone. The same set existed for revs A (2010) and I (2024), and the Altium source `.SchDoc` files for E–H survived — only the exported PDFs were missing. + +Confirmed no local recovery path: AD2 had no shadow copies; its MSP360 (ACG-branded "Online Backup") agent showed an image plan and a Files plan both "Never started" locally, but the MSP360 account view (api.mspbackups.com) showed the AD2 Image plan running daily. The breakthrough was a second backup set in the `ACG-Dataforth` storage: a file-level NBF backup ("Backup plan on 8/29/2025", bunch `faad5a67`) with restore points 8/29–9/29/2025. Browsing it (`cbb.exe list -b -rp -path ...`) found the files under `D:\c-drive\...` (the share's pre-migration physical path) — 19 of John's 20 files present (REV F's `TOP PASTE LAYER` absent in every backup; it never existed as a separate F export). + +Established WHEN the files were lost via NTFS timestamps: the `C:\Shares\c-drive` tree was created 10/1–10/2/2025 by the post-ransomware recovery restore (`Restore plan 10/1/2025`, ~3.4M files). That restore brought back only the drill panel into each PRINTOUTS folder and dropped the rest — i.e. an incomplete recovery restore, not a later user deletion. Files were intact in backup through 9/29/2025. The image backup retention only reaches back to 5/6/2026 (post-loss), so it cannot contain them. + +Restored the 19 files from HGHAUBNER's pre-attack backup (`D:\DF C-Drive`, accessible after Mike installed GuruRMM on HGHAUBNER) rather than the cloud backup — same files, no B2 egress. Cross-machine copy was blocked by Windows auth (SSH double-hop; WTS-impersonation tokens can't open fresh UNC). Solution: ran the copy on HGHAUBNER in `user_session` (as logged-in `ghaubner`), reading local `D:\DF C-Drive` and writing to his existing GPO-mapped `Q:` (→ `\\ad2\c-drive`) — local read + existing-mapping write needs no fresh auth. Verified 6 files/rev landed in the live `C:\Shares\c-drive` path. Created Syncro ticket #32385, billed 1.0 hr remote labor (prepaid → $0, block 35.5→34.5), resolved + invoiced. + +Set up follow-on work and parked it: rescanned the GuruRMM fleet (grew 13 → 45 agents incl. servers AD1/FILES-D1/SAGE-SQL); prepared (but did not run) an AD1 Files backup plan matching AD2's (180-day retention); and scoped a broader migration-gap audit (WizTree both sides, ~8.7M files / 5.7 TB across 7 shares). Mike will run the WizTree-on-servers pass tomorrow. All parked state is in `clients/dataforth/migration-gap-diff-RESUME.md`. + +## Key Decisions + +- Restored from HGHAUBNER's local pre-attack backup rather than the MSP360 cloud backup — identical files, no B2 egress, and it independently cross-validated the cloud backup (both 19/20). +- Ran the cross-machine copy on HGHAUBNER in `user_session` writing to an existing mapped drive, after both SSH-from-AD2 and AD2-side `user_session` failed (double-hop / impersonation has no network creds). Existing GPO mappings work in the impersonated token; fresh UNC does not. +- Did NOT restore REV F's paste file — confirmed absent from both independent backups; framed it as "not in our backups under that name" rather than "never existed," per Mike's caution that the ask may be slightly off. +- Moved the WizTree CSV (a sensitive full file-list) OFF the c-drive share into private `C:\ClaudeTools` on AD2 — it was wrongly staged in a share visible to all c-drive users. +- For the broad migration-gap diff, chose WizTree-both-sides (MFT-fast, exact, CSV-to-CSV) over live RMM enumeration, given ~8.7M files. Catalog is review-only — no auto-restore, since some deletions were intentional and the HGH backup is additive-only. +- AD1 backup: build fresh via `addBackupPlan` CLI (Mike's choice, option b), matched to AD2's real `.cbb` config (read `SerializationSupportRetentionTime=180 days`). + +## Problems Encountered + +- AD2's local `cbb.exe` reported the image/Files plans "Never started" and `listIBBContent` found "No disk image backups" — stale local repo view. Mike had me restart the Online Backup services; the `list` command then surfaced the file-backup bunch. +- Path confusion: backup stored the share under `D:\c-drive` while the live share is `C:\Shares\c-drive`. Reconciled via NTFS metadata — the old `D:` data volume is gone (now a mounted Windows install ISO); the 10/1/2025 restore migrated the data to `C:\Shares` on the C: volume. +- Cross-machine file copy repeatedly blocked by Windows double-hop / WTS-impersonation (no network creds). Resolved by running on the source machine in `user_session` and writing to an existing mapped drive. +- Repeated bash-heredoc backslash mangling of PowerShell/Python — resolved by base64-encoding PowerShell (`-EncodedCommand`) and writing Python via the Write tool / `chr(92)` instead of literal backslashes. +- WizTree export was in Georg's `Documents`, not `Downloads` as expected — found by listing largest files under the profile. +- Coord API was unreachable for the parking todo — used a repo resume doc instead. + +## Configuration Changes + +- **AD2 `C:\Shares\c-drive\...\{E,F,G,H}\PCB1366 REV PRINTOUTS FOR MANUFACTURING\`** — added 19 recovered PDFs (additive; existing files untouched). +- **AD2 `C:\ClaudeTools\clients\dataforth\WizTree_20260604184904.zip`** — moved here (private) from the c-drive share staging; `C:\Shares\c-drive\__wiztree` staging folder removed. +- **AD2 Online Backup services** — restarted (by request) to resync the local repo. No plan changes. +- Repo: created `clients/dataforth/session-logs/2026-06-04-session.md`, `clients/dataforth/migration-gap-diff-RESUME.md`. +- **No AD1 backup plan created yet** (command prepared, parked). No diff catalog written yet (parked). + +## Credentials & Secrets + +- AD2 SSH: `sysadmin` (INTRANET\\sysadmin), vault `clients/dataforth/ad2.sops.yaml → credentials.password` (note: strip stray backslash). +- HGHAUBNER: no SSH; reached via GuruRMM agent; logged-in user `intranet\ghaubner`. +- MSP360 Managed Backup API: vault `msp-tools/msp360-api.sops.yaml` (api.mspbackups.com, /api/Provider/Login). +- GuruRMM API: vault `infrastructure/gururmm-server.sops.yaml`. Syncro: per-user key (mike) in the syncro skill. +- No new credentials created. + +## Infrastructure & Servers + +- **AD2** — 192.168.0.6, Win Server 2022 DC + file server. Shares now `C:\Shares\{c-drive,e-drive,webshare}`; old `D:\c-drive` data volume repurposed (D: = mounted install ISO). MSP360 agent `C:\Program Files\Arizona Computer Guru\Online Backup\cbb.exe`; storage account `ACG-Dataforth` (`0b49ca5e-…`). GuruRMM agent `cfa93bb6-…`. +- **AD1** — DC; shares `Engineering`→`C:\Engineering`, `ITSvc`→`C:\Shares\ITSvc`. GuruRMM agent `bf7bc5ee-…`. Only `Image2025` backup plan. +- **FILES-D1** — file server; shares `E:\Shares\{sales,archive}` (no `staff` share — missing). Agent `8566a19d-…`. +- **SAGE-SQL** — `C:\sage`. Agent `120ba7bf-…`. +- **HGHAUBNER** — Georg Haubner's PC; `D:` = pre-attack backup of DF shares (`DF C-Drive`, `DF E-Drive`, `DF WebShare`, `DF Sage`, `DF Server Sales/Archive/Engineering`, + personal `DF Staff`/`Dataforth`). Agent `2aefe0d5-…`. +- Backup sets in `ACG-Dataforth`: `AD2 Image` (image, `35a5c3d2`), file backup `Backup plan on 8/29/2025` (`faad5a67`, restore points 8/29–9/29/2025). + +## Commands & Outputs + +- Browse file backup: `cbb.exe list -a "ACG-Dataforth" -b faad5a67-… -rp 20250830005237 -path "D:\c-drive\DOCUMENT\DESIGN\SP\SP1366 MAQ20 Communications Module\F\PCB1366 REV F PRINTOUTS FOR MANUFACTURING"`. +- Forensic: `C:\Shares` Created `10/1/2025 2:23 PM`; SP1366 rev/PRINTOUTS folders Created `10/2/2025 ~12:17 PM`; surviving drill PDFs Created `10/2/2025`, Modified = original 2012–2024. +- Copy (HGHAUBNER user_session): local `D:\DF C-Drive\…` → `Q:\…` (mapped `\\ad2\c-drive`) — 19 copied, 5 skipped, 6 files/rev verified. +- AD2 Files plan retention (from `de4fd4fd*.cbb`): `180.00:00:00`, GFS disabled. +- WizTree backup totals: DF C-Drive 2.74M files/426GB; DF E-Drive 2.29M/2261GB; DF Server Sales 461k/1487GB; DF Server Engineering 971k/1079GB; DF Server Archive 1.09M/392GB; DF Sage 58.6k/88GB; DF WebShare 1.06M/2.9GB. + +## Pending / Incomplete Tasks + +See `clients/dataforth/migration-gap-diff-RESUME.md` for full detail. Parked: +1. **AD1 Files backup** — `addBackupPlan` command ready (NBF, daily 2 AM, 180-day, `C:\Engineering` + `C:\Shares\ITSvc`); run on Mike's OK. +2. **Migration-gap diff** — WizTree both sides tomorrow; diff CSV-to-CSV per share → `clients/dataforth/migration-gap-catalog-2026-06-04.md`. Backup-side CSV at AD2 `C:\ClaudeTools\clients\dataforth\WizTree_20260604184904.zip`. +3. **AD2 Claude** capability updates (syncro/coord + DF wiki read-write + Dataforth data; its repo is `C:\ClaudeTools`). +4. **Dataforth wiki** GuruRMM-enrollment section: update 13 → 45 agents. +5. **REV F `TOP PASTE LAYER`** — John doesn't care; closed. +6. Housekeeping: delete sensitive local copy `GURU-5070 C:\Users\guru\AppData\Local\Temp\wiztree.zip` after the diff. + +## Reference Information + +- Syncro ticket **#32385** (id 112202781) — https://computerguru.syncromsp.com/tickets/112202781 ; invoice 1650579125 ($0, prepaid). +- Dataforth Corp Syncro customer 578095; contact John Lehman 2851723 (jlehman@dataforth.com). +- GuruRMM API http://172.16.3.30:3001 ; MSP360 API https://api.mspbackups.com. +- Resume doc: `clients/dataforth/migration-gap-diff-RESUME.md`. diff --git a/session-logs/2026-06-04-session.md b/session-logs/2026-06-04-session.md index 965074a..a0edad4 100644 --- a/session-logs/2026-06-04-session.md +++ b/session-logs/2026-06-04-session.md @@ -190,3 +190,55 @@ Get-ScheduledTask -TaskPath "\Microsoft\Windows\Windows Defender\" | Enable-Sche - Disable is NOT update-proof: a Windows feature update may re-enable real-time protection. For a genuinely permanent disable, offered (deferred): Safe Mode service-disable of WinDefend/Sense/WdNisSvc/WdFilter, OR install Bitdefender to auto-supersede Defender. - Machine currently has NO active AV. Consider Bitdefender if this is to remain a working posture. + +--- + +## Update: 19:26 PT — GuruRMM tray-icon bug fix (shipped) + SPEC-016 VSS backend (checkpointed) + +### Session Summary + +Fixed the recurring GuruRMM duplicate/ghost tray-icon bug end to end. Diagnosed three compounding defects via code review, live evidence on GURU-5070 (5 stacked `gururmm-tray.exe` in Session 1, one per watchdog restart), and an independent Grok review: (1) `TrayLauncher` tracked launches in an in-memory map that resets on watchdog restart/auto-update, so it relaunched trays into sessions that already had one; (2) `terminate_all` used `TerminateProcess` (hard kill) which skips the tray's Drop -> `Shell_NotifyIcon(NIM_DELETE)`, orphaning icons; (3) no single-instance guard in the tray. Coding Agent implemented a per-session `Local\GuruRMM_Tray` mutex, `WTSEnumerateProcessesW` launcher reconciliation, and a graceful `Global\GuruRMM_TrayShutdown_{sid}` event. Code Review Agent APPROVE. Committed to gururmm main (`137dd85`) -> beta build. Killed the 5 stray processes on GURU-5070. Verified via live Postgres that GURU-5070 is the lone beta agent (explicit per-agent `update_channel=beta`; stable fleet pinned 0.6.47), so the fix auto-lands here. + +Recompiled the `gururmm` wiki article (corrected the stale "GURU-5070 promoted to stable" line — DB shows beta; added BUG-020) and created a `guru-rmm` -> `gururmm` redirect tombstone (the on-disk dir is hyphenated, the wiki/repo slug is not, which had caused a dead-end lookup earlier in the session). + +Began SPEC-016 (VSS Shadow Copy Management) as a full build per Mike, using Grok as design sounding-board + code reviewer. Grok's review reshaped the design: WMI `Win32_ShadowCopy.Create` (not vssadmin on client SKUs), robocopy `/COPYALL` restore (Copy-Item drops ACLs), bounded shadowstorage provisioning, and mandatory guardrails before default-on. Rewrote SPEC-016 to v2 (JSONB policy model, migration 049->050 correction, 8 guardrails). Mid-build, Mike refined the core decision: VSS ON by default for SERVERS only, OFF for workstations (tiny-disk servers covered by existing low-space alerts). This made the default OS-type-aware. Rebuilt the brittle OS identifier (Caption + ProductType + DisplayVersion + edition; migration 049_os_identity; `agent_is_server()` classifier) to fix Mike's "ugly names / no edition" gripes and provide a reliable server/workstation flag. Built the agent VSS core (Stage 1, reviewed + fixed: C1/H1/H2/M2/M4/L1, 5 tests) and the server stage (Stage 2: VssConfig policy, OS-aware default, migration 050_vss, db/vss.rs, api/vss.rs, WS ingest, capability gate; 10 tests). Checkpointed the backend to gururmm branch `feat/vss-shadow-copy` (`8f61624`) per Mike; dashboard + OS/server review + migration apply remain (coord todo 8c86d987). + +### Key Decisions + +- Tray fix shipped #1+#2 (mutex + reconciliation) live; #3 (graceful shutdown) implemented but dormant because `terminate_all` has no caller in the agent — tracked follow-up (todo 25fdf31a) rather than wiring it speculatively into the watchdog teardown. +- VSS default-on made OS-type-aware (Mike): server ON / workstation OFF, decided server-side in `get_effective_policy()` via `agent_is_server()`, not in the OS-agnostic static `system_defaults()`. Workstations were the disk blast-radius Grok warned about. +- `min_volume_gb` default = None (no size gate): rely on existing low-space alerts for tiny-disk servers rather than silently skipping them (Mike). The Stage-1 agent wrongly coerced None->100GB (C1); fixed. +- OS identifier sources `Win32_OperatingSystem.Caption`/`ProductType`/registry `DisplayVersion` as primary, keeping the old build-number map only as fallback — robust against unlisted builds. +- Checkpointed the VSS backend to a feature branch (not main) so no beta build of dormant code (agent VSS is inert until the server emits a `vss` policy section); secures ~4500 lines of uncommitted work. +- Kept the submodule gitlink lagging main (fe551e4) — normal/expected per project rules; did not force-bump to 137dd85. + +### Problems Encountered + +- PowerShell tool `EPERM uv_spawn` on Defender/VSS-touching commands earlier was the harness sandbox, not AV — bypass with `dangerouslyDisableSandbox` (carried over from the Defender work). +- Grok code-review runs hit the headless "Cancelled" finalization quirk 3x this session; deferred Grok code review to the (more useful) fixed code / next session. Grok design sounding-board (text mode) worked. +- Code Review found 3 blockers in the VSS agent (C1 min_volume_gb None->100GB gate breaking small-disk servers; H1 dest blocklist bypassable via 8.3 short names / C:-only; H2 unbounded recursive C:\Users backup-artifact scan). All fixed + tests added. +- Gitea Agent discovered the submodule was on detached HEAD `fe551e4` (the human-flow commit the gitlink tracks), not main `137dd85`; the VSS WIP was built on fe551e4. Branched from there and returned to fe551e4 to keep the parent gitlink clean, instead of blindly checking out main (which would have dirtied the parent). + +### Configuration Changes + +- gururmm main `137dd85`: tray fix — `agent/src/watchdog/wts.rs`, `tray/src/winsingleton.rs` (new), `tray/src/main.rs`, `tray/src/tray.rs`, `tray/Cargo.toml`. +- gururmm branch `feat/vss-shadow-copy` `8f61624` (22 files): `agent/src/vss.rs` (new), `agent/src/inventory.rs` (OS rebuild), `agent/src/transport/{mod,websocket}.rs`, `agent/src/main.rs`, `server/src/db/{policies,vss(new),agents,inventory,enroll,mod}.rs`, `server/src/policy/{merge,effective,config_update}.rs`, `server/src/api/{vss(new),mod,policies}.rs`, `server/src/ws/mod.rs`, `server/src/main.rs`, `server/migrations/049_os_identity.sql` (new), `server/migrations/050_vss.sql` (new), `docs/specs/SPEC-016-vss-shadow-copy-management.md` (v2), `docs/FEATURE_ROADMAP.md` (BUG-020). +- ClaudeTools root (this save): `wiki/projects/gururmm.md` (recompiled), `wiki/projects/guru-rmm.md` (tombstone, new), `wiki/index.md`. + +### Infrastructure & Servers + +- GURU-5070: GuruRMM agent 0.6.54, AgentKey `agk_ybg4Ty6zXU_2Ee0ddlUUtuZdz0B9Qw4_`, SiteId `103c10b9-c1de-4dd8-b382-b8362ed3143e` ("Mike's Car"), device_id `a5c3fa53-193a-46e9-a83e-675eb1baaff0`, agent_id `c043d9ac-4020-4cab-a5f4-b90213d11e73`. Lone beta agent (explicit `update_channel=beta`). +- GuruRMM Postgres `gururmm` @ 172.16.3.30:5432 (binds 127.0.0.1; query over SSH guru@172.16.3.30, creds SOPS `projects/gururmm/database.sops.yaml`). Stable channel pinned 0.6.47 win / 0.6.46 linux (update_rollouts, 2026-05-28); beta has 0 rollout rows (serves newest signed artifact). +- Migrations 049_os_identity + 050_vss NOT yet applied to live Postgres (pending). + +### Pending / Incomplete Tasks + +- VSS (todo 8c86d987): Stage 3 dashboard UI; Code Review + Grok of OS-identifier + server stages; apply migrations 049/050 to live Postgres; wire kill-switch to a server-settings table (none exists); merge `feat/vss-shadow-copy` -> main after review. +- Tray (todo 25fdf31a): wire `terminate_all` into watchdog policy-disable/uninstall teardown so VSS-style graceful tray shutdown (#3) actually fires. + +### Reference Information + +- gururmm commits: tray fix `137dd85` (main); VSS backend `8f61624` (branch feat/vss-shadow-copy). Gitlink tracks `fe551e4`. +- Coord todos: 8c86d987 (VSS finish), 25fdf31a (terminate_all wiring). +- Spec: `projects/msp-tools/guru-rmm/docs/specs/SPEC-016-vss-shadow-copy-management.md` (v2, Approved). +- Bug register: `docs/FEATURE_ROADMAP.md` (BUG-020 tray).