Commit Graph
556 Commits
Author SHA1 Message Date
Juan DenisandClaude Opus 4.7 5541504ef8 Fix the systemic silent failures: empty log, dead WS, locked-out agents
Four real root causes that produced the symptoms we've been chasing:

1. agent.log was 0 bytes because io.MultiWriter aborts the entire
   write chain on the first writer error. On Windows services where
   os.Stdout writes can transiently fail, the lumberjack file writer
   never got the slog records — events.json (direct os.File) worked
   fine while agent.log silently stayed empty for the entire process
   lifetime. Replace io.MultiWriter with resilientWriter that
   independently writes to each underlying writer and swallows
   per-writer errors. Also surface logger init failures (MkdirAll,
   OpenFile) instead of silently falling back to stdout-only, and
   emit an explicit "logger initialized" startup line so an empty
   file is now an obvious bug rather than ambiguous.

2. WS connections appeared to "drop every 2-3 minutes" but actually
   the read loop had no ReadDeadline at all — ReadMessage() blocked
   forever on a network-killed connection until the OS-level TCP
   timeout fired, which is exactly what produced the
   ws_connected → ws_disconnected pattern in events.json. Add
   readWait = pingInterval*2.5 + 5s, reset it on every successful
   read AND in SetPongHandler. Now CF/ngrok killing the conn at the
   network layer (without sending a WS close frame) is detected
   within seconds, the read errors out cleanly, the Manager's flap
   detector counts it, and we fall back to polling far faster.

3. Newly-registered servers defaulted to permissions=[] which made
   every action 403. The user hit "Permission denied" on
   docker:image:list, system:info, agent:recapabilities, and probably
   half the rest. Default to ['*'] when no profile or list is
   specified — single-tenant deployments shouldn't need to manually
   open a profile editor before anything works.

4. Migration 006 retroactively fixes already-stuck servers: any row
   with permissions=[] gets ['*']. Non-empty admin-defined ACLs are
   left alone. Solves "I registered before this fix and now I can't
   do anything" without bulldozing legitimate configurations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 07:06:58 -04:00
Juan DenisandClaude Opus 4.7 c31da726f6 Detect WS flapping and fall back to polling permanently
The current Manager only falls back on hard handshake failures
(RSV1 / engine.io). It doesn't catch the more common CF-tunnel
failure mode the user observed in events.json: WS authenticates
fine, stays alive 2-3 minutes, drops, reconnects, drops again,
forever. Each cycle pays an auth round-trip and burns bandwidth on
retry/backoff loops without ever delivering live streams.

Add a stability monitor that samples IsConnected() at 1Hz, records
disconnect timestamps in a sliding 10-minute window, and triggers
runFallback() permanently after 3 disconnects in window. Once on
poll, no more reconnect churn — heartbeat + buffered capability/
sysinfo get delivered cleanly through the REST endpoint that the
intermediary doesn't mangle. Restart-to-recover semantics preserved
(matches the existing "stay on poll until process restart" rule).

Threshold (3 drops / 10 min) is conservative: a single drop or
two from a brief network blip won't trigger; only sustained
unreliability does. Users with healthy direct WS connections never
hit this path at all.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 07:02:04 -04:00
Juan DenisandClaude Opus 4.7 e99e65cff6 Auto-correct stale 'online' status when no in-memory agent
When the panel restarts or the agent process crashes without a clean
disconnect, Server.status stays 'online' in the DB even though
agent_registry has no in-memory record. The UI then shows a
contradiction: "online" pill in the header, "Agent not connected"
on the Docker tab.

Reconcile in get_server: if there's no in-memory agent and the row
says online, flip to offline and persist. The capabilities cache +
last_seen still surface so the user sees the last known state, but
the UI now correctly reflects that the agent isn't reachable right
now.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 06:52:15 -04:00
Juan DenisandClaude Opus 4.7 19907dec43 Stop dropping capability/sysinfo payloads on transient /poll failures
pollOnce was clearing c.caps and c.sysInfo *before* postJSON ran,
so any failed /poll request (tunnel reconnect, transient 5xx,
timeout) silently lost the buffered payload. The agent's periodic
resend would only repopulate it 5 seconds later, and if the panel
was checking just before that tick the capability map looked empty.

Plus the very first /poll after auth happens before the
connectionWatcher's 1Hz tick gets a chance to fire sendCapabilities,
so /poll #1 had nothing to ship.

Fix: don't clear the buffers on /poll. The agent re-populates them
on every 5–60s tick, the panel's update_capabilities is a pure
overwrite, and re-sending the same payload twice is free. This
trades a few unnecessary writes for "your capabilities never go
missing because of a flaky network."

Also harden update_system_info: only overwrite a column when the new
value is truthy. Previously a single probe failure (Docker briefly
unreachable, gopsutil WMI hiccup) would wipe a healthy value to
empty/0 and leave it that way until the next successful probe — see
the regression where Docker Version went 27.3.1 → N/A across builds.

And: log the top-level keys + inner caps count + sudo mode in
update_capabilities so we can diagnose the "panel says empty"
failure mode from the panel logs without instrumenting further.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 06:46:13 -04:00
Juan DenisandClaude Opus 4.7 6e5bccda01 Permission expansion + Go probe + persisted system info fallback
Three wins exposed by the redeployed panel showing real data:

1. Permission expansion now covers every namespace, not just docker
   and system. Extend _expand_permission_scope so any action with a
   read-style verb (list, list_installed, list_units, status, info,
   inspect, search, logs, stats, available, current) accepts a
   `<ns>:read` or `<ns>:<sub>:read` candidate. Mutating verbs add a
   `<ns>:write` candidate. This unblocks docker:image:list,
   system:info, packages:list_installed, systemd:list_units, and the
   pyenv read paths for users on read-style profiles.

2. Go runtime probe was using `--version` (a flag), but Go takes
   `version` as a subcommand. The agent's runtime detector tries
   each form and falls back gracefully; Go is now correctly
   identified by `go version` and the panel shows a real version
   string instead of the "go flag provided but not defined" error
   text.

3. SystemInfo gains Platform + CPUModel fields (pushed alongside
   the existing hostname/cores/memory/disk). OverviewTab now reads
   from the persisted server row first and falls back to the
   synchronous getRemoteSystemInfo response — so CPU and memory
   render even when the system:info action is permission-denied or
   the agent is offline.

   metrics.GetSystemInfo also gets a runtime.NumCPU() fallback so
   CPU cores never reports 0 on Windows hosts where gopsutil's WMI
   queries flake.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 06:34:20 -04:00
Juan DenisandClaude Opus 4.7 d528d27296 Bypass per-server ACL for control-plane actions; add diagnostic logs
The Refresh button on the System Status card was returning 403
because the per-server permissions allowlist (e.g. 'docker_manager'
profile) doesn't include 'agent:recapabilities' and the scope
expander has no rule for the agent: namespace. The action is purely
panel-driven discovery — it doesn't mutate the host — so it
shouldn't be subject to the same ACL as install/exec actions.

- Add Server.CONTROL_PLANE_ACTIONS bypass set: agent:recapabilities,
  agent:update. has_permission() returns True for these unconditionally;
  JWT auth at the API layer is what gates access.
- /poll endpoint now logs the keys it received in metrics / system_info
  / capabilities so we can debug "panel says N/A" failure modes from
  the panel logs without instrumenting the agent.
- Agent's sendCapabilities now logs at INFO with sudo mode + capability
  count + runtime count so the agent.log shows whether the periodic
  resend is firing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 06:17:31 -04:00
Juan DenisandClaude Opus 4.7 7d55a9c05d Add panel-driven cloudflared login flow
Users had to SSH in to run `cloudflared tunnel login` before any of
the Tunnels tab worked. Wire up the OAuth flow so the panel can
trigger it and surface the auth URL for the user to open from their
own browser.

Agent:
- New cloudflared.LoginEvent + Manager.Login() that spawns the
  process, regex-matches the dash.cloudflare.com/argotunnel URL on
  stdout/stderr, and watches cert.pem in parallel as a reliable
  completion signal. 15-minute hard ceiling.
- New cloudflared:login action returns {job_id, channel} immediately;
  the goroutine emits start → status (with auth_url) → done events
  on the job channel.
- Non-linux stub returns "unsupported".
- jobs.HasTerminated() helper so handler shutdown paths can avoid
  double-emitting the terminator.

Panel:
- POST /servers/<id>/cloudflared/login + RemoteCloudflaredService.login
- ApiService.startRemoteCloudflaredLogin

Frontend:
- CloudflaredTab gains a "Login to Cloudflare" CTA when not authed.
  Click → starts the agent flow, joins the job's Socket.IO room,
  listens for the auth_url event, and renders an Open-in-Browser
  button. Once the agent emits done, refreshes capabilities + status
  + tunnel list automatically — the rest of the tab unlocks itself.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 05:52:11 -04:00
Juan DenisandClaude Opus 4.7 244eef80c6 Push system_info from agent and persist server IP
The Server.ip_address column was never written: register_polling
captured the source IP into the in-memory ConnectedAgent but didn't
copy it to the Server row, so the Overview tab showed "IP Address:
N/A" for every connected agent forever. Persist it on agent
registration; existing rows backfill on the next reconnect.

The agent never actually pushed a system_info message either —
it only answered system:info synchronously on demand, so update_
system_info was never called from the request/response path. CPU,
memory, disk, kernel version, and docker version stayed N/A on the
Server row no matter how long the agent had been online.

- New sendSystemInfo() in agent.go builds a typed SystemInfoMessage
  and pushes via the transport. Wired into connectionWatcher
  alongside sendCapabilities so the data flows on connect and on
  the periodic resend cadence (5s for the first minute, 60s
  thereafter).
- poll.Send() gains a typed branch for SystemInfoMessage that
  marshals to a map and stashes for the next /poll body, mirroring
  the CapabilitiesMessage path.
- agent_registry.register_polling now writes ip_address to the
  Server row when present.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 05:36:16 -04:00
Juan DenisandClaude Opus 4.7 af60b4c982 Re-send agent capabilities on a periodic cadence
The connectionWatcher only fired sendCapabilities() on a single
false→true transition of IsConnected(). When the WS→poll fallback
dance briefly raised IsConnected() against the WS backend right
before it died, the message landed on a transport whose Send()
silently buffered it forever — the panel ended up with an empty
capability map for the lifetime of the agent process.

Add a parallel resend ticker that fires every 5s for the first
minute then backs off to every 60s thereafter. The panel's
update_capabilities is a pure overwrite, so re-shipping the same
payload costs nothing; the worst case is a 60s gap before the next
refresh once the agent has been up for a minute.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 05:26:54 -04:00
Juan DenisandClaude Opus 4.7 32bf2b8081 Cache agent capabilities to DB and surface them in System Status card
The agent reports a rich capability payload (sudo mode, runtime
managers, detected runtimes, allowed paths, systemd JSON support)
that the panel was discarding once the WebSocket disconnected. The
Overview tab also gave no visibility into what the agent had
discovered, which left users guessing why a feature tab was missing
or a Docker call returned empty.

Backend:
- Server model gains seven nullable columns: cached_capabilities,
  cached_runtimes, cached_runtime_managers, cached_allowed_paths,
  cached_sudo, cached_systemd_json, capabilities_at. Migration 005
  is idempotent (checks existing columns before adding) so it's safe
  on already-bootstrapped databases.
- agent_registry.update_capabilities() now persists a snapshot to the
  Server row whenever the agent reports state. Wrapped in try/except
  so a DB hiccup doesn't drop the in-memory update.
- /servers/<id> falls back to the cached snapshot when the agent is
  offline and exposes capabilities_stale + capabilities_at so the UI
  can badge stale data.

Frontend:
- New SystemStatusCard renders sudo mode, package manager, runtime
  managers, detected runtime versions, capability map (as colored
  chips), and file-access roots. "Stale" badge + relative timestamp
  + Refresh button (calls agent:recapabilities).
- DockerTab now distinguishes "agent online but no docker daemon"
  from "no containers found", with concrete remediation hints. Load
  errors surface as a banner instead of being swallowed to console.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 05:16:42 -04:00
Juan Denis 930705fa3b Mirror agent version; plugin install & UI improvements
Sync build Version into ws and poll transport packages and use it in User-Agent headers to avoid mismatched version strings. Improve plugin installer robustness: support SERVERKIT_BACKEND_PLUGINS_DIR and SERVERKIT_FRONTEND_PLUGINS_DIR env overrides, add clearer Docker-aware error messages, lazy-create frontend plugin dir (with helpful guidance for Docker), validate local paths (reject Windows paths on non-Windows hosts), preflight zip contents to detect frontend assets before extraction, and skip frontend manifest regeneration when frontend dir is absent. Frontend UI updates: redesign Docker page layout and stats, integrate TargetPicker, introduce container cards with richer actions and resource indicators, wire in LogToolbar/LogContent for log viewing (download, auto-refresh, search, line numbers, wrap), and update Logs modal to a drawer-style preview. Marketplace text clarified that install-from-path refers to the panel host. Terminal/Journal improvements: new journal UI and controls, persistent prefs, auto-refresh, download support, and remote-target handling.
2026-05-01 05:12:23 -04:00
Juan DenisandClaude Opus 4.7 a534fbf002 Add Packages/Services tabs, JobProgressModal, pyenv runtime mgmt and template library
Phase 3 (frontend), Phase 4 (template library), Phase 5 (pyenv runtimes).

Frontend:
- New Packages tab on ServerDetail: search, install/remove, upgrade-all,
  update-cache, quick-install presets (nginx, redis, mariadb, postgres,
  docker, fail2ban, certbot, htop). Capability-gated on packages.
- New Services tab: list systemd units with state filter, start/stop/
  restart/logs per row, daemon-reload at top. Capability-gated on systemd.
- JobProgressModal subscribes to a server-stream Socket.IO room and
  renders live install/build progress until the agent emits phase=done.
- ApiService: 13 packages/services methods + 9 runtime methods +
  refresh-capabilities helper.
- LESS partials for both new tabs imported in main.scss.

Template library: 9 new one-click stacks added to ServerTemplate
TEMPLATE_LIBRARY: lemp, lamp, docker-host, node-host, python-host, redis,
postgres, cloudflared, fail2ban. Reuses existing packages/services/
firewall_rules JSON columns; the workflow engine's agent_command +
capability_gate nodes drive execution against the new agent surface.

Phase 5 — pyenv / pyenv-win runtime management:
- Agent: 9 new runtimes:* actions (list, pyenv:bootstrap, python:installed,
  python:available, python:install, python:uninstall, python:set_global,
  python:set_local, python:current). Bootstrap and install stream via
  the job-channel pattern. pyenvLock mutex serializes mutations.
  Capability probe surfaces RuntimeManagers["python"] = pyenv | pyenv-win.
- Panel: remote_runtimes_service.py + 9 routes under /servers/<id>/runtimes.
- Frontend: ApiService methods to drive the new endpoints.
  (Dedicated RuntimesTab component left as a follow-up; the API
   surface is the foundation.)

Build, vet, and tests pass across all three layers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 04:42:30 -04:00
Juan DenisandClaude Opus 4.7 e71099a4e9 Add remote packages, services, sudo, job streaming and capability re-probe
Foundation for the remote server setup experience: agent gains
auto-sudo, package and systemd handler additions, missing docker
verbs, and a job-channel registry for streaming long-running
operations. Panel exposes the new agent surface as /servers/<id>/
packages, /services, and /refresh-capabilities routes.

Agent:
- New protocol actions: agent:recapabilities, packages:update_cache/
  install_async/upgrade/search/info, systemd:daemon_reload/list_units/
  logs/logs_follow, docker:container:create/exec, docker:image:build,
  docker:volume:create, docker:network:create.
- Auto-sudo helper (sudo -n) probed at boot, surfaced as a capability;
  apt invocations get DEBIAN_FRONTEND=noninteractive + dpkg force-confold.
- jobs registry with ring-buffer replay so panels that subscribe to a
  job:<id> channel mid-flight still see prior progress events.
- Capability re-probe is mutex-guarded and additive (transient probe
  failures don't drop features the panel already saw).
- Existing systemd handlers now sudo and use 2-min timeouts for cold
  service starts (postgresql etc.).

Panel:
- remote_packages_service.py and remote_systemd_service.py mirror the
  cron service shape (thin send_command dispatcher).
- 13 new routes on servers.py covering packages CRUD + search/info,
  systemd unit control + logs + daemon-reload, and capability refresh.
- Long-running install/upgrade return {job_id, channel} for the
  frontend to subscribe to via Socket.IO.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 04:33:08 -04:00
Juan Denis 07a778d2bb Add log viewer UI and plugin local/upload install
Introduce a full log viewer feature and add backend/frontend support for installing plugins from local folders or uploaded zips. Backend: add /plugins/install-local and /plugins/install-upload endpoints (admin-only, 50MB cap for uploads) that reuse existing install pipeline and emit audit logs. Frontend: add LogContent, LogFileList, LogToolbar and logHelpers, integrate into Terminal.jsx with target picker, search, auto-refresh, wrap/line-number prefs and remote-target handling; add styles for the viewer and marketplace install tabs. API: detect FormData in the client to avoid forced JSON Content-Type and add installPluginFromPath/installPluginFromZip helpers. Misc: marketplace UI now supports URL / path / upload install modes and minor SCSS fixes (font-size variable adjustments).
2026-05-01 03:48:27 -04:00
Juan Denis 1f61513c26 Add agent Phase4 primitives, remote files & UI
Add Phase 4 agent primitives (package management, systemd control, bounded exec) and advertise file-access roots so the panel can target agents safely. Introduces agent/internal/agent/workflow_handlers.go with handlers for packages, systemd and system:exec, registers those actions, and extends capabilities.Probe and capability messages to include runtimes and allowed_paths.

Backend: add RemoteFileService and new /servers/<id>/files/* endpoints, store advertised allowed_paths in agent_registry and expose a getter, normalize agent system metrics shape in remote_docker_service, and wire capabilities/allowed_paths into the servers list. Extend workflow_engine with agent_command, capability_gate and runtime_gate nodes and basic runtime-version comparison.

Frontend: add TargetPicker component and update FileManager to support remote targets (browse/read/write via agent), guard unsupported remote ops, and normalize agent file responses for the UI. Overall this enables remote file browsing and Phase 4 workflows against connected agents.
2026-05-01 03:37:33 -04:00
Juan Denis 611e332b4d Add file manager UI components and features
Introduce a modular file manager UI: add ContextMenu, FileCard, FileRow, FileIcon, FolderTree, ImageThumb, PreviewDrawer and fileTypes utilities. Refactor FileManager.jsx to use these components and implement selection, multi-select/shift-range, context menu, preview drawer with editable files, image thumbnails (auth download), drag-and-drop and input uploads with progress, pinned quick-access, folder tree with caching/expand behavior, breadcrumbs, persistent view preferences, search, and improved navigation/history. Update styles and persist various UI settings in localStorage. Also add /docs/plans to .gitignore.
2026-05-01 03:15:14 -04:00
Juan Denis 8ddd60f83d Add Cloudflared tunnel management
Introduce Cloudflare Tunnel management end-to-end.

Highlights:
- Add agent/internal/cloudflared package (Manager interface, Linux impl, non-Linux stub) to shell out to cloudflared and detect auth via cert.pem.
- Wire cloudflared Manager into the agent and register cloudflared:* handlers for status/list/create/route/delete.
- Extend protocol.Capabilities and agent payloads with runtimes detection and a cloudflared capability; implement runtime version probes.
- Add backend API endpoints and RemoteCloudflaredService that forward cloudflared actions to agents; update agent registry to store runtimes.
- Frontend: new CloudflaredTab UI, API client methods for remote cloudflared operations, styles, and UX tweaks (plus minor component/class refinements in LogViewer, ProcessTable, FileManager, StyleGuide, terminal styles).

Purpose: allow the panel to manage Cloudflare named tunnels by delegating commands to the agent's cloudflared CLI, while surfacing binary/auth state (install vs authenticated) and detected language runtimes.
2026-05-01 02:26:15 -04:00
Juan Denis dca5c3af67 Add remote cron management (agent, API, UI)
Introduce remote cron management across agent, backend and frontend.

- Agent: add a cron.Manager to agent, register handlers (cron:status,list,add,remove,toggle) and implement thin JSON handlers. Add agent/pkg/protocol message constants.
- Cron package: new platform-agnostic interface with Linux implementation (crontab-driven) and non-Linux stub. Includes content-based stable IDs, validation, list/add/remove/toggle and human-friendly schedule descriptions.
- Backend: expose /servers/<id>/cron/* endpoints and add RemoteCronService to proxy requests to agents via agent_registry, mapping agent responses to HTTP codes.
- Frontend: enhance Tabs component with overflow "More" popover; add API calls for remote cron ops; wire a Cron tab in ServerDetail (guarded by server.capabilities.cron) with UI for listing, adding, toggling and removing jobs; add Cron UI in Git page by switching to the new Tabs component.

Notes: cron functionality is Linux-only; non-Linux agents return an explicit unsupported status. Validation prevents unsafe shell operators and requires absolute command paths.
2026-05-01 01:54:17 -04:00
Juan Denis 3963321e92 Add GUI capture SDK; refactor UI components
Introduce a small agent-side GUI SDK to expose desktop-capture primitives (capabilities + screenshot) with platform implementations (windows, linux, other) and register handlers in the agent; add protocol actions gui:capabilities and gui:screenshot.

Refactor frontend UI for consistency and usability: replace multiple custom banners with a unified alert system, introduce EmptyState component usage across pages, switch Modal implementation to a Sheet (responsive side sheet with size tokens), make StatCard clickable with detail and active states and update Servers to use StatCard/StatsGrid, and standardize error/alert classes in QueryRunner, RemoteTerminal, CompareView, PipelineView, PromoteModal, ResourceLimitsModal, BasicAuthModal, etc. Also adjust badge/sheet sizing, alert & card styles, theme border variables, and small polish in ConfirmDialog, StyleGuide, and other components.
2026-05-01 01:32:20 -04:00
Juan Denis a93697c7f6 Add agent capability probing and reporting
Probe and report agent feature capabilities (cron, docker, systemd, nginx, etc.) so the panel can gate target pickers without extra round-trips.

Key changes:
- Add agent/internal/capabilities: probes host for features and platform/distro, returns protocol.CapabilitiesMessage cached at agent startup.
- Agent: store probed capabilities, send them on every transport reconnect (sendCapabilities) and include them when using poll transport.
- Protocol: introduce TypeCapabilities and CapabilitiesMessage (map[string]bool + platform/distro fields).
- Poll transport: accept CapabilitiesMessage in Send(), serialize to raw payload and queue for next /poll; support one-shot capabilities in poll body.
- Backend: handle capabilities from socket (on_capabilities) and poll endpoint; persist capabilities in in-memory ConnectedAgent (agent_registry) with helpers get_capabilities/has_capability; include capabilities/platform info in servers API.
- New fleet API (GET /api/v1/fleet/targets): list runnable targets (local + connected agents) and optionally filter agents by a requested feature using the advertised capability map.

Rationale: make agent feature availability explicit and discoverable to the panel so UI pickers can show only applicable agents without asking agents on every UI interaction.
2026-05-01 00:37:48 -04:00
Juan Denis 8ea0586d88 Agent key migration, DB fix, UI tabs/page cleanup
Add robust credential handling and migration for agent encryption keys: surface LoadError on startup, log clear guidance when creds fail to decrypt, try legacy (pre-1.6.14) machine key fallback and transparently re-encrypt under the new host-stable key. Fix machine-key derivation (make host-stable instead of user-stable) and encapsulate decryption/migration helpers.

Fix SQLite autoincrement issue: change ServerMetrics.id from BigInteger to Integer so SQLite will autoincrement rows and metrics are recorded.

Ensure background heartbeat checker can touch the DB by capturing the Flask app in AgentRegistry and entering an app_context in the heartbeat thread (with a test-friendly fallback for when no app is available).

Frontend UI: simplify Tabs component classes and update pages to use a unified .page-container wrapper; replace many manual tab button implementations with Tabs/TabsList/TabsTrigger and add improved tab styles (disabled/focus states). Misc: add docs/PLAN_AGENT_FLEET.md to .gitignore.
2026-05-01 00:27:37 -04:00
Juan Denis 19c727be4c Add Windows service support and new UI components
Agent: factor run logic into agentMainLoop and detect SCM launch; add Windows service dispatcher (service_windows.go) and POSIX stub (service_other.go) to properly handle SCM lifecycle and avoid Windows SCM error 1053. Frontend: add a set of presentational components (DangerZone, InfoList/InfoItem, JournalControls, LogViewer, MetricRow/MetricItem, ProcessTable, ProgressBar, ServiceCard, StatCard) and wire them into multiple pages and security tabs, replacing many ad-hoc info-list blocks. Also add a route for style-guide/:tab and update AgentFleet to use the new StatCard/StatsGrid layout. These changes improve service reliability on Windows and DRY up UI layouts with reusable components.
2026-04-30 23:11:26 -04:00
Juan Denis 96a6f31d75 Add poll transport; Windows UI & service fixes
Introduce a fallback polling transport and manager: add internal/transport (Manager + poll client) so the agent can fall back from WebSocket to REST long-poll when tunnels mangle WS frames. Wire the Manager into the Agent and expose transport mode in IPC status.

Windows/service fixes: add service-scoped mutex to prevent concurrent service starts, probe IPC port on start to fail fast if occupied, and mirror main.Version into agent package at init. Fix spawned wizard visibility by setting HideWindow=false and add focus helpers that force foreground on Windows.

UI/asset changes: enable DevTools by default (env to disable), inject a small JS shim to forward console errors/navigation readiness to Go logs, hide WebView host until bundle ready (with timeout), and wrap static assets with no-store headers to avoid stale cached bundles. Add local /local/status endpoint so the UI can detect registration when IPC is unreachable.

Pairing/service handling: ensure service stop/start errors are surfaced, wait for service to reach RUNNING after pairing and surface helpful error messages if it doesn't. Implement platform-specific waitForServiceRunning and service control stubs.

Auth/backend alignment: expand API key prefix from 8 to 12 chars to match backend panel expectations and avoid authentication mismatches.

Misc: add focus_windows.go (Windows-only), various small refactors and logging improvements to make blank-page and pairing failures debuggable.
2026-04-30 22:31:04 -04:00
Juan Denis 354c625fa4 Add console actions, logs UI, and log rotation
Expose local console actions and log rotation for the desktop console. Adds a localAsset API (service start/stop/restart, open path/URL, spawn pairing wizard) with Windows and non-Windows implementations and registers it in the asset server. Introduces Agent.ClearLogs and an IPC /logs/clear endpoint + handler that calls into the agent to rotate logs. Enhance Logger to hold the lumberjack rotator and provide Rotate() to trigger manual rotation. Wire client-side support (ipc client & hooks), add new Actions and Logs React pages with styles, and tweak the Windows webview sizing. These changes let the console clear/rotate agent.log safely, control the service from the interactive session, and provide a live, searchable log tail in the UI.
2026-04-30 02:08:23 -04:00
Juan Denis 3ff432be25 Add activity event store and UI
Introduce a small append-only events store and surface agent lifecycle/activity events to the UI. Adds internal/events with a concurrent ring buffer (capacity 200) and optional JSON persistence (events.json next to agent data), plus Append/Snapshot/Clear APIs. Wire the store into Agent (create store, GetEvents, append service start/stop/restart and connection transition events) and add connectionWatcher to emit WS connect/disconnect events.

Expose events via IPC (/events) and update the IPC client and hooks (ipc.events, useEvents) so the frontend can poll for new events. Implement a complete Activity page UI (list, icons, severity filter) and corresponding styles. Persistence is best-effort and safe (temp-file rename); malformed or missing files are ignored to avoid startup failures.
2026-04-29 20:38:30 -04:00
Juan Denis 04571a8d0a Add metrics sampler and new agent console UI
Introduce a lightweight metricSampler (1 Hz, 300-sample ring buffer) to record recent CPU/memory samples for the desktop console and integrate it into Agent (field, startup loop, and GetMetricsHistory accessor). Add IPC types/route for MetricSample and a /metrics/history handler to expose the ring buffer. Implement samplerLoop with resilient collection and a thread-safe snapshot API.

Revamp the React UI: remove the old ConsolePage, add a Shell with Sidebar and new pages (Overview, Activity, Logs, Actions, About), plus IPC client/hooks for polling (including metrics history). Overview renders sparklines using the sampled data. Update main.scss with layout, sidebar, cards, pills and metrics styling to support the new UI.
2026-04-29 20:32:37 -04:00
Juan Denis 11e3b1ceef Add WebView2-based agent console and UI
Bump version to 1.5.9 and add a Windows-only WebView2-based desktop console driven by an embedded React SPA. Introduces agent/internal/agentui with an embedded dist, an HTTP asset server, and platform-specific WebView2 launcher; adds console CLI command to open the window. Adds a new agent/ui React app (source, package.json, lockfile) and .gitignore entries for built UI. Update Go modules to include WebView2/winloader deps and update go.sum. Improve pairing wizard UX: use lowercase passphrase alphabet and add Copy buttons/clipboard support with transient feedback. Harden websocket client: disable permessage-deflate and set ngrok header to avoid tunnel interstitials. Update MSI packaging to auto-start service, grant user permissions for service and ProgramData config, and include Wix util extension in build script.
2026-04-29 19:40:10 -04:00
Juan Denis 4d6e712fb5 Generate and display pairing passphrase
Generate an 8-char cryptographically-random passphrase (using a reduced alphabet that excludes ambiguous chars) on the agent side and show it in the Windows setup wizard instead of asking the user to type one. Adds generatePassphrase(), updates wizard UI to display the passphrase (and clear it on cancel), and removes the passphrase input/validation.

Also improves the web UI pairing form to auto-lookup the pair code once 6 characters are entered (using useEffect with cancellation to avoid premature "must be 6 chars" errors), updates instructional text/placeholders to reflect the agent-displayed passphrase, and tweaks lookup error/loading handling.
2026-04-29 17:53:12 -04:00
Juan Denis bcaa3dff2d Windows setup UI + MSI launcher & frontend tweaks
Add Windows-specific theming and dark-mode helpers and refactor the setup wizard to use a palette-based layout (new theme_windows.go, darkmode_windows.go and layout updates in window_windows.go). Improve pair-code rendering (displayCode) and various UI spacing, fonts and controls. Add a SmartScreen-bypass launcher (launcher.vbs), wire it into the MSI (Product.wxs) and copy it during the MSI build (build.ps1); Start menu shortcut and auto-start now invoke wscript.exe with the launcher to avoid SmartScreen killing the unsigned exe. Frontend: minor guard in Servers.jsx to avoid empty lookups, add a dev-only Style Guide link in Settings and small SCSS tweak for settings nav items. Bump VERSION to 1.5.8.
2026-04-29 17:30:46 -04:00
Juan Denis 0d76726936 Add native Windows desktop wizard & ARM64 builds
Introduce a native Windows desktop pairing experience and add ARM64 Windows builds/MSI.

Key changes:
- Add native Windows UI support: app.manifest, walk/win deps, icons, header image, and foreground activation helpers.
- Replace the old local HTTP/webview wizard with a native setup UI (remove wizard.html, refactor setupui). Add setupui.Run integration.
- Implement desktop/tray behavior: runDesktop/runTray refactor, single-instance mutex, detached spawn for the pairing wizard, desktop file-backed logging, and MessageBox wrapper for early errors.
- Build/CI updates: add windows/arm64 to build matrix, include -H=windowsgui for windows builds, produce per-arch MSI artifacts, and update release workflow summaries.
- Packaging & resources: add .syso resources for amd64/arm64, MSI build script updates, icon generation script and packaging tweaks, and update .gitignore to ignore dist and MSI outputs.
- Dependency and version bumps: update agent/go.mod/go.sum for walk/win and other indirect deps; bump VERSION to 1.5.4.

These changes enable a native pairing wizard on Windows (no browser/WebView2 required), keep the tray visible while the wizard runs, and add ARM64 support end-to-end (binary and MSI installers).
2026-04-29 15:16:25 -04:00
Juan Denis c62497bbf0 Style tabs as underline bar and enable scrolling
Refactor Tabs styles to use an underline-style tab bar and make the tab list horizontally scrollable. TabsList switched from a pill background to a border-bottom layout, hides scrollbars and adds spacing; TabsTrigger was updated to remove the pill active background, add an accent underline (data-[state=active]), hover/focus/disabled states, and cleaner spacing; TabsContent focus styles were slightly adjusted for consistent focus rounding. This improves visual consistency, accessibility (focus states), and usability for overflowed tab sets.
2026-04-29 05:29:51 -04:00
Juan Denis b0b2f57b60 Replace native controls with UI components
Replace ad-hoc HTML controls with shared UI primitives across multiple frontend components. Migrated buttons, inputs, textareas, checkboxes, switches, badges, skeletons and selects to components from '@/components/ui/*'. Rewrote CommandPalette to use CommandDialog/CommandList primitives (removed manual keyboard handling and focus/scroll logic). Updated EnvironmentVariables, LogsDrawer, LogsTab, CommandsTab, EventsTab, GitConnectModal, GunicornTab, PackagesTab, SettingsTab, ShellTab, Setup steps, WordPress components and various workflow panels to use the new UI components and variants; improved UI consistency and badge/skeleton usage. Also tightened error handling in a few places (explicit catch param) and cleaned up modal form layouts and action buttons.
2026-04-29 05:23:09 -04:00
Juan Denis e734fd6d27 Add setup debug logging & refactor security UI
Add diagnostic setup logging and Windows-friendly error UI, plus a large refactor of security frontend components.

- Agent: introduce openSetupDebugLog, write diagnostics during runSetup, LockOSThread for Windows WebView2, and catch panics to surface failures. Add platform-specific showFatalError implementations (MessageBox on Windows, stderr elsewhere). Update setup UI Run behavior to create the native WebView2 window synchronously and fall back to the browser.
- Frontend: replace raw HTML buttons/badges/inputs/selects/textareas across many security-related components with shared UI primitives (Button, Badge, Input, Label, Select, Textarea) and update modal forms to use them.
- Misc: add /agent/packaging to .gitignore.

These changes improve diagnostics for the setup wizard (especially when launched without a console), provide clearer error surfacing on Windows, and standardize the security UI on the new component library.
2026-04-29 05:08:52 -04:00
Juan Denis 21b5715345 Merge branch 'dev' of https://github.com/jhd3197/ServerKit into dev 2026-04-29 04:56:54 -04:00
Juan Denis 956c8e7964 Add browser setup wizard and MSI shortcuts
Introduce a local-loopback pairing wizard and related installer/packaging changes.

- Add a new CLI command `setup` (agent/cmd/agent/main.go) that launches a small HTTP server and opens a browser/native window to run a pairing wizard.
- Implement the setup UI server and wizard HTML (agent/internal/setupui/*). The wizard runs a local HTTP API to start pairing, poll status, save credentials, and on Windows attempts to open a native WebView2 window (github.com/jchv/go-webview2) falling back to the system browser. After successful pairing the agent service is switched to auto-start (best-effort on Windows).
- Add platform-specific helpers: WebView2 window on Windows and no-op stubs on other OSes, plus service-start helper for Windows.
- Update go.mod/go.sum to include WebView2/winloader deps.
- MSI changes: add Start Menu shortcuts (Setup/Status), do not auto-start the service on install (start remains demand), add an Icon entry, and adjust build.ps1 to resolve the output directory to an absolute path for stable output paths. Packaged MSI outputs were added under packaging/msi/output/.
- Frontend additions: add shadcn/ui configuration, jsconfig, new globals and UI components used by the wizard (frontend/src/... and assets).

These changes provide an easier desktop pairing flow while keeping CLI pairing available for headless servers, and tweak the installer so the service isn't started before credentials exist.
2026-04-29 04:56:03 -04:00
github-actions[bot] 2ed3b50d72 chore: bump version to 1.4.18 [skip ci] 2026-04-29 07:28:21 +00:00
Juan DenisandCopilot 3a0fd76fff Fix Docker (Go 1.23) + MSI (pin WiX v5) builds in agent-release
- agent/Dockerfile: bump golang base from 1.21 to 1.23 to match go.mod
- agent-release.yml: pin WiX to 5.0.2 to avoid the OSMF EULA prompt
  introduced in WiX 7

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-29 03:28:10 -04:00
github-actions[bot] 2f25fd8bb2 chore: bump version to 1.4.17 [skip ci] 2026-04-29 07:14:34 +00:00
Juan DenisandCopilot 05a70f1a3b Bump vulnerable backend deps flagged by Safety
- python-dotenv 1.0.0 -> 1.2.2 (CVE-2026-28684, arbitrary file overwrite via symlinks)
- cryptography 46.0.5 -> 46.0.7 (CVE-2026-39892 buffer overflow, CVE-2026-34073 cert validation)
- requests 2.32.5 -> 2.33.1 (CVE-2026-25645, insecure temp file reuse)
- Authlib 1.6.9 -> 1.6.11 (CVE: missing CSRF protection)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-29 03:14:25 -04:00
Juan DenisandCopilot f82c12ae41 Pin agent to Go 1.23 for CI compatibility
The previous commit accidentally bumped the toolchain to Go 1.25 via
`go get`. Downgrade golang.org/x/term and golang.org/x/sys to versions
that work on Go 1.23 and update the agent-release workflow to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-29 03:12:47 -04:00
Juan Denis e5a90a3085 Add short-code agent pairing flow
Implements a RustDesk-style short-code pairing feature across agent, backend, frontend and docs.

Key changes:
- Agent CLI: adds `serverkit-agent pair` command (agent/cmd/agent/pair.go) that generates/loads an Ed25519 keypair, enrolls with the panel, shows a rotating pair code, and saves credentials on claim. Adds passphrase marker handling and interactive/headless modes.
- Agent internals: new pairing package with client and keypair (agent/internal/pairing/*.go). Keypair files are encrypted using new exported config EncryptBytes/DecryptBytes utilities and MachineID() helper in agent/internal/config/config.go. go.mod/go.sum updated (Go version and x/term, x/sys bumps).
- Backend API: new pairing blueprint exposing endpoints for enroll, poll, code refresh/freeze, lookup and claim (backend/app/api/pairing.py). Adds PendingAgent model (backend/app/models/pending_agent.py) to track enrollments and their lifecycle.
- Backend service: pairing_service (backend/app/services/pairing_service.py) implements enrollment, rotation, long-polling, claim handling, credential minting and one-shot delivery. Adds a background pairing pruner thread to remove expired pending enrollments (registered in backend/app/__init__.py).
- Frontend: add API client support and page changes to integrate pairing flow (frontend/src/services/api/pairing.js, modifications to Servers.jsx and api index).
- Docs: adds pairing.md explaining the pairing flow.

Why: provide a secure, user-friendly mechanism for operators to claim new agents via short rotating codes and a passphrase, simplifying server onboarding while protecting credentials and preventing brute-force attempts.
2026-04-29 03:08:21 -04:00
Juan Denis e25cf6f83e Add tunnel mode and enhance servers UI
Add ngrok 'tunnel' mode to dev scripts and documentation, plus a large UI overhaul for the Servers pages.

- Add .gitattributes and new scripts/setup-wsl.sh helper.
- Extend dev.ps1 and dev.sh with a new 'tunnel' mode that starts backend+frontend and launches an ngrok tunnel (supports NGROK_DOMAIN, NGROK_AUTHTOKEN, and sets sensible CORS_ORIGINS). Includes polling of ngrok API, process cleanup, and helpful error messages.
- Update docs/LOCAL_DEVELOPMENT.md with an "Exposing Your Local Control Plane (ngrok)" guide and WSL setup notes.
- Revamp frontend pages: ServerDetail.jsx and Servers.jsx refactored with new header layouts, status/avatars, status pills, telemetry rows, selectable table rows, bulk actions, confirm dialogs, improved add-server modal, new icons (FolderTinyIcon, MoreIcon), utilities (formatLastSeen, clamp), and accessibility/interaction improvements (menus, selection, copy install command).
- Update servers SCSS to support the new layouts and loading states.

These changes add a developer-friendly tunnel mode for remote testing and significantly improve the server management UX in the frontend.
2026-04-29 02:56:23 -04:00
Juan DenisandCopilot e9d8af241a Add Deployments page and fix templates SCSS build
Introduce a centralized Deployments page that lists all deployment jobs across local and remote agents with real-time status, step progress, and live log tail. Adds route /deployments, sidebar link under Services, and command palette entry. Fixes undefined $primary variable in _templates.scss by switching to $accent-primary, restoring the frontend build.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-29 00:45:52 -04:00
Juan Denis cc1151d0ce Add deployment jobs and remote deployment runner
Introduce a deployment jobs system to support cross-server template installations and remote execution. Adds DeploymentJob and DeploymentJobLog models, DeploymentJobService for job lifecycle, and DeploymentPlanRunner to execute plans locally or via agents. TemplateService gains build_install_plan and related helpers to produce executable plans; Template installs can run async (202) or synchronously. Backend API/CLI updated: new deployment-jobs endpoints, apps API uses RemoteDockerService for remote compose actions, and CLI commands (deploy-template, deployment-status, list-servers) were added. Agent and config changes: file access validation with allowed_paths, file write create_dirs option, default allowed paths, and install script/systemd read-write paths updated to permit /var/lib/serverkit and /var/serverkit. Migration file for deployment_jobs schema included.
2026-04-29 00:39:16 -04:00
Juan Denis 313f1a8f6b Remote Docker remove, normalize API & permissions
Add end-to-end support for removing remote Docker networks and volumes and normalize remote API responses. Server: new Flask endpoints to DELETE remote networks/volumes and helpers to compute external base/ws URLs and v1 API paths. Agent: register new handler docker:network:remove and Client.RemoveNetwork implementation. Backend service: RemoteDockerService.remove_network uses agent registry for remote servers and falls back to local DockerService. Models: expand Server permission logic to map agent actions to profile/legacy scopes (DOCKER_READ_ACTIONS, scope expansion and wildcard matching) and add unit tests covering permission mappings. Frontend: handle agent-backed response shapes (unwrapRemoteData, normalizeListResponse), call new removeRemoteNetwork/removeRemoteVolume API methods, update download/install URLs to /api/v1, and tweak several UI texts. Install scripts: change config/log directories, pass --config when registering/starting agent, and update systemd/service/unit and Windows service install paths. README: small wording updates about fleet/remote deployment and monitoring.
2026-04-29 00:11:46 -04:00
github-actions[bot] cdf951a22f chore: bump version to 1.4.16 [skip ci] 2026-03-29 08:46:06 +00:00
Juan Denis 099c7a3081 EmptyState loading/size + theme SCSS refactor
Add loading and size props to EmptyState (imports Spinner, shows spinner when loading, adjusts icon sizes) and add a large variant styling. Update StyleGuide to demonstrate loading, large/not-installed/unavailable states, and card contexts. Refactor SCSS across pages/components to use Sass theme variables ($bg-card, $border-subtle, $text-secondary, $accent-primary, etc.) replacing many var(...) usages and tweak related spacing/typography styles.
2026-03-29 04:45:55 -04:00
github-actions[bot] c811fd8579 chore: bump version to 1.4.15 [skip ci] 2026-03-29 08:25:50 +00:00
Juan Denis 9c053c907d Add developer Style Guide page and styles
Introduce a comprehensive Style Guide (frontend/src/pages/StyleGuide.jsx) as a developer-only design system reference, plus new SCSS modules (_style-guide.scss, _alerts.scss, _tables.scss) and updates to existing component styles. Register the page route and title in App.jsx and add a DEV-only sidebar link (import.meta.env.DEV) in Sidebar.jsx; also import SIDEBAR_ITEMS from sidebarItems. These changes centralize UI patterns, components and utilities for easier visual QA and consistent styling without exposing the guide in production builds.
2026-03-29 04:25:41 -04:00
github-actions[bot] 808078f10c chore: bump version to 1.4.14 [skip ci] 2026-03-28 19:58:44 +00:00