The Jellyseerr API key was stored as plaintext in the Jellyfin service config.
It is now a SecretField on the Jellyfin service, so it is encrypted at rest and
rendered as a masked secret input (the generic config editor stops exposing
it, and the secret editor picks it up automatically).
Migration (idempotent, runs in ensure_defaults):
- _migrate_jellyseerr_api_key_to_secret: for every Jellyfin service with a
plaintext jellyseerr_api_key still in config, encrypt it ONCE into the
secrets blob (direct UPDATE so existing encrypted secrets are preserved, not
re-encrypted) and remove it from config.
- _migrate_jellyseerr_into_jellyfin: standalone-jellyseerr absorption now
stores the key as a secret, and decrypts the Jellyfin api_key before handing
it to upsert_service (fixes a pre-existing double-encrypt on that rare path).
The stats provider already reads jellyseerr_api_key from secrets-or-config, so
it works before, during, and after the migration.
Tests: absorbed-key lands in secrets (and existing api_key isn't corrupted);
new plaintext-config -> secret migration + idempotency. 401/401 backend pass.
Slice 1 of jellyfin-service-registry. Jellyfin is configured exclusively
via the service registry now; the machine-level media_root/path_prefix
fields were dead duplicates of the global config.
- services/settings_store.py: DEFAULT_SERVICES no longer includes
"jellyfin" (now ["monitoring", "files"]). Removed machine-level
media_root/path_prefix from _default_local_machine, _row_to_machine,
_normalize_machine_payload, _seed_local_machine, get_machine_config,
and upsert_machine. _default_local_machine no longer reads global
config, so the get_settings import is dropped.
- routers/settings.py: removed media_root/path_prefix from
MonitoringMachineInput (dead API input; store already ignored them).
The global config remote_media_root/path_prefix properties + path_utils.py
are unchanged (files.py and media_index still use them for Jellyfin->SSH
path resolution). ruff clean; 239 backend tests pass.
- Archive the completed observability-service-registry SDD change into
openspec/changes/archive/ (delivered across 5 slices; only
jellyfin-service-registry remains active).
- Stop ignoring .pi-map.md / .pi-map.index.md so the navigation maps are
versioned alongside the code, and add the regenerated map pairs repo-wide.