feat(server-fns): wire pages to live vervain-server data #8

Merged
David merged 1 commit from feat/wire-live-server-data into main 2026-06-06 17:42:14 +02:00
Owner

Replaces the canned-data server fns with live proxies to vervain-server, adds a /login page, and makes fetch failures visible.

What changed

  • New src/server_fns/control.rs: WebSocket client for vervain-server's /control.ashx control channel. Connects with the browser's session token forwarded as the mc_session cookie, then skims the connect burst (serverinfo, userinfo, ...) and unsolicited event frames until the matching action reply arrives. A 401 at upgrade maps to a stable "not signed in" marker the UI keys off.
  • get_dashboard_stats, list_devices, get_device, list_meshes, list_users, list_events, list_plugins now map live control-channel replies (meshes, nodes, users, events, serverstats, plugins). Device rows resolve mesh names; mesh rows get device counts; events get a severity heuristic (the channel has no severity field).
  • New login server fn proxying POST /login (form-encoded): 303 + Set-Cookie on success re-issued as the HTTP-only vervain_session cookie (same pattern as the setup flow), err=otp reveals a TOTP field on the new /login page, err=1 maps to a friendly bad-credentials message.
  • Layout redirects to /login when the session cookie is missing; the setup NeedsFirstUser redirect still wins. Pages show a LoadError banner on fetch failure (with a sign-in link for auth errors) instead of silently rendering empty tables.

Server API caveats this codifies

  • serverstats and plugins are admin-only control actions the server silently ignores otherwise; they use a 3s timeout and the dashboard renders the Users/Relays KPIs as a dash for non-admins.
  • Node docs carry no OS string, so the Devices table shows the agent's platform type (icon) and the column is now "Platform".
  • There is no per-relay listing; the Relays page shows aggregate RelaySessions/RelayCount from serverstats until the server grows a relay API.
  • Device.last_seen and Mesh.created became Option: never-connected devices and meshes without a creation field render a dash.

Verification

  • just check clean (fmt, clippy -D warnings, server + wasm cargo check, tests).
  • End to end against a local vervain-server (MESHCENTRAL_ENV=development, setup enabled): registered the first user, confirmed the POST /login contract with curl (303 + cookie on success, err=1 on bad creds), then ran the built app with VERVAIN_SERVER_URL pointed at it. SSR with the session cookie showed live data on every page (user list with admin badge, login event on dashboard and events, KPIs Users=1 / Relays=0 / Events 24h=1, empty device/mesh tables for a fresh server); without the cookie the auth banner renders.

Not in scope

  • Logout button, per-device detail tabs, search/filter inputs, and a real login-session check beyond cookie presence (an expired token surfaces as the auth banner at first fetch).
Replaces the canned-data server fns with live proxies to vervain-server, adds a /login page, and makes fetch failures visible. ## What changed - New `src/server_fns/control.rs`: WebSocket client for vervain-server's `/control.ashx` control channel. Connects with the browser's session token forwarded as the `mc_session` cookie, then skims the connect burst (`serverinfo`, `userinfo`, ...) and unsolicited `event` frames until the matching action reply arrives. A 401 at upgrade maps to a stable "not signed in" marker the UI keys off. - `get_dashboard_stats`, `list_devices`, `get_device`, `list_meshes`, `list_users`, `list_events`, `list_plugins` now map live control-channel replies (`meshes`, `nodes`, `users`, `events`, `serverstats`, `plugins`). Device rows resolve mesh names; mesh rows get device counts; events get a severity heuristic (the channel has no severity field). - New `login` server fn proxying `POST /login` (form-encoded): 303 + `Set-Cookie` on success re-issued as the HTTP-only `vervain_session` cookie (same pattern as the setup flow), `err=otp` reveals a TOTP field on the new `/login` page, `err=1` maps to a friendly bad-credentials message. - `Layout` redirects to `/login` when the session cookie is missing; the setup `NeedsFirstUser` redirect still wins. Pages show a `LoadError` banner on fetch failure (with a sign-in link for auth errors) instead of silently rendering empty tables. ## Server API caveats this codifies - `serverstats` and `plugins` are admin-only control actions the server silently ignores otherwise; they use a 3s timeout and the dashboard renders the Users/Relays KPIs as a dash for non-admins. - Node docs carry no OS string, so the Devices table shows the agent's platform type (`icon`) and the column is now "Platform". - There is no per-relay listing; the Relays page shows aggregate `RelaySessions`/`RelayCount` from `serverstats` until the server grows a relay API. - `Device.last_seen` and `Mesh.created` became `Option`: never-connected devices and meshes without a `creation` field render a dash. ## Verification - `just check` clean (fmt, clippy -D warnings, server + wasm cargo check, tests). - End to end against a local vervain-server (`MESHCENTRAL_ENV=development`, setup enabled): registered the first user, confirmed the `POST /login` contract with curl (303 + cookie on success, `err=1` on bad creds), then ran the built app with `VERVAIN_SERVER_URL` pointed at it. SSR with the session cookie showed live data on every page (user list with admin badge, login event on dashboard and events, KPIs Users=1 / Relays=0 / Events 24h=1, empty device/mesh tables for a fresh server); without the cookie the auth banner renders. ## Not in scope - Logout button, per-device detail tabs, search/filter inputs, and a real login-session check beyond cookie presence (an expired token surfaces as the auth banner at first fetch).
feat(server-fns): wire pages to live vervain-server data
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 1m42s
Create release / Create release from merged PR (pull_request) Has been skipped
795c9fde16
Replace the canned-data server fns with real proxies to vervain-server. List/data actions go over the /control.ashx WebSocket control channel (new src/server_fns/control.rs client: connects with the session forwarded as mc_session, skims the connect burst and unsolicited frames until the matching action reply). Auth stays HTTP: a new login server fn proxies POST /login (303 + Set-Cookie on success, err=otp surfaces a TOTP prompt) and re-issues the token as the vervain_session cookie, same as the existing setup flow.

- get_dashboard_stats / list_devices / get_device / list_meshes / list_users / list_events / list_plugins now map live control-channel replies; devices get mesh names resolved, meshes get device counts.
- serverstats and plugins are admin-only and silently unanswered otherwise, so they use a short timeout and the dashboard renders Users/Relays KPIs as a dash for non-admins instead of erroring.
- Node docs carry no OS string, so the Devices table shows the agent platform type (icon field) and the column is renamed Platform.
- No per-relay listing exists server-side; the Relays page now shows aggregate counts from serverstats instead of a fixture table.
- New /login page outside the app shell; Layout redirects to it when the session cookie is missing (setup NeedsFirstUser still wins).
- Pages render a LoadError banner on fetch failure (auth errors link to /login) instead of silently showing empty tables; the dashboard health card drops its invented subsystem rows.
- Device.last_seen and Mesh.created are now Option since never-connected devices and legacy meshes lack the timestamps.

Verified end to end against a local vervain-server (setup register, login contract, SSR of every page with and without a session; users/events/serverstats data confirmed live).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
David merged commit d4d6958f77 into main 2026-06-06 17:42:14 +02:00
David deleted branch feat/wire-live-server-data 2026-06-06 17:42:14 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-apps!8
No description provided.