feat(services): resolve Jellyfin/Jellyseerr from the service registry (backend)

Slice 4b backend half. Jellyfin and Jellyseerr clients are now resolved from
service instances instead of machine-level app config.

- Add jellyseerr service definition (6 service types total); add user_id to
  the Jellyfin service config.
- dependencies.py: jellyfin_service_id query param + _service_record
  (decrypt-on-read); get_jellyfin_client / get_jellyseerr_client / get_user_id
  resolve against the service registry (first enabled instance as fallback).
- SSH/Files transport (get_ssh_client) unchanged; still uses machine_id.
- Update service-registry tests for 6 types.

Selection model: split params — ?jellyfin_service_id= for Jellyfin/Jellyseerr,
?machine_id= for SSH/Files. Frontend threading follows in the next PR.

Verification: backend ruff clean, pytest 222 passed; frontend green (unchanged).
This commit is contained in:
Developer
2026-06-23 11:43:33 +00:00
parent d998e6ab0c
commit 8ff735d644
5 changed files with 155 additions and 45 deletions
+9 -1
View File
@@ -61,6 +61,7 @@ def test_registry_contains_five_service_types():
"grafana",
"prometheus",
"jellyfin",
"jellyseerr",
"nextcloud",
"ssh_tasks",
}
@@ -133,7 +134,14 @@ def test_list_service_types(client):
response = client.get("/api/services/types")
assert response.status_code == 200
types = {item["service_type"] for item in response.json()}
assert types == {"grafana", "prometheus", "jellyfin", "nextcloud", "ssh_tasks"}
assert types == {
"grafana",
"jellyfin",
"jellyseerr",
"nextcloud",
"prometheus",
"ssh_tasks",
}
def test_service_type_includes_secret_and_widget_metadata(client):