feat(gui): add optional tkinter and Qt6 desktop dashboards

Add two optional windowed frontends over the same local state the TUI and
web console read: `enodia-sentinel gui` (stdlib tkinter) and
`enodia-sentinel gui-qt` (PySide6, new `[qt]` extra).

Both share `gui/model.py`, a GUI-free presentation model over
`tui.collect_model`, so every formatter is unit-testable without a display
server. Only `app.py` and `qt_app.py` import GUI libraries, enforced by
import-guard tests mirroring the tray applet's boundary.

Tabs cover status, alerts, incidents, posture, integrity, response plans,
and the event tail, plus daemon-control buttons via systemctl. Response
plans are display-only; the GUIs never execute containment commands. Core
runtime dependencies stay empty.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JX86xeoBJVBb16qHkDf53K
This commit is contained in:
Luna 2026-07-22 04:33:49 -07:00
parent 9e3575461b
commit 457c7604ba
No known key found for this signature in database
15 changed files with 1270 additions and 0 deletions

View file

@ -25,10 +25,13 @@ dependencies = []
enodia-sentinel = "enodia_sentinel.cli:main"
enodia-sentinel-tui = "enodia_sentinel.tui:main"
enodia-sentinel-tray = "enodia_sentinel.tray.app:main"
enodia-sentinel-gui = "enodia_sentinel.gui.app:main"
enodia-sentinel-gui-qt = "enodia_sentinel.gui.qt_app:main"
[project.optional-dependencies]
dev = ["pytest"]
tray = ["pystray", "Pillow"]
qt = ["PySide6"]
[tool.setuptools.packages.find]
include = ["enodia_sentinel*"]