Files
manage/openspec/changes/service-registry/apply-progress.md
T
Developer 8ff735d644 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).
2026-06-23 11:43:33 +00:00

100 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Apply Progress: Runtime Service Registry
**Change:** `service-registry`
**Apply run:** PRs #7#10 (Slices 14a)
**Date:** 2026-06-19
## Slices 13 (MERGED)
- Slice 1 (#7): backend service foundation — encryption, integrations registry,
services + service_task_runs tables, `/api/services*` CRUD.
- Slice 2 (#8): backend widget rebind — service_id + widget_kind, ServiceRecord
adapters, built-ins, SSH run logging, retired old widget registry.
- Slice 3 (#9): frontend services runtime — types/API/hooks, frontend registry,
ServicePage, route swap, reconciled widget components + config dialog.
## Slice 4a — Cleanup + services admin UI + docs (this PR)
### Completed tasks
- [x] Removed addon pages (`/addons/:addonId`, `AddonPage.tsx`, `addons/*`) —
superseded by service pages.
- [x] Removed `grafana_url` / `prometheus_url` from `config.py`, both compose
files, `.env.example`, and README. (Frontend `VITE_GRAFANA_URL` /
`VITE_PROMETHEUS_URL` deep-link vars retained.)
- [x] Added a **Services page** (`/services`) with create/list/delete and a nav
entry, so service pages are reachable and services are configurable in the
tool itself.
- [x] Registered `/services` route in both route trees + sidebar nav.
- [x] Updated `docs/REQUIREMENTS.md` (service registry section) and added
`CHANGELOG.md` with the breaking-upgrade note.
### Decision resolved mid-slice
"Full machine migration" was scoped into **4a (cleanup) + 4b (Jellyfin/Jellyseerr
migration)** because removing machine-level Jellyfin/Jellyseerr fields is deeply
coupled to the Media/Users/Files pages (load-bearing) and there is no
`jellyseerr` service definition yet. 4a ships the safe cleanup + the services
admin UI; 4b does the machine-app-field migration as its own reviewable change.
### Files changed (Slice 4a)
- Backend: `config.py` (removed grafana_url/prometheus_url).
- Compose/env/docs: `docker-compose.yml`, `docker-compose.dev.yml`,
`.env.example`, `README.md`, `docs/REQUIREMENTS.md`, `CHANGELOG.md` (new).
- Frontend: new `pages/ServicesPage.tsx`; `App.tsx` (routes + nav); removed
`pages/AddonPage.tsx`, `addons/*`.
### Verification (Slice 4a)
```bash
cd backend
.venv/bin/ruff check . # clean
PYTHONPATH=src .venv/bin/python -m pytest # 222 passed
cd ../frontend
npm run lint # 0 errors
npm run build # success
npm run test # 70 passed
```
## Slice 4b — Jellyfin/Jellyseerr → services migration (in progress)
### Completed (backend, this PR)
- [x] Added `jellyseerr` service definition (`integrations/jellyseerr.py`) and
registered it (6 service types total).
- [x] Added `user_id` to the Jellyfin service config.
- [x] `dependencies.py`: new `_request_jellyfin_service_id` + `_service_record`
(decrypt-on-read). Rewrote `get_jellyfin_client`, `get_jellyseerr_client`,
and `get_user_id` to resolve against the service registry via the
`jellyfin_service_id` query param (first enabled instance as fallback).
- [x] SSH/Files transport (`get_ssh_client`) unchanged — still uses
`machine_id`.
- [x] Updated service-registry tests for 6 types.
### Selection model (decided)
Split query params: `?jellyfin_service_id=` selects the Jellyfin/Jellyseerr
instance; `?machine_id=` selects SSH/Files transport. Pages that need both pass
both.
### Remaining (frontend, next PR)
- Thread `jellyfinServiceId` through Media / Applications / Dashboard / Users:
list `jellyfin` service instances instead of `useMonitoringSettings()`
Jellyfin machines; pass `jellyfin_service_id` to Jellyfin API calls.
- Files page keeps `machine_id`.
- Settings UI: remove machine-level Jellyfin/Jellyseerr fields.
- Remove machine app fields from `settings_store.py` + `routers/settings.py`
once the UI no longer writes them.
### Verification (backend half)
```bash
cd backend
.venv/bin/ruff check . # clean
PYTHONPATH=src .venv/bin/python -m pytest # 222 passed
cd ../frontend
npm run lint && npm run build && npm run test # green (unchanged)
```