feat(skills): add gc-audit skill for GuruConnect end-to-end audit

Modeled on rmm-audit but adapted to GuruConnect's architecture: 7 passes
(6 parallel + sequential CI/CD), protobuf 4-way wire-drift matrix, sqlx
compile-time macros allowed (GC norm), Gitea Actions pipeline + deploy host
checks, reconciles docs/FEATURE_ROADMAP.md + TECHNICAL_DEBT.md. Invoke via
/gc-audit; --pass=<name> for a single pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 17:24:53 -07:00
parent e211a3045a
commit c70cd70070

View File

@@ -0,0 +1,627 @@
---
name: gc-audit
description: |
Periodic end-to-end verification of the GuruConnect codebase and CI/CD
infrastructure. Runs 6 parallel audit passes: (1) API/route & surface
inventory, (2) Rust code quality & standards, (3) TypeScript/dashboard
quality, (4) protocol & wire-format integrity (proto <-> prost <-> manual TS
decode), (5) security & remote-session integrity, (6) docs/roadmap
reconciliation. A 7th sequential pass audits CI/CD pipeline health (Gitea
Actions workflows, runner registration, clippy/audit gates, deploy host).
Produces a timestamped audit report and updates the living docs
(FEATURE_ROADMAP.md, TECHNICAL_DEBT.md). Takes 10-20 minutes.
Invoke explicitly only — no auto-trigger. Use /gc-audit for a full audit.
Optional arg: --pass=<name> to run a single pass
(api, rust, ts, protocol, security, docs, pipeline).
The docs pass reconciles FEATURE_ROADMAP.md / TECHNICAL_DEBT.md against the
code and cleans up stale entries.
---
# GuruConnect End-to-End Audit
Periodic full-stack sanity check for **GuruConnect** — the standalone MSP remote-desktop
product (Rust/Axum relay server + Windows Rust agent + React/TS viewer component library,
Protobuf-over-WebSocket transport). Read-only by default — findings are written to a report
file and living docs are updated. No production code is changed.
> **This is GuruConnect, not GuruRMM.** GC diverges from the RMM audit in ways that matter —
> do NOT copy RMM assumptions. The biggest traps, called out where they apply below:
> - **sqlx compile-time macros (`sqlx::query!` / `query_as!`) are the GC NORM and are allowed.**
> RMM bans them; GC does not. Do not flag them as violations.
> - **Wire format is Protobuf**, not RMM's JSON `AgentMessage`/`ServerMessage` enums. The
> integrity pass chases drift across four artifacts: `proto/guruconnect.proto` →
> prost-generated agent code → prost-generated server code → **hand-written binary decode in
> `dashboard/src/lib/protobuf.ts` (hardcoded message IDs)**. That manual TS decoder is GC's
> signature failure mode.
> - **The dashboard is a React component library + server-served static HTML**
> (`server/static/{login,dashboard,viewer}.html`), NOT a React Router SPA. There is no
> `App.tsx` route tree and no `dashboard/src/api/client.ts`. The surface pass adapts.
> - **CI is Gitea Actions** (`.gitea/workflows/*.yml`) with a Windows runner on Pluto — not
> RMM's `webhook-handler.py` + `build-shared.sh` pipeline.
---
## Execution Overview
```
Phase 0: Context load (coordinator reads key files)
Phase 1: Spawn 6 parallel audit agents (codebase passes A-F)
Phase 2: Run CI/CD pipeline audit (Agent G — sequential; SSH to deploy host)
Phase 3: Collect findings, aggregate, score
Phase 4: Write report + update living docs
Phase 5: Present summary to user
```
The audit is orchestrated here (Claude coordinator). All codebase passes run in parallel
subagents. The pipeline pass runs sequentially after (it touches live state via SSH / HTTP).
Each agent returns structured findings; the coordinator aggregates and writes the final report.
### Model (MANDATORY)
**Always run every audit pass on Opus.** Spawn each agent with `model: "opus"` (the `opus`
alias resolves to the latest Opus). This overrides default complexity-based routing — do NOT
downgrade any pass to Sonnet or Haiku, even the lower-stakes ones (API surface, TypeScript).
The coordinator orchestration also runs on Opus.
### Repo root
All paths below are relative to `projects/msp-tools/guru-connect/` unless prefixed otherwise.
GuruConnect is a **separate Gitea repo** (`azcomputerguru/guru-connect`), not a submodule of
the monorepo in the RMM sense — it lives at `projects/msp-tools/guru-connect/` with its own
`.git`. Deploy host: **172.16.3.30:3002**, systemd service `guruconnect.service`.
---
## Phase 0: Context Load (Coordinator Reads These)
Before spawning agents, read these yourself:
1. `CLAUDE.md` — GC project instructions, coding standards, ports, auth model
2. `docs/FEATURE_ROADMAP.md` — planned features (`[ ]`/`[~]`/`[x]` + P1-P3)
3. `TECHNICAL_DEBT.md` — living debt backlog + "Completed Items" section (repo root, NOT docs/)
4. `docs/ARCHITECTURE_DECISIONS.md` — ADR-001 (RMM↔GC contract), ADR-002 (release eng)
5. `docs/specs/SPEC-001-operational-tooling-parity.md` — release-engineering deliverables
6. `.claude/CODING_GUIDELINES.md` (repo root) — shared standards GC inherits
Capture from `server/src/api/mod.rs` (+ `server/src/main.rs` route registration) the complete
route list — every `.route(...)` plus the two WebSocket upgrade endpoints in
`server/src/relay/mod.rs` (`agent_ws_handler`, `viewer_ws_handler`). This becomes the
**authority route list** passed to Agents A and E.
Also extract every checkbox line from `FEATURE_ROADMAP.md` (with section + priority) into a
**roadmap claims list** — passed to Agent F for reconciliation against the code.
---
## Phase 1: Parallel Audit Agents
Spawn all six parallel agents (A, B, C, D, E, F) simultaneously in a single message. Each
agent receives the full context it needs inline — do not assume they share context. (Agent G —
Pipeline — runs sequentially afterward; it SSHes the live deploy host and hits HTTP endpoints.)
---
### Agent A — API Surface & Route Inventory
**Goal:** Find server endpoints with no UI/consumer exposure, handlers that are dead code, and
references in the dashboard/static HTML to routes that don't exist.
**Instructions for agent:**
1. Read `server/src/api/mod.rs` and `server/src/main.rs` — extract every `.route(path, method)`
into a list grouped by resource (auth, users, sessions, downloads, releases, changelog,
health, metrics). Include the two WS endpoints from `server/src/relay/mod.rs`.
2. **The dashboard is NOT a routed SPA.** Instead cross-reference route usage against:
- `server/static/login.html`, `dashboard.html`, `viewer.html` — grep for `fetch(`, `/api/`,
and `ws`/`wss` URLs the static pages call.
- `dashboard/src/hooks/useRemoteSession.ts` — the WS connection URLs it opens.
- `dashboard/src/components/*.tsx` — any REST calls.
3. Classify:
- Server route never referenced by any static page / component / hook → **ORPHANED ROUTE**
(dead code vs. intentionally external/integration — distinguish by context, e.g. routes the
RMM integration calls per ADR-001 are not dead).
- A `fetch`/WS URL in the frontend that matches no server route → **BROKEN CALL**.
- Method mismatch (frontend POSTs to a GET route) → **METHOD MISMATCH**.
4. For each API resource group, assess whether the UI (static pages + viewer component) exposes
the major operations. Flag resources with full server CRUD but no UI surface.
5. Return structured findings: `[SEVERITY] Description — file:line`.
---
### Agent B — Rust Code Quality & Standards
**Goal:** Find violations of GC's Rust standards and common quality issues across server + agent.
**Instructions for agent:**
Read `CLAUDE.md` (GC standards section) and `.claude/CODING_GUIDELINES.md` first. GC standards:
`tracing` for logging (not `println!`/`log`), `anyhow` in binaries, `thiserror` in libraries,
`async`/`await` preferred, clippy clean.
**Compliance checks:**
- `.unwrap()` / `.expect()` outside `#[cfg(test)]` — panic in production. Flag each with context.
`.expect("invariant reason")` on a truly-impossible path is acceptable if the reason is clear.
- `todo!()` / `unimplemented!()` in non-test production paths.
- `println!` / `eprintln!` used for logging instead of `tracing::` macros.
- `format!()` used to build SQL strings (injection risk — parameterize instead).
- **DO NOT flag `sqlx::query!` / `sqlx::query_as!` compile-time macros.** They are the GC
convention (the codebase relies on compile-time query checking). This is the inverse of the
RMM rule — flagging them here is a false positive.
**Auth coverage (server):**
- Read `server/src/api/mod.rs` + `server/src/auth/mod.rs`. Identify which route groups go through
the `AuthenticatedUser` extractor / auth middleware vs. which are public (login, health,
downloads, metrics may be intentionally public).
- Verify the **agent plane and viewer/admin plane are separated**: the agent WS
(`agent_ws_handler`, auth via `support_code` OR `api_key`) and the viewer WS
(`viewer_ws_handler`, auth via JWT) must not accept each other's credentials. Any non-public
admin route reachable without JWT → `[CRITICAL]`.
- Confirm JWT secret + min-length enforcement at startup (`server/src/main.rs`) and the logout
token blacklist (`server/src/auth/token_blacklist.rs`) is actually consulted on each request.
**Logging hygiene:**
- Grep `tracing::` calls that include JWT secrets, API keys, support codes, passwords, or PII
(emails, usernames). These must be redacted.
**Error handling:**
- HTTP handlers returning 500 with raw `e.to_string()` — leaks internals to callers. Log
server-side, return a generic message.
**Search paths:** `server/src/` and `agent/src/`. Exclude generated proto (`OUT_DIR`) and
`server/src/db/mod.rs` re-exports.
Return structured findings with file:line references.
---
### Agent C — TypeScript / Dashboard Quality
**Goal:** Find dashboard quality issues, with special focus on the hand-written protobuf decoder
(GC has no schema library on the TS side — correctness is manual).
**Instructions for agent:**
The dashboard (`dashboard/`) is a **React component library** (peer-dep React, no app router,
no bundler in-repo). Main artifacts: `components/RemoteViewer.tsx`, `components/SessionControls.tsx`,
`hooks/useRemoteSession.ts`, `lib/protobuf.ts`, `types/protocol.ts`.
**TypeScript quality:**
- `any` annotations in `dashboard/src/` — each is a type-safety gap (the binary/canvas code is
exactly where `any` hides bugs).
- `@ts-ignore` / `@ts-expect-error` — note reason and whether still needed.
- `console.log` / `console.error` left in non-dev paths.
- Hardcoded server URLs instead of a passed `serverUrl` prop / config.
**Manual protobuf decoder correctness (`lib/protobuf.ts`) — HIGH PRIORITY:**
- The decoder parses binary frames with `DataView` and **hardcoded message IDs** (e.g.
`MSG_VIDEO_FRAME`, `MSG_MOUSE_EVENT`, `MSG_KEY_EVENT`). Verify these IDs and field offsets
match `proto/guruconnect.proto` field numbers / wire layout. A mismatch silently corrupts
frames or events. (Agent D cross-checks the same surface from the proto side — coordinate via
the report; this side checks the TS implementation correctness.)
- Bounds checking: does the decoder validate buffer length before reading offsets? A short/hostile
frame should not throw an unhandled error or read OOB.
**Component patterns:**
- `RemoteViewer.tsx` canvas rendering: BGRA→RGBA conversion correctness; is the canvas sized to
the frame? Are out-of-order frames (the `sequence` field) handled or dropped?
- `useRemoteSession.ts`: WebSocket lifecycle — reconnect handling, cleanup on unmount, error
surfacing (a dropped session should not silently hang).
- Icon-only buttons without `aria-label`/`title`; inputs without `<label>`.
**Search paths:** `dashboard/src/` only.
Return structured findings with file:line references.
---
### Agent D — Protocol & Wire-Format Integrity
**Goal:** This is GC's signature pass. Detect drift across the four representations of the wire
protocol, plus migration/version integrity.
**Instructions for agent:**
**Four-way protocol drift (the core check):**
1. Read `proto/guruconnect.proto` — list every top-level `Message` `oneof` variant and each
message's fields with their **field numbers**. Note `session_type`, `VideoFrame`/`RawFrame`/
`EncodedFrame`, `MouseEvent`, `KeyEvent`, `AgentStatus`, `AdminCommand`, `UpdateInfo`,
`Heartbeat`/`HeartbeatAck`, `StartStream`/`StopStream`.
2. Agent side: `agent/src/transport/mod.rs` + `agent/src/transport/websocket.rs` — confirm it
encodes/decodes via prost (`encode_to_vec` / `Message::decode`) and handles every inbound
variant it should. Any server→agent variant with no handler → dead/missing.
3. Server side: `server/src/relay/mod.rs` — confirm the relay decodes agent frames and forwards
the right variants to viewers, and decodes viewer input and forwards to the agent. Any proto
variant the relay never matches → dead code or missing relay path.
4. Dashboard side: `dashboard/src/lib/protobuf.ts` hardcoded message IDs + `types/protocol.ts`
field names. **Cross-check the hardcoded IDs against the proto field numbers** and the TS field
names against the proto field names. Mismatch → `[HIGH]` (silent frame/event corruption).
Build the drift matrix: `message/field | proto | agent (prost) | server (prost) | dashboard (manual)`
and flag every row that isn't consistent across all four.
**Migration integrity:**
- List `server/migrations/*.sql` — verify sequential numbering with no gaps (currently
`001_initial_schema`, `002_user_management`, `003_auto_update`).
- For each `CREATE TABLE` (users, machines, sessions, support_codes, events, releases…), verify a
corresponding `server/src/db/<name>.rs` module exists and its struct fields match the columns.
**Version consistency:**
- `agent/Cargo.toml`, `server/Cargo.toml`, `dashboard/package.json` versions — are they in sync?
(All were `0.2.0` at last map.) The agent embeds version via `agent/build.rs` (CARGO_PKG_VERSION
+ git hash). Note divergence; there is **no automatic version bump yet** (SPEC-001 §3 pending) —
so out-of-sync versions are a `[MEDIUM]` worth surfacing, not necessarily a bug.
**WebSocket frame validation:**
- In `server/src/relay/mod.rs`, are inbound frames size-capped before decode/relay? An unbounded
`VideoFrame` from a hostile agent → server OOM. No cap → `[HIGH]` (see Agent E for the security
framing).
Return structured findings with file:line references and the drift matrix.
---
### Agent E — Security & Remote-Session Integrity
**Goal:** GC is a remote-control product — the threat surface is session hijack, input injection,
and relay abuse. Verify the boundaries the SEC* audits established still hold and check the gaps
they flagged.
**Instructions for agent:**
Read the existing security audit docs first so you don't re-report settled items (note their
status and only re-flag if the code regressed): `SEC3_SQL_INJECTION_AUDIT.md`,
`SEC4_AGENT_VALIDATION_AUDIT.md` / `_COMPLETE.md`, `SEC5_SESSION_TAKEOVER_AUDIT.md` / `_COMPLETE.md`,
and `TECHNICAL_DEBT.md` security items.
**Session & auth boundaries:**
- Viewer WS auth: `viewer_ws_handler` validates a JWT (query param). Confirm the token is verified
(signature + expiry + blacklist), not just parsed. A viewer joining a session must be authorized
for *that* session, not any session.
- Agent WS auth: `agent_ws_handler` accepts `support_code` OR `api_key`. Confirm support codes are
single-use and **revocation updates the in-memory store immediately** (a revoked code must fail
even if the agent reconnects before a server restart — `server/src/db/support_codes.rs` /
in-memory map).
- Session takeover: sessions keyed by UUID, heartbeat timeout ~90s. Confirm a new viewer cannot
attach to or hijack an existing session without authorization, and that session IDs aren't
guessable/loggable in a way that enables replay.
**Relay abuse / DoS:**
- Frame size caps on inbound WS messages (agent video frames AND viewer input) — unbounded →
`[HIGH]` OOM/DoS vector.
- Input event injection: viewer→agent mouse/key events — is there rate limiting or a bounded queue
on the agent input path (`agent/src/input/`)? Unbounded input spam → agent CPU/queue exhaustion.
- Rate limiting on auth endpoints (`server/src/middleware/rate_limit.rs`, `tower_governor`) — still
applied to `/api/auth/login`? Confirm it's wired, not just present.
**Secrets & transport:**
- JWT secret, agent API key sourced from env (not hardcoded) and length-checked at startup.
- TLS/WSS required for relay; no plaintext fallback that carries frames or credentials.
- Passwords hashed with Argon2id (`server/src/auth/password.rs`).
Return structured findings with file:line references. Severity by impact (a session-hijack path is
`[CRITICAL]` even if the fix is small).
---
### Agent F — Docs & Roadmap Reconciliation
**Goal:** Make GC's living docs tell the truth. Reconcile every roadmap checkbox and debt item
against the actual code.
**Runs in parallel with A-E (read-only code search, no SSH).**
**Instructions for agent:**
1. Read `docs/FEATURE_ROADMAP.md` and extract every checkbox line with state (`[ ]`/`[~]`/`[x]`),
section, and priority. Also read `TECHNICAL_DEBT.md` (repo root; items + the "Completed Items"
section) and `docs/specs/SPEC-001-operational-tooling-parity.md` (its §1-§6 deliverables).
2. For EACH item, find the implementing artifact in code — do NOT trust the checkbox:
- API/endpoint features → `server/src/api/mod.rs` routes + handler module
- Relay/session features → `server/src/relay/mod.rs`, `server/src/session/`
- Protocol features → `proto/guruconnect.proto` + agent/server prost usage
- Agent capabilities (capture, input, tray, update) → `agent/src/`
- Dashboard/viewer features → `dashboard/src/components|hooks/*` + static HTML
- CI/release deliverables (SPEC-001: versioning, signing, changelog API, gc-feature-request
skill, coord-API) → `.gitea/workflows/*`, `scripts/*`, `.claude/commands/gc-feature-request.md`
Use Grep/GrepAI. Cite the exact artifact (file:line, migration name, route path, workflow job).
3. Classify each item:
- **STALE-INCOMPLETE** — `[ ]`/`[~]` but code fully implements it end-to-end → recommend `[x]`.
- **PARTIAL** — `[ ]`/`[~]`, some layers exist but not end-to-end for the stated scope → keep
`[ ]`/`[~]`, recommend an inline scope annotation. Do NOT flip to `[x]`.
- **STALE-COMPLETE** — `[x]` but code does not implement it (never built / reverted) →
recommend flip to `[ ]`, flag `[HIGH]` (the roadmap is lying).
- **ACCURATE** — matches. No change.
4. For `TECHNICAL_DEBT.md`: identify debt items the code shows are now fixed → recommend moving them
to the "Completed Items" section with a date. Identify items still open that the code confirms.
5. Be conservative: only flip `[ ]``[x]` when evidence is unambiguous AND end-to-end. When in
doubt → PARTIAL with a note. Bias toward under-flipping.
Return two tables:
`roadmap item | section | current | verdict | proving-or-missing artifact`
`debt item | current status | verdict (fixed/open/partial) | artifact`
---
### Agent G — CI/CD Pipeline & Deploy Health
**Goal:** Verify the build/deploy infrastructure is functioning and the SPEC-001 quality gates are
in the state the docs claim. Catches issues invisible to codebase-only audits: broken workflows,
unregistered runners, stale deploys, gate drift.
**NOTE:** Runs sequentially (after A-F) because it SSHes the live deploy host and hits HTTP
endpoints. Read-only — checks state, never triggers a build or deploy.
**Instructions for agent:**
**1. Gitea Actions workflow integrity (read the repo files):**
- `.gitea/workflows/build-and-test.yml` — confirm jobs: `build-server` (fmt --check, clippy,
build, test), `build-agent` (Windows MSVC on the Pluto runner, PROTOC + crt-static), and
`security-audit` (`cargo audit`). Note whether clippy/audit are **informational** (warn-only) or
**hard-fail** (`-D warnings` / fail-on-vuln).
- `.gitea/workflows/deploy.yml` — confirm trigger (tag `v*.*.*` / manual) and whether the actual
SSH deploy step is real or still a stub (`echo "[INFO] SSH to 172.16.3.30…"`).
- `.gitea/workflows/release.yml` (if present) — SPEC-001 §2-§4: version bump, changelog gen,
`jsign` + Azure Trusted Signing step. Note which deliverables are wired vs. pending.
- `bash -n` is not applicable to YAML; instead sanity-check each workflow for: valid `on:` triggers,
every `uses:`/`run:` step present, no job referencing a secret that the audit notes as unset.
**SPEC-001 gate cross-check (ties to the active lint-debt work):** the SPEC-001 quality gates aim to
flip clippy to hard-fail + enforce `cargo audit`. Report the CURRENT enforced state vs. the SPEC-001
target so it's clear whether the tightening has landed. (~65 pre-spec clippy warnings were noted as
informational at last map — confirm count/state.)
**2. Gitea runner registration & health:**
- TECHNICAL_DEBT.md item #1 flagged runner registration as CRITICAL/blocking. Verify a runner is
registered and online for both `ubuntu-latest` (server/audit jobs) and the Windows/Pluto runner
(agent job). On the Gitea host or via the Gitea API, check the actions runner list. If no Windows
runner is online → `[CRITICAL]` agent builds cannot run. Reference `.claude/machines/pluto.md` for
the Pluto runner setup (PROTOC at `C:\protoc\bin\protoc.exe`, Administrator `.cargo`/`.rustup`).
**3. Deploy host health (`ssh guru@172.16.3.30`):**
```bash
systemctl status guruconnect.service --no-pager
curl -s -o /dev/null -w '%{http_code}' http://localhost:3002/health
curl -s http://localhost:3002/metrics | head -20
ls -lht /home/guru/guru-connect/server/migrations/
```
- `guruconnect.service` not `active (running)``[CRITICAL]`.
- `/health` non-200 / refused → `[CRITICAL]`.
- `/metrics` empty or refused → `[HIGH]` (Prometheus scrape broken).
- Confirm the binary on disk matches a recent commit:
`cd /home/guru/guru-connect && git log --oneline -5` and compare to the running version
(the service version vs. `git rev-parse HEAD`). Months-old running binary while git shows recent
work → `[HIGH]` deploy stuck (consistent with the stubbed deploy step).
- Confirm migrations applied: query `_sqlx_migrations` (003 should be present). Missing → `[HIGH]`.
**4. Artifact distribution:**
- Agent download served at `https://connect.azcomputerguru.com/downloads/guruconnect.exe`
(or the path configured in `server/src/api/downloads.rs`). Verify the file exists and its mtime is
recent relative to agent commits. Stale/missing → `[HIGH]` (clients download an old agent).
- Confirm the served EXE is **signed** if SPEC-001 §2 signing has landed; unsigned while signing is
marked done → `[HIGH]`.
**5. Monitoring stack (per INFRASTRUCTURE_STATUS.md):**
- Prometheus scraping GC `/metrics`; Grafana dashboard reachable. Backup timer
(`guruconnect-backup.timer`) enabled: `systemctl status guruconnect-backup.timer --no-pager`.
Disabled/failed backup timer → `[MEDIUM]`.
Return structured findings with source (file path + line, or command + output) for every finding.
---
## Phase 3: Aggregating Findings
Collect all agents' outputs. Classify each finding:
| Severity | Meaning |
|----------|---------|
| `[CRITICAL]` | Security vuln (session hijack, auth bypass), data loss, production crash, or broken-build/deploy blocker |
| `[HIGH]` | Functional gap blocking a core workflow, protocol drift causing silent corruption, or standards violation with user impact |
| `[MEDIUM]` | Code quality issue, version skew, or inconsistency without immediate impact |
| `[LOW]` | Minor polish, dead code, missing comment |
| `[INFO]` | Neutral observation, completed item, or context note |
Deduplicate: if two agents flag the same issue from different angles (e.g. Agent C on the TS
decoder and Agent D on the proto side of the same field), merge into one finding with both
references.
---
## Phase 4: Write Report + Update Living Docs
### Report Location
Write to: `projects/msp-tools/guru-connect/reports/YYYY-MM-DD-gc-audit.md` (use the actual date).
**The `reports/` directory does not exist yet — create it on first run.** If a report from today
already exists, append a `-2` suffix.
### Report Format
```markdown
# GuruConnect Audit Report — YYYY-MM-DD
**Auditor:** Claude (<model id>)
**Passes:** API Surface, Rust Quality, TypeScript/Dashboard, Protocol Integrity, Security & Session, Docs Reconciliation, CI/CD Pipeline
**Previous audit:** [link to prior report if one exists, else "First audit"]
---
## Executive Summary
| Pass | Total | Critical | High | Medium | Low |
|------|-------|---------|------|--------|-----|
| API Surface | N | N | N | N | N |
| Rust Quality | N | N | N | N | N |
| TypeScript/Dashboard | N | N | N | N | N |
| Protocol Integrity | N | N | N | N | N |
| Security & Session | N | N | N | N | N |
| CI/CD Pipeline | N | N | N | N | N |
| **TOTAL** | **N** | **N** | **N** | **N** | **N** |
**Requires immediate action:** [one line per CRITICAL finding]
---
## Pass 1: API Surface
### [SEVERITY] Finding Title
**File:** path:LINE
**Detail:** What the problem is, why it matters.
**Recommendation:** What to do.
[repeat per finding]
---
## Pass 2: Rust Code Quality
## Pass 3: TypeScript / Dashboard Quality
## Pass 4: Protocol & Wire-Format Integrity
[include the 4-way drift matrix]
## Pass 5: Security & Remote-Session Integrity
## Pass 6: CI/CD Pipeline Health
[Gitea Actions workflow state, runner registration, gate state vs SPEC-001 target, deploy host, artifact freshness]
---
## FEATURE_ROADMAP.md Delta (Agent F)
Checkboxes corrected to match code reality this audit:
- `[ ]`/`[~]``[x]` **<item>** — shipped. Proof: `<artifact>`.
- `[x]``[ ]` **<item>** — marked complete but NOT in code (regression / never built). `[HIGH]`
Annotated as partial (scope clarified): - `[ ]` **<item>** (<scope note>) — `<artifact>`
Verified accurate (no change): N items.
## TECHNICAL_DEBT.md Delta (Agent F)
Items moved to "Completed Items": - **<item>** — fixed. Proof: `<artifact>`.
Still open (confirmed): N items.
---
## Recommended Action Order
1. [CRITICAL items, sorted by impact]
2. [HIGH items]
3. [MEDIUM items — can be batched]
```
### Update Living Docs
After writing the report, apply Agent F's reconciliation (this is the cleanup the audit owns;
editing living docs fits the "living docs are updated" exception to read-only):
- **`docs/FEATURE_ROADMAP.md`** — default is reconcile-and-flip:
- STALE-INCOMPLETE → flip `[ ]`/`[~]` to `[x]` for every item proven shipped end-to-end; optionally
append `(verified <date>)`.
- PARTIAL → leave the box, append the scope annotation. Never flip a partial to `[x]`.
- STALE-COMPLETE → flip `[x]` to `[ ]`, add `[REGRESSION — flagged YYYY-MM-DD]`, mirror as a
`[HIGH]` finding in the report.
- **`TECHNICAL_DEBT.md`** — move confirmed-fixed items into the "Completed Items" section with a date;
leave open items in place.
- Every doc change MUST also appear in the report's Delta section with its proving artifact — no
silent edits. When evidence is ambiguous, do NOT change the doc; record as PARTIAL/INFO for human
review. Bias toward under-flipping.
---
## Phase 5: User Summary
Present a concise summary to the user:
```
Audit complete. Report: projects/msp-tools/guru-connect/reports/YYYY-MM-DD-gc-audit.md
CRITICAL (N): [one-line each]
HIGH (N): [one-line each]
MEDIUM (N): Batched in report.
Protocol drift: [one-line — e.g. "proto/agent/server/dashboard consistent" or the worst mismatch]
Pipeline: [one-line — e.g. "all green" or highest-severity finding; note clippy/audit gate state vs SPEC-001]
Roadmap: N checkboxes corrected (N stale-incomplete flipped, N partial annotated, N regressions flagged).
Tech debt: N items moved to Completed.
Recommended first action: [the single highest-priority finding]
```
Then ask: "Want me to start on any of these findings?"
---
## Conventions
- **Read, don't run.** Never executes production code or triggers builds/deploys. Reads files,
uses Grep/GrepAI, and (Agent G only) runs read-only status/HTTP checks.
- **Derive from code, not docs.** Treat all `.md`/`.json` status docs as potentially stale. Code is
truth. (The whole point of Agent F.)
- **Be specific.** Every finding needs a file:line reference. Vague findings are useless.
- **No false positives.** If something looks wrong but context makes it acceptable, note it `[INFO]`
with the reason. (Especially: `sqlx::query!` macros are fine here; informational clippy/audit gates
are a known SPEC-001 state, not a bug — report the state, don't cry wolf.)
- **Severity is impact, not effort.** A two-line fix can be `[CRITICAL]` if it's a session-hijack path.
- **Commit the report.** After writing, delegate to the Gitea Agent to commit the report file and the
living-doc updates to the `guru-connect` repo (not any code fixes — those are separate work items).
Respect any active coord lock on `guruconnect` before editing `.gitea/workflows` or docs.
---
## Reference: Key Files by Area
### Server (`server/src/`)
| Area | Key Files |
|------|-----------|
| Routes | `api/mod.rs` (+ `main.rs` registration), submodules `api/{auth,users,downloads,releases,changelog}.rs` |
| WebSocket relay | `relay/mod.rs` (`agent_ws_handler`, `viewer_ws_handler`) |
| Sessions | `session/mod.rs` |
| DB layer | `db/mod.rs`, `db/{users,machines,sessions,events,support_codes,releases}.rs` |
| Migrations | `migrations/00{1,2,3}_*.sql` |
| Auth | `auth/{jwt,token_blacklist,password,mod}.rs` |
| Rate limiting | `middleware/rate_limit.rs` |
| Generated proto | `OUT_DIR` via `server/build.rs` (do not audit generated code) |
### Agent (`agent/src/`)
| Area | Key Files |
|------|-----------|
| Transport / wire | `transport/mod.rs`, `transport/websocket.rs` |
| Capture | screen/DXGI-GDI capture modules |
| Input injection | `input/` |
| Version embed | `agent/build.rs` |
### Dashboard (`dashboard/src/`)
| Area | Key Files |
|------|-----------|
| Viewer component | `components/RemoteViewer.tsx`, `components/SessionControls.tsx` |
| Session hook | `hooks/useRemoteSession.ts` |
| Manual protobuf | `lib/protobuf.ts` (hardcoded message IDs — drift hazard) |
| Protocol types | `types/protocol.ts` |
| Served static UI | `server/static/{login,dashboard,viewer}.html` |
### Protocol
| Area | Path |
|------|------|
| Proto definition | `proto/guruconnect.proto` |
### CI/CD & Infra
| Area | Path |
|------|------|
| CI gate | `.gitea/workflows/build-and-test.yml` |
| Deploy | `.gitea/workflows/deploy.yml` |
| Release/signing | `.gitea/workflows/release.yml`, SPEC-001 |
| Runner setup | `scripts/install-gitea-runner.sh`, `.claude/machines/pluto.md` |
| Deploy host | 172.16.3.30:3002, systemd `guruconnect.service` |
| Monitoring | `infrastructure/{prometheus.yml,grafana-dashboard.json,alerts.yml}`, `guruconnect-backup.timer` |
### Docs / Standards
| Area | Path |
|------|------|
| GC instructions/standards | `CLAUDE.md` |
| Shared coding standards | `.claude/CODING_GUIDELINES.md` (monorepo root) |
| Feature roadmap | `docs/FEATURE_ROADMAP.md` |
| Tech debt backlog | `TECHNICAL_DEBT.md` (repo root) |
| Architecture decisions | `docs/ARCHITECTURE_DECISIONS.md` (ADR-001 RMM↔GC contract, ADR-002 release eng) |
| Release-eng spec | `docs/specs/SPEC-001-operational-tooling-parity.md` |
| Changelogs (SPEC-001 changelog API) | `changelogs/LATEST_{SERVER,AGENT,DASHBOARD}.md`, `changelogs/<component>/v*.md`, `CHANGELOG.md` |
| Security audits | `SEC{3,4,5}_*_AUDIT.md` / `_COMPLETE.md` |
| Past audit reports | `reports/` (create on first run) |