26 KiB
Session Log — 2026-05-30 (work spanning 2026-05-29 evening → 2026-05-30)
User
- User: Mike Swanson (mike)
- Machine: GURU-5070
- Role: admin
Session Summary
The session opened as a GuruRMM feature request ("Mobile device support") and ran through the /feature-request flow. After clarifying scope (MDM for phones/tablets plus a GuruRMM mobile agent app — treated as one coherent feature), produced SPEC-017-mobile-device-support.md. The central technical finding documented: the iOS/Android capability asymmetry — an Android Device Admin app delivers real remote lock/wipe with no server certificate, but a sandboxed iOS App Store app cannot lock/wipe without an MDM enrollment profile (which needs the free Apple MDM Push Certificate). Mike then confirmed ACG now holds both Apple certificates (Developer Program + signing, and the MDM Push Certificate), so the spec was updated to mark both iOS phases Apple-cert-unblocked, with the annual MDM-push-cert renewal trap flagged.
The bulk of the session was a full GuruConnect (GC) modernization effort. Mike asked whether a gc-audit equivalent to /rmm-audit existed; it did not, so a gc-audit skill was authored, adapted to GC's actual architecture (protobuf wire format, runtime sqlx, Gitea Actions CI, static-HTML+component-library dashboard) rather than copying RMM assumptions. The skill was then run as a dry run: seven parallel/ sequential audit passes on Opus surfaced three CRITICAL relay-plane auth failures (any-JWT-joins-any-session, viewer-WS blacklist bypass, JWT-accepted-as-agent-key) plus the dashboard's wire-incompatible "protobuf" decoder, a stubbed deploy step leaving production 57 commits stale, and several HIGH/MEDIUM items. The audit report was committed and the skill was refined (use .claude/standards/ as the compliance baseline; reconcile all docs/specs/SPEC-*.md + specs/*/plan.md [DONE] markers; tag already-planned findings [TRACKED] during a rebuild).
Mike then directed a ground-up re-spec. Produced SPEC-002-v2-modernization-architecture.md from four locked decisions: greenfield-but-salvage-proven-Rust-cores; native-first with full key fidelity (Win+R / Ctrl+Alt+Del / clipboard) and WebRTC only as a fallback; standalone-first with a versioned /api/integration/v1/ RMM contract; hardened single-tenant now with a tenancy-ready schema. File transfer (clipboard cut/paste + drag-and-drop, bidirectional) was elevated to a headline differentiator after Mike named it as a favorite ScreenConnect feature. /shape-spec then produced specs/v2-secure-session-core/ (Phase 1).
The Phase-1 keystone was implemented end to end across four tasks, each via a Coding Agent (Opus) → mandatory Code Review (Opus) → Gitea Agent commit loop: Task 1 (v2 schema + per-agent cak_ keys + tenancy-ready columns), Task 2 (auth rebuild deleting the JWT-as-agent-key branch, session-scoped viewer tokens, per-agent key issuance, folding in a pre-existing machine-metadata bug fix), Task 3 (secure relay WS — viewer-token verification with blacklist + session-claim match, agent identity binding, frame caps, input throttle), and Task 4 (in-memory rate limiting + single-use widened support codes). A review-driven authorization-strength fix split viewer tokens into VIEW_ONLY vs CONTROL gated on permission, fully closing CRITICAL #1. Because the dev machine has no Rust toolchain, all code was verified on the build host (172.16.3.30) and confirmed compiling + passing tests (32/32), and the Gitea Actions CI was confirmed green. Every audit CRITICAL and HIGH in the auth/session core is now remediated in code.
The session closed with a /sync (pulled four of Howard's auto-sync commits) and a radio-show task: set the "promised vs got / best invention" episode to today's date (Saturday 2026-05-30), preserved Howard's Segments 1-2, and expanded the reserved Segment 3 into a topical May-2026 tech-news segment (AI glasses, AI-and-jobs, subscription squeeze, orbital data centers, AI security reality check, gadget hits) using live web research, since the assistant's training only runs to ~Jan 2026.
Key Decisions
- SPEC-017 scope: treat "mobile device support" as MDM + a GuruRMM mobile agent app together; document the iOS/Android lock-wipe asymmetry rather than over-promising iOS parity.
- gc-audit adapted, not copied: GC uses runtime sqlx (not RMM's macros — and CLAUDE.md's "compile-time checked queries" line is stale), protobuf wire format, Gitea Actions CI, and a static-HTML+component-library dashboard. The skill's passes were rewritten accordingly; Pass B's initial "macros are the GC norm" rule was later corrected to flag new
query!macros as a[LOW]deviation. - GC v2 direction (4 locked decisions): greenfield-salvage-cores; native-first full key fidelity (WebRTC fallback only); standalone-first + versioned RMM contract; hardened single-tenant with a tenancy-ready (nullable
tenant_id) schema so Phase 4 flips on isolation with no migration rewrite. - File transfer elevated: clipboard cut/paste + drag-and-drop (both directions) made a core differentiator with a delayed-render clipboard design, not a deferred panel.
- v2 sqlx + repo: confirmed runtime
sqlx::query()for v2 (GC already uses it); clean architectural reset in-place in the existingguru-connectrepo (not a new repo). - Auth-strength (CRITICAL #1): viewer-token minting gated on permission, and — after review found
viewis held by every default role — split into VIEW_ONLY (gated onview, relay refuses input) vs CONTROL (gated oncontrol/admin) tokens. This is what actually closed CRITICAL #1. - Codec/transport/cutover: H.264 default (HEVC opt-in); Phase-2 web viewer on protobuf-over-WSS first (WebRTC later); widened higher-entropy support codes; clean wholesale v1→v2 cutover (no client data to migrate).
- Verification path: with no local Rust toolchain, all Rust was verified by building + testing on the build host (172.16.3.30) and by confirming Gitea Actions CI, rather than trusting self-review.
- Radio Segment 3: built as a "present-day" bookend tying each item back to Segments 1-2; pulled live (web search) because training is stale for a same-day show.
Problems Encountered
- Gitea push failed mid-session (internal :3000 refused, public 502) — a transient blip; later confirmed reachable and the pending commit had already been swept upstream by auto-sync. No loss.
- Explore agent reported two GC docs at the repo root (
FEATURE_ROADMAP.md,ARCHITECTURE_DECISIONS.md) that actually live underdocs/; caught and corrected the gc-audit skill's paths before finalizing. - CI red on Tasks 2/3/authz — but only at the
cargo fmt --all --checkgate, which short-circuits before clippy/build/test, so the code had never actually compiled in CI. Verified on the build host that it compiled + passed; applied the fmt patch + two clippy one-liners (8a01935) → CI green. - Task 4 clippy red —
empty_line_after_doc_comments(rate_limit.rs) and two dead-code event constants (events.rs); fixed (2118942, build-host-verified) → CI green. - Audit authz finding: Task 2/3's first authz gate used
has_permission("view"), which is held by every default role, so it didn't actually narrow access; reviewer caught it, leading to the VIEW_ONLY/CONTROL split. - Coord todo POSTs failed twice on an em-dash ("error parsing the body"); resolved by using ASCII-only text. (Same lesson recurred and was applied.)
- No Rust toolchain on GURU-5070 — every Coding Agent could author but not compile; mitigated by build-host verification (172.16.3.30) for each task.
Configuration Changes
azcomputerguru/guru-connect (separate repo):
- New:
docs/specs/SPEC-002-v2-modernization-architecture.md,reports/2026-05-29-gc-audit.md,specs/v2-secure-session-core/{plan,shape,references,standards}.md. - New (server):
migrations/004_v2_secure_session_core.sql,005_machine_metadata.sql,006_widen_support_code.sql;src/db/{agent_keys.rs,tenancy.rs};src/auth/agent_keys.rs;src/api/machine_keys.rs. - Rebuilt/modified (server):
src/middleware/rate_limit.rs(+mod.rs),src/relay/mod.rs,src/api/sessions.rs,src/auth/{jwt.rs,mod.rs},src/db/{machines,sessions,support_codes,events,users,mod}.rs,src/support_codes.rs,src/main.rs,Cargo.toml(removedtower_governor). - Episode/radio: n/a (different repo).
azcomputerguru/gururmm (submodule):
- New:
docs/specs/SPEC-017-mobile-device-support.md;docs/FEATURE_ROADMAP.mdupdated (MDM checklist + Asset Location Tracking cross-link to SPEC-017).
azcomputerguru/claudetools (this repo):
- New:
.claude/skills/gc-audit/SKILL.md(then refined twice). - New memory:
.claude/memory/project_apple_mdm_certs.md,.claude/memory/project_guruconnect_v2_direction.md;MEMORY.mdindex updated. - Radio: created
projects/radio-show/episodes/2026-05-30-promised-vs-got-and-inventions/show-prep.md(expanded, 25KB);git rmofprojects/radio-show/episodes/tbd-promised-vs-got-and-inventions/. - This session log.
Credentials & Secrets
- No new secrets created.
- Gitea API token used for CI status checks: SOPS vault
services/gitea.sops.yaml, fieldcredentials.api.api-token. - ACG holds both Apple certs as of 2026-05-29 (Developer Program + signing; MDM Push Certificate). Still to capture: the exact owning Apple ID and expiry for the MDM Push Certificate (renews annually on the same Apple ID or all enrolled iOS devices break) — see
.claude/memory/project_apple_mdm_certs.md.
Infrastructure & Servers
- Coordination API:
http://172.16.3.30:8001/api/coord(locks, todos) — no auth. - Gitea (internal):
http://172.16.3.20:3000(azcomputerguru org). Public:git.azcomputerguru.com(NPM/Cloudflare; prefer internal). - GC build/deploy host:
172.16.3.30(Linux, Rust toolchain present; GC server runs on:3002behind NPM atconnect.azcomputerguru.com; GC clone at/home/guru/guru-connect). Production GC binary was stale (git1bfd476, ~2026-01-18) vs submodule HEAD — deploy step is a stub. - Gitea Actions runners (online):
guruconnect-builder(ubuntu-latest),pluto-guruconnect(windows-msvc, on Pluto 172.16.3.36). - GC DB: PostgreSQL on the GC host; v2 migrations 004-006 added (not yet applied to production).
Commands & Outputs
cargo fmt --all/cargo clippy --all-targets --all-features -- -D warnings/cargo build --release --target x86_64-unknown-linux-gnu/cargo test --release— run on172.16.3.30to verify GC v2 (no local toolchain). Note: must setCARGO_BUILD_TARGET=x86_64-unknown-linux-gnuon Linux because the repo.cargo/config.tomldefaults tox86_64-pc-windows-msvc.- GC v2 keystone test result on build host:
32 passed; 0 failed. - CI: build-and-test run on
2118942— build-server, build-agent, security-audit all success. - Coord todo POST: requires ASCII-only body (
text,created_by_user,created_by_machinerequired); em-dashes cause "error parsing the body". git rm -r projects/radio-show/episodes/tbd-promised-vs-got-and-inventions/— old radio folder removed after writing the dated one.
Pending / Incomplete Tasks
- GC v2 Phase 1 remainder: Task 5 (attended-mode consent — proto
ConsentRequest/ConsentResponse), Task 6 (native viewer full key fidelity — WH_KEYBOARD_LL hook, scan-code injection, SAS for Ctrl+Alt+Del, clipboard sync), Task 7 (HW H.264 + raw/Zstd fallback). Then Phase 2 (file transfer + dashboard + web viewer), Phase 3 (/api/integration/v1/RMM contract), Phase 4 (multi-tenancy switch-on). Source of truth:specs/v2-secure-session-core/plan.md+docs/specs/SPEC-002-*.md. - Open coord todos (guruconnect):
9a462965(revoke viewer tokens on logout),3c1f372a(trusted-proxy client-IP keying — NPM-on-loopback collapses clients to 127.0.0.1),542137df(multi-instance fail-closed DB single-use gate). Plus twoTODO(audit-events)comments indb/events.rs. - GC v2 deploy: wire the real
deploy.ymlSSH step (currently a stub) and chaincargo auditinto release/deploy; v1→v2 cutover after the product-capability tasks. - SPEC-017 mobile: capture the Apple MDM Push Certificate's owning Apple ID + expiry; provision Google Play/FCM.
- Radio: Mike's "best invention" pick (Segment 2); refresh Segment 3 items if the show slips past 2026-05-30.
Reference Information
- Specs:
guru-connect/docs/specs/SPEC-002-v2-modernization-architecture.md,guru-connect/specs/v2-secure-session-core/,guru-connect/specs/native-remote-control/;gururmm/docs/specs/SPEC-017-mobile-device-support.md. - Audit report:
guru-connect/reports/2026-05-29-gc-audit.md. - gc-audit skill:
.claude/skills/gc-audit/SKILL.md. - Memory:
.claude/memory/project_apple_mdm_certs.md,.claude/memory/project_guruconnect_v2_direction.md. - Commit SHAs — guru-connect:
486debf(audit report),5c60a10(SPEC-002),81e4b99(shape spec),fef8111(T1),41691bf(T2),0f25878(T3),a453e79(authz split),8a01935(fmt/clippy),bfcdbb5(T4),2118942(clippy fix). - Commit SHAs — gururmm:
417856e(SPEC-017). - Commit SHAs — claudetools:
e8ac759,df6a2dd,e5ccb6a,c670471,c70cd70(gc-audit skill). - Coord todos (guruconnect): done —
faf39fe0,c8916c89; open —9a462965,3c1f372a,542137df. - Radio episode:
projects/radio-show/episodes/2026-05-30-promised-vs-got-and-inventions/show-prep.md.
Update: 11:49 PT — GuruConnect v2 Phase 1 COMPLETED (Tasks 5-7, trusted-proxy fix) + local Rust toolchain
Session Summary (this update)
Continued from the morning save and completed all of GuruConnect v2 Phase 1 (the secure-session-core). After the morning's Tasks 1-4 + authz split, this block delivered, in order: the trusted-proxy client-IP fix, Task 5 (attended consent), a local Rust toolchain on GURU-5070, the agent-crate clippy cleanup, Task 6 (full key fidelity — the headline), and Task 7 (HW H.264 + negotiated raw fallback). Each followed the Coding Agent (Opus) → Code Review (Opus) → commit loop. Phase 1 is now complete; every CRITICAL and HIGH from the 2026-05-29 audit is remediated in code.
Trusted-proxy fix (todo 3c1f372a): GC runs behind NPM on loopback, so axum ConnectInfo was always 127.0.0.1 — the Task-4 rate limiter/lockout bucketed every external client into one key (one abuser could lock out everyone). Added shared utils::ip_extract::client_ip honoring X-Real-IP / rightmost-untrusted X-Forwarded-For ONLY when the TCP peer is a configured trusted proxy (CONNECT_TRUSTED_PROXIES env, default loopback, fail-closed); wired into the limiter, relay, and audit logging. Task 5 (consent): proto ConsentRequest/ConsentResponse; the server gates an attended session at join_session (invisible to the tech until granted; StartStream only fires from join_session, so an unconsented session never streams), 60s timeout → teardown, Windows MessageBox dialog (fail-closed).
Mid-session, installed a full local Rust toolchain on GURU-5070 (rustup/cargo 1.96, MSVC C++ Build Tools, protoc 35.0 via winget; PROTOC env set), ending the per-task build-host round-trips. This Windows machine builds BOTH the server and the Windows agent locally — better coverage than the Linux build host, which can't compile the agent. The local clippy immediately exposed that CI never clippy-checks the agent crate (build-server clippy is Linux-only; build-agent only runs cargo build); 77 pre-existing agent clippy errors had accumulated. Cleaned them up (commit d0de888, behavior-preserving, code-reviewed) and filed a todo to add agent-clippy to CI.
Task 6 (full key fidelity — headline): WH_KEYBOARD_LL hook on the viewer diverts system combos (Win/Win+R, Alt+Tab, Ctrl+Esc) to the remote as full KeyEvents and suppresses local handling, GATED on viewer focus + a toggle so it never bricks the technician's own keyboard; scan-code SendInput with correct extended-key flags; Ctrl+Alt+Del completes through the SAS helper (SYSTEM SendSAS, SoftwareSASGeneration policy); modifier hygiene re-syncs key-ups on focus loss. Review caught a BLOCKER — the hook wasn't focus-scoped — fixed. Task 7 (codec, last): encoder trait + factory; capability negotiation (AgentStatus.supports_h264 + server select_video_codec + StartStream.video_codec); MF H.264 encoder + viewer decoder (FIRST-CUT, compile-verified-only, default-OFF via DEFAULT_PREFER_H264=false); raw+Zstd byte-for-byte unchanged as the guaranteed default. Task 6/7 were authored AND verified locally (fmt/clippy/test/build) — the toolchain payoff.
Key Decisions (this update)
- Installed the local Rust+MSVC+protoc toolchain on GURU-5070 to end build-host round-trips; Coding Agents now self-verify locally and hand back CI-green code. Recorded in memory
reference_guru5070_rust_toolchain. - Cleaned the 77 pre-existing agent clippy errors BEFORE Task 6 (which edits agent code) so the local clippy loop runs on a clean base; filed a CI todo (CI never lints the agent).
- Trusted-proxy IP: honor forwarding headers ONLY from a configured trusted-proxy allowlist (default loopback), fail-closed; never trust a header from an untrusted (spoofable) peer.
- Task 6 hook focus-gated (
VIEWER_FOCUSEDAtomicBool, set fromWindowEvent::Focused) so it diverts system keys only when the viewer window is focused. SAS named-pipe DACL tightened from NULL/Everyone to Authenticated Users. - Task 7 ships H.264 dormant (
DEFAULT_PREFER_H264=false): raw+Zstd is what runs; H.264 is compile-verified-only until live hardware validation (Task 8).unsafe impl Send for H264Encoderverified sound (session future isblock_on-driven, neverspawned).
Problems Encountered (this update)
- Local clippy (cargo 1.96, newer than CI's 1.94) exposed 77 pre-existing agent clippy errors CI never caught → cleaned up + filed the CI-gap todo. (Local rustfmt 1.9 vs CI 1.8: empirically verified NO skew —
cargo fmt --checkclean on the CI-green HEAD.) - Task 6 Code Review BLOCKER: the
WH_KEYBOARD_LLhook diverted system combos regardless of viewer focus, so an unfocused viewer would swallow the technician's own Win/Alt+Tab/Ctrl+Esc → fixed with the focus gate. - Coord lock-release jq one-liner failed (locks endpoint shape); left to auto-expire (harmless). Em-dash in a todo POST failed again ("error parsing the body") → ASCII-only retry.
- Bash-tool CWD persisted into the
guru-connectsubmodule fromgit applycalls, so a relative.claude/scripts/...path resolved wrong; use absolute paths.
Configuration Changes (this update)
guru-connect: new server/src/utils/ip_extract.rs (trusted-proxy client-IP); new agent/src/consent/mod.rs (Task 5); new agent/src/encoder/{h264,capability,color}.rs + agent/src/viewer/decoder.rs (Task 7). Modified across server (relay, session, middleware/rate_limit+mod, main, auth, db/{machines,sessions,events,users}, api) and agent (viewer/{input,render,mod}, input/{keyboard,mod}, session, bin/sas_service, ~22 files in the clippy sweep), proto/guruconnect.proto, agent/Cargo.toml, Cargo.lock (pruned), and the plan.md task markers.
claudetools: new memory .claude/memory/reference_guru5070_rust_toolchain.md + MEMORY.md index line.
GURU-5070 machine: rustup (cargo 1.96 at ~/.cargo/bin), VS2022 Build Tools (VCTools workload), protoc 35.0 (winget). PROTOC set as a User env var.
Commands & Outputs (this update)
- Local GC verify (PowerShell, from the guru-connect dir):
$env:PROTOC="C:\Users\guru\AppData\Local\Microsoft\WinGet\Packages\Google.Protobuf_Microsoft.Winget.Source_8wekyb3d8bbwe\bin\protoc.exe"; cargo fmt --all; cargo clippy --workspace --all-targets --all-features -- -D warnings; cargo test --workspace; cargo build --workspace— all green (Task 7: 89 tests). Default target isx86_64-pc-windows-msvc; builds server + agent. winget install Rustlang.Rustup/Microsoft.VisualStudio.2022.BuildTools(--override "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended") /Google.Protobuf.
Pending / Incomplete Tasks (this update)
- GC v2 Phase 1 is COMPLETE (Tasks 1-7). Next: Task 8 — live hardware validation (esp. the H.264 first-cut go-live gates), then Phase 2 (file transfer + dashboard + web viewer — v2 has NO operator dashboard yet, so it is NOT a full v1 replacement until Phase 2), Phase 3 (
/api/integration/v1/RMM contract), Phase 4 (multi-tenancy switch-on). - Open coord todos (guruconnect):
9a462965(viewer-token revocation on logout),542137df(multi-instance fail-closed DB single-use gate),addd7eea(add agent-clippy to the build-agent CI job), + the H.264-go-live gating todo (live-validate, real force-IDR via CODECAPI, document the no-spawn invariant, graceful decode-worker spawn). Closed this update:3c1f372a(trusted-proxy). - GC v2 deploy:
deploy.ymlSSH step still a stub; v1→v2 cutover deferred until at least Phase 2 (needs the dashboard).
Reference Information (this update)
- New commit SHAs — guru-connect:
5d5cd26+8cb0b5b(trusted-proxy IP),9082e11+fbf9e26(Task 5 consent),d0de888(agent clippy cleanup),bb73ba6(Task 6 key fidelity),f9bdecb(Task 7 codec). - Local toolchain memory:
.claude/memory/reference_guru5070_rust_toolchain.md. - Plan (source of truth):
guru-connect/specs/v2-secure-session-core/plan.md(Tasks 1-7 all marked done/implemented).
Update: 12:59 PT — GuruConnect v2 Dashboard (Phase 2 pass 1)
Session Summary (this update)
Built pass 1 of the GuruConnect v2 operator dashboard, picking up the Phase 2 "make it usable" track after Phase 1 (secure session core) was completed earlier in the day. The framework was chosen as a React + Vite + TypeScript SPA. A Coding Agent produced the scaffold, an operations-terminal design system, Bearer-token auth, and the Machines view (~30 new files), all local gates green (tsc/lint/build). A CSS bundling bug was caught and fixed during that pass (ui.css had been imported only by a dead barrel; moved the import to the live entry).
Per the agreed standard sequence (build -> impeccable pass -> frontend-design validation + Code Review -> commit), an impeccable critique-and-polish pass ran next via an Opus Coding Agent using the impeccable skill's reference rubric. It converted the modal-heavy machine-detail flow into a non-blocking side drawer (keeping modals only for irreversible delete and the copy-once key reveal), rewrote the palette to OKLCH-tinted neutrals with AA contrast verified numerically, added real dialog a11y (focus trap + inert-on-root + portal-to-body + a dialogStack topmost-only-Esc), replaced the spinner load with table skeletons, made row actions keyboard/touch reachable, fixed an inverted type hierarchy, and standardized destructive copy. All gates stayed green.
A dedicated Opus Code Review of the uncommitted dashboard returned APPROVE with no blockers: admin gating is server-enforced (not hidden UI), the cak_ key is never logged/persisted/cached, error envelopes normalize across the two known shapes, and the a11y is correct rather than cosmetic. The reviewer's one HIGH (a malformed CSS comment opener at table.css:89) was a false alarm against an intermediate state; the committed-to-disk file is correct (grep confirmed no stray escape sequence). The toast-inert-behind-modal behavior was explicitly ruled acceptable (toasts auto-dismiss; aria-live still announces while inert).
The Gitea Agent committed the work inside the guru-connect submodule and pushed it, then created the parent claudetools submodule-pointer commit locally. Coordination state was closed out: the Phase 2 dashboard lock was released and the guruconnect/dashboard component marked built.
Key Decisions (this update)
- Framework: React + Vite + TypeScript SPA (operations-console posture: dense, status-forward, trustworthy; not marketing).
- Machine detail uses a side drawer, not a modal; modals reserved for irreversible delete and copy-once key reveal (impeccable modal-as-last-resort law).
- Palette migrated from flat hex to OKLCH-tinted neutrals; AA contrast verified by computing sRGB luminance, not by eye.
- Deleting the v1 dashboard remote-session/protobuf stubs (RemoteViewer, SessionControls, useRemoteSession, protobuf.ts, types/protocol.ts) is intentional under the greenfield-salvage-cores + clean-v1-cutover decisions; the web viewer's wire logic gets rebuilt in Phase 2 proper, not salvaged.
- Toast-inert-behind-modal accepted as-is (standard modal semantics; auto-dismiss; aria-live unaffected) rather than blocking on a portal change.
Problems Encountered (this update)
- CSS bundling bug: ui.css imported only by a dead barrel, so styles did not bundle. Fixed by importing from the live render entry (main.tsx) and removing the barrel. Caught during pass 1, verified by build emitting dist/assets/index-*.css.
- Code Review HIGH (table.css:89 malformed comment) was a false positive against an intermediate working-tree state; grep for the escape sequence returned no matches, current file is correct. No edit needed.
Configuration Changes (this update)
- New: GuruConnect v2 dashboard under projects/msp-tools/guru-connect/dashboard/src/ (scaffold, ui primitives, layout, auth feature, machines feature, lib, styles/tokens.css) — ~30 new files plus impeccable-pass additions (Drawer.tsx, TableSkeleton.tsx, dialogStack.ts, MachineDetailDrawer.tsx).
- Removed: dashboard v1 stubs RemoteViewer.tsx, SessionControls.tsx, useRemoteSession.ts, protobuf.ts, types/protocol.ts (6 obsolete files).
- Parent repo: submodule pointer projects/msp-tools/guru-connect advanced.
Pending / Incomplete Tasks (this update)
- Dashboard later passes: Sessions view (join via viewer-token -> static viewer), Support Codes view, Users admin view, production-serving wiring (dist -> server/static + Axum catch-all).
- Phase 2 proper: file transfer (clipboard cut/paste + drag-drop) and the web viewer.
- Phase 3: /api/integration/v1 RMM contract. Phase 4: multi-tenancy switch-on. GC v2 Task 8: live hardware validation.
- Open coord todos (guruconnect): 9a462965 (viewer-token revocation on logout), 542137df (multi-instance fail-closed DB single-use gate), addd7eea (add agent clippy to build-agent CI), the H.264 go-live gating todo.
Reference Information (this update)
- New commit SHAs — guru-connect:
43a9432(feat(dashboard): v2 operator console pass 1, pushed f9bdecb..43a9432 via http://172.16.3.20:3000). - Parent pointer commit (claudetools, local, unpushed):
5fce962. - Dashboard root: projects/msp-tools/guru-connect/dashboard/ — React+Vite+TS, dev Vite proxy /api,/ws -> localhost:3002.
- Coord: guruconnect/dashboard component = built; Phase 2 dashboard lock e783feb4 released.