feat(packaging): add desktop launcher entries for both GUI dashboards

The tray applet shipped with a .desktop file but the GUI dashboards had
none, so desktop users had no menu entry for them.

Unlike the tray entry, these carry no autostart key: a dashboard window
should open when the operator asks for it, not at login. Tests assert the
Exec names match the pyproject console scripts and that neither entry can
regain an autostart key.

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:35:37 -07:00
parent 3dd82ab18b
commit 1d1dee7f6e
No known key found for this signature in database
4 changed files with 58 additions and 0 deletions

View file

@ -215,6 +215,13 @@ Notes:
`gui/model.py` stays import-clean so headless builders can run the test
suite without a display server or `PySide6` installed.
`packaging/enodia-sentinel-gui.desktop` and
`packaging/enodia-sentinel-gui-qt.desktop` are application-menu launchers.
Unlike `enodia-sentinel-tray.desktop`, they carry no autostart key — a
dashboard window should open when the operator asks for it, not at login.
Desktop packagers may install them to `/usr/share/applications/`; source
installs can copy them to `~/.local/share/applications/`.
## Terminal TUI and Completion
The terminal dashboard is stdlib-only and available through

View file

@ -0,0 +1,11 @@
[Desktop Entry]
Type=Application
Name=Enodia Sentinel Dashboard (Qt)
GenericName=Security Dashboard
Comment=Read-only Qt desktop dashboard for the Enodia Sentinel security agent
Exec=enodia-sentinel-gui-qt
Icon=security-high
Terminal=false
Categories=System;Security;Monitor;
Keywords=security;ids;ips;edr;intrusion;monitor;
StartupNotify=true

View file

@ -0,0 +1,11 @@
[Desktop Entry]
Type=Application
Name=Enodia Sentinel Dashboard
GenericName=Security Dashboard
Comment=Read-only desktop dashboard for the Enodia Sentinel security agent
Exec=enodia-sentinel-gui
Icon=security-high
Terminal=false
Categories=System;Security;Monitor;
Keywords=security;ids;ips;edr;intrusion;monitor;
StartupNotify=true

View file

@ -166,5 +166,34 @@ class TestTrayDesktopEntry(unittest.TestCase):
self.assertRegex(text, r"(?m)^Name=.*Sentinel")
class TestGuiDesktopEntries(unittest.TestCase):
ENTRIES = {
"packaging/enodia-sentinel-gui.desktop": "enodia-sentinel-gui",
"packaging/enodia-sentinel-gui-qt.desktop": "enodia-sentinel-gui-qt",
}
def test_desktop_files_launch_gui_entry_points(self):
for path, exec_name in self.ENTRIES.items():
with self.subTest(path=path):
text = _read(path)
self.assertIn("[Desktop Entry]", text)
self.assertIn("Type=Application", text)
self.assertRegex(text, rf"(?m)^Exec={exec_name}$")
self.assertRegex(text, r"(?m)^Name=.*Sentinel")
def test_gui_entry_points_match_pyproject_scripts(self):
scripts = tomllib.loads(_read("pyproject.toml"))["project"]["scripts"]
for exec_name in self.ENTRIES.values():
with self.subTest(script=exec_name):
self.assertIn(exec_name, scripts)
def test_gui_entries_are_launchers_not_autostart(self):
# The tray applet is opt-in autostart; the dashboards are menu
# launchers and must never start themselves at login.
for path in self.ENTRIES:
with self.subTest(path=path):
self.assertNotIn("Autostart", _read(path))
if __name__ == "__main__":
unittest.main()