feat(birth-biologic): KSTEEN SmartBadge daily watch + remediation scripts
Corrected the 2026-05-28 SmartBadge fix on KSTEENBB2025: the older Datto Workplace Desktop v8 had been left in place (diverged from the fleet, which runs Datto Workplace v10.53.4 / Workplace2). Removed v8, installed v10, aligned the SmartBadge _CC add-in + CLSID to the EVO-X1 reference, and cleared Kristin's stuck per-user LoadBehavior=2. - ksteen-smartbadge-verify.ps1: PASS/FAIL verdict vs fleet reference - ksteen-smartbadge-fix.ps1: machine + per-user remediation - check-ksteen-smartbadge.sh: daily runner (RMM -> verdict -> #bot-alerts, coord message to Mike on drift); driven by a 7-day scheduled task on GURU-5070 - wiki: agents table, dual-Workplace SmartBadge known issue + fleet standard, 2026-05-28/29 history Syncro #32339. Coord todo 4a5b09b3 (watch expires 2026-06-05). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
62
.claude/scripts/check-ksteen-smartbadge.sh
Normal file
62
.claude/scripts/check-ksteen-smartbadge.sh
Normal file
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
# Daily verification that KSTEENBB2025 (Birth Biologic) Datto SmartBadge config
|
||||
# still matches the EVO-X1 fleet reference. Posts a #bot-alerts heartbeat each run;
|
||||
# on drift also sends a coord message to Mike. Intended to run once/day for ~1 week
|
||||
# via the "ClaudeTools - KSTEEN SmartBadge Daily" scheduled task on GURU-5070.
|
||||
set -uo pipefail
|
||||
|
||||
REPO_ROOT="${CLAUDETOOLS_ROOT:-/d/claudetools}"
|
||||
[ -d "$REPO_ROOT" ] || REPO_ROOT="$(git -C "$(dirname "$0")" rev-parse --show-toplevel 2>/dev/null)"
|
||||
VAULT="$REPO_ROOT/.claude/scripts/vault.sh"
|
||||
RMM="http://172.16.3.30:3001"
|
||||
COORD="http://172.16.3.30:8001/api/coord"
|
||||
KSTEEN="ee3c6aea-e9cc-4d2f-9e79-a38dd0eb129e"
|
||||
VERIFY_PS="$REPO_ROOT/.claude/scripts/ksteen-smartbadge-verify.ps1"
|
||||
LOG="$REPO_ROOT/.claude/logs/ksteen-smartbadge.log"
|
||||
mkdir -p "$(dirname "$LOG")"
|
||||
ts() { date '+%Y-%m-%d %H:%M:%S %Z'; }
|
||||
|
||||
alert() { bash "$REPO_ROOT/.claude/scripts/post-bot-alert.sh" "$1" >/dev/null 2>&1; }
|
||||
fail_exit() { echo "$(ts) [ERROR] $1" >> "$LOG"; alert "[SMARTBADGE-WATCH] ERROR on KSTEENBB2025 check: $1"; exit 1; }
|
||||
|
||||
EMAIL=$(bash "$VAULT" get-field infrastructure/gururmm-server.sops.yaml credentials.gururmm-api.admin-email 2>/dev/null)
|
||||
PASS=$(bash "$VAULT" get-field infrastructure/gururmm-server.sops.yaml credentials.gururmm-api.admin-password 2>/dev/null)
|
||||
[ -z "$EMAIL" ] && fail_exit "could not read RMM creds from vault"
|
||||
|
||||
TOKEN=$(curl -s -X POST "$RMM/api/auth/login" -H "Content-Type: application/json" \
|
||||
--data-binary "{\"email\":\"$EMAIL\",\"password\":\"$PASS\"}" | jq -r '.token // empty')
|
||||
[ -z "$TOKEN" ] && fail_exit "RMM login failed"
|
||||
|
||||
# Is the agent connected? If offline, note and exit cleanly (will catch it tomorrow).
|
||||
ONLINE=$(curl -s "$RMM/api/agents" -H "Authorization: Bearer $TOKEN" | jq -r --arg id "$KSTEEN" '.[] | select(.id==$id) | .status')
|
||||
if [ "$ONLINE" != "online" ]; then
|
||||
echo "$(ts) [SKIP] agent offline ($ONLINE)" >> "$LOG"
|
||||
alert "[SMARTBADGE-WATCH] KSTEENBB2025 offline - SmartBadge check skipped, will retry next run"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PAYLOAD=$(jq -n --rawfile cmd "$VERIFY_PS" '{command_type:"powershell", command:$cmd, timeout_seconds:60}')
|
||||
CID=$(curl -s -X POST "$RMM/api/agents/$KSTEEN/command" -H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" -d "$PAYLOAD" | jq -r '.command_id // empty')
|
||||
[ -z "$CID" ] && fail_exit "command dispatch failed"
|
||||
|
||||
for i in $(seq 1 20); do
|
||||
ST=$(curl -s "$RMM/api/commands/$CID" -H "Authorization: Bearer $TOKEN" | jq -r '.status')
|
||||
case "$ST" in completed|failed|cancelled|interrupted) break;; esac
|
||||
sleep 4
|
||||
done
|
||||
OUT=$(curl -s "$RMM/api/commands/$CID" -H "Authorization: Bearer $TOKEN" | jq -r '.stdout')
|
||||
RESULT=$(printf '%s' "$OUT" | grep -m1 'RESULT:')
|
||||
|
||||
if printf '%s' "$RESULT" | grep -q 'RESULT: PASS'; then
|
||||
echo "$(ts) PASS" >> "$LOG"
|
||||
alert "[SMARTBADGE-WATCH] KSTEENBB2025 PASS - Datto Workplace v10 + SmartBadge _CC add-in aligned"
|
||||
else
|
||||
REASON=$(printf '%s' "$RESULT" | sed 's/^RESULT: //')
|
||||
[ -z "$REASON" ] && REASON="no RESULT line returned: ${OUT:0:200}"
|
||||
echo "$(ts) FAIL | $REASON" >> "$LOG"
|
||||
alert "[SMARTBADGE-WATCH] *** DRIFT *** KSTEENBB2025 FAIL | $REASON"
|
||||
curl -s -X POST "$COORD/messages" -H "Content-Type: application/json" --data-binary @- <<JSON >/dev/null 2>&1
|
||||
{"from_session":"GURU-5070/smartbadge-watch","to_user":"mike","subject":"KSTEENBB2025 SmartBadge drift detected","body":"Daily watch found drift on Kristin Steen's machine: $REASON. Re-run the SmartBadge remediation (.claude/scripts ksteen-smartbadge-verify.ps1 + datto-fix.ps1).","priority":"high"}
|
||||
JSON
|
||||
fi
|
||||
65
.claude/scripts/ksteen-smartbadge-fix.ps1
Normal file
65
.claude/scripts/ksteen-smartbadge-fix.ps1
Normal file
@@ -0,0 +1,65 @@
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
$SID = 'S-1-12-1-4150293861-1139320743-1956584882-216650436' # kristinsteen
|
||||
$wp2x64 = 'C:\Program Files\Datto\Workplace2\SmartBadge\DattoSmartBadgeShim_x64.dll'
|
||||
$wp2x86 = 'C:\Program Files\Datto\Workplace2\SmartBadge\DattoSmartBadgeShim_x86.dll'
|
||||
|
||||
# --- Guard: Excel must be closed (it rewrites per-user add-in state on exit) ---
|
||||
$xl = Get-Process EXCEL -ErrorAction SilentlyContinue
|
||||
if ($xl) { Write-Output "[ABORT] EXCEL.EXE is running (pid $($xl.Id)). Close Excel before running the per-user fix."; exit 2 }
|
||||
|
||||
Write-Output "=== MACHINE-WIDE: remove v8 leftovers (match EVO-X1) ==="
|
||||
# Drop the Workplace Desktop CLSID {2B96EDC1} (x64 + WOW64)
|
||||
foreach ($k in @(
|
||||
'HKLM:\Software\Classes\CLSID\{2B96EDC1-FDF3-47E1-B177-F205E7B98DF4}',
|
||||
'HKLM:\Software\WOW6432Node\Classes\CLSID\{2B96EDC1-FDF3-47E1-B177-F205E7B98DF4}')) {
|
||||
if (Test-Path $k) { Remove-Item $k -Recurse -Force; Write-Output " removed $k" } else { Write-Output " absent $k" }
|
||||
}
|
||||
# Drop the non-_CC Datto.SmartBadgeShim add-in keys (EVO-X1 only has _CC)
|
||||
foreach ($k in @(
|
||||
'HKLM:\Software\Microsoft\Office\Excel\Addins\Datto.SmartBadgeShim',
|
||||
'HKLM:\Software\WOW6432Node\Microsoft\Office\Excel\Addins\Datto.SmartBadgeShim',
|
||||
'HKLM:\Software\Microsoft\Office\Word\Addins\Datto.SmartBadgeShim',
|
||||
'HKLM:\Software\Microsoft\Office\PowerPoint\Addins\Datto.SmartBadgeShim')) {
|
||||
if (Test-Path $k) { Remove-Item $k -Recurse -Force; Write-Output " removed $k" } else { Write-Output " absent $k" }
|
||||
}
|
||||
|
||||
Write-Output ""
|
||||
Write-Output "=== MACHINE-WIDE: verify _CC CLSID -> Workplace2 DLLs ==="
|
||||
$cc = '{3C639243-95A2-400D-B4B4-4384DA7F61D3}'
|
||||
foreach ($pair in @(@("HKLM:\Software\Classes\CLSID\$cc\InprocServer32",$wp2x64), @("HKLM:\Software\WOW6432Node\Classes\CLSID\$cc\InprocServer32",$wp2x86))) {
|
||||
$path = $pair[0]; $want = $pair[1]
|
||||
$cur = (Get-Item $path -ErrorAction SilentlyContinue)
|
||||
$val = if ($cur) { $cur.GetValue('') } else { $null }
|
||||
if ($val -ne $want) {
|
||||
if (-not (Test-Path $path)) { New-Item $path -Force | Out-Null }
|
||||
Set-ItemProperty $path -Name '(default)' -Value $want
|
||||
Set-ItemProperty $path -Name 'ThreadingModel' -Value 'Apartment'
|
||||
Write-Output " set $path -> $want"
|
||||
} else { Write-Output " ok $path -> $val" }
|
||||
}
|
||||
|
||||
Write-Output ""
|
||||
Write-Output "=== PER-USER ($SID): clear stuck disabled state ==="
|
||||
$xlAddins = "Registry::HKEY_USERS\$SID\Software\Microsoft\Office\Excel\Addins"
|
||||
# Remove non-_CC leftover in user hive (match EVO-X1 = no per-user Datto entries)
|
||||
if (Test-Path "$xlAddins\Datto.SmartBadgeShim") { Remove-Item "$xlAddins\Datto.SmartBadgeShim" -Recurse -Force; Write-Output " removed HKCU Datto.SmartBadgeShim" }
|
||||
# Reset _CC per-user override to 3 (Excel had set it to 2 = disabled)
|
||||
if (Test-Path "$xlAddins\Datto.SmartBadgeShim_CC") {
|
||||
Set-ItemProperty "$xlAddins\Datto.SmartBadgeShim_CC" -Name 'LoadBehavior' -Value 3 -Type DWord
|
||||
Write-Output " set HKCU Datto.SmartBadgeShim_CC LoadBehavior=3"
|
||||
}
|
||||
# Clear Excel Resiliency DisabledItems + crash records
|
||||
$res = "Registry::HKEY_USERS\$SID\Software\Microsoft\Office\16.0\Excel\Resiliency"
|
||||
foreach ($sub in @('DisabledItems','CrashingAddinList','DocumentRecovery')) {
|
||||
if (Test-Path "$res\$sub") {
|
||||
$i = Get-Item "$res\$sub"
|
||||
$i.GetValueNames() | ForEach-Object { Remove-ItemProperty "$res\$sub" -Name $_ -Force }
|
||||
Write-Output " cleared values under Resiliency\$sub"
|
||||
}
|
||||
}
|
||||
# Keep add-in protected from auto-disable
|
||||
$dnd = "$res\DoNotDisableAddinList"
|
||||
if (-not (Test-Path $dnd)) { New-Item $dnd -Force | Out-Null }
|
||||
Set-ItemProperty $dnd -Name 'Datto.SmartBadgeShim_CC' -Value 1 -Type DWord
|
||||
Write-Output " ensured DoNotDisableAddinList Datto.SmartBadgeShim_CC=1"
|
||||
Write-Output "=== FIX COMPLETE ==="
|
||||
44
.claude/scripts/ksteen-smartbadge-verify.ps1
Normal file
44
.claude/scripts/ksteen-smartbadge-verify.ps1
Normal file
@@ -0,0 +1,44 @@
|
||||
# Verdict check: KSTEENBB2025 Datto SmartBadge alignment vs EVO-X1 fleet reference.
|
||||
# Emits a single line: "RESULT: PASS" or "RESULT: FAIL | reason1; reason2; ..."
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
$fail = @()
|
||||
$SID = 'S-1-12-1-4150293861-1139320743-1956584882-216650436' # kristinsteen
|
||||
$cc = '{3C639243-95A2-400D-B4B4-4384DA7F61D3}' # _CC (Workplace2)
|
||||
$desk = '{2B96EDC1-FDF3-47E1-B177-F205E7B98DF4}' # Workplace Desktop (must be absent)
|
||||
$wp2x64 = 'C:\Program Files\Datto\Workplace2\SmartBadge\DattoSmartBadgeShim_x64.dll'
|
||||
$wp2x86 = 'C:\Program Files\Datto\Workplace2\SmartBadge\DattoSmartBadgeShim_x86.dll'
|
||||
|
||||
# 1. Product: Datto Workplace v10.x present, Workplace Desktop absent
|
||||
$prods = Get-ItemProperty 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*','HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' -ErrorAction SilentlyContinue
|
||||
if (-not ($prods | Where-Object { $_.DisplayName -eq 'Datto Workplace' -and $_.DisplayVersion -like '10.*' })) { $fail += 'Datto Workplace v10 not installed' }
|
||||
if ($prods | Where-Object { $_.DisplayName -like '*Workplace Desktop*' }) { $fail += 'Workplace Desktop (v8) is back' }
|
||||
|
||||
# 2. DLLs present
|
||||
if (-not (Test-Path $wp2x64)) { $fail += 'Workplace2 x64 SmartBadge DLL missing' }
|
||||
if (-not (Test-Path $wp2x86)) { $fail += 'Workplace2 x86 SmartBadge DLL missing' }
|
||||
|
||||
# 3. HKLM _CC add-in LoadBehavior=3 (HKLM + WOW64), and non-_CC absent
|
||||
foreach ($base in @('HKLM:\Software\Microsoft\Office\Excel\Addins','HKLM:\Software\WOW6432Node\Microsoft\Office\Excel\Addins')) {
|
||||
$lb = (Get-ItemProperty "$base\Datto.SmartBadgeShim_CC" -ErrorAction SilentlyContinue).LoadBehavior
|
||||
if ($lb -ne 3) { $fail += "HKLM _CC add-in LoadBehavior=$lb (want 3) at $base" }
|
||||
if (Test-Path "$base\Datto.SmartBadgeShim") { $fail += "stale non-_CC add-in present at $base" }
|
||||
}
|
||||
|
||||
# 4. _CC CLSID -> Workplace2 DLLs; Desktop CLSID absent
|
||||
$x64 = (Get-Item "HKLM:\Software\Classes\CLSID\$cc\InprocServer32" -ErrorAction SilentlyContinue)
|
||||
if (-not $x64 -or $x64.GetValue('') -ne $wp2x64) { $fail += '_CC x64 CLSID not pointing to Workplace2 x64 DLL' }
|
||||
$x86 = (Get-Item "HKLM:\Software\WOW6432Node\Classes\CLSID\$cc\InprocServer32" -ErrorAction SilentlyContinue)
|
||||
if (-not $x86 -or $x86.GetValue('') -ne $wp2x86) { $fail += '_CC WOW64 CLSID not pointing to Workplace2 x86 DLL' }
|
||||
if (Test-Path "HKLM:\Software\Classes\CLSID\$desk") { $fail += 'Workplace Desktop CLSID {2B96EDC1} reappeared' }
|
||||
|
||||
# 5. Per-user _CC not disabled (LoadBehavior must not be 2; if key absent, HKLM governs = OK)
|
||||
$ua = "Registry::HKEY_USERS\$SID\Software\Microsoft\Office\Excel\Addins\Datto.SmartBadgeShim_CC"
|
||||
if (Test-Path $ua) {
|
||||
$ulb = (Get-ItemProperty $ua -ErrorAction SilentlyContinue).LoadBehavior
|
||||
if ($ulb -eq 2 -or $ulb -eq 0) { $fail += "per-user _CC LoadBehavior=$ulb (Excel disabled it)" }
|
||||
}
|
||||
# 6. Disabled-items check
|
||||
$res = "Registry::HKEY_USERS\$SID\Software\Microsoft\Office\16.0\Excel\Resiliency\DisabledItems"
|
||||
if (Test-Path $res) { if ((Get-Item $res).ValueCount -gt 0) { $fail += 'Excel Resiliency DisabledItems has entries' } }
|
||||
|
||||
if ($fail.Count -eq 0) { Write-Output 'RESULT: PASS' } else { Write-Output ("RESULT: FAIL | " + ($fail -join '; ')) }
|
||||
Reference in New Issue
Block a user