Commit Graph

19 Commits

Author SHA1 Message Date
67f3722b3c feat(server): serve dashboard SPA with deep-link fallback; remove v1 portal
Some checks failed
Build and Test / Build Server (Linux) (push) Failing after 3m26s
Build and Test / Build Agent (Windows) (push) Successful in 7m17s
Build and Test / Security Audit (push) Successful in 4m29s
Build and Test / Build Summary (push) Has been skipped
Axum now serves the v2 React/Vite dashboard SPA at / with a client-side
routing fallback, and the dead v1 HTML portal is removed (nothing was
live on the server to preserve).

- SPA served from server/static/app via ServeDir with a fallback to
  index.html, so deep links (/machines, /sessions) resolve to the SPA.
- /api/*rest and /ws/*rest return JSON 404 so unrouted API/WS paths never
  leak index.html to clients; real /api, /ws, /health, /metrics, and the
  /downloads nest keep precedence (matchit static-over-wildcard).
- Path-aware Cache-Control: hashed /assets immutable, index.html no-cache.
- Vite builds to server/static/app (base /); the artifact is gitignored
  and rebuilt at deploy time (npm ci && npm run build).
- Removed v1 portal files (login/dashboard/users/index/viewer .html) and
  their dead serve_* handlers; the SPA owns /, /login, /dashboard, /users.

Verified locally: server boots, / and deep links serve the SPA, unknown
/api path returns JSON 404 (not HTML), /health and /downloads intact.
cargo build + clippy -D warnings green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 13:44:13 -07:00
5d5cd26572 fix(server): trusted-proxy client-IP extraction for rate-limit/audit keying
Some checks failed
Build and Test / Build Server (Linux) (push) Failing after 5m9s
Build and Test / Build Agent (Windows) (push) Successful in 7m38s
Build and Test / Security Audit (push) Successful in 4m59s
Build and Test / Build Summary (push) Has been skipped
Resolves coord todo 3c1f372a (Task-4 review SHOULD-FIX). Behind NPM-on-loopback,
ConnectInfo was 127.0.0.1 so the rate limiter + lockout bucketed every client
under one IP. New shared utils::ip_extract::client_ip() honors X-Real-IP /
X-Forwarded-For (rightmost-untrusted hop) ONLY when the TCP peer is a configured
trusted proxy (CONNECT_TRUSTED_PROXIES env, default loopback, fail-closed);
untrusted peers are keyed by their true peer IP (forged headers ignored). Wired
into the 3 rate-limit middleware, the validate_code lockout feed, and the agent/
viewer WS handlers so the limiter, lockout, and audit ip_address all key on the
real client consistently. 13 unit tests (spoof rejection, XFF walk, fail-safe
defaults). Code-reviewed APPROVED. Not cargo-check-verified locally (no toolchain);
build-host/CI verification follows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 07:15:45 -07:00
bfcdbb5379 feat(server): v2 secure-session-core Task 4 - rate limit + single-use codes
Some checks failed
Build and Test / Build Server (Linux) (push) Failing after 6m12s
Build and Test / Build Agent (Windows) (push) Successful in 6m43s
Build and Test / Security Audit (push) Successful in 4m23s
Build and Test / Build Summary (push) Has been skipped
SPEC-002 Phase 1 Task 4 (the final keystone task), code-reviewed APPROVED.
Closes the audit's reusable-code HIGH and rate-limiting-disabled HIGH.

- Rebuilt rate limiting as a self-contained in-memory per-IP limiter (replaces
  the non-compiling tower_governor; removed that dep). Fixed-window caps wired
  to login (8/min), change-password (5/min), code-validate (15/min) -> 429;
  per-IP lockout after 10 consecutive failed code validations (15-min cooldown).
- Single-use support codes: atomic consume on first agent bind (in-memory
  Pending->Connected under write lock + DB conditional UPDATE), rejecting a
  second presenter; validate/preview does not consume.
- Widened code format: XXX-XXX-XXX, 31-char unambiguous alphabet (no 0/O/1/I/L),
  CSPRNG + rejection sampling, ~44.6 bits (replaces 6-digit numeric); migration
  006 widens the code columns to TEXT.

Completes the keystone (Tasks 1-4): every audit CRITICAL + HIGH in the secure
auth/session core is now addressed. Known follow-up todos (not blocking): (1)
trusted-proxy client-IP extraction (NPM-on-loopback collapses clients to
127.0.0.1); (2) multi-instance fail-closed DB single-use gate. Not
cargo-check-verified locally - build-host/CI verification follows this commit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 21:04:54 -07:00
0f258788f9 feat(server): v2 secure-session-core Task 3 - secure relay WS
Some checks failed
Build and Test / Build Server (Linux) (push) Failing after 4m3s
Build and Test / Build Agent (Windows) (push) Successful in 7m48s
Build and Test / Security Audit (push) Successful in 4m20s
Build and Test / Build Summary (push) Has been skipped
SPEC-002 Phase 1 Task 3 (specs/v2-secure-session-core), code-reviewed APPROVED.

- viewer_ws_handler: verify the session-scoped VIEWER token (validate_viewer_token
  sig+exp+purpose) + token_blacklist.is_revoked + session_id claim == requested
  session, before upgrade. Raw login JWTs no longer accepted on the viewer plane
  (closes audit CRITICAL #2; closes the *mechanism* of CRITICAL #1).
- mint_viewer_token: authz gate is_admin() || has_permission("view") -> 403.
- Agent identity binding: validate_agent_api_key returns AgentKeyAuth; a cak_-
  verified agent rebinds to the key's machine identity (fails closed if
  unresolvable), so a key for machine X cannot seize machine Y's session slot.
- Frame caps on both WS upgrades (agent 4 MiB, viewer 64 KiB) - closes WS-OOM HIGH.
- Viewer->agent input throttle (200 ev/s token bucket, bounded try_send) - closes
  input-injection MEDIUM.
- Startup managed-session reconcile clarified.

KNOWN FOLLOW-UPS (tracked todos): (1) authz STRENGTH - the "view" permission is
held by every default role incl. viewer, and a viewer token grants input control,
so the gate should be "control" or a VIEW_ONLY/CONTROL token split; CRITICAL #1 is
mechanism-closed, strength pending decision. (2) revoke minted viewer tokens on
logout (currently bounded only by 5-min TTL). Not cargo-check-verified (no toolchain
on the authoring host).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 19:13:03 -07:00
41691bfb2c feat(server): v2 secure-session-core Task 2 - auth rebuild
Some checks failed
Build and Test / Build Server (Linux) (push) Failing after 3m37s
Build and Test / Build Agent (Windows) (push) Successful in 6m37s
Build and Test / Security Audit (push) Successful in 4m10s
Build and Test / Build Summary (push) Has been skipped
SPEC-002 Phase 1 Task 2 (specs/v2-secure-session-core), code-reviewed APPROVED.

- DELETE the JWT-as-agent-key branch in relay validate_agent_api_key (audit
  CRITICAL): agent auth now = per-agent cak_ key (SHA-256 -> connect_agent_keys,
  revoked filtered) OR support code OR deprecated shared AGENT_API_KEY (warned).
  A user JWT can no longer authenticate an agent.
- auth/agent_keys.rs: cak_ gen (OsRng 256-bit) + SHA-256 hash + verify.
- auth/jwt.rs: ViewerClaims + create/validate_viewer_token (5-min TTL,
  purpose=viewer, session_id+tenant_id claims; non-interchangeable with login).
- Admin key issuance: POST/GET/DELETE /api/machines/:agent_id/keys.
- POST /api/sessions/:id/viewer-token mints a session-bound short-lived token.
- Migration 005: organization/site/tags on connect_machines (fixes the silent
  update_machine_metadata write, coord todo faf39fe0).

NOTE: viewer-token minting is gated by AuthenticatedUser only; the AUTHORIZATION
check (admin/permission gate) that closes audit CRITICAL #1 lands in Task 3 (the
viewer WS verification). The viewer WS path (relay/mod.rs:285) is untouched here.
Not cargo-check-verified (no toolchain on the authoring host) - self-reviewed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 18:57:12 -07:00
ccc6ba9c02 ci: enforce clippy -D warnings and cargo audit as hard gates
All checks were successful
Build and Test / Build Agent (Windows) (push) Successful in 12m18s
Build and Test / Build Server (Linux) (push) Successful in 14m11s
Build and Test / Security Audit (push) Successful in 5m32s
Build and Test / Build Summary (push) Successful in 9s
Flip both CI gates from informational to hard-fail (SPEC-001 quality gates):
- clippy: `-- -D warnings` on the server crate. Cleared the debt via clippy --fix
  (unused imports/style), targeted #[allow(dead_code)] on native-remote-control
  future API, and #[allow(clippy::too_many_arguments)] on 3 protocol-mirroring fns.
- cargo audit: hard-fail with documented per-ID --ignore flags (rsa RUSTSEC-2023-0071
  unfixable/unreachable in active tree; gtk-rs + glib Linux-only tray backend not
  compiled into the Windows agent; proc-macro-error build-time). New advisories fail.
- Move [profile.release] to the workspace root (it was silently ignored in the server
  member), activating lto/codegen-units/strip.

No behavioral changes. Reviewed and gates verified passing on the build host.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 00:18:50 +00:00
1c5c1e78e7 style: cargo fmt --all — make codebase rustfmt-clean
Some checks failed
Build and Test / Build Server (Linux) (push) Failing after 2m59s
Build and Test / Build Agent (Windows) (push) Has started running
Build and Test / Security Audit (push) Has been cancelled
Build and Test / Build Summary (push) Has been cancelled
Run Tests / Test Server (push) Has been cancelled
Run Tests / Test Agent (push) Has been cancelled
Run Tests / Code Coverage (push) Has been cancelled
Run Tests / Lint and Format Check (push) Has been cancelled
First run of the build-and-test CI gate (cargo fmt --all -- --check) surfaced
pre-existing formatting drift across the agent and server crates. Apply rustfmt
across the workspace so the codebase meets its own CI gate. Pure formatting; no
logic changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 15:02:12 +00:00
60519be28a feat: operational tooling — signing, versioning, changelog, roadmap (SPEC-001)
Establish GuruConnect's release engineering and project tracking (SPEC-001):
- docs/ scaffold: FEATURE_ROADMAP, ARCHITECTURE_DECISIONS (ADR-001 standalone+contract,
  ADR-002 Gitea Actions + Azure Trusted Signing), docs/specs/SPEC-001, CHANGELOG.
- .gitea/workflows/release.yml: conventional-commit auto-versioning, git-cliff changelog,
  Windows agent build, Azure Trusted Signing via jsign (reusing the shared ACG cert profile),
  Gitea release via REST API. build-and-test.yml is the PR/push gate; deploy.yml de-duplicated.
- server: GET /api/changelog/:component/:version (latest + by-version), path-traversal hardened.
- cliff.toml; server/.env.example documents CHANGELOG_DIR.

Reviewed (Code Review Agent): axum route-conflict blocker fixed; CHANGELOG ordering, toolchain
target, breaking-change parsing, empty-changelog fallback addressed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 07:19:29 -07:00
e3e95f8fa7 chore: sync repository to current working state
Some checks failed
Build and Test / Build Server (Linux) (push) Has been cancelled
Build and Test / Build Agent (Windows) (push) Has been cancelled
Build and Test / Security Audit (push) Has been cancelled
Build and Test / Build Summary (push) Has been cancelled
Run Tests / Test Server (push) Has been cancelled
Run Tests / Test Agent (push) Has been cancelled
Run Tests / Code Coverage (push) Has been cancelled
Run Tests / Lint and Format Check (push) Has been cancelled
Brings azcomputerguru/guru-connect up to the authoritative working copy that
had been maintained in the claudetools monorepo: Phase 1 security and
infrastructure (middleware, metrics, utils, token blacklist, deployment
scripts, security audits) plus the native-remote-control integration spec.
Preserves the repo .gitignore, .cargo, and server/static/downloads.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 06:15:29 -07:00
5a82637a04 Add magic bytes deployment system for agent modes
- Agent config: Added EmbeddedConfig struct and RunMode enum for
  filename-based mode detection (Viewer, TempSupport, PermanentAgent)
- Agent main: Updated to detect run mode from filename or embedded config
- Server: Added /api/download/* endpoints for generating configured binaries
  - /api/download/viewer - Downloads GuruConnect-Viewer.exe
  - /api/download/support?code=123456 - Downloads GuruConnect-123456.exe
  - /api/download/agent?company=X&site=Y - Downloads with embedded config
- Dashboard: Updated Build tab with Quick Downloads and Permanent Agent Builder
- Included base agent binary in static/downloads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 11:13:16 -07:00
4e5328fe4a Implement robust auto-update system for GuruConnect agent
Features:
- Agent checks for updates periodically (hourly) during idle
- Admin can trigger immediate updates via dashboard "Update Agent" button
- Silent updates with in-place binary replacement (no reboot required)
- SHA-256 checksum verification before installation
- Semantic version comparison

Server changes:
- New releases table for tracking available versions
- GET /api/version endpoint for agent polling (unauthenticated)
- POST /api/machines/:id/update endpoint for admin push updates
- Release management API (/api/releases CRUD)
- Track agent_version in machine status

Agent changes:
- New update.rs module with download/verify/install/restart logic
- Handle ADMIN_UPDATE WebSocket command for push updates
- --post-update flag for cleanup after successful update
- Periodic update check in idle loop (persistent agents only)
- agent_version included in AgentStatus messages

Dashboard changes:
- Version display in machine detail panel
- "Update Agent" button for each connected machine

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 09:31:23 -07:00
4614df04fb Security: Require authentication for all WebSocket and API endpoints
- REST API: All session/code/machine endpoints now require AuthenticatedUser
- Viewer WebSocket: Requires JWT token in query params (token=...)
- Agent WebSocket: Requires either valid support code OR API key
- Dashboard: Passes JWT token when connecting to viewer WS
- Native viewer: Passes token in protocol URL and WebSocket connection
- Added AGENT_API_KEY env var support for persistent agents
- Added get_status() to SupportCodeManager for auth validation

This fixes the security vulnerability where unauthenticated agents
could connect and appear in the dashboard without any credentials.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 06:30:28 -07:00
3fc4e1f96a Add user management system with JWT authentication
- Database schema: users, permissions, client_access tables
- Auth: JWT tokens with Argon2 password hashing
- API: login, user CRUD, permission management
- Dashboard: login required, admin Users tab
- Auto-creates initial admin user on first run
2025-12-29 21:00:20 -07:00
AZ Computer Guru
dc7b7427ce Add machine deletion API with uninstall command support
- Add AdminCommand message to protobuf (uninstall, restart, update)
- Add DELETE /api/machines/:agent_id endpoint with options:
  - ?uninstall=true - send uninstall command to online agent
  - ?export=true - return session history before deletion
- Add GET /api/machines/:agent_id/history endpoint for history export
- Add GET /api/machines endpoint to list all machines
- Handle AdminCommand in agent session handler
- Handle ADMIN_UNINSTALL error in agent main loop to trigger uninstall

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 19:15:16 -07:00
f6bf0cfd26 Add PostgreSQL database persistence
- Add connect_machines, connect_sessions, connect_session_events, connect_support_codes tables
- Implement db module with connection pooling (sqlx)
- Add machine persistence across server restarts
- Add audit logging for session/viewer events
- Support codes now persisted to database

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 19:51:01 -07:00
4b29dbe6c8 Add disconnect/uninstall for persistent sessions
- Server: Add DELETE /api/sessions/:id endpoint to disconnect agents
- Server: SessionManager.disconnect_session() sends Disconnect message
- Agent: Handle ADMIN_DISCONNECT to trigger uninstall
- Agent: Add startup::uninstall() to remove from startup and schedule exe deletion
- Dashboard: Add Disconnect button in Access tab machine details
- Dashboard: Add Chat button for persistent sessions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 16:53:29 -07:00
3f1fd8f20d Add technician login and dashboard pages
- Add /login page with dark theme matching portal
- Add /dashboard with 4 tabs: Support, Access, Build, Settings
- Add clean URL routes (/login, /dashboard) to server
- Add "Technician Login" link to portal footer
- Dashboard shows active support codes with generate/cancel
- Build tab has installer builder form (placeholder for agent)
- Access tab has 3-panel layout for machine management

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 12:04:16 -07:00
611bc00d06 Add support codes API and portal server changes
- support_codes.rs: 6-digit code management
- main.rs: Portal routes, static file serving, AppState
- relay/mod.rs: Updated for AppState
- Cargo.toml: Added rand, tower-http fs feature

Generated with Claude Code
2025-12-28 17:54:05 +00:00
AZ Computer Guru
33893ea73b Initial GuruConnect implementation - Phase 1 MVP
- Agent: DXGI/GDI screen capture, mouse/keyboard input, WebSocket transport
- Server: Axum relay, session management, REST API
- Dashboard: React viewer components with TypeScript
- Protocol: Protobuf definitions for all message types

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 17:18:05 -07:00