From 3dd82ab18b05df441aad2a9c094984c796c4d916 Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 22 Jul 2026 04:33:55 -0700 Subject: [PATCH] docs(packaging): document desktop GUI frontends and optdepends The GUI frontends landed with README/CLI/operations docs but no packaging coverage. Add a PACKAGING.md section with the command/script/requirement table for both frontends, note why stdlib tkinter is still an optdepend rather than a hard dependency, and record that packaging must not grant the GUIs privileges beyond the operator's own account. Add the matching PKGBUILD optdepends (`tk`, `pyside6`), plus `python-pystray`/`python-pillow` for the tray applet, which were never listed when it shipped. Also add `gui/` to the CLAUDE.md architecture notes and state snapshot. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01JX86xeoBJVBb16qHkDf53K --- CLAUDE.md | 8 ++++++++ docs/PACKAGING.md | 25 +++++++++++++++++++++++++ packaging/PKGBUILD | 6 +++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index b51b434..7cd1ada 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -87,6 +87,10 @@ Implemented investigation/response state: runs `check --json` quick checks. Its logic modules (`tray/state.py`, `actions.py`, `notify.py`) are GUI-free and tested; only `tray/app.py` imports GUI libs, and the core agent stays stdlib-only. +- Optional windowed desktop dashboards mirror the same pattern: + `enodia-sentinel gui` (stdlib tkinter) and `enodia-sentinel gui-qt` + (`[qt]` extra with PySide6). Both are read-only over detection state, share + the GUI-free `gui/model.py`, and display response plans for review only. - IPS behavior is currently explicit workflow: posture hardening plus reviewed dry-run containment actions. There is no automatic inline blocking or silent host mutation yet. @@ -156,6 +160,10 @@ Start with: - `tray/` is the optional desktop tray frontend over the CLI and systemctl; only `tray/app.py` may import `pystray`/`PIL` (enforced by an import-guard test). +- `gui/` is the optional windowed desktop dashboard. `gui/model.py` is the + GUI-free presentation model over `tui.collect_model`; only `gui/app.py` + (tkinter) and `gui/qt_app.py` (PySide6, `[qt]` extra) import GUI libraries, + enforced by import-guard tests. - `go-agent/` is the isolated Phase 1 sidecar with Go config, process-state, detector, schema, and sweep-loop packages. It writes JSONL to stdout and must not share or mutate Python daemon state during parity development. diff --git a/docs/PACKAGING.md b/docs/PACKAGING.md index 97d2a65..d588f28 100644 --- a/docs/PACKAGING.md +++ b/docs/PACKAGING.md @@ -190,6 +190,31 @@ empty. not installed to a system autostart path by default — desktop users copy it to `~/.config/autostart/` themselves. +## Desktop GUI Frontends (optional) + +Two windowed dashboards ship alongside the tray applet. Both are optional +frontends over the same local state the TUI and web console read; neither is +required by the daemon, and core runtime dependencies stay empty. + +| Frontend | Command | Console script | Requirement | +| --- | --- | --- | --- | +| tkinter | `enodia-sentinel gui` | `enodia-sentinel-gui` | stdlib `tkinter` (distro `tk` / `python-tk` / `python-tkinter`) | +| Qt6 | `enodia-sentinel gui-qt` | `enodia-sentinel-gui-qt` | `[qt]` extra (`PySide6`) | + +Notes: + +- `tkinter` is stdlib but is packaged separately on most distros, so it is an + `optdepends` (Arch `tk`), never a hard dependency. +- The `[qt]` extra (`pip install 'enodia-sentinel[qt]'`) pulls in `PySide6` + only for the Qt frontend; the Arch package lists `pyside6` as an optdepend. +- Both GUIs are read-only over detection state and display response plans for + review only — packaging must not grant them privileges beyond what the + operator's own account has. Daemon start/stop/restart goes through + `systemctl` and prompts for polkit authorization as usual. +- Only `gui/app.py` (tkinter) and `gui/qt_app.py` (Qt) import GUI libraries; + `gui/model.py` stays import-clean so headless builders can run the test + suite without a display server or `PySide6` installed. + ## Terminal TUI and Completion The terminal dashboard is stdlib-only and available through diff --git a/packaging/PKGBUILD b/packaging/PKGBUILD index b5cf949..2f1b912 100644 --- a/packaging/PKGBUILD +++ b/packaging/PKGBUILD @@ -10,7 +10,11 @@ depends=('python>=3.11' 'iproute2' 'procps-ng') optdepends=('python-bpfcc: eBPF event-driven execve/syscall monitors (catches short-lived processes and memory telemetry)' 'bpftrace: execve tracing of short-lived processes in snapshots' 'libnotify: desktop notifications on alert' - 'libarchive: signed-package verification against cached package .MTREE manifests') + 'libarchive: signed-package verification against cached package .MTREE manifests' + 'tk: stdlib tkinter desktop dashboard (enodia-sentinel gui)' + 'pyside6: Qt6 desktop dashboard (enodia-sentinel gui-qt)' + 'python-pystray: desktop tray applet (enodia-sentinel-tray)' + 'python-pillow: desktop tray applet icon rendering') backup=('etc/enodia-sentinel.toml') source=() sha256sums=()