Require SecurityCenter2 productState RTP-enabled bit before treating a
registered AV as active (lapsed/disabled AV no longer suppresses the
critical Defender finding), and tighten the Datto fallback to AV/EDR
services only — excluding Datto RMM/Backup/Workplace/Continuity/File so
non-AV Datto products can't masquerade as antivirus. Fix misleading comment.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The probe flagged ACG's own MSP tooling (ScreenConnect/ConnectWise Control,
Splashtop, Syncro, Datto RMM, Datto EDR/AV) as CRITICAL "foreign agent" and
flagged Defender-off as CRITICAL even when a 3rd-party AV had legitimately
disabled it. Now: allowlisted tools emit an INFO "expected ACG tooling"
finding (genuinely-foreign tools still CRITICAL); Defender-off is downgraded
to INFO only when a 3rd-party AV is active. JSON contract + grading unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PowerShell ConvertTo-Json collapses a single-element array into a bare
object (or, for string arrays, a bare string). The runner iterated/joined
several facts.* fields, so single-volume / single-NIC / single-admin
machines silently dropped the Fixed Volumes table and errored the network
adapter, local-administrator, and installed-software-diff lines.
Fix jq-side in the runner (backward-compatible with already-written
immutable baselines; PS1 untouched per the todo decision) using
`if type=="array" then . elif .==null then [] else [.] end` at:
volumes, network_adapters (+ inner ip/dns), local_administrators, and
installed_software (both sides of the diff). Verified with synthetic
single-element JSON and a multi-element no-regression check.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixed post-commit hook to properly escape JSON payloads using python.
Previous implementation was vulnerable to breaking on commit messages
with special characters (quotes, newlines, etc.).
CHANGES:
- Use python json.dumps() for proper JSON escaping
- Prevents 422 validation errors from coordination API
- Handles multi-line commit messages correctly
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Host guard in /opt/gururmm/webhook-handler.py skips docs-only pushes; note the
stale repo copy must not be redeployed over it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match a known external IP to the RMM agent rather than reconning every
candidate machine (Mike's correction during the Pavon GuruConnect-client
removal). Notes the GuruRMM agent-IP tracking gap (todo 7459428e).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Several bugs found and fixed during live testing against the ACG GravityZone
tenant:
- security_sweep_all_clients: iterate each company (the companies container is
not a valid endpoint parent; passing it 400'd the whole sweep)
- list_quarantine: use service-scoped path quarantine/computers with companyId
(bare quarantine module 404'd; param is companyId not parentId)
- rename GZEndpointSummary.detection_active -> threat_detected with corrected
semantics (True = active threat, tracks with infected; not an engine-on flag)
- status: readable sectioned table renderer for the nested apiKey/license dict
- portable CLAUDETOOLS_ROOT resolution (derive from file path, not a Windows
literal) so it works on the Mac/Linux fleet
Adds scripts/selftest.py: a 29-check read-only harness (all passing) covering
every read command, --json, error exit codes, and destructive-action gating.
EDR/incident commands (blocklist, isolate/unisolate, blocklist-add/remove) and
raw destructive-method gating are included from this session's work.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- raw now refuses destructive methods (delete/uninstall/remove/reconfigure)
without --confirm (it previously bypassed all gating)
- --json is now accepted after the subcommand (shared via a common parent
parser), matching the documented usage
- drop a placeholder-less f-string
- SKILL.md: document raw gating + that raw echoes upstream responses verbatim
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a /bitdefender skill that drives the ACG GravityZone partner tenant
via the JSON-RPC Public API. Read + management ops (companies, endpoints,
live security sweep, policies [read-only/shallow], packages, quarantine,
scans, groups, move/delete). Identity-tier JSON cache (24h TTL,
--refresh); volatile status is always pulled live, never cached.
Security hardening: API key loaded from SOPS vault at runtime (never on
disk/logs/argv/cache); destructive deletes gated behind --confirm; `raw`
also gates destructive methods; upstream error bodies truncated. UNVERIFIED
API methods reachable only via `raw`. Reuses the auth/JSON-RPC pattern from
api/services/gravityzone_service.py.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GC's db layer uses runtime sqlx::query()/query_as() throughout - zero
compile-time macros (verified during v2 Task 1; CLAUDE.md's "compile-time
checked queries" line is stale). Pass B now treats a NEW sqlx::query! macro
as a [LOW] deviation (reintroduces the .sqlx-cache footgun + build-time
DATABASE_URL) instead of blessing macros as the GC norm. Fixed both the
intro divergence note and the Pass B check.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Load .claude/standards/ (index.yml + files) as the compliance baseline;
Rust/TS passes now cite the specific standard each finding violates
- Glob all docs/specs/SPEC-*.md (incl. SPEC-002) + specs/*/plan.md; Pass F
reconciles SPEC phases and plan.md [DONE] markers against code (3rd table)
- Extract a planned-work list from SPEC-002 + active plans; tag findings that
match already-planned work as [TRACKED] so mid-rebuild audits surface net-new
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Update guru-rmm submodule pointer (SPEC-017 mobile device support)
- Record Apple Developer + MDM Push certs (acquired 2026-05-29); MDM push
cert renews annually on the same Apple ID or all enrolled iOS devices break
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Created .claude/TEMP_GRADUATION.md with review protocol before cleanup
- Graduation decision tree and checklist
- Examples from May 2026 cleanup (what should have been kept)
- Added to CLAUDE.md reference section
/rmm diagnose: dispatches a Windows security/health probe to a newly onboarded
agent, grades RED/AMBER/GREEN, writes an immutable per-client baseline
(clients/<slug>/onboarding-baselines/), diffs vs prior, and alerts CRITICALs to
#dev-alerts. Probe is PS5.1/ASCII/SYSTEM-safe, never-abort, base64 chunked upload
around the agent command-size cap. Code-reviewed (no blockers); folded in
immutability guard, severity-independent finding ids, Defender-unknown sentinel,
expanded competitor/backup detection.
First baselines captured: Rednour FRONTDESKRECEPT + LEGALASST (both RED - prior
MSP ScreenConnect/Splashtop/Syncro still live; LEGALASST OS EOL).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Pluto memory/wiki/machine notes: Unraid VM "Claude-Builder" == hostname PLUTO ==
172.16.3.36 (same box); RMM-agent access path when SSH key unauthorized; now also
builds the GuruConnect Windows agent + hosts a Gitea Actions runner.
- New feedback memories: post #bot-alerts only for client/ticket-affecting RMM commands;
proceed autonomously through routine infra/build prerequisites.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Documents the full GuruRMM onboarding process (POST /api/clients, POST /api/sites
with one-time api_key capture), the vault storage step, and the sops-encryption
gotchas hit while onboarding Rednour Law Offices (--config required, quote dates,
secrets under credentials:).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
guru-connect is now tracked as a submodule (azcomputerguru/guru-connect @ e3e95f8);
its working state was published to the GC repo first, so no content is lost. guru-rmm
advanced to include ADR-008 (GC integration boundary) replayed on top of the team's
Integrations Center / discovery advances. Includes the native-remote-control spec
(now inside the GC submodule), the versionable-products memory, and the session log.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Any ticket, estimate, appointment, or schedule created for testing or API
research must have its subject/name prefixed with [TEST]. Added as a Hard
Rule and cross-referenced in the recurring schedules section.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sanitize_json() called `python3` unconditionally, but on ACG Windows boxes
the Microsoft Store python3 alias is disabled and `py` is the launcher
(feedback_python_windows). When `python3` was missing the function silently
returned empty, and the surrounding `result_safe='{"messages":[]}'` default
dropped every unread coord message — no error, no warning, no toast.
Now prefers identity.json's `.python.command` (set during machine onboarding,
matching the pattern other scripts already use), falls back to
`command -v python3 || command -v py || command -v python`, and if no Python
is available falls back to `tr -d '\000-\037'` so jq can still parse — lossy
on real \n/\t in string fields but keeps messages visible instead of dropping
them.
"Emergency" is a billing modifier, not a delivery channel. Added explicit
hard rule that Remote/Onsite/In-Shop must be confirmed separately when billing
emergency — the delivery channel determines price_retail and cannot be guessed.
Updated both the Hard Rules section and the Billing workflow Step 1 gather prompt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pin down the coord messages endpoint shape after repeated mark-read failures:
{total,skip,limit,messages[]}; parse .messages[], strip control chars, read may be null.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Read and send mail for an ACG mailbox via the shared Claude-MSP-Access Graph app
(fabb3421), defaulting to the running user's mailbox from identity.json (mike/howard).
Send and reply are hard-gated: full To/Cc/Subject/Body preview + explicit confirm,
external recipients flagged, no retries/bulk, saved to Sent. Read path verified live;
token cached to .claude/tmp (gitignored), secret from SOPS vault.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>