# sources-admin Specification ## Purpose Страница управления источниками в веб-интерфейсе VESTI: добавление, изменение, удаление, пауза и смена приоритета источников без ручной правки YAML. `sources.yaml` остаётся источником истины, веб пишет в него и синкает БД. ## Requirements ### Requirement: Просмотр списка источников Страница /sources показывает таблицу всех источников с их полями и статусом. #### Scenario: просмотр списка источников - **Given** веб запущен, пользователь авторизован - **When** он открывает `/sources` - **Then** страница показывает таблицу всех источников: slug, name, crawler, direction, lang, priority, enabled (пауза), url/feed_url, статус (last_fetch/error) ### Requirement: Добавление нового источника Форма «Добавить» создаёт запись в sources.yaml и БД. #### Scenario: добавление нового источника - **Given** страница /sources - **When** форма «Добавить» заполнена (slug, name, crawler=rss, feed_url, direction=tech, priority=P1) - **And** отправлена - **Then** запись появляется в `sources/sources.yaml` и таблице `sources` БД - **And** страница показывает новый источник в таблице #### Scenario: валидация добавления - **Given** форма добавления с невалидным slug (`my source!`) - **When** отправлена - **Then** добавление отклонено, показана ошибка (flash), ничего не записано - **And** slug принимается только `[a-z0-9_-]+` ### Requirement: Изменение полей источника Форма «Изменить» обновляет name/priority/направление и пр. в yaml и БД. #### Scenario: переименование / изменение полей - **Given** существующий источник `lwn` - **When** форма «Изменить» меняет `name` на «LWN Tech» и `priority` на P2 - **Then** изменения применяются в yaml и БД, таблица обновляется ### Requirement: Пауза и снятие с паузы Переключатель enabled=false останавливает сбор источника, enabled=true возобновляет. #### Scenario: пауза и снятие с паузы - **Given** источник `lwn` (enabled=true) - **When** пользователь нажимает «Пауза» - **Then** `enabled=false` в yaml и БД - **And** краулеры больше не собирают этот источник (`get_enabled_sources` исключает) - **When** пользователь нажимает «Снять с паузы» - **Then** `enabled=true`, сбор возобновляется ### Requirement: Удаление источника Удаление (с подтверждением) убирает источник из yaml и БД, сохраняя его посты. #### Scenario: удаление источника - **Given** источник `opennet` с постами в БД - **When** пользователь подтверждает удаление (confirm) - **Then** запись удалена из yaml и sources БД - **And** его посты НЕ удалены: `source_id=NULL` (история сохраняется) - **And** rss_state для него удалён #### Scenario: удаление без подтверждения - **Given** форма удаления - **When** confirm отклонён (Cancel) - **Then** ничего не удалено, данные не меняются ### Requirement: Доступ без авторизации Страница /sources защищена паролем, как остальные админ-страницы. #### Scenario: доступ без авторизации - **Given** пользователь не авторизован - **When** он открывает `/sources` - **Then** происходит редирект на /login (303) ### Requirement: Приоритет источника Приоритет P0–P3 влияет на порядок обработки источников. #### Scenario: приоритет - **Given** источники с priority P0–P3 - **When** страница /sources загружена - **Then** приоритеты отображаются и доступны для изменения (P0–P3) - **And** /crawlers сортирует по (enabled, priority, slug) с учётом нового приоритета ### Requirement: Навигация Ссылка «Источники» присутствует в навбаре. #### Scenario: навигация - **Given** любая страница веб (base.html) - **When** открыт навбар - **Then** есть ссылка «Источники» на `/sources`