From 5b285321c082ac48d8fe4e87c1636520a5af806b Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Sat, 30 May 2026 14:46:14 -0700 Subject: [PATCH] scc: Session save and push from GURU-5070 at 2026-05-30 14:47 Co-Authored-By: Claude Opus 4.6 --- .claude/memory/MEMORY.md | 1 + .claude/memory/project_guruconnect_deploy.md | 51 +++++++++++++++ session-logs/2026-05-30-session.md | 66 ++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 .claude/memory/project_guruconnect_deploy.md diff --git a/.claude/memory/MEMORY.md b/.claude/memory/MEMORY.md index 667fb6c..4e19f1d 100644 --- a/.claude/memory/MEMORY.md +++ b/.claude/memory/MEMORY.md @@ -16,6 +16,7 @@ - [Client Docs Structure](reference_client_docs_structure.md) — clients//docs/ layout (overview, network, servers, cloud, security, rmm). Template: clients/_client_template/. - [MSP Audit Scripts](reference_msp_audit_scripts.md) — server_audit.ps1 / workstation_audit.ps1 at projects/msp-tools/msp-audit-scripts/. - [GuruRMM Server Layout](reference_gururmm_server.md) - SSH as `guru`, repo at /home/guru/gururmm, deploy to /var/www/gururmm/dashboard/ +- [GuruConnect deploy](project_guruconnect_deploy.md) — Deploys MANUALLY by building on the server itself (172.16.3.30 has rust+node, use a login shell). Gotchas: installed systemd unit has NO watchdog (don't run setup-systemd.sh), set CONNECT_TRUSTED_PROXIES, migrations auto-run on boot, NULL-tags decode bug. v2 live 2026-05-30 at connect.azcomputerguru.com. - [GuruRMM API — run script on agent](reference_gururmm_api.md) — POST /api/agents/:id/command (command_type=powershell); poll /api/commands/:id for output. Beats ScreenConnect copy-paste. - [GuruRMM user_session command context](reference_gururmm_user_session_context.md) — command API `context=user_session` runs as the logged-on user (WTS); does interactive-only cmds that fail as SYSTEM. Needs an active (admin) user. - [Pluto Build Server](reference_pluto_build_server.md) — Windows build VM: hostname PLUTO = Unraid VM "Claude-Builder" = 172.16.3.36 (all the same box). MSVC + WiX. No `pluto` vault entry. Drive via /rmm (agent enrolls as PLUTO) when SSH key isn't authorized. diff --git a/.claude/memory/project_guruconnect_deploy.md b/.claude/memory/project_guruconnect_deploy.md new file mode 100644 index 0000000..1b3ed4c --- /dev/null +++ b/.claude/memory/project_guruconnect_deploy.md @@ -0,0 +1,51 @@ +--- +name: project_guruconnect_deploy +description: How to deploy GuruConnect (v2+) to production — the server (172.16.3.30) builds its own Linux binary; gotchas with the systemd watchdog, trusted-proxy env, and auto-run migrations +metadata: + type: project +--- + +GuruConnect v2 went live in production on 2026-05-30 (server + dashboard at v0.2.0, +public at connect.azcomputerguru.com via NPM -> localhost:3002). The deploy is **manual** +(the `.gitea/workflows/deploy.yml` "deploy to server" step is a stub that only builds a +package artifact). Repo on the box: `/home/guru/guru-connect` (separate repo +`azcomputerguru/guru-connect`, NOT a submodule there). + +**Build host = the server itself.** 172.16.3.30 has rust (rustup, cargo 1.94, the +`x86_64-unknown-linux-gnu` target), node 20 + npm 10, and protoc (~/.local/bin, libprotoc 28.3) +— all on PATH only in a **login shell** (`ssh guru@172.16.3.30 'bash -lc "..."'`; a +non-interactive shell does NOT source ~/.profile so cargo/protoc look "missing"). GURU-5070 +builds the *Windows* agent + a windows-target server, NOT the Linux release — so build the +Linux server ON the box. See [[reference_guru5070_rust_toolchain]]. + +Deploy sequence (build while v1 runs, then a quick cutover restart): +1. **Backup first:** `pg_dump "$DATABASE_URL" | gzip > ~/backups/guruconnect/pre-deploy-*.sql.gz`; + save the current commit + copy the running binary to `~/guruconnect-server.vN.bak`. +2. Get the code: the server's local `main` may have **diverged** from origin (the v2 greenfield + respec rewrote history — `git pull --ff-only` will refuse). Tree is clean, so + `git fetch origin && git reset --hard origin/main` (rollback SHA is saved). `.env` is + gitignored, untouched. +3. SPA: `cd dashboard && npm ci && npm run build` -> emits to `../server/static/app/` (gitignored). +4. Binary (from repo ROOT, login shell, PROTOC set): `cargo build --release -p guruconnect-server + --target x86_64-unknown-linux-gnu`. `-p` scopes to the server so the Windows-only agent crate + isn't compiled; explicit `--target` overrides `.cargo/config.toml`'s windows-msvc default. + Output lands at `target/x86_64-unknown-linux-gnu/release/guruconnect-server` = the unit's ExecStart. + ~3 min. sqlx uses RUNTIME queries (no `query!` macros, no `.sqlx` cache) so the build needs no DB. +5. **Cutover:** `sudo systemctl restart guruconnect`. Migrations are sqlx-embedded in the binary and + **auto-run on startup** (`db.migrate()`), so no manual `psql`. Watch + `journalctl -u guruconnect` for "Migrations complete" + "Server listening". + +GOTCHAS (all hit on the 2026-05-30 deploy): +- **systemd unit:** the INSTALLED `/etc/systemd/system/guruconnect.service` has **no `WatchdogSec`** + (correct for v2, which sends no `sd_notify`). The repo's `server/guruconnect.service` DOES set + `WatchdogSec=30s` — so do NOT run `setup-systemd.sh` / copy the repo unit, or v2 restart-loops + every 30s. Unit: User=guru, EnvironmentFile=server/.env, WorkingDirectory=server/, ProtectSystem=strict. +- **`CONNECT_TRUSTED_PROXIES`** is a v2 env var (comma-separated IPs; defaults to loopback fail-closed). + NPM proxies from `172.16.3.30`, so set `CONNECT_TRUSTED_PROXIES=127.0.0.1,::1,172.16.3.30` in + `server/.env` or client-IP extraction (rate-limit-per-IP, logging) is wrong. Only `JWT_SECRET` is hard-required. +- **NULL tags bug:** `connect_machines.tags` is `text[]` nullable with no default; v2 decodes it as + non-`Option`, so rows with NULL tags throw "unexpected null" at reconcile (and likely the Machines + list). Mitigated with `UPDATE connect_machines SET tags='{}' WHERE tags IS NULL`. Real fix is a + todo (decode Option + migration default). +- DB is Postgres 14 `guruconnect` on localhost; existing users (admin, howard, both role admin) + survive migration. Rollback: `git reset --hard `, rebuild, restart, `psql < backup`. diff --git a/session-logs/2026-05-30-session.md b/session-logs/2026-05-30-session.md index 0416eae..1e5ee6e 100644 --- a/session-logs/2026-05-30-session.md +++ b/session-logs/2026-05-30-session.md @@ -286,3 +286,69 @@ Activation requires Mike to close the current (legacy-conhost) session and relau - Revert default terminal: Settings → Privacy & security → For developers → Terminal → "Let Windows decide". - Revert Wispr elevation: `Unregister-ScheduledTask "Wispr Flow (Elevated)"`; rename `Wispr Flow.lnk.disabled` → `Wispr Flow.lnk`. - Windows Terminal delegation GUIDs: Console `{2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69}`, Terminal `{E12CFF52-A866-4C77-9A90-F570A7AA2C6B}`. + +--- + +## Update: Reverted Wispr Flow elevation; fixed Claude shortcut elevation error (GURU-5070) + +Mike asked to undo the Wispr Flow dictation-fix changes and have the Claude shortcut run `wt` without elevation. + +### Actions + +- **Unregistered scheduled task** `Wispr Flow (Elevated)` — Wispr no longer auto-starts at High integrity. +- **Restored non-elevated Wispr autostart:** a normal `Wispr Flow.lnk` (non-elevated, targets `...\WisprFlow\Wispr Flow.exe`) was already present in the Startup folder, so removed the now-redundant `Wispr Flow.lnk.disabled` duplicate. +- **Reverted default-terminal delegation** in `HKCU:\Console\%%Startup`: `DelegationConsole` and `DelegationTerminal` set back to `{00000000-0000-0000-0000-000000000000}` ("Let Windows decide"). +- **Claude shortcut left on `wt`, non-elevated:** `Claude.lnk` already targeted `wt.exe -d "D:\claudetools" "...\claude.exe" --chrome --dangerously-skip-permissions` with RunAsAdmin = False — no change needed. Claude still opens in Windows Terminal because the shortcut invokes `wt.exe` explicitly, independent of the reverted global default. + +### Root cause of the `0x800702E4` ("requires elevation") error + +After the revert, launching the shortcut threw `ERROR_ELEVATION_REQUIRED` on `claude.exe --chrome --dangerously-skip-permissions`. Cause: per-user **Run as administrator** AppCompat flags set during the earlier elevated session in `HKCU:\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers`: + +- `C:\Users\guru\.local\bin\claude.exe` = `~ RUNASADMIN GDIDPISCALING DPIUNAWARE` +- `C:\Users\guru\AppData\Local\Microsoft\WindowsApps\wt.exe` = `~ RUNASADMIN` + +These force elevation on every launch, so a non-elevated shortcut failed. + +**Fix:** +- `claude.exe` → stripped `RUNASADMIN`, kept DPI flags → `~ GDIDPISCALING DPIUNAWARE` +- `wt.exe` → removed the `RUNASADMIN` value entirely + +Both now launch non-elevated. Pending Mike's confirmation that relaunching from `Claude.lnk` opens WT without the elevation error. + +### Reference (re-revert / re-apply) + +- Re-add RUNASADMIN (if ever needed): set the Layers value back to include `RUNASADMIN` for the exe path. +- Re-elevate Wispr: re-create the `Wispr Flow (Elevated)` scheduled task (AtLogOn, RunLevel Highest, action = `...\WisprFlow\Wispr Flow.exe`) and disable the Startup `Wispr Flow.lnk`. +- The AppCompat Layers key is HKCU — editable without elevation. + +--- + +## Update: Claude taskbar/profile icon via dedicated Windows Terminal profile (GURU-5070) + +Mike asked whether the taskbar could show the Claude icon instead of the generic Windows Terminal icon when launching via `wt.exe`. + +### Constraint + +A shortcut's icon only brands the `.lnk` itself. Once `wt.exe` is the running process, the taskbar button belongs to Windows Terminal — it uses WT's window icon and groups under WT's AppUserModelID (AUMID). A `.lnk` icon cannot override that. The controllable lever is WT's **per-profile `icon`**; on WT 1.24 the window/taskbar icon follows the active profile's icon. Taskbar *grouping* is still keyed to WT's AUMID and cannot be changed without leaving `wt.exe` for a terminal that owns its own identity (e.g. WezTerm/Alacritty). + +### Actions + +- **Extracted the Claude icon** from `C:\Users\guru\.local\bin\claude.exe` (index 0) to a 256x256 PNG at `C:\Users\guru\.local\bin\claude-icon.png` via `user32!PrivateExtractIcons`. +- **Added a dedicated "Claude" profile** to WT `settings.json` (backed up to `settings.json.bak`): + - guid `{9cbe74ea-2403-4e9e-89aa-23780ee3c19a}` + - `commandline`: `"C:\Users\guru\.local\bin\claude.exe" --chrome --dangerously-skip-permissions` + - `startingDirectory`: `D:\claudetools` + - `icon`: `C:\Users\guru\.local\bin\claude-icon.png` +- **Repointed `Claude.lnk`** to `wt.exe` with args `-p Claude` (profile now carries the command, dir, and icon). Still non-elevated; `IconLocation` left at `claude.exe,0`. +- Validated `settings.json` parses as JSON after the edit. + +### Result / Pending + +- Tab icon, new-tab dropdown, and WT jump-list → Claude icon (reliable). +- Taskbar button → expected to show the Claude icon on WT 1.24, but **pending Mike's visual confirmation** (WT taskbar-icon behavior varies by version). If it stays the generic WT logo, fallback options are a WezTerm/Alacritty terminal with a Claude icon, or a custom-AUMID experiment. + +### Reference (revert) + +- Restore WT settings: copy `settings.json.bak` over `settings.json` (path: `%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\`). +- Revert shortcut to inline launch: set `Claude.lnk` Args back to `-d "D:\claudetools" "C:\Users\guru\.local\bin\claude.exe" --chrome --dangerously-skip-permissions`. +- Icon source PNG: `C:\Users\guru\.local\bin\claude-icon.png` (safe to delete if profile removed).