feat: session sharing over the relay (M12) — Share tab
release / release (push) Successful in 14s

Add a Share tab that hosts or joins a read-only live session through the
rigdoctor-relay over WebSocket (QtWebSockets), gated by the Gitea access token.

- gui/share_page.py: Start shared session (host: get a code, stream snapshot +
  health + inventory) and Enter share code (guest: view a host's data read-only)
- core/share.py: host_full_frame / host_snapshot_frame + guest_html renderer
- config: relay_url (default wss://rigdoctor.jesseyvanofferen.com)
- setup: token now powers updates AND sharing — hint asks for read:user +
  read:repository scopes (relay validates the account via Gitea)
- main_window: Share nav tab + socket cleanup on close
- tests for the relay frame builders and guest HTML

Verified end-to-end against the deployed relay (host code -> guest frame).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-21 20:03:17 +02:00
parent e33cc0ef3a
commit 67d4c1cb99
13 changed files with 551 additions and 9 deletions
+38
View File
@@ -0,0 +1,38 @@
"""Tests for M12 relay frames + guest HTML rendering (host/guest data shapes)."""
import json
import unittest
from rigdoctor.core import share
from rigdoctor.core.sampler import Sampler
from rigdoctor.core.sources import available_sources
class RelayFrameTests(unittest.TestCase):
def setUp(self):
self.sampler = Sampler(available_sources())
def test_full_frame_shape(self):
frame = json.loads(share.host_full_frame(self.sampler))
self.assertEqual(frame["type"], "full")
self.assertIn("groups", frame["snapshot"])
self.assertIsInstance(frame["report"], list)
self.assertIsInstance(frame["inventory"], dict)
def test_snapshot_frame_shape(self):
frame = json.loads(share.host_snapshot_frame(self.sampler))
self.assertEqual(frame["type"], "snapshot")
self.assertIn("groups", frame["snapshot"])
def test_guest_html_renders(self):
snap = {"groups": {"gpu": [{"name": "temp", "value": 51.0, "unit": "°C"}]}}
report = [{"severity": "ok", "category": "Logs", "title": "No errors"}]
inv = {"System": {"Kernel": "7.0.0"}}
html = share.guest_html(snap, report, inv)
self.assertIn("51.0 °C", html)
self.assertIn("No errors", html)
self.assertIn("Kernel", html)
if __name__ == "__main__":
unittest.main()