New service types:
- backups: BackupsConfig(ingestion_label), no secrets, summary widget kind.
Modeled as a service so it can be named/multi-instanced like others.
- authentik: AuthentikConfig(base_url, timeout_seconds), api_token secret
(required). Directory source for the upcoming Users tab.
Jellyseerr absorption:
- JellyfinConfig gains optional jellyseerr_url + jellyseerr_api_key fields.
- integrations/jellyseerr.py deleted; registry entry removed.
- clients/jellyseerr.py stays (JellyseerrClient still used by enrichment).
- One-time idempotent migration in settings_store.ensure_defaults():
jellyseerr service rows merge into a paired Jellyfin (exactly-one merges;
multiple picks first unpaired; none/all-paired drops with a logged
warning). The api_key is decrypted from secrets before moving to config.
Registry is now 8 types: alertmanager, authentik, backups, grafana,
jellyfin, nextcloud, prometheus, ssh_tasks.
Tests: registry count updated to 8, jellyseerr-absent assertion, new-type
definition assertions, and migration tests (single-jellyfin merge, no-
jellyfin drop, idempotency). 256 backend tests pass; ruff clean.
Refs openspec/changes/services-as-hub-ia/ (spec R6, tasks slice 1).
Add a shared ServiceBaseUrl type (BeforeValidator + Field description) in
integrations/base.py and apply it to base_url across all six service configs
(grafana, prometheus, alertmanager, jellyfin, jellyseerr, nextcloud). Missing
http:// or https:// schema now fails fast with a clear 422 instead of breaking
HTTP clients silently. Tests cover reject/accept cases; REQUIREMENTS updated.