Commit Graph

5 Commits

Author SHA1 Message Date
Developer 01527ae4f0 Rebase services-as-hub-ia onto mobile-responsive-parity
Combine both branches into a single coherent branch:
- Full mobile responsive parity (useIsMobile, MobileCardRow, SheetForm,
  .mobile-touch-target, mobile cards, SheetForm forms, 44px targets,
  dirty-state confirm, TablePagination, refetchIntervalInBackground).
- Full services-as-hub IA (data-driven nav, service-page tab skeleton,
  new service types, Authentik directory + messaging, named dashboards,
  legacy routes 404, Observability split, Jellyseerr absorbed).

Enhancement: service tabs now use mobile-parity primitives:
- MediaTab: MobileCardRow below md (title/size/HDR/library/year) +
  TablePagination; DataTable at md+ (desktop branch preserved).
- FilesTab: MobileCardRow below md (name/type/size/modified) +
  handleRowClick; DataTable at md+.
- ServicePage: SheetForm branch below md (open-on-mount, sticky header
  + save bar, cancel navigates back to /services, dirty-state guard).
- Dashboard: single-column + section anchors below md (from mobile-parity)
  + empty-state CTA (from services-hub).
- App.tsx: useIsMobile() replaces inline matchMedia (from mobile-parity)
  + data-driven useNavItems (from services-hub).
- Backup tables (BackupAlerts/Jobs/Runs) already have MobileCardRow from
  mobile-parity; JobsTab inherits mobile behavior through its sub-components.

Conflict resolutions:
- Backend: entirely from services-hub (mobile didn't touch it).
- Deleted pages (Media/FileBrowser/Actions/Users/UsersPage/Applications/
  ObservabilityPage/BackupsPage + hooks/useUsers + tests): kept deleted
  (services-hub deleted them; content moved into service tabs).
- New service-tabs/*: from services-hub, enhanced with mobile patterns.
- App.tsx: services-hub's data-driven nav + mobile-parity's useIsMobile.
- Dashboard.tsx: merged (services-hub CTA + mobile-parity sections/anchors).
- ServicePage.tsx: services-hub's tab skeleton + mobile-parity's SheetForm.
- Primitives (useIsMobile/mobile-card/sheet-form/etc.): from mobile-parity.

117 frontend tests pass (mobile-parity's 122 - 5 deleted page tests +
services-hub's new tab/dashboard tests); 271 backend tests pass; lint/
build green both sides.
2026-06-26 21:08:51 +00:00
Developer eebc86a52b Enforce http(s) schema on service base_url fields
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.
2026-06-26 09:52:20 +00:00
Developer 7d49df3e7d feat(observability): add alertmanager service type and widget
Slice 1 of observability-service-registry. Alertmanager becomes a
first-class service-registry type, mirroring grafana/prometheus.

- integrations/alertmanager.py (new): AlertmanagerConfig
  (base_url, timeout_seconds), AlertmanagerAlertsWidgetConfig (optional
  severity_filter), shared summarize_alerts() helper, and DEFINITION
  (service_type "alertmanager", secret api_key, widget "active_alerts").
- integrations/registry.py: register ALERTMANAGER (7 types now).
- widgets/sources.py: AlertmanagerWidgetSource fetches
  {base_url}/api/v1/alerts, sends optional Bearer token from the api_key
  secret, applies optional severity_filter, and summarizes via the shared
  helper; registered in SERVICE_ADAPTERS.
- routers/monitoring.py: _summary_from_alerts delegates to the shared
  summarize_alerts (behavior unchanged).
- tests: registry now 7 types; /api/services/types lists alertmanager;
  4 new adapter tests (summarize, severity filter, bearer token, missing
  service).

Backend-only slice; the frontend active_alerts widget binding lands in a
later slice. ruff clean; 228 backend tests pass.

Reviewed fresh-context (read-only): no blockers.
2026-06-23 22:25:50 +00:00
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
Developer 8cdeadd6dd feat(services): backend service registry foundation (encryption, definitions, CRUD)
PR 1 of 4 for the runtime service registry change.

- Add Fernet encryption helper (services/secrets.py) with a required
  MANAGE_ENCRYPTION_KEY; validate it on startup.
- Add closed integrations/ registry with Pydantic config + widget-config
  definitions for grafana, prometheus, jellyfin, nextcloud, and ssh_tasks.
- Add services + service_task_runs tables and SettingsStore CRUD with
  cascade-delete (defensive until widgets carry service_id).
- Add /api/services/types and /api/services/instances CRUD (encrypted secrets,
  secrets_set flags only; never plaintext).
- Declare cryptography as a direct dependency.
- Require MANAGE_ENCRYPTION_KEY in compose + .env.example + README.
- Add 25 backend tests (registry, encryption, CRUD, cascade, task-run history).

Verification: ruff clean; pytest 225 passed; frontend lint/build green.
2026-06-22 12:56:03 +00:00