From 8bc209b27eecc8f6d11f37be9e04e465e2b77e25 Mon Sep 17 00:00:00 2001 From: Developer Date: Thu, 25 Jun 2026 08:31:05 +0000 Subject: [PATCH] docs: fix stale-live docs and drop obsolete Obsidian spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refreshes the docs that were actively misleading about the current FastAPI + React + service-registry app, and deletes one obsolete design. - CONTRIBUTING.md: full rewrite — Streamlit-era guidance replaced with the current backend (ruff/pytest, src/ layout) + frontend (npm lint/build/test) workflow, service-registry model, and shadcn/Tailwind stack. Mirrors AGENTS.md. - README.md: removed the non-existent /addons/:addonId route (Services page is current); fixed the per-machine Jellyfin wording; replaced the py_compile dev snippet with ruff + pytest / npm lint+build+test. - backend/README.md: updated the structure tree (removed deleted clients/resources.py; added routers backups/services/tasks/widgets, integrations/, models/, widgets/, workers/); dropped the "starts the collector" sentence (MonitoringPoller is decommissioned). - frontend/README.md: corrected the uvicorn module path (main:app -> media_library_viewer_api.main:app). - Deleted docs/superpowers/specs/2026-05-08-obsidian-documentation-design.md (Obsidian vault never built; stack refs MUI/D3/AG Grid all removed). Historical docs (MIGRATION_PLAN, superpowers backup-monitoring, the bannered design/runbook/context files) deferred to a later banner pass. --- CONTRIBUTING.md | 97 +++++++++++++++---- README.md | 16 +-- backend/README.md | 37 +++++-- ...026-05-08-obsidian-documentation-design.md | 53 ---------- frontend/README.md | 2 +- frontend/src/pages/Settings.tsx | 5 +- 6 files changed, 118 insertions(+), 92 deletions(-) delete mode 100644 docs/superpowers/specs/2026-05-08-obsidian-documentation-design.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d74c711..43534cd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,55 +1,114 @@ # Contributing -Thanks for considering a contribution. +Thanks for considering a contribution to Manage. + +Manage is a media and server-operations dashboard built from two subprojects: + +- **`backend/`** — FastAPI (Python 3.11) REST API using a `src/` layout. +- **`frontend/`** — Vite + React + TypeScript SPA. +- **`archive/`** — the original Streamlit prototype, preserved for reference only. Do **not** use it as a guide; the app is FastAPI + React now. + +The authoritative contributor quick-reference is [`AGENTS.md`](./AGENTS.md). This document mirrors it for human contributors. ## Setup +### Backend + ```bash +cd backend python -m venv .venv source .venv/bin/activate pip install -e '.[dev]' ``` -Copy env template: +### Frontend ```bash -cp .env.example .env +cd frontend +npm install ``` -Then set real values in `.env` and run: +### Local stack (optional) + +For a full local dev stack with hot reload (auth disabled): ```bash -streamlit run app.py +docker compose -f docker-compose.dev.yml up --build ``` -## Development guidelines +The dev compose deploys only the backend and frontend; Manage never deploys an +observability stack. For the optional standalone observability example, see +`docker-compose.observability.yml` and `docs/observability-runbooks.md`. + +## Development commands + +Run backend checks from `backend/` and frontend checks from `frontend/`. + +```bash +# Backend: lint + tests +cd backend && ruff check . && python -m pytest + +# Run the API locally (if the package is installed as above) +uvicorn media_library_viewer_api.main:app --reload --port 8000 +# Otherwise, without installing: PYTHONPATH=src uvicorn media_library_viewer_api.main:app --reload --port 8000 + +# Focused backend tests +pytest tests/test_api.py +pytest -k +``` + +```bash +# Frontend: dev server (proxies /api to http://localhost:8000) +cd frontend && npm run dev + +# Frontend: lint + typecheck/build (build runs tsc -b + vite build) + tests +npm run lint +npm run build +npm run test +``` + +## Guidelines - Keep architecture boundaries clear: - - `clients/` for external integrations - - `domain/` for normalization/business logic - - `services/` for app services/indexing - - `ui/` for Streamlit rendering + - `clients/` for external service transports (Jellyfin, Jellyseerr, SSH, local shell). + - `integrations/` for service-registry definitions (config schema, secrets, widget kinds). + - `domain/` for normalization/business logic. + - `services/` for app services, indexing, persistence, and background workers. + - `routers/` for FastAPI route handlers. + - `models/` for Pydantic request/response schemas. +- Prefer small, focused functions and explicit names. +- Preserve safe SSH behavior and shell quoting — job templates must quote all interpolated values. +- External services (Jellyfin, Grafana, Prometheus, Alertmanager, …) are configured at runtime via the **service registry** in the UI, not environment variables. The only observability env var is `PROMETHEUS_ENABLED` (Manage's own `/metrics` toggle). - Avoid introducing optional fallback paths unless required. -- Prefer small, focused functions and explicit session-state keys. -- Preserve safe SSH behavior and path quoting. -## Validation +### Backend style -Before opening a merge request, run: +Backend linting/format is Ruff (line length 120, Python 3.11); config lives in `backend/pyproject.toml`. + +### Frontend style + +The frontend uses **shadcn/ui + Tailwind CSS v4 + lucide-react + TanStack Query + TanStack Table**. Do not introduce MUI, Emotion, recharts, d3, or AG Grid — those were removed and are not coming back. + +## Validation before opening a merge request + +Before opening a merge request, run and ensure green: ```bash -PYTHONPATH=src python -m py_compile app.py src/media_library_viewer/*.py src/media_library_viewer/clients/*.py src/media_library_viewer/domain/*.py src/media_library_viewer/services/*.py src/media_library_viewer/ui/*.py +cd backend && ruff check . && python -m pytest +cd frontend && npm run lint && npm run build && npm run test ``` +If behavior, UX, or architecture changed, also update `docs/REQUIREMENTS.md`. + ## Security / secrets Never commit: - `.env` -- `.streamlit/secrets.toml` - private keys or API tokens +- service secrets -Use `.env.example` for documented placeholders only. +Service secrets are encrypted at rest with `MANAGE_ENCRYPTION_KEY` (required to start the backend). Use `.env.example` for documented placeholders only. ## Pull requests @@ -57,6 +116,4 @@ Please include: - what changed - why it changed -- how it was tested - -If behavior/requirements changed, also update `docs/REQUIREMENTS.md`. +- how it was tested (commands run / tests added) diff --git a/README.md b/README.md index e0dec3b..e439499 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,15 @@ The project consists of two subprojects: ## Features -- Configurable dashboard with persisted widgets (Jellyfin activity, backups summary, Grafana deep-links, Prometheus metrics, SSH task output, static text) and shortcuts +- Configurable dashboard with persisted widgets (Jellyfin activity, backups summary, Grafana deep-links, Prometheus metrics, Alertmanager alerts, SSH task output, static text) and shortcuts - Thin-dashboard observability: Alertmanager alerts, Prometheus target health, machine status, and Grafana deep-links (no in-app charting) -- Per-machine settings for Jellyfin, Jellyseerr, SSH, and monitoring targets +- Service registry: configure Jellyfin, Jellyseerr, Alertmanager, Grafana, Prometheus, Nextcloud, and SSH task runner instances in the UI +- Per-machine settings for SSH, monitoring targets, and file browsing - SQLite-indexed media table with full-library sort/filter - Read-only Users tab with Jellyfin as the base source and optional Jellyseerr enrichment - Remote file browser with ffprobe preview and job execution - Jellyfin API integration for library metadata and user identity data - SSH-based file inspection and safe remote job templates -- Addon pages for Grafana, Prometheus, and SSH tasks at `/addons/:addonId` ## Quick Start @@ -172,13 +172,15 @@ ssh user@host ## Development ```bash -# Backend -cd backend && PYTHONPATH=src python -m py_compile src/media_library_viewer_api/main.py +# Backend (lint + tests) +cd backend && .venv/bin/ruff check . && .venv/bin/python -m pytest -# Frontend -cd frontend && npx tsc --noEmit && npm run build +# Frontend (lint + typecheck/build + tests) +cd frontend && npm run lint && npm run build && npm run test ``` +Focused frontend typecheck: `npx tsc --noEmit`. + ## Notes - Jellyfin server root URL required (not `/web`). The client strips trailing `/web` defensively. diff --git a/backend/README.md b/backend/README.md index 998821d..31c7a10 100644 --- a/backend/README.md +++ b/backend/README.md @@ -13,29 +13,46 @@ backend/ │ ├── __init__.py │ ├── main.py # FastAPI app entrypoint │ ├── config.py # pydantic-settings config +│ ├── auth.py # OIDC/JWT + API key auth │ ├── dependencies.py # Dependency injection +│ ├── observability.py # Prometheus metrics + request IDs +│ ├── logging_utils.py # Structured JSON/text logging │ ├── path_utils.py # Jellyfin→SSH path resolution │ ├── jobs.py # Job templates │ ├── utils.py # Formatting helpers │ ├── routers/ +│ │ ├── backups.py │ │ ├── dashboard.py -│ │ ├── monitoring.py -│ │ ├── media.py -│ │ ├── users.py -│ │ ├── settings.py │ │ ├── files.py -│ │ └── jobs.py +│ │ ├── jobs.py +│ │ ├── media.py +│ │ ├── monitoring.py +│ │ ├── services.py +│ │ ├── settings.py +│ │ ├── tasks.py +│ │ ├── users.py (+ users_impl.py) +│ │ └── widgets.py │ ├── clients/ │ │ ├── jellyfin.py │ │ ├── jellyseerr.py │ │ ├── local.py -│ │ ├── resources.py │ │ └── ssh.py +│ ├── integrations/ # Service-registry definitions │ ├── domain/ │ │ └── media.py -│ └── services/ -│ ├── media_index.py -│ └── settings_store.py +│ ├── models/ # Pydantic request/response models +│ ├── services/ +│ │ ├── media_index.py (+ _impl.py) +│ │ ├── settings_store.py +│ │ ├── secrets.py # Fernet encryption at rest +│ │ ├── targets.py # Node Exporter target discovery +│ │ ├── task_runner.py +│ │ ├── mail_queue.py (+ mailer.py/_impl.py) +│ │ ├── backup_alert_engine.py (+ backup_poller.py) +│ │ ├── known_hosts.py +│ │ └── db_maintenance.py +│ ├── widgets/ # Widget sources (dashboard data adapters) +│ └── workers/ # Background workers (media index) └── tests/ ``` @@ -127,7 +144,7 @@ docker compose up --build - **Local**: monitors the API host itself without SSH. - **SSH**: monitors another machine using a host, username, and a private key pasted directly into the machine settings, with an optional passphrase. - The machine editor groups Connection, Monitoring / Files, Jellyfin, Jellyseerr, and Notes under separate headings so each service area is easier to scan. - - Saving a monitoring machine now validates the banner/auth flow, records the first trusted host key into the backend-managed `known_hosts` file, and starts the collector so charts populate without a separate manual step. + - Saving a monitoring machine validates the banner/auth flow and records the first trusted host key into the backend-managed `known_hosts` file. - If the host cannot be reached or authenticated, the save flow surfaces the SSH error directly in the dialog. - Use **Validate SSH + trust host** in the machine editor before saving if you want to test the banner/auth flow explicitly. - The first successful SSH connection uses trust-on-first-use: the backend records that machine's host key into its managed `known_hosts` file automatically, then continues verifying it strictly on later connects. diff --git a/docs/superpowers/specs/2026-05-08-obsidian-documentation-design.md b/docs/superpowers/specs/2026-05-08-obsidian-documentation-design.md deleted file mode 100644 index 7e2d876..0000000 --- a/docs/superpowers/specs/2026-05-08-obsidian-documentation-design.md +++ /dev/null @@ -1,53 +0,0 @@ -# Obsidian Documentation Structure for Manage (Media Library Viewer) - -**Date:** 2026-05-08 -**Status:** Approved - -## Purpose - -Create a comprehensive, interconnected Obsidian documentation vault for the Manage project (media library viewer application). The documentation targets all audiences: future developers, contributors, operators, and deployers. - -## Structure - -### Map of Content (MOC) -- `manage/Overview.md` — Central hub with wikilinks to all documentation areas - -### Architecture & Overview -- `manage/Architecture.md` — System design, data flow, tech stack -- `manage/Directory Structure.md` — Annotated codebase layout - -### Backend -- `manage/Backend/API Endpoints.md` — Complete REST endpoint map -- `manage/Backend/Configuration.md` — Settings, env vars, OIDC -- `manage/Backend/Services.md` — Core services: settings store, media index, poller, mail -- `manage/Backend/Clients.md` — External integrations: Jellyfin, Jellyseerr, SSH - -### Frontend -- `manage/Frontend/Pages & Routing.md` — Routes, page components -- `manage/Frontend/Components.md` — Reusable components -- `manage/Frontend/State & Data.md` — Hooks, QueryClient, data fetching -- `manage/Frontend/Auth & Theme.md` — OIDC auth, MUI theme - -### Deployment -- `manage/Deployment/Production.md` — Docker Compose, Traefik, TLS -- `manage/Deployment/Development.md` — Dev workflow, hot reload - -### Operations -- `manage/Operations/Machine Management.md` — SSH keys, collectors -- `manage/Operations/Monitoring.md` — Poller, metrics -- `manage/Operations/Tasks & Jobs.md` — Saved tasks, job templates - -### Development -- `manage/Development/Setup.md` — Getting started for backend + frontend -- `manage/Development/Testing.md` — Test structure and commands -- `manage/Development/Contributing.md` — Conventions, PR workflow - -## Cross-Linking Conventions -- Every note uses YAML frontmatter with `tags` and `aliases` -- Related docs linked via `[[wikilinks]]` -- Callouts for warnings, tips, and notes - -## Technologies Referenced -- Backend: Python 3.11+, FastAPI, SQLite, Paramiko, PyJWT -- Frontend: React 19, TypeScript 6, Vite 8, MUI 9, D3 7, AG Grid -- Infra: Docker, Traefik, Authentik/OIDC diff --git a/frontend/README.md b/frontend/README.md index 7aeda57..30329ab 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -31,7 +31,7 @@ Make sure the backend is running: ```bash cd ../backend -uvicorn main:app --reload --port 8000 +uvicorn media_library_viewer_api.main:app --reload --port 8000 ``` ## Build diff --git a/frontend/src/pages/Settings.tsx b/frontend/src/pages/Settings.tsx index 7102764..5d76a68 100644 --- a/frontend/src/pages/Settings.tsx +++ b/frontend/src/pages/Settings.tsx @@ -1077,7 +1077,10 @@ export function Settings() { ) : ( - + )}