diff --git a/session-logs/2026-05-29-session.md b/session-logs/2026-05-29-session.md index 6091d5e..4ae4c2e 100644 --- a/session-logs/2026-05-29-session.md +++ b/session-logs/2026-05-29-session.md @@ -224,3 +224,106 @@ manifest versions now start at 0.2.2 (legitimate first signed release). ### Reference Information - GC release commits: `e7f38ce`/`5727ccf` (jsign 7.1 + verify fix). Release run #22 green. Release `v0.2.2`. - claudetools: `…70d2190` (submodule bump for verify fix). + +--- + +## Update: 20:47 PT — Birth Biologic SmartBadge correction, GuruRMM 0.3.36 deploy, alert re-routing, Rednour onboarding + onboarding diagnostic + +## User +- **User:** Mike Swanson (mike) +- **Machine:** GURU-5070 +- **Role:** admin + +### Session Summary + +Began with Birth Biologic: Kristin Steen (KSTEENBB2025) could not use the Datto SmartBadge Excel add-in. RMM recon against her machine and the working reference (EVO-X1) showed the 2026-05-28 fix had gone the wrong direction — it removed the newer Datto Workplace v10.53.4 (Workplace2, the fleet standard) and left the older Workplace Desktop v8.50.13. Corrected it: Mike Revo-uninstalled v8 (clean, swept the `{2B96EDC1}` CLSID + non-`_CC` add-in keys), then via RMM installed Workplace v10.53.4 from her Downloads, aligned the SmartBadge `_CC` CLSID/add-in to EVO-X1, and cleared her stuck per-user `LoadBehavior=2`. Verified byte-for-byte against EVO-X1. Filed Syncro #32339 public tech notes + 1hr warranty, and stood up a 7-day daily verification (scheduled task on GURU-5070 + coord todo). + +GuruRMM Integration Center ("Store") planning: confirmed it is greenfield (MSP360 built, Syncro/catalog not). Locked five design decisions (partner-scoped, generic JSONB config storage with MSP360 migrated in, catalog + Syncro built together, code-defined plugin registry, AES-256-GCM reuse) and landed a revised SPEC-005 as gururmm PR #28. Parked per Mike; tracked in coord todo. Mike also questioned why site API keys are published when enrollment correlates by site_id — code review confirmed the modern `POST /enroll` gate is site_id-only and the site api_key is used only by the legacy WS path + install-info; filed as a security/arch decision. + +Resolved Howard's blocker: the gururmm server on 172.16.3.30 was still running 0.3.32 despite an 18:51 restart. Root cause — the 0.3.36 binary had been copied to `/usr/local/bin/gururmm-server`, but the systemd `ExecStart` is `/opt/gururmm/gururmm-server`, which was still yesterday's 0.3.32. Copied 0.3.36 to the correct path, restarted, verified `/status` = 0.3.36 and command flow (test command to ACG-DC16 returned completed/exit 0). Replied to Howard on coord. + +Re-routed bot alerts: RMM/Dev alerts (`[RMM]/[DEPLOY]/[DEV]/[BUILD]/[GURURMM]/[SMARTBADGE-WATCH]`) now auto-route to the new private #dev-alerts (Howard + Mike); Syncro/general stay in #bot-alerts. Onboarded Rednour Law Offices (client + site "Main", `GREEN-FALCON-7214`), vaulted the one-time enrollment key, and documented the whole flow as `/rmm onboard` in the skill. Three Rednour agents enrolled and online. + +Built Phase 1 of an onboarding diagnostic (`/rmm diagnose`): a PS5.1/ASCII/SYSTEM-safe security+health probe dispatched via RMM, a triage layer grading RED/AMBER/GREEN, immutable per-client baselines, prior-baseline diff, and CRITICAL alerts to #dev-alerts. Code-reviewed (no blockers; folded in immutability guard, severity-independent finding ids, Defender-unknown sentinel, expanded competitor/backup detection). Baselined all three Rednour machines. Mike clarified the "foreign agents" it flagged (ScreenConnect/CW Control, Splashtop, Syncro, Datto RMM+EDR) are ACG's own stack — filed a detection-tuning todo and saved a memory so they aren't re-flagged. Real day-one findings surfaced: two machines on EOL Win10 22H2, RDP-without-NLA on REDNOURCARRIEVI, missing BitLocker, low disk, no backup agent on FrontDeskReception. + +### Key Decisions + +- **Reversed the 2026-05-28 SmartBadge fix** — the fleet standard is the *newer* Datto Workplace v10.53.4 (Workplace2); Workplace Desktop v8 is older despite the name. EVO-X1 used as the canonical reference. +- **Let Mike Revo-uninstall v8** rather than silent-uninstall via RMM — GUI uninstaller sweeps leftovers a silent uninstall leaves; coordinated to avoid both touching the live box at once. +- **SmartBadge daily watch via local scheduled task, not /schedule** — `/schedule` provisions cloud agents that can't reach the internal RMM API (172.16.3.30); only a LAN machine can. +- **Integration Center: partner-scoped, generic JSONB storage, catalog+Syncro together, code plugin registry, AES-256-GCM reuse** — corrected SPEC-005's internal-only, DB-catalog-table assumptions. +- **Server deploy to `/opt/gururmm/gururmm-server`** — that is the real `ExecStart`; the wiki's `/usr/local/bin` path is stale and caused the failed deploy. +- **Alert routing by message prefix** — auto-routes existing call sites with no edits; explicit `dev`/`bot` 2nd-arg override retained. +- **Onboarding diagnostic Phase 1 = script via /rmm now, Phase 3 = native GuruRMM feature later**; baselines stored in repo now, GuruRMM DB when the native feature lands ("both"). + +### Problems Encountered + +- **Excel rewrote per-user add-in state on exit** — required Excel closed before clearing Kristin's `LoadBehavior=2`; the fix script guards on EXCEL.EXE. +- **sops encrypt failures** — needed `--config "$VR/.sops.yaml"` from outside the vault dir; bare YAML dates threw `Cannot walk value, unknown type: time.Time` (quote them); failed encrypt leaves plaintext on disk (verify with `grep -c 'ENC['`). Documented in `/rmm onboard`. +- **Server "rebuild" didn't take** — 0.3.36 binary was deployed to the wrong path (`/usr/local/bin` vs the service's `/opt/gururmm`). Fixed by copying to the correct path + restart. +- **Discord 400 on em-dash** — a unicode em-dash in an alert broke the JSON post (Windows Git Bash argv encoding); ASCII-only is already the rule. +- **Agent ~32KB command-size cap** — the 62KB diagnostic probe was rejected; runner base64-chunks the upload (<24KB chunks) then decodes/runs/cleans up. +- **Detection false positives** — substring matches (`cove`->Recovery, `ltsvc`->Vaultsvc) and PS5.1 scalar `.Count`; fixed with `\b` anchors and `@(...)` wrapping. Then ACG's own stack flagged as "foreign" — filed tuning todo + memory. +- **git push rejected (non-fast-forward)** twice — other instances had advanced origin; resolved with `pull --rebase` then push. + +### Configuration Changes + +- KSTEENBB2025 (via RMM): uninstalled Datto Workplace Desktop v8.50.13 (Revo); installed Datto Workplace v10.53.4; `_CC` CLSID `{3C639243}` -> Workplace2 x64/x86 DLLs; removed `{2B96EDC1}` + non-`_CC` add-in keys; per-user `Datto.SmartBadgeShim_CC` LoadBehavior 2->3, cleared Resiliency, set DoNotDisableAddinList. +- 172.16.3.30: `cp /usr/local/bin/gururmm-server /opt/gururmm/gururmm-server` (0.3.36), old saved `/opt/gururmm/gururmm-server.0.3.32.bak`, `systemctl restart gururmm-server`. +- `.claude/scripts/post-bot-alert.sh` — dev/bot channel routing by prefix + override arg. +- `.claude/scripts/ksteen-smartbadge-verify.ps1`, `ksteen-smartbadge-fix.ps1`, `check-ksteen-smartbadge.sh` — new (SmartBadge verify/fix/daily-runner). +- `.claude/scripts/onboarding-diagnostic.ps1`, `run-onboarding-diagnostic.sh` — new (onboarding diagnostic Phase 1). +- `.claude/commands/rmm.md` — added `/rmm onboard`, `/rmm diagnose`, dev-alerts routing notes. +- `.claude/memory/reference_acg_msp_stack.md` (+ MEMORY.md index) — new. +- `wiki/clients/birth-biologic.md` — agents table, dual-Workplace SmartBadge known issue + fleet standard, 5/28-5/29 history. +- Vault `D:/vault/clients/rednour/gururmm-site-main.sops.yaml` — new (Rednour enrollment key). +- Scheduled task "ClaudeTools - KSTEEN SmartBadge Daily" on GURU-5070 (daily 09:00, 2026-05-30..06-05). +- gururmm PR #28 (branch `feat/spec-005-integration-center`) — revised SPEC-005. + +### Credentials & Secrets + +- Rednour GuruRMM site API key (one-time, `grmm_...`): vaulted at `clients/rednour/gururmm-site-main.sops.yaml` (credentials.api_key). Site `GREEN-FALCON-7214`. +- Gitea API token field path correction: `services/gitea.sops.yaml` -> `credentials.api.api-token` (not `credentials.api-token`). +- Syncro API key: `msp-tools/syncro.sops.yaml` -> `credentials.credential` (unchanged). +- No new secrets created beyond the Rednour site key. + +### Infrastructure & Servers + +- GuruRMM server 172.16.3.30: `/status` -> 0.3.36; service `ExecStart=/opt/gururmm/gururmm-server` (NOT /usr/local/bin — wiki stale); build via `sudo /opt/gururmm/build-server.sh` (builds in `/home/guru/gururmm/server`, log `/var/log/gururmm-build.log`). +- Rednour Law Offices: client `85f7cff4-d4db-48a8-b477-b8788122a361`, site Main `c7f5787c-8e71-45b3-841f-fa52436f7d26` / `GREEN-FALCON-7214`. Agents: FrontDeskReception `04765560-...`, LegalAsst `18825ea7-...`, rednourcarrievirt `8e4e2221-...`. +- BB agents: BB-SERVER `6c02baa7`, KSTEENBB2025 `ee3c6aea`, EVO-X1 `9595f002`, BB-Office2 `48763401`. +- Discord channels: #bot-alerts `624710699771232265`, #dev-alerts `1509998508198068484` (private). + +### Commands & Outputs + +```bash +# Server fix (172.16.3.30) +sudo cp /opt/gururmm/gururmm-server /opt/gururmm/gururmm-server.0.3.32.bak +sudo systemctl stop gururmm-server +sudo cp /usr/local/bin/gururmm-server /opt/gururmm/gururmm-server +sudo systemctl start gururmm-server +curl -s localhost:3001/status | jq .version # -> "0.3.36" + +# vault new entry (non-interactive) +sops --config "$VR/.sops.yaml" --encrypt --in-place # quote dates; secrets under credentials: + +# onboarding diagnostic +bash .claude/scripts/run-onboarding-diagnostic.sh +``` + +### Pending / Incomplete Tasks + +- **Rednour:** real findings to action — 2x EOL Win10 22H2 (LegalAsst, REDNOURCARRIEVI), RDP-without-NLA (REDNOURCARRIEVI), missing BitLocker, low disk (REDNOURCARRIEVI ~12%), no backup agent (FrontDeskReception). Mike to direct remediation. +- **KSTEENBB2025:** SmartBadge confirmed working; 7-day watch running (coord todo `4a5b09b3`). +- **Integration Center:** PR #28 open for review/merge; then /shape-spec + scaffold (coord todo `0198ba04`). PARKED. +- **GuruRMM enrollment security:** site_id-only enrollment gate decision (coord todo `00074cd8`). +- **Onboarding diagnostic:** Phase 3 native feature (coord todo `76c6050b`); single-element-array MD-table bug (`cc5dbdfa`); ACG-stack detection allowlist tuning (`3d886f1a`). +- **Wiki:** gururmm.md ExecStart path (/opt vs /usr/local/bin) should be corrected; no wiki article for Rednour yet. + +### Reference Information + +- Syncro #32339 (BB SmartBadge): public cmt 414607766, warranty li 42639366. Customer 17983014. +- gururmm PR #28: https://git.azcomputerguru.com/azcomputerguru/gururmm/pulls/28 +- Coord: Howard reply f888b21c; broadcast bafae411; todos 4a5b09b3 / 0198ba04 / 00074cd8 / 76c6050b / cc5dbdfa / 3d886f1a. +- Rednour install page: https://rmm.azcomputerguru.com/install/GREEN-FALCON-7214 +- Baselines: `clients/rednour/onboarding-baselines/` (FRONTDESKRECEPT, LEGALASST, REDNOURCARRIEVI). diff --git a/temp/SPEC-005-integration-catalog.md b/temp/SPEC-005-integration-catalog.md new file mode 100644 index 0000000..81bdf57 --- /dev/null +++ b/temp/SPEC-005-integration-catalog.md @@ -0,0 +1,196 @@ +# SPEC-005: Integration Catalog ("Integration Center") + +**Status:** Approved for build (planning locked 2026-05-29) +**Priority:** P2 — built in tandem with SPEC-002 (Syncro PSA) +**Requested By:** Mike Swanson (2026-05-18; scope locked 2026-05-29) +**Estimated Effort:** Large (catalog + Syncro plugin + MSP360 migration) + +--- + +## Overview + +The GuruRMM **Integration Center** is a centralized, **partner-scoped** surface for managing third-party integrations (Syncro PSA, MSP360 Managed Backup, and future providers). Each **partner (MSP)** browses the available catalog, configures the integrations they want for their own tenant, and monitors health/status — without per-tool fragmentation. + +This is an **internal catalog**, not a public marketplace. App-store-style discovery, monetization/entitlement, and third-party-submitted integrations are explicitly **out of scope** (may be revisited as a separate "Store" initiative later). + +**Audience:** Partner-level users (ADR-001 Dev -> Partner -> Client model). Partner-admins configure; partner-users have read-only status visibility. Dev/ACG (partner #1) sees all partners. + +**User Benefits** +- Centralized, one-screen management of all integrations for a partner. +- One-click configure with validation; clear status (Not Configured / Configured / Active / Error). +- Per-partner health monitoring + audit trail. + +--- + +## Locked Decisions (2026-05-29) + +1. **Partner-scoped.** Every configuration and audit row carries `partner_id NOT NULL REFERENCES partners(id)`. The API derives `partner_id` from the caller's JWT; it is never client-supplied. This mirrors the existing `mspbackups_config(partner_id, UNIQUE(partner_id))` pattern and enforces tenant isolation server-side (closing the same horizontal-privilege class as the known `credentials/:id/reveal` finding). +2. **Generic JSONB config storage.** A single `integration_configurations` table holds all per-partner configs in a `settings JSONB` column. MSP360's existing `mspbackups_config` is **migrated into this table** (see Migration). No per-plugin config tables. +3. **Catalog + Syncro built together.** MSP360 is wrapped as the first plugin (its config migrated in); Syncro (SPEC-002) is implemented as the first *new* plugin through the catalog pattern, proving the full configure flow. Both ship with the catalog. +4. **Available-integration metadata lives in code**, not the DB. The plugin registry (the `IntegrationPlugin` trait implementations) is the source of truth for the catalog listing (name, provider, category, required fields). The DB stores only per-partner configurations, status, and audit — no `integrations` catalog table to drift out of sync with shipped code. +5. **Reuse AES-256-GCM** (migration `016` credentials encryption) for secret-typed fields. Secret fields within `settings` are encrypted at rest and masked on read; non-secret fields stored plaintext in the JSONB. + +--- + +## Scope + +### Included (v1) +- Integration Center UI: browse the catalog (from the code registry), configure, and monitor — partner-scoped. +- Plugins: **MSP360** (migrated from standalone) and **Syncro PSA** (new, built alongside). +- One-click configuration flow with per-plugin field validation. +- Status tracking: Not Configured / Configured / Active / Error, with last-health-check + error message. +- Per-partner audit logging of all configuration changes. +- Plugin/extension architecture (trait + registry) so new integrations are additive. + +### Out of Scope +- Public/marketplace discovery, third-party-submitted integrations. +- Monetization / licensing / entitlement. +- Multiple instances of the same integration per partner (v1 = one instance per integration per partner; multi-instance deferred to Phase 2). +- Non-IT integrations. + +### Success Criteria +- A partner can configure Syncro and MSP360 from one screen; status reflects real health. +- MSP360 migration is transparent — the existing MSPBackups feature keeps working, no partner reconfiguration. +- Tenant isolation verified: no partner can read or affect another partner's integration config. + +--- + +## Architecture + +### Plugin registry (code = source of truth for the catalog) + +```rust +// server/src/integrations/plugin_interface.rs +#[async_trait] +pub trait IntegrationPlugin: Send + Sync { + fn metadata(&self) -> IntegrationMetadata; // static catalog info + async fn validate(&self, settings: &serde_json::Value) -> Result<()>; // pre-save validation + async fn configure(&self, partner_id: Uuid, settings: serde_json::Value) -> Result<()>; + async fn health_check(&self, partner_id: Uuid) -> Result; +} + +pub struct IntegrationMetadata { + pub key: String, // stable id, e.g. "syncro", "msp360" + pub name: String, + pub provider: String, + pub category: IntegrationCategory, // Psa, Backup, Rmm, Monitoring, ... + pub description: String, + pub fields: Vec, // drives the dynamic config form +} + +pub struct FieldSpec { + pub key: String, + pub label: String, + pub kind: FieldKind, // Text | Secret | Select(Vec) | Url | Bool + pub required: bool, + pub help: Option, +} + +pub enum HealthStatus { Ok, Degraded(String), Error(String) } +``` + +A static `IntegrationRegistry` holds `HashMap>`, built at startup. `GET /api/integrations` returns registry metadata joined with the calling partner's stored config status. + +### Data model (generic, partner-scoped) + +```sql +-- New: per-partner integration configuration (generic JSONB) +CREATE TABLE integration_configurations ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + partner_id UUID NOT NULL REFERENCES partners(id) ON DELETE CASCADE, + integration_key VARCHAR(64) NOT NULL, -- matches plugin registry key + settings JSONB NOT NULL DEFAULT '{}', -- secret-typed fields encrypted at rest + status VARCHAR(20) NOT NULL DEFAULT 'Configured' + CHECK (status IN ('Not Configured','Configured','Active','Error')), + last_health_check TIMESTAMPTZ, + error_message TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), + CONSTRAINT uk_integration_partner_key UNIQUE (partner_id, integration_key) +); +CREATE INDEX idx_integration_cfg_partner ON integration_configurations(partner_id); + +-- New: per-partner audit +CREATE TABLE integration_audit_logs ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + partner_id UUID NOT NULL REFERENCES partners(id) ON DELETE CASCADE, + user_id UUID REFERENCES users(id), + integration_key VARCHAR(64) NOT NULL, + action VARCHAR(100) NOT NULL, -- configured | reconfigured | enabled | disabled | health_error + details JSONB, + created_at TIMESTAMPTZ NOT NULL DEFAULT now() +); +CREATE INDEX idx_integration_audit_partner ON integration_audit_logs(partner_id); +CREATE INDEX idx_integration_audit_created ON integration_audit_logs(created_at DESC); +``` + +> Note: there is intentionally **no `integrations` catalog table** — available integrations come from the code registry (Decision #4). + +### MSP360 migration (live integration — handle with care) + +`mspbackups_config` is live and partner-scoped already. Migration: +1. Add the new tables (above). +2. Data migration: for each `mspbackups_config` row, insert an `integration_configurations` row with `integration_key='msp360'`, `status='Active'`, and `settings` = the MSP360 fields (secret fields re-encrypted via the credentials AES-256-GCM module). +3. Refactor the `mspbackups` module to read/write its config through the generic store (an accessor that serializes/deserializes the MSP360 settings shape), OR keep `mspbackups_config` as the system of record and have the `msp360` plugin **adapt** to it during a transition window. **Recommended: dual-write + read-from-new behind a flag, verify parity, then drop `mspbackups_config`** in a follow-up migration — never a hard cutover on a working integration. +4. The existing `MSPBackups.tsx` page stays; the Integration Center adds a unified entry that deep-links to it. + +> This is the one genuinely risky step. It must ship behind a feature flag with a verified rollback (keep `mspbackups_config` until parity is confirmed in production). + +### API (partner-scoped; keyed by plugin key) + +- `GET /api/integrations` — catalog (registry metadata) + this partner's status per integration +- `GET /api/integrations/:key` — detail + field spec + current (masked) config + status +- `POST /api/integrations/:key/configure` — validate + store (partner from JWT); audit +- `POST /api/integrations/:key/reconfigure` — update existing +- `POST /api/integrations/:key/test` — run `health_check` on demand +- `DELETE /api/integrations/:key` — remove this partner's configuration +- `GET /api/integrations/:key/audit` — partner-scoped audit log + +RBAC: configure/reconfigure/delete require partner-admin; reads require partner membership. `partner_id` always from JWT, never the body/path. + +### Health checks +A scheduled job (every ~15 min) iterates each partner's configured integrations, calls `health_check(partner_id)`, updates `status`/`last_health_check`/`error_message`, and writes an audit row on any status transition. Error transitions may raise an alert via the existing alerting subsystem. + +### Dashboard +- `pages/IntegrationCenter.tsx` — grid of `IntegrationCard` tiles (name, category, status badge), filterable by category. +- `pages/IntegrationDetail.tsx` — dynamic `ConfigurationForm` rendered from the plugin's `FieldSpec[]`, status panel, audit list, "Test connection" button. +- Reuse the existing status-badge helper pattern (explicit `getStatusBadgeClass()` function — not a `Record` const; see project anti-patterns). + +--- + +## Security +- **Tenant isolation:** every query filters by `partner_id` from JWT. Server-side enforced; covered by tests that attempt cross-partner access. +- **Secrets:** secret-typed fields encrypted at rest (AES-256-GCM, migration 016 module); masked in all API responses; never logged. Audit `details` must redact secrets. +- **Input validation:** each plugin validates `settings` against its `FieldSpec` before persist. +- **Audit:** all config mutations logged with user + partner + action. + +--- + +## Rollout (combined catalog + Syncro) +1. **Infra:** migrations (new tables), plugin trait + registry, health-check scheduler, encryption helpers. +2. **Plugins:** MSP360 adapter (dual-write/verify) + Syncro plugin (SPEC-002 functionality behind the plugin interface). +3. **API:** partner-scoped endpoints + RBAC + tests (incl. cross-partner isolation). +4. **Dashboard:** Integration Center + detail/config form + status/audit. +5. **Cutover:** behind `feature/integration-center` flag; verify MSP360 parity in prod; drop `mspbackups_config` in a follow-up migration. + +Holistic-development rule applies: backend + API + dashboard + docs ship together (DESIGN.md). + +--- + +## Dependencies +- **SPEC-002 (Syncro PSA)** — built in tandem; its connection/config logic implemented as the `syncro` plugin. +- **SPEC-004 (MSP360)** — existing; migrated into the catalog as the `msp360` plugin. +- **partners / multi-tenancy (ADR-001)** — already in place (`partners` table, `clients.partner_id`). + +## Resolved Open Questions +- Multiple instances per partner? **No in v1** (UNIQUE(partner_id, integration_key)); Phase 2. +- Config storage? **Generic JSONB** (Decision #2). +- Build order? **Catalog + Syncro together** (Decision #3). +- Non-admin visibility? **Read-only status**, yes. + +--- + +## References +- [SPEC-002 Syncro PSA](./SPEC-002-syncro-psa-integration.md), [SPEC-004 MSP360](./SPEC-004-mspbackups-integration.md) +- ADR-001 multi-tenancy (Dev/Partner/Client); migration `016` (credentials AES-256-GCM); `034/035/044` (MSP360) +- Patterns: plugin/registry, generic JSONB config, partner-scoped tenancy diff --git a/temp/datto-fix.ps1 b/temp/datto-fix.ps1 new file mode 100644 index 0000000..e7053bc --- /dev/null +++ b/temp/datto-fix.ps1 @@ -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 ===" diff --git a/temp/datto-install-v10.ps1 b/temp/datto-install-v10.ps1 new file mode 100644 index 0000000..fe6601a --- /dev/null +++ b/temp/datto-install-v10.ps1 @@ -0,0 +1,19 @@ +$ErrorActionPreference = 'Stop' +$exe = 'C:\Users\kristinsteen\Downloads\DattoWorkplaceSetup_v10.5.3.4.exe' +if (-not (Test-Path $exe)) { Write-Output "[ERROR] installer missing: $exe"; exit 1 } + +# Safety: confirm v8 is actually gone before installing v10 +$v8 = Get-ItemProperty 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*','HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like '*Workplace Desktop*' } +if ($v8) { Write-Output "[ABORT] Workplace Desktop v8 still present - not installing yet:"; $v8 | ForEach-Object { Write-Output (" {0} v{1}" -f $_.DisplayName,$_.DisplayVersion) }; exit 2 } + +Write-Output "[INFO] v8 confirmed absent. Starting silent install of v10..." +$p = Start-Process -FilePath $exe -ArgumentList '/install','/quiet','/norestart' -Wait -PassThru +Write-Output ("[INFO] Installer exit code: {0}" -f $p.ExitCode) +if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) { Write-Output "[WARNING] non-zero/non-3010 exit; check Bootstrap log" } + +Start-Sleep -Seconds 8 +Write-Output "=== Post-install product check ===" +Get-ItemProperty 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*','HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like '*Workplace*' } | ForEach-Object { Write-Output (" {0} v{1} {2}" -f $_.DisplayName,$_.DisplayVersion,$_.InstallLocation) } +Get-ChildItem 'C:\Program Files\Datto' -ErrorAction SilentlyContinue | ForEach-Object { Write-Output (" folder: {0}" -f $_.Name) } +Get-ChildItem 'C:\Program Files\Datto\Workplace2\SmartBadge' -Filter 'DattoSmartBadgeShim*.dll' -ErrorAction SilentlyContinue | ForEach-Object { Write-Output (" dll: {0}" -f $_.FullName) } +Write-Output "=== END ===" diff --git a/temp/datto-prestage.ps1 b/temp/datto-prestage.ps1 new file mode 100644 index 0000000..615edfe --- /dev/null +++ b/temp/datto-prestage.ps1 @@ -0,0 +1,27 @@ +$ErrorActionPreference = 'SilentlyContinue' +Write-Output "=== Locate v10 installer (all user Downloads + common) ===" +$roots = @("C:\Users\kristinsteen\Downloads","C:\Users\Public\Downloads") +Get-ChildItem 'C:\Users\*\Downloads' -Filter 'DattoWorkplace*' -ErrorAction SilentlyContinue | ForEach-Object { + Write-Output (" {0} ({1:N1} MB, modified {2})" -f $_.FullName, ($_.Length/1MB), $_.LastWriteTime) +} +Get-ChildItem 'C:\Users\*\Downloads' -Filter '*Workplace*Setup*' -ErrorAction SilentlyContinue | ForEach-Object { + Write-Output (" {0} ({1:N1} MB, modified {2})" -f $_.FullName, ($_.Length/1MB), $_.LastWriteTime) +} + +Write-Output "" +Write-Output "=== Datto Workplace Desktop uninstall strings ===" +$paths = @('HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*','HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*') +foreach ($p in $paths) { + Get-ItemProperty $p -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like '*Workplace*' } | ForEach-Object { + Write-Output (" Name: {0} v{1}" -f $_.DisplayName, $_.DisplayVersion) + Write-Output (" Key: {0}" -f $_.PSChildName) + Write-Output (" Uninstall: {0}" -f $_.UninstallString) + Write-Output (" QuietUninstall: {0}" -f $_.QuietUninstallString) + } +} + +Write-Output "" +Write-Output "=== Datto Workplace Desktop process/service state ===" +Get-Process WorkplaceDesktop -ErrorAction SilentlyContinue | ForEach-Object { Write-Output (" proc WorkplaceDesktop pid {0}" -f $_.Id) } +Get-Service -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like '*Workplace*' } | ForEach-Object { Write-Output (" svc {0} [{1}]" -f $_.Name, $_.Status) } +Write-Output "=== END ===" diff --git a/temp/datto-recon.ps1 b/temp/datto-recon.ps1 new file mode 100644 index 0000000..b344201 --- /dev/null +++ b/temp/datto-recon.ps1 @@ -0,0 +1,73 @@ +$ErrorActionPreference = 'SilentlyContinue' +Write-Output "=== HOST ===" +Write-Output $env:COMPUTERNAME +Write-Output "=== LOGGED-ON USER ===" +query user 2>$null + +Write-Output "" +Write-Output "=== INSTALLED DATTO/WORKPLACE PRODUCTS (uninstall keys) ===" +$paths = @( + 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*', + 'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' +) +foreach ($p in $paths) { + Get-ItemProperty $p -ErrorAction SilentlyContinue | + Where-Object { $_.DisplayName -like '*Datto*' -or $_.DisplayName -like '*Workplace*' } | + ForEach-Object { Write-Output (" {0} | v{1} | {2}" -f $_.DisplayName, $_.DisplayVersion, $_.InstallLocation) } +} + +Write-Output "" +Write-Output "=== DATTO PROGRAM FOLDERS ===" +Get-ChildItem 'C:\Program Files\Datto' -ErrorAction SilentlyContinue | ForEach-Object { Write-Output (" {0} (modified {1})" -f $_.Name, $_.LastWriteTime) } +Write-Output "--- SmartBadge DLLs present ---" +Get-ChildItem 'C:\Program Files\Datto' -Recurse -Filter 'DattoSmartBadgeShim*.dll' -ErrorAction SilentlyContinue | ForEach-Object { Write-Output (" {0}" -f $_.FullName) } + +Write-Output "" +Write-Output "=== DATTO WORKPLACE SERVICES / PROCESSES ===" +Get-Service -ErrorAction SilentlyContinue | Where-Object { $_.Name -like '*Datto*' -or $_.DisplayName -like '*Workplace*' } | ForEach-Object { Write-Output (" svc {0} [{1}] {2}" -f $_.Name, $_.Status, $_.DisplayName) } +Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.ProcessName -like '*Workplace*' -or $_.ProcessName -like '*Datto*' } | ForEach-Object { Write-Output (" proc {0} (pid {1}) {2}" -f $_.ProcessName, $_.Id, $_.Path) } + +Write-Output "" +Write-Output "=== HKLM Excel Addins (Datto) ===" +foreach ($base in @('HKLM:\Software\Microsoft\Office\Excel\Addins','HKLM:\Software\WOW6432Node\Microsoft\Office\Excel\Addins')) { + Write-Output "[$base]" + Get-ChildItem $base -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -like '*Datto*' } | ForEach-Object { + Write-Output (" {0} LoadBehavior={1}" -f $_.PSChildName, (Get-ItemProperty $_.PSPath).LoadBehavior) + } +} + +Write-Output "" +Write-Output "=== CLSID InprocServer32 (SmartBadge shims) ===" +foreach ($clsid in @('{2B96EDC1-FDF3-47E1-B177-F205E7B98DF4}','{3C639243-95A2-400D-B4B4-4384DA7F61D3}')) { + foreach ($base in @("HKLM:\Software\Classes\CLSID\$clsid\InprocServer32","HKLM:\Software\WOW6432Node\Classes\CLSID\$clsid\InprocServer32")) { + $item = Get-Item $base -ErrorAction SilentlyContinue + if ($item) { + $def = $item.GetValue('') + $tm = $item.GetValue('ThreadingModel') + Write-Output (" {0}`n -> {1} [TM={2}]" -f $base, $def, $tm) + } else { + Write-Output (" {0}`n -> " -f $base) + } + } +} + +Write-Output "" +Write-Output "=== Active user hive: Excel addin LoadBehavior + Resiliency ===" +Get-ChildItem 'Registry::HKEY_USERS' -ErrorAction SilentlyContinue | Where-Object { $_.Name -match 'S-1-12-1-|S-1-5-21-' -and $_.Name -notmatch '_Classes$' } | ForEach-Object { + $sid = $_.PSChildName + $ua = "Registry::HKEY_USERS\$sid\Software\Microsoft\Office\Excel\Addins" + if (Test-Path $ua) { + Get-ChildItem $ua -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -like '*Datto*' } | ForEach-Object { + Write-Output (" [$sid] HKCU addin {0} LoadBehavior={1}" -f $_.PSChildName, (Get-ItemProperty $_.PSPath).LoadBehavior) + } + } + $rb = "Registry::HKEY_USERS\$sid\Software\Microsoft\Office\16.0\Excel\Resiliency" + if (Test-Path "$rb\DoNotDisableAddinList") { + (Get-ItemProperty "$rb\DoNotDisableAddinList").PSObject.Properties | Where-Object { $_.Name -notlike 'PS*' } | ForEach-Object { Write-Output (" [$sid] DoNotDisable {0}={1}" -f $_.Name, $_.Value) } + } + if (Test-Path "$rb\DisabledItems") { + $di = Get-Item "$rb\DisabledItems" + if ($di.ValueCount -gt 0) { Write-Output (" [$sid] DisabledItems has {0} entries (Excel has disabled an add-in)" -f $di.ValueCount) } + } +} +Write-Output "=== END RECON ===" diff --git a/temp/update.md b/temp/update.md new file mode 100644 index 0000000..b3a97b0 --- /dev/null +++ b/temp/update.md @@ -0,0 +1,103 @@ + +--- + +## Update: 20:47 PT — Birth Biologic SmartBadge correction, GuruRMM 0.3.36 deploy, alert re-routing, Rednour onboarding + onboarding diagnostic + +## User +- **User:** Mike Swanson (mike) +- **Machine:** GURU-5070 +- **Role:** admin + +### Session Summary + +Began with Birth Biologic: Kristin Steen (KSTEENBB2025) could not use the Datto SmartBadge Excel add-in. RMM recon against her machine and the working reference (EVO-X1) showed the 2026-05-28 fix had gone the wrong direction — it removed the newer Datto Workplace v10.53.4 (Workplace2, the fleet standard) and left the older Workplace Desktop v8.50.13. Corrected it: Mike Revo-uninstalled v8 (clean, swept the `{2B96EDC1}` CLSID + non-`_CC` add-in keys), then via RMM installed Workplace v10.53.4 from her Downloads, aligned the SmartBadge `_CC` CLSID/add-in to EVO-X1, and cleared her stuck per-user `LoadBehavior=2`. Verified byte-for-byte against EVO-X1. Filed Syncro #32339 public tech notes + 1hr warranty, and stood up a 7-day daily verification (scheduled task on GURU-5070 + coord todo). + +GuruRMM Integration Center ("Store") planning: confirmed it is greenfield (MSP360 built, Syncro/catalog not). Locked five design decisions (partner-scoped, generic JSONB config storage with MSP360 migrated in, catalog + Syncro built together, code-defined plugin registry, AES-256-GCM reuse) and landed a revised SPEC-005 as gururmm PR #28. Parked per Mike; tracked in coord todo. Mike also questioned why site API keys are published when enrollment correlates by site_id — code review confirmed the modern `POST /enroll` gate is site_id-only and the site api_key is used only by the legacy WS path + install-info; filed as a security/arch decision. + +Resolved Howard's blocker: the gururmm server on 172.16.3.30 was still running 0.3.32 despite an 18:51 restart. Root cause — the 0.3.36 binary had been copied to `/usr/local/bin/gururmm-server`, but the systemd `ExecStart` is `/opt/gururmm/gururmm-server`, which was still yesterday's 0.3.32. Copied 0.3.36 to the correct path, restarted, verified `/status` = 0.3.36 and command flow (test command to ACG-DC16 returned completed/exit 0). Replied to Howard on coord. + +Re-routed bot alerts: RMM/Dev alerts (`[RMM]/[DEPLOY]/[DEV]/[BUILD]/[GURURMM]/[SMARTBADGE-WATCH]`) now auto-route to the new private #dev-alerts (Howard + Mike); Syncro/general stay in #bot-alerts. Onboarded Rednour Law Offices (client + site "Main", `GREEN-FALCON-7214`), vaulted the one-time enrollment key, and documented the whole flow as `/rmm onboard` in the skill. Three Rednour agents enrolled and online. + +Built Phase 1 of an onboarding diagnostic (`/rmm diagnose`): a PS5.1/ASCII/SYSTEM-safe security+health probe dispatched via RMM, a triage layer grading RED/AMBER/GREEN, immutable per-client baselines, prior-baseline diff, and CRITICAL alerts to #dev-alerts. Code-reviewed (no blockers; folded in immutability guard, severity-independent finding ids, Defender-unknown sentinel, expanded competitor/backup detection). Baselined all three Rednour machines. Mike clarified the "foreign agents" it flagged (ScreenConnect/CW Control, Splashtop, Syncro, Datto RMM+EDR) are ACG's own stack — filed a detection-tuning todo and saved a memory so they aren't re-flagged. Real day-one findings surfaced: two machines on EOL Win10 22H2, RDP-without-NLA on REDNOURCARRIEVI, missing BitLocker, low disk, no backup agent on FrontDeskReception. + +### Key Decisions + +- **Reversed the 2026-05-28 SmartBadge fix** — the fleet standard is the *newer* Datto Workplace v10.53.4 (Workplace2); Workplace Desktop v8 is older despite the name. EVO-X1 used as the canonical reference. +- **Let Mike Revo-uninstall v8** rather than silent-uninstall via RMM — GUI uninstaller sweeps leftovers a silent uninstall leaves; coordinated to avoid both touching the live box at once. +- **SmartBadge daily watch via local scheduled task, not /schedule** — `/schedule` provisions cloud agents that can't reach the internal RMM API (172.16.3.30); only a LAN machine can. +- **Integration Center: partner-scoped, generic JSONB storage, catalog+Syncro together, code plugin registry, AES-256-GCM reuse** — corrected SPEC-005's internal-only, DB-catalog-table assumptions. +- **Server deploy to `/opt/gururmm/gururmm-server`** — that is the real `ExecStart`; the wiki's `/usr/local/bin` path is stale and caused the failed deploy. +- **Alert routing by message prefix** — auto-routes existing call sites with no edits; explicit `dev`/`bot` 2nd-arg override retained. +- **Onboarding diagnostic Phase 1 = script via /rmm now, Phase 3 = native GuruRMM feature later**; baselines stored in repo now, GuruRMM DB when the native feature lands ("both"). + +### Problems Encountered + +- **Excel rewrote per-user add-in state on exit** — required Excel closed before clearing Kristin's `LoadBehavior=2`; the fix script guards on EXCEL.EXE. +- **sops encrypt failures** — needed `--config "$VR/.sops.yaml"` from outside the vault dir; bare YAML dates threw `Cannot walk value, unknown type: time.Time` (quote them); failed encrypt leaves plaintext on disk (verify with `grep -c 'ENC['`). Documented in `/rmm onboard`. +- **Server "rebuild" didn't take** — 0.3.36 binary was deployed to the wrong path (`/usr/local/bin` vs the service's `/opt/gururmm`). Fixed by copying to the correct path + restart. +- **Discord 400 on em-dash** — a unicode em-dash in an alert broke the JSON post (Windows Git Bash argv encoding); ASCII-only is already the rule. +- **Agent ~32KB command-size cap** — the 62KB diagnostic probe was rejected; runner base64-chunks the upload (<24KB chunks) then decodes/runs/cleans up. +- **Detection false positives** — substring matches (`cove`->Recovery, `ltsvc`->Vaultsvc) and PS5.1 scalar `.Count`; fixed with `\b` anchors and `@(...)` wrapping. Then ACG's own stack flagged as "foreign" — filed tuning todo + memory. +- **git push rejected (non-fast-forward)** twice — other instances had advanced origin; resolved with `pull --rebase` then push. + +### Configuration Changes + +- KSTEENBB2025 (via RMM): uninstalled Datto Workplace Desktop v8.50.13 (Revo); installed Datto Workplace v10.53.4; `_CC` CLSID `{3C639243}` -> Workplace2 x64/x86 DLLs; removed `{2B96EDC1}` + non-`_CC` add-in keys; per-user `Datto.SmartBadgeShim_CC` LoadBehavior 2->3, cleared Resiliency, set DoNotDisableAddinList. +- 172.16.3.30: `cp /usr/local/bin/gururmm-server /opt/gururmm/gururmm-server` (0.3.36), old saved `/opt/gururmm/gururmm-server.0.3.32.bak`, `systemctl restart gururmm-server`. +- `.claude/scripts/post-bot-alert.sh` — dev/bot channel routing by prefix + override arg. +- `.claude/scripts/ksteen-smartbadge-verify.ps1`, `ksteen-smartbadge-fix.ps1`, `check-ksteen-smartbadge.sh` — new (SmartBadge verify/fix/daily-runner). +- `.claude/scripts/onboarding-diagnostic.ps1`, `run-onboarding-diagnostic.sh` — new (onboarding diagnostic Phase 1). +- `.claude/commands/rmm.md` — added `/rmm onboard`, `/rmm diagnose`, dev-alerts routing notes. +- `.claude/memory/reference_acg_msp_stack.md` (+ MEMORY.md index) — new. +- `wiki/clients/birth-biologic.md` — agents table, dual-Workplace SmartBadge known issue + fleet standard, 5/28-5/29 history. +- Vault `D:/vault/clients/rednour/gururmm-site-main.sops.yaml` — new (Rednour enrollment key). +- Scheduled task "ClaudeTools - KSTEEN SmartBadge Daily" on GURU-5070 (daily 09:00, 2026-05-30..06-05). +- gururmm PR #28 (branch `feat/spec-005-integration-center`) — revised SPEC-005. + +### Credentials & Secrets + +- Rednour GuruRMM site API key (one-time, `grmm_...`): vaulted at `clients/rednour/gururmm-site-main.sops.yaml` (credentials.api_key). Site `GREEN-FALCON-7214`. +- Gitea API token field path correction: `services/gitea.sops.yaml` -> `credentials.api.api-token` (not `credentials.api-token`). +- Syncro API key: `msp-tools/syncro.sops.yaml` -> `credentials.credential` (unchanged). +- No new secrets created beyond the Rednour site key. + +### Infrastructure & Servers + +- GuruRMM server 172.16.3.30: `/status` -> 0.3.36; service `ExecStart=/opt/gururmm/gururmm-server` (NOT /usr/local/bin — wiki stale); build via `sudo /opt/gururmm/build-server.sh` (builds in `/home/guru/gururmm/server`, log `/var/log/gururmm-build.log`). +- Rednour Law Offices: client `85f7cff4-d4db-48a8-b477-b8788122a361`, site Main `c7f5787c-8e71-45b3-841f-fa52436f7d26` / `GREEN-FALCON-7214`. Agents: FrontDeskReception `04765560-...`, LegalAsst `18825ea7-...`, rednourcarrievirt `8e4e2221-...`. +- BB agents: BB-SERVER `6c02baa7`, KSTEENBB2025 `ee3c6aea`, EVO-X1 `9595f002`, BB-Office2 `48763401`. +- Discord channels: #bot-alerts `624710699771232265`, #dev-alerts `1509998508198068484` (private). + +### Commands & Outputs + +```bash +# Server fix (172.16.3.30) +sudo cp /opt/gururmm/gururmm-server /opt/gururmm/gururmm-server.0.3.32.bak +sudo systemctl stop gururmm-server +sudo cp /usr/local/bin/gururmm-server /opt/gururmm/gururmm-server +sudo systemctl start gururmm-server +curl -s localhost:3001/status | jq .version # -> "0.3.36" + +# vault new entry (non-interactive) +sops --config "$VR/.sops.yaml" --encrypt --in-place # quote dates; secrets under credentials: + +# onboarding diagnostic +bash .claude/scripts/run-onboarding-diagnostic.sh +``` + +### Pending / Incomplete Tasks + +- **Rednour:** real findings to action — 2x EOL Win10 22H2 (LegalAsst, REDNOURCARRIEVI), RDP-without-NLA (REDNOURCARRIEVI), missing BitLocker, low disk (REDNOURCARRIEVI ~12%), no backup agent (FrontDeskReception). Mike to direct remediation. +- **KSTEENBB2025:** SmartBadge confirmed working; 7-day watch running (coord todo `4a5b09b3`). +- **Integration Center:** PR #28 open for review/merge; then /shape-spec + scaffold (coord todo `0198ba04`). PARKED. +- **GuruRMM enrollment security:** site_id-only enrollment gate decision (coord todo `00074cd8`). +- **Onboarding diagnostic:** Phase 3 native feature (coord todo `76c6050b`); single-element-array MD-table bug (`cc5dbdfa`); ACG-stack detection allowlist tuning (`3d886f1a`). +- **Wiki:** gururmm.md ExecStart path (/opt vs /usr/local/bin) should be corrected; no wiki article for Rednour yet. + +### Reference Information + +- Syncro #32339 (BB SmartBadge): public cmt 414607766, warranty li 42639366. Customer 17983014. +- gururmm PR #28: https://git.azcomputerguru.com/azcomputerguru/gururmm/pulls/28 +- Coord: Howard reply f888b21c; broadcast bafae411; todos 4a5b09b3 / 0198ba04 / 00074cd8 / 76c6050b / cc5dbdfa / 3d886f1a. +- Rednour install page: https://rmm.azcomputerguru.com/install/GREEN-FALCON-7214 +- Baselines: `clients/rednour/onboarding-baselines/` (FRONTDESKRECEPT, LEGALASST, REDNOURCARRIEVI).