diff --git a/backend/app/config.py b/backend/app/config.py index 6e7abb91..ac399007 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -57,7 +57,7 @@ class Settings(BaseSettings): # VPS Caddy front door. A request from any other peer (someone hitting the app port directly) # is NOT trusted and its raw socket IP is used, so it can't spoof its rate-limit identity via # XFF. Empty = trust no proxy (use the direct peer) — correct for a directly-exposed / local-dev - # deploy. Comma-separated. See auth._client_ip + the deploy docs. + # deploy. Comma-separated. See routes.auth._client_ip + the deploy docs. trusted_proxy_ips: str = "" # --- Outbound email (onboarding: access-request + approval notices) --- diff --git a/backend/app/db.py b/backend/app/db.py index fb9b0874..8ca8ecf2 100644 --- a/backend/app/db.py +++ b/backend/app/db.py @@ -12,7 +12,7 @@ class Base(DeclarativeBase): # Pool sized above the sync-endpoint threadpool (~40) so a burst of short DB sessions can't starve on # checkout. The image proxies deliberately DON'T hold a connection during their slow external fetch -# (see routes/plex.py), so this headroom is only for the many brief sessions, not long ones. +# (see routes/plex/), so this headroom is only for the many brief sessions, not long ones. engine = create_engine( settings.database_url, pool_pre_ping=True, diff --git a/backend/app/routes/channels.py b/backend/app/routes/channels.py index fa4148e5..a4c7af43 100644 --- a/backend/app/routes/channels.py +++ b/backend/app/routes/channels.py @@ -1,6 +1,6 @@ """Channel manager: the user's subscriptions with their personal overrides (priority, -hidden, tags) and per-channel sync state. Read + local-write only — YouTube-side writes -(unsubscribe) live behind the optional write scope and are added in a later phase.""" +hidden, tags) and per-channel sync state. Local reads/writes plus YouTube-side writes +(subscribe / unsubscribe) that require the optional write scope.""" import logging from datetime import datetime, timezone diff --git a/backend/app/routes/playlists.py b/backend/app/routes/playlists.py index 43f0aa1f..a4699aea 100644 --- a/backend/app/routes/playlists.py +++ b/backend/app/routes/playlists.py @@ -1,6 +1,7 @@ -"""Local playlists: per-user named, ordered collections of videos from the shared -catalog. Foundation phase = local only (create / rename / delete, add / remove / reorder -items). YouTube two-way sync (mirror existing playlists, push edits) lands in later phases.""" +"""Playlists: per-user named, ordered collections of videos from the shared catalog. Local +CRUD (create / rename / delete, add / remove / reorder items) plus YouTube two-way sync — +mirror the user's own YouTube playlists in (`/sync-youtube`) and push/revert local edits back +out (`/{id}/push-plan`, `/{id}/revert-youtube`), behind the optional write scope.""" from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from sqlalchemy import func, select, and_ diff --git a/backend/app/routes/setup.py b/backend/app/routes/setup.py index be1b7168..baca1135 100644 --- a/backend/app/routes/setup.py +++ b/backend/app/routes/setup.py @@ -3,7 +3,7 @@ `GET /api/setup/status` is public (the SPA uses it to decide whether to show the wizard). Every mutating step goes through `require_setup`: it rejects once the instance is configured AND requires the one-time setup token (printed to the container logs at first boot, carried by the wizard as the -X-Setup-Token header). The wizard steps themselves are added in epic 6c. +X-Setup-Token header). """ from typing import Any diff --git a/backend/app/sync/playlists.py b/backend/app/sync/playlists.py index d12c3365..7c419296 100644 --- a/backend/app/sync/playlists.py +++ b/backend/app/sync/playlists.py @@ -1,6 +1,6 @@ -"""Read-direction YouTube playlist sync: mirror each user's own YouTube playlists into -local `source='youtube'` playlists (kept fresh by the scheduler). One-way (YT -> local); -the write-back direction (local edits -> YouTube) is a later phase. +"""YouTube playlist sync, both directions. Read: mirror each user's own YouTube playlists +into local `source='youtube'` playlists (kept fresh by the scheduler). Write-back: push local +edits out to YouTube (`plan_push` / `push_playlist`), behind the optional write scope. YouTube's special Watch Later / History playlists are not exposed by the Data API and are never synced. Videos in a playlist that aren't in our shared catalog yet are fetched and diff --git a/backend/app/sysconfig.py b/backend/app/sysconfig.py index 3c531e69..2f6d19fb 100644 --- a/backend/app/sysconfig.py +++ b/backend/app/sysconfig.py @@ -96,8 +96,8 @@ SPECS: tuple[ConfigSpec, ...] = ( ConfigSpec("plex_overlay_map", "str", "plex", "plex_overlay_map"), # (plex_sync_interval_min is tuned from the Scheduler dashboard, not here — it's a scheduler job.) ConfigSpec("plex_max_transcodes", "int", "plex", "plex_max_transcodes", min=0, max=16), - # NOTE: plex_watch_sync_interval_min (config.py default) is surfaced here in Phase C, when the - # incremental watch-sync scheduler job that reads it lands. + # NOTE: plex_watch_sync_interval_min is a config.py default read by the watch-sync scheduler job + # (scheduler.py); it is intentionally NOT a runtime admin knob, so it stays out of SPECS. ) _BY_KEY: dict[str, ConfigSpec] = {s.key: s for s in SPECS}