feat(cluster): v2.6 — remote control, manual peers, per-node health#20
Merged
Conversation
Builds on the v2.5 fleet view so you can manage the whole fleet from one screen. Remote control: - Key-guarded POST /api/cluster/control on the target node applies start/stop/ restart to one of its mappings (shares _apply_action with the UI handler; CSRF-exempt + in PUBLIC_PATHS — authenticated by the shared key, not a session). - Browser uses session-authed POST /api/cluster/control-peer (operator+), which validates the target against cluster.known_addresses() (anti-SSRF allowlist) before calling the peer with the key. Start/Stop/Restart buttons on remote rows. Manual peers (routed/L3 networks broadcast can't reach): - ClusterSettings.peers (list of host:port / scheme://host:port); cluster.all_targets() merges auto-discovered + manual peers, deduped by (ip, port). Settings textarea. Per-node health: - /api/cluster/local payload adds uptime/version/running-count; the fleet table is now grouped by node with a health header (up · version · running/total) and an online/offline indicator. A banner surfaces when UDP discovery can't bind (manual peers still work). Misc: - Version single-sourced in app/__init__.py (__version__), imported by ser2net.py and the web layer; bumped to 2.6.0. - tests/test_cluster.py: two real nodes linked by a manual peer (no UDP dependency) exercise aggregation+health, the key guard, remote start/stop, and the anti-SSRF allowlist. Screenshots + README/ROADMAP updated.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds on the v2.5 LAN-cluster fleet view so you can manage the whole fleet from one screen, not just watch it.
Remote control
POST /api/cluster/controlon the target node applies start/stop/restart to one of its mappings — shares_apply_actionwith the normal UI handler, CSRF-exempt and inPUBLIC_PATHSbecause it's authenticated by the shared cluster key, not a session.POST /api/cluster/control-peer(operator+), which validates the target againstcluster.known_addresses()(an anti-SSRF allowlist of auto + manual peers) before calling the peer with the key. Start/Stop/Restart buttons appear on remote rows in the unified table.Manual peers
ClusterSettings.peers(list ofhost:portorscheme://host:port).cluster.all_targets()merges auto-discovered + manual peers, deduped by(ip, port). Added a Settings textarea.Per-node health
/api/cluster/localnow returns uptime / version / running-count. The fleet table is grouped by node with a health header (up · vX.Y · running/total) and an online/offline indicator. A banner surfaces when UDP discovery can't bind (manual peers still work).Trust model
Remote control = anyone with an operator+ account on a cluster node + the shared key can control any peer. The local session role gates initiation; the key authorizes the cross-node call; the allowlist bounds the target.
Misc
app/__init__.py(__version__), imported byser2net.pyand the web layer — bumped to 2.6.0 (fixes the kind of drift the last review caught).ConfigErroron a baddiscovery_port).Tests
tests/test_cluster.pyadds a deterministic end-to-end: two real nodes linked by a manual peer (different discovery ports, so no UDP dependency) exercise aggregation + health, the peer-control key guard, remote start/stop taking effect, and the anti-SSRF allowlist rejecting an unknown address. Full suite 32/32; ruff clean.Screenshots regenerated (fleet panel now shows node health + remote-control buttons); README (TR/EN) + ROADMAP updated.