8ff735d644
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).
100 lines
4.2 KiB
Markdown
100 lines
4.2 KiB
Markdown
# Apply Progress: Runtime Service Registry
|
||
|
||
**Change:** `service-registry`
|
||
**Apply run:** PRs #7–#10 (Slices 1–4a)
|
||
**Date:** 2026-06-19
|
||
|
||
## Slices 1–3 (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)
|
||
```
|