feat(monitor): bring the web panel level with the app

Open
#1,623 1 comment 1 reaction 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
35/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
dart, flutter, rust
Domain
full-stack

Research direction

Start with docs/dev/monitor-permissions.md and the completed monitor pages, then inspect the relevant sbm_parser commands, agent endpoints, and panel entry points. Choose one unchecked slice and trace its grant, capability flag, tests, page, localization, and documentation requirements; it is done when that slice works with permissions and audit coverage across the listed layers.

Written by the indexing model from the issue text.

Description

enhancement feature

The monitor web panel should do roughly what the app does for a server. Where a browser cannot (below), it does not have to.

Approach

Rebuilt on main. feat/web-panel-server-management (stopped at 2026-09-25, 42 commits behind) is reference only and will not be merged: it predates roles/grants (#1611), port forwarding over the agent (#1609), the Virtualization tab (#1560) and firewall (#1617), and its 49 full_access_allowed checks no longer exist on main. Its Rust command builders and parsers, tests and pages are reused where they still fit.

Kept from the earlier plan:

  • Commands are built and parsed in Rust (sbm_parser) behind agent endpoints, not assembled in TypeScript and sent to /exec.
  • Remote desktop: noVNC over /stream/ws, RDP through IronRDP (wasm).
  • BMC/PVE credentials, AI keys, snippets, benchmark history and desktop profiles live on the agent. Secrets are write-only; null keeps the stored value.
  • Backup: the agent hosts an encrypted blob, a fourth RemoteStorage for the app's BakSyncer. The panel imports and exports the same srvbox_bak_v3.json.

One implementation: Rust

The end state splits each feature in two:

  • Rust (sbm_parser): the commands, the parsers for what they print, the models they produce, and the calls that expose them. The agent uses them directly and serves them as its endpoints; the app calls the same functions through FFI (sbm_ffi). One API, one result shape.
  • Each client: state management and UI. The app keeps its Riverpod providers and Flutter pages, the panel its Svelte pages; both only call into the Rust layer.

No feature keeps a Dart copy of a command, parser or model. Each port follows "tests as spec": port the Dart fixture tests to Rust, assert the FFI result identical, then move the app's provider onto FFI and delete the Dart command and parsing code.

Where it stands:

Feature Rust (agent, panel) App (Dart) Status
Status script and parsers, custom commands sbm_parser FFI Done
Virtualization (libvirt) sbm_virt::libvirt (was sbm_parser::virt*) FFI Done
Processes sbm_parser::proc FFI Done (#1645)
Services sbm_parser::service FFI Done (#1645)
Benchmark sbm_parser::bench FFI Done (#1645)
Containers sbm_parser::container FFI Done (#1646)
Cron sbm_parser::cron (cron_compat.rs) FFI Done (#1646)
Firewall sbm_parser::firewall (firewall_compat.rs, change plans in firewall::change) FFI (sbm_ffi::api::firewall, models mirrored) Done (#1654, plans #1655)
PVE console websocket sbm_virt::pve::console::Console (agent relay and app share it) FFI (PveConsoleChannel) Done (#1654)
System users and groups sbm_parser::users none (service/user_manager.dart only calls the FFI) Done (#1628)
PVE live-network check before a bridge change sbm_virt::pve::net FFI Done (#1636)
File browser shell commands (SCP, sudo SFTP: find/stat, mkdir, rm, chmod, mv, home, wc -c, extract) sbm_parser::files FFI Done (#1651)
tmux session and window discovery sbm_parser::tmux FFI Done (#1651)
Terminal login as a system user (su -) sbm_parser::users::login_shell_command FFI Done (#1651)
Agent tools: read/write a file in the local userland sbm_parser::files (capped_read_command, atomic_write_command) FFI Done (#1651)
Sudo password-rejected check sbm_parser::script::sudo_password_rejected FFI Done (#1649)
iperf client command sbm_parser::iperf FFI Done (#1656)

Paths are under lib/data/ unless they start with core/ or view/. Not in scope: HTTP JSON clients (the PVE API, Redfish), which parse an API rather than a command's output; tmux control mode, a live protocol rather than one-shot output; and marker or exit-code checks (OS detection from uname, id -u, the sudo prompt).

Each Dart copy of an existing Rust module carries a TODO(migration). Until it is removed, a fix to a command or parser lands in both copies.

Permissions (docs/dev/monitor-permissions.md)

Feature Grant
Power, processes, services, cron, containers, system users, benchmark, firewall, custom commands, iperf shell
AI agent shell (it runs commands and edits files)
Snippets edit and run: shell
Remote desktop open: connect (allow list); edit profiles: connect
Proxmox VE, libvirt, BMC see and control: virt (new); connection and credentials: admin
Backup admin

Read-only accounts see what their role allows, and nothing that needs a grant.

Pull requests

  • 1. Grant and first pages
    • virt grant (agent, panel, app; migration 011)
    • Power
    • Processes
    • Services
    • Cron
    • Containers
    • Benchmark
  • 2. Accounts on the machine
    • System users (route not /users, which is the agent's accounts)
    • Snippets
  • 3. Remote desktop
    • VNC (noVNC)
    • RDP (IronRDP)
  • 4. BMC and backup
    • BMC
    • Backup (also changes the app's sync; ships with an app release)
  • 5. Virtualization: one page for Proxmox VE and libvirt, on a new sbm_virt crate. Each PR covers both backends and moves the app's Dart for what it touches onto sbm_virt (FFI). Merged in #1636 (ecff074a); the console's websocket moved onto sbm_virt in #1654.
    • 5.1 Hosts and guests
      • sbm_virt: the libvirt command layer moved out of sbm_parser (first of the per-domain crates sbm_parser splits into)
      • sbm_virt model: host, guest, state mapping, power actions, capabilities, usage and rates, errors
      • sbm_virt::pve: transport trait (direct TCP for the agent; the app's authenticated ServerTcpDialer.loopback), certificate pinning, password + TOTP and API token, ticket renewal, tasks
      • Agent: PVE configuration (admin; secrets write-only), host detection, guest list, power; virt grant, sudo password for libvirt
      • Panel: the Virtualization page (KVM Manager design), PVE setup, TOTP prompt
      • App: PveBackend session, login, TLS, load and power on FFI; its other calls through one FFI request until their PR; LibvirtBackend's mapping and rates on sbm_virt
    • 5.2 Detail, history charts, consoles (noVNC; serial and termproxy in the panel terminal)
    • 5.3 Snapshots (internal, external, configuration diff)
    • 5.4 Storage and networks: read, manage, pending network changes, upload
    • 5.5 Create, delete, clone, templates, cloud images
    • 5.6 Hardware, settings, cloud-init, host devices
    • 5.7 Backups and backup jobs
  • 6. AI agent page
  • 7. Not done anywhere yet
    • Firewall (#1655): changes are planned once in Rust (sbm_parser::firewall::change) and shared by the app (FFI) and the agent (/firewall, /firewall/plan, /firewall/act); a plan that needs confirmation runs only with its plan_id
    • Container images, and exec into a container (#1656): image pull/remove/prune, system prune and run as typed ContainerActions; a shell inside a container through the terminal target (container_exec feature)
    • Custom command outputs (#1656): the dashboard card the app has, from custom_cmds in /metrics
    • iperf (#1656): sbm_parser::iperf, run through the terminal target (iperf feature)
    • A text editor in Files (#1657): UTF-8 files up to 1 MiB, line endings kept, saves guarded by if_version (409 when the file changed)
    • Server search in the sidebar (#1657)
    • tmux in the panel terminal (#1657): GET /tmux and the terminal target (tmux feature), tmux's own UI
  • 8. The app onto the shared Rust layer (see "One implementation: Rust")
    • Processes (#1645)
    • Services (#1645)
    • Benchmark (#1645)
    • Containers (#1646)
    • Cron (#1646)
    • Firewall (#1654)
    • PVE console websocket (#1654)
    • System users and groups (Rust port first, with item 2)
    • PVE live-network check (Rust port first, with item 5; #1636)
    • File browser shell commands for SCP and sudo SFTP (#1651)
    • tmux discovery (#1651)
    • Terminal login as a system user, su - (#1651)
    • Agent tools: guest file read/write (#1651)
    • Sudo password-rejected check (#1649)
    • iperf host, port and command (#1656)
  • 9. Verification on real devices and servers. A commit is ticked once verified on a real device; the unticked ones have had only CI, unit/integration tests and emulated e2e (e.g. OpenBMC in QEMU for BMC).
    • fdaa60b1 virt grant, power and processes (#1624)
    • 8858a979 services, cron, containers and benchmark (#1625)
    • f657dc97 system users (#1628)
    • 0345827a snippets (#1630)
    • 035c0530 remote desktops, VNC and RDP (#1631)
    • 23184e5a BMC and backup (#1632)
    • ecff074a virtualization (#1636): PVE 9.2.2 and libvirt 11.3.0 through the agent and the app's virt_real_test.dart (84 passed, 2 skipped), the merged code (docs/dev/virt.md)
    • ef95b41e processes, services and benchmark on the FFI (#1645)
    • c0c35e15 containers and cron on the FFI (#1646)
    • 4cb23649 sudo password-rejected check on the FFI (#1649)
    • c74bc3fb tmux discovery, file browser shell commands, su - and the Agent's guest file tools on the FFI (#1651). Not yet on a device; the commands passed ssh_e2e on real hosts (Ubuntu with bash, WSL with fish as the login shell)
    • 0eb909bf firewall and the PVE console on Rust (#1654). Not yet on a device. PVE console: virt_real_test.dart against PVE 9.2 over SSH and direct (termproxy with a keep-alive, serial, VNC auth, a refused ticket). Firewall: ufw/firewalld fixtures from real hosts and a Dart-vs-FFI differential run before the Dart copy went; not run against a live firewall
    • b8a852fe panel firewall page on shared firewall plans (#1655). Not yet on a device. The agent endpoints ran against live firewalls: ufw on Ubuntu (enable with keep-open, rules, policy, logging, reload, sudo password) and firewalld in an LXC container (drift, reload, save runtime, zone items, masquerade, stop / offline edit / start); a stale plan_id returned the new plan and ran nothing
    • 8c215b9f container images and exec, iperf, custom command outputs (#1656). Not yet on a device. The agent and the panel ran on a real Ubuntu host (Docker 29.1.3, Podman 5.7.0, iperf 2.2.1) through the API, the terminal websocket and the panel in a browser; the app's iperf page moved onto the FFI
    • 5a727d91 file editor, server search and tmux (#1657). Not yet on a device. Agent and panel on a real Ubuntu host (tmux 3.6a) through the API and the panel in a browser; tmux session times fixed for current tmux (app too, over FFI)
    • Commits of items 5-8, as they land

Each slice: Rust command layer and tests, agent endpoint with grant checks and audit, capability flag, panel page, i18n (15 locales), docs. Migrations from 012.

App-only (not planned for the panel): port forwarding (a page cannot listen on a port), home-screen widgets, watch, tray, serverbox:// links, this device as a server, themes and the theme store, Wake-on-LAN.

Dominant language
Dart
Stars
8.9k
Forks
573
Avg merge
2h 11m
Merged PRs (30d)
134

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from lollipopkit/flutter_server_box

All issues in lollipopkit/flutter_server_box

Similar issues

More Dart issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.