From cfc91e0a424163869c64d30e55d55a53f18a3dbf Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Tue, 1 Sep 2026 14:08:32 +0200 Subject: refactor(node): JSON-only control API, Node page absorbs the admin dashboard Remove the node daemon's server-rendered admin UI (GET / and /audit, the _render_* helpers and inline templates) and the `meshbay-node ui` CLI verb. The loopback control API stays; it is now JSON only, ruff-clean, and 453 lines (was 1074). Also drop three never-wired endpoints (/api/config, /api/chat/history, /ws/chat, plus broadcast_chat) and the pointless 18000/tcp firewall profiles. The desktop client's Node page (static/node-page.js) takes over what the dashboard showed, reorganised into six tabs (Overview, Groups, Roster, Peers, Audit, Settings): - Overview: version, node id, QUIC port, hub, index-cache maintenance - Roster: node-wide view with unpin - Peers and Audit: auto-load on open, no Load button - Audit: real usernames and group names (resolved from the roster and node.toml), Previous/Next pagination newest-first, Export CSV of every matching row - Settings: node settings, STUN, ICE, denylist, then Unlink from hub Backend: audit.get_entries gains `offset`; /api/audit and /api/peers resolve ids to names via a new _display_names helper; CSP tightened to default-src 'none' now that no HTML is served. draft-v6 sections 2.11 and 2.12 corrected -- the Node page uses the loopback API, not MNP. One capability is intentionally dropped: browser-based admin on a headless server. The CLI covers every operation there. See docs/refactor-node-ui.md. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01MQCaZnde4Bjjdu84dhSuF5 --- packages/meshbay-node/tests/test_audit.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'packages/meshbay-node/tests/test_audit.py') diff --git a/packages/meshbay-node/tests/test_audit.py b/packages/meshbay-node/tests/test_audit.py index b2ed15e..8755be2 100644 --- a/packages/meshbay-node/tests/test_audit.py +++ b/packages/meshbay-node/tests/test_audit.py @@ -52,6 +52,27 @@ async def test_filter_by_user(audit): assert entries[0].user_id == "u1" +@pytest.mark.asyncio +async def test_pagination_newest_first(audit): + for i in range(5): + await audit.log_event(user_id="u1", event="connect", detail=f"e{i}") + # distinct timestamps so ORDER BY is deterministic + await audit._db.execute( + "UPDATE audit_log SET timestamp = ? WHERE detail = ?", + (1000 + i, f"e{i}")) + await audit._db.commit() + + page1 = await audit.get_entries(limit=2, offset=0) + page2 = await audit.get_entries(limit=2, offset=2) + page3 = await audit.get_entries(limit=2, offset=4) + + assert [e.detail for e in page1] == ["e4", "e3"] # newest first + assert [e.detail for e in page2] == ["e2", "e1"] + assert [e.detail for e in page3] == ["e0"] # last, partial page + # offset past the end is empty, not an error + assert await audit.get_entries(limit=2, offset=99) == [] + + @pytest.mark.asyncio async def test_entry_count(audit): assert await audit.entry_count() == 0 -- cgit v1.2.3