Files
claudetools/session-logs/2026-05-30-session.md
Mike Swanson b643d6846b sync: auto-sync from GURU-5070 at 2026-05-30 13:00:29
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-05-30 13:00:29
2026-05-30 13:00:36 -07:00

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 existing guru-connect repo (not a new repo).
  • Auth-strength (CRITICAL #1): viewer-token minting gated on permission, and — after review found view is held by every default role — split into VIEW_ONLY (gated on view, relay refuses input) vs CONTROL (gated on control/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 under docs/; 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 --check gate, 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 redempty_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 (removed tower_governor).
  • Episode/radio: n/a (different repo).

azcomputerguru/gururmm (submodule):

  • New: docs/specs/SPEC-017-mobile-device-support.md; docs/FEATURE_ROADMAP.md updated (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.md index updated.
  • Radio: created projects/radio-show/episodes/2026-05-30-promised-vs-got-and-inventions/show-prep.md (expanded, 25KB); git rm of projects/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, field credentials.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 :3002 behind NPM at connect.azcomputerguru.com; GC clone at /home/guru/guru-connect). Production GC binary was stale (git 1bfd476, ~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 on 172.16.3.30 to verify GC v2 (no local toolchain). Note: must set CARGO_BUILD_TARGET=x86_64-unknown-linux-gnu on Linux because the repo .cargo/config.toml defaults to x86_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_machine required); 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 two TODO(audit-events) comments in db/events.rs.
  • GC v2 deploy: wire the real deploy.yml SSH step (currently a stub) and chain cargo audit into 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_FOCUSED AtomicBool, set from WindowEvent::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 H264Encoder verified sound (session future is block_on-driven, never spawned).

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 --check clean on the CI-green HEAD.)
  • Task 6 Code Review BLOCKER: the WH_KEYBOARD_LL hook 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-connect submodule from git apply calls, 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 is x86_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.yml SSH 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.