openspec: архив 14 завершённых change-ов (веб-фиксы, crawler-queue, own-content-hub, publisher-service); спеки влиты в openspec/specs

This commit is contained in:
kpa39l
2026-09-16 17:01:00 +00:00
parent 584582a48c
commit 771f6a8276
88 changed files with 1632 additions and 3 deletions
@@ -0,0 +1,51 @@
# Design: sources-admin
## Модель данных и источник истины
- `sources/sources.yaml` — **источник истины** (в Git). Краулеры при запуске
вызывают `sync_sources_to_db()` → таблица `sources`.
- Любое веб-изменение: сначала пишем в yaml (`upsert_source_yaml` /
`delete_source_yaml` / toggle enabled), затем синкаем yaml → БД
(`sync_yaml_to_db_and_back`), чтобы бд-строка не расходилась.
## Изменения в sources/sources.py
1. `delete_source_db(slug)` — удаляет строку из `sources` по slug. Связанные
данные: `posts` (FK source_id) — задаём `source_id=NULL` (посты остаются
историей, без источника); `runs` — `source_id=NULL`; `rss_state` — DELETE;
`classifications` — не трогаем (привязаны к posts).
Порядок: `delete_source_yaml` (yaml) → `delete_source_db` (БД).
2. `set_source_enabled(slug, enabled)` — обновляет enabled в yaml
(через upsert_source_yaml с ключом enabled) и в БД (`sync_yaml_to_db_and_back`).
Пауза: enabled=false; снятие: enabled=true.
3. `add_or_update_source(data)` — валидация (slug обязателен, уникален;
crawler ∈ {telegram, rss}; priority ∈ {P0..P3}; для rss — feed_url обязателен)
→ upsert_source_yaml → sync_yaml_to_db_and_back → возврат slug.
## Веб-слой (web/app.py)
- `GET /sources` — страница (за auth): таблица всех источников (slug, name,
crawler, direction, lang, priority, enabled, url/feed_url, last_fetch/status),
форма добавления, кнопки действий. Шаблон `web/templates/sources.html`.
- `POST /sources/add` — добавление (форма). Redirect на /sources.
- `POST /sources/update/<slug>` — переименование/правка полей.
- `POST /sources/{slug}/toggle` — пауза/снятие с паузы.
- `POST /sources/{slug}/delete` — удаление (с подтверждением на стороне формы:
`onclick="return confirm(...)"`).
- Все POST — с `_require_auth`, следуют паттерну /crawlers (async + form).
- Валидация ошибок → flash message + редирект (не 500).
- Навбар: ссылка «Источники» между «Краулеры» и «Выйти».
## Шаблон sources.html
- Таблица + модальный диалог (Bootstrap) для add/edit (одна форма).
- Кнопки: Изменить (заполняет модалку), Удалить (confirm), Пауза/Снять (toggle).
- Приоритет — селект P0/P1/P2/P3; crawler — селект telegram/rss; direction —
селект из DIRECTIONS_CANON (keywords) + «—».
- Для rss: поле feed_url; для telegram: channel.
## Безопасность
- Пароль ADMIN_PASSWORD, как на /crawlers.
- slug — белый список [a-z0-9_-], валидация на добавление (иначе 400).
- Удаление — только POST + confirm (никаких GET-удалений).