From 1878f912932b8ecc21a139fb94c5a4f19a2c38a4 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Thu, 15 Oct 2026 11:35:41 -0400 Subject: [PATCH] chore: the systemd unit runs Steward, not FabledNetMon systemd/fablednetmon.service still carried the project's first name in its user, paths, command and config location, so it couldn't start Steward as written. It is now systemd/steward.service: user steward, /opt/steward, `steward --config /etc/steward/config.yaml`, with a note that /data must be writable (secret.key, safety backups) and why Restart=on-failure brings Steward back after a web UI restore (exit 3). The legacy-name guard now reads service units too, and forbids "netmon" beside "scryer" and "roundtable". The 2026-04 rebrand plan and spec under docs/superpowers keep the old names: they record the rename. Co-Authored-By: Claude Opus 5.5 --- systemd/fablednetmon.service | 15 --------------- systemd/steward.service | 21 +++++++++++++++++++++ tests/test_no_legacy_names.py | 21 +++++++++++++-------- 3 files changed, 34 insertions(+), 23 deletions(-) delete mode 100644 systemd/fablednetmon.service create mode 100644 systemd/steward.service diff --git a/systemd/fablednetmon.service b/systemd/fablednetmon.service deleted file mode 100644 index 397c6d4..0000000 --- a/systemd/fablednetmon.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=FabledNetMon monitoring server -After=network.target postgresql.service - -[Service] -Type=simple -User=fablednetmon -WorkingDirectory=/opt/fablednetmon -ExecStart=/opt/fablednetmon/.venv/bin/fablednetmon --config /etc/fablednetmon/config.yaml -Restart=on-failure -RestartSec=5s -Environment=PYTHONUNBUFFERED=1 - -[Install] -WantedBy=multi-user.target diff --git a/systemd/steward.service b/systemd/steward.service new file mode 100644 index 0000000..840cf7e --- /dev/null +++ b/systemd/steward.service @@ -0,0 +1,21 @@ +# Steward without Docker: the server, run from a virtualenv in /opt/steward. +# The image is the usual way to run it; this unit is for a host without one. +# Steward keeps its secret key (secret.key) and its safety backups (backups/) +# under /data, so the steward user needs to be able to write there. +[Unit] +Description=Steward monitoring server +After=network.target postgresql.service + +[Service] +Type=simple +User=steward +WorkingDirectory=/opt/steward +ExecStart=/opt/steward/.venv/bin/steward --config /etc/steward/config.yaml +# A restore from the web UI ends with exit code 3, so this brings Steward +# back with the restored settings (a clean exit 0 would be left stopped). +Restart=on-failure +RestartSec=5s +Environment=PYTHONUNBUFFERED=1 + +[Install] +WantedBy=multi-user.target diff --git a/tests/test_no_legacy_names.py b/tests/test_no_legacy_names.py index 0e75198..e789e99 100644 --- a/tests/test_no_legacy_names.py +++ b/tests/test_no_legacy_names.py @@ -1,10 +1,11 @@ """Regression guard: shipped code must not reference old project names. -The FabledScryer -> Roundtable -> Steward renames repeatedly left stale package -imports behind in the (then separate) plugins (e.g. `from fabledscryer.models...`), -silently breaking every non-host_agent plugin. Now that plugins are folded in-tree -and version with core, this test fails loudly if either legacy name reappears in -the shipped Python / templates / plugin manifests. +The FabledNetMon -> FabledScryer -> Roundtable -> Steward renames repeatedly left +stale names behind: package imports in the (then separate) plugins (e.g. `from +fabledscryer.models...`), silently breaking every non-host_agent plugin, and a +systemd unit still running `fablednetmon` as user `fablednetmon`. This test fails +loudly if a legacy name reappears in the shipped Python, templates, plugin +manifests or service units. """ from __future__ import annotations @@ -13,9 +14,9 @@ from pathlib import Path import pytest _ROOT = Path(__file__).resolve().parent.parent -_TREES = [_ROOT / "steward", _ROOT / "plugins"] -_EXTENSIONS = {".py", ".yaml", ".yml", ".html", ".j2"} -_FORBIDDEN = ("scryer", "roundtable") # case-insensitive; old project names +_TREES = [_ROOT / "steward", _ROOT / "plugins", _ROOT / "systemd"] +_EXTENSIONS = {".py", ".yaml", ".yml", ".html", ".j2", ".service"} +_FORBIDDEN = ("scryer", "roundtable", "netmon") # case-insensitive; old project names def _shipped_files(): @@ -25,6 +26,10 @@ def _shipped_files(): yield path +def test_the_guard_reads_the_service_units(): + assert any(p.suffix == ".service" for p in _shipped_files()) + + @pytest.mark.parametrize("name", _FORBIDDEN) def test_no_legacy_project_name(name): offenders = [