diff --git a/docs/PACKAGING.md b/docs/PACKAGING.md index d588f28..05942b6 100644 --- a/docs/PACKAGING.md +++ b/docs/PACKAGING.md @@ -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 diff --git a/packaging/enodia-sentinel-gui-qt.desktop b/packaging/enodia-sentinel-gui-qt.desktop new file mode 100644 index 0000000..ce41e5d --- /dev/null +++ b/packaging/enodia-sentinel-gui-qt.desktop @@ -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 diff --git a/packaging/enodia-sentinel-gui.desktop b/packaging/enodia-sentinel-gui.desktop new file mode 100644 index 0000000..58b1c60 --- /dev/null +++ b/packaging/enodia-sentinel-gui.desktop @@ -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 diff --git a/tests/test_packaging.py b/tests/test_packaging.py index 0944a8a..7bea07b 100644 --- a/tests/test_packaging.py +++ b/tests/test_packaging.py @@ -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()