From 7ef1af218429622c5ebb14db46fcdc6e67bfe10f Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Tue, 16 Jun 2026 20:57:10 -0400 Subject: [PATCH] =?UTF-8?q?feat(settings):=20Phase=204=20=E2=80=94=20capab?= =?UTF-8?q?ilities=20vs=20integrations=20+=20nav=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Final phase of the host-IA unification (milestone 70). - Settings → Plugins split into two tiers: "Monitoring capabilities" (host_agent, http, snmp, docker — built-in host facets, surfaced via Hosts/Status, on by default) and "Integrations" (traefik, unifi — external systems, off until configured). Presentation only: a CAPABILITY_PLUGINS set (overridable by plugin.yaml `kind:`) tags each plugin; module loading, optional deps, and migrations are untouched. - Drop the "default-enable a plugin" framing in the UI copy — capabilities are described as built-in, not optional add-ons. - Nav: remove the standalone "Uptime" item (folded into Hosts; still reachable via the SLA button on the Hosts list). Co-Authored-By: Claude Opus 4.8 (1M context) --- steward/settings/routes.py | 12 +++ steward/templates/base.html | 1 - steward/templates/settings/plugins.html | 123 +++++++++++++----------- 3 files changed, 78 insertions(+), 58 deletions(-) diff --git a/steward/settings/routes.py b/steward/settings/routes.py index 64d623c..69e3c0e 100644 --- a/steward/settings/routes.py +++ b/steward/settings/routes.py @@ -505,6 +505,13 @@ def _build_plugin_cfg_from_form(plugin: dict, form) -> dict: # ── Plugins list ────────────────────────────────────────────────────────────── +# Bundled plugins that are really built-in *host/monitoring capabilities* (facets +# of a host), not discrete vendor integrations. Presentation-only split — they +# still load through the normal plugin mechanism. A plugin.yaml may set +# kind: capability|integration to override. +CAPABILITY_PLUGINS = {"host_agent", "http", "snmp", "docker"} + + @settings_bp.get("/plugins/") @require_role(UserRole.admin) async def plugins(): @@ -512,9 +519,14 @@ async def plugins(): settings = await get_all_settings(db) discovered = _discover_plugins() _merge_plugin_config(discovered, to_plugins_cfg(settings)) + for p in discovered: + p["_kind"] = p.get("kind") or ( + "capability" if p["_dir"] in CAPABILITY_PLUGINS else "integration") repos = _get_plugin_repos(settings) return await render_template( "settings/plugins.html", + capabilities=[p for p in discovered if p["_kind"] == "capability"], + integrations=[p for p in discovered if p["_kind"] != "capability"], discovered_plugins=discovered, repos=repos, settings=settings, diff --git a/steward/templates/base.html b/steward/templates/base.html index 2e81c39..49dff1f 100644 --- a/steward/templates/base.html +++ b/steward/templates/base.html @@ -209,7 +209,6 @@ textarea { resize: vertical; } Dashboard Status Hosts - Uptime Ping DNS Alerts diff --git a/steward/templates/settings/plugins.html b/steward/templates/settings/plugins.html index 60bd70d..1116d3d 100644 --- a/steward/templates/settings/plugins.html +++ b/steward/templates/settings/plugins.html @@ -10,72 +10,81 @@ {# ── Restart banner ────────────────────────────────────────────────────────── #}
-{# ── Installed Plugins ─────────────────────────────────────────────────────── #} -
-
Installed Plugins
+{% macro plugin_card(plugin) %} +{% set fail_reason = plugin_failures.get(plugin._dir) %} +
+ {% if fail_reason %} + + {% elif plugin._enabled %} + + {% else %} + + {% endif %} +
+
+ {{ plugin.get('name', plugin._dir) }} + v{{ plugin.get('version', '?') }} + {% if fail_reason %} + Error + {% elif plugin._enabled %} + Enabled + {% else %} + Disabled + {% endif %} +
+ {% if plugin.get('description') %} +
{{ plugin.description }}
+ {% endif %} + {% if fail_reason %} +
{{ fail_reason }}
+ {% endif %} +
+ Settings → +
+{% endmacro %} + +{# ── Monitoring capabilities (host facets) ─────────────────────────────────── #} +
+
Monitoring capabilities
- -{% if not discovered_plugins %} -
- No plugins installed. The table awaits new seats. +

+ Built-in ways to monitor your hosts (agent metrics, HTTP/uptime, SNMP, Docker). These are + facets of a host — you'll see their data in the Hosts and + Status sections, not as separate areas. On by default. +

+{% if capabilities %} +
+ {% for plugin in capabilities %}{{ plugin_card(plugin) }}{% endfor %}
{% else %} +
None installed.
+{% endif %} + +{# ── Integrations (external systems) ───────────────────────────────────────── #} +
Integrations
+

+ External systems Steward pulls data from (e.g. Traefik, UniFi). Enable and configure each one + to surface its own dashboard. Off until you set them up. +

+{% if integrations %}
- {% for plugin in discovered_plugins %} - {% set fail_reason = plugin_failures.get(plugin._dir) %} -
- - {# Status indicator #} - {% if fail_reason %} - - {% elif plugin._enabled %} - - {% else %} - - {% endif %} - - {# Name + version + description #} -
-
- {{ plugin.get('name', plugin._dir) }} - v{{ plugin.get('version', '?') }} - {% if fail_reason %} - Error - {% elif plugin._enabled %} - Enabled - {% else %} - Disabled - {% endif %} -
- {% if plugin.get('description') %} -
{{ plugin.description }}
- {% endif %} - {% if fail_reason %} -
{{ fail_reason }}
- {% endif %} -
- - {# Settings button #} - Settings → -
- {% endfor %} + {% for plugin in integrations %}{{ plugin_card(plugin) }}{% endfor %} +
+{% else %} +
+ No integrations installed. Browse the catalog below.
{% endif %}