rss-news/backend
Oliver G 7163b1bd7e
feat(wordpress): only assign tags that are established
_resolve_wp_tag_ids created a WordPress tag for every keyword the rewriter
invented, up to 12 per post. That is where the 3.055 tags for 955 posts
came from - 1.683 of them used exactly once, 473 attached to no post at
all. The categories are stable now, but the tags would simply grow back.

Three changes, all on the write path:

A proposed tag has to appear for wordpress_new_tag_min_proposals (3)
different articles before it is created. Proposals are counted in the new
tag_proposals table, keyed on (name, article), so re-publishing an article
does not inflate its own count. Tags that already exist in WordPress are
assigned as before - the gate only guards creation.

Only the first wordpress_max_tags_per_post (5) tags reach WordPress. The
full list still feeds the category rules, which were validated against it.

The lookup fallback of reusing the first search hit is gone. It filed
"Camping" under the unrelated existing tag "Campingplatz" whenever the
exact tag was missing, which quietly produced wrong tags rather than none.

If the proposal bookkeeping fails, nothing is creatable that run: existing
tags still get assigned and the taxonomy stays put, rather than falling
back to creating everything.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 08:21:53 +02:00
..
app feat(wordpress): only assign tags that are established 2026-07-31 08:21:53 +02:00
data chore: finalize current state and prepare next wordpress-focused roadmap 2026-02-18 11:11:49 +01:00
static feat(admin): add feed/source management, rewrite editor, reopen flow, and WP block output 2026-02-21 14:03:49 +01:00
templates feat(admin): bulk-editable article list with WP ID inline editing 2026-04-10 09:00:25 +00:00
tests feat(wordpress): only assign tags that are established 2026-07-31 08:21:53 +02:00
.env.example Use four fixed daily publish slots 2026-07-24 10:38:04 +02:00
__init__.py feat: rebuild rss-news backend, admin ui, and legal extraction pipeline 2026-02-18 09:52:36 +01:00
README.md feat: rebuild rss-news backend, admin ui, and legal extraction pipeline 2026-02-18 09:52:36 +01:00
requirements-test.txt feat: rebuild rss-news backend, admin ui, and legal extraction pipeline 2026-02-18 09:52:36 +01:00
requirements.txt feat: rebuild rss-news backend, admin ui, and legal extraction pipeline 2026-02-18 09:52:36 +01:00

Backend Skeleton (FastAPI)

Dieses Verzeichnis enthaelt das technische Grundgeruest fuer den Rebuild von rss-news.

Start (lokal)

python -m venv .venv
source .venv/bin/activate
pip install -r backend/requirements.txt
uvicorn backend.app.main:app --reload --port 8501

Admin UI

  • Login: http://127.0.0.1:8501/admin/login
  • Dashboard: http://127.0.0.1:8501/admin/dashboard

Environment

  • Datei: backend/.env
  • Vorlage: backend/.env.example

Endpoints

  • GET /health - Healthcheck
  • POST /auth/login - Login mit Admin-User
  • POST /auth/logout - Logout
  • GET /auth/me - Aktiver User
  • GET /api/protected - Geschuetzter Test-Endpoint
  • GET /api/pipeline/status - Basisstatus inkl. Datensatzzaehler
  • GET /api/sources - Quellenliste
  • POST /api/sources - Quelle anlegen
  • GET /api/sources/{source_id}/policy-check - Policy-Pruefung fuer Quelle
  • GET /api/feeds - Feedliste
  • POST /api/feeds - Feed anlegen
  • GET /api/feeds/{feed_id}/policy-check - Policy-Pruefung fuer Feed
  • GET /api/runs - Import-/Job-Runs anzeigen
  • GET /api/runs/{run_id} - Detailansicht eines Runs
  • POST /api/runs - Run starten
  • POST /api/runs/{run_id}/finish - Run abschliessen
  • GET /api/articles - Artikel anzeigen
  • GET /api/articles/{article_id} - Artikeldetail
  • POST /api/articles/upsert - Artikel idempotent anlegen/aktualisieren
  • POST /api/articles/{article_id}/transition - Statuswechsel nach Workflow-Regeln
  • POST /api/articles/{article_id}/review - Review-Entscheidung (approve/reject)
  • POST /api/ingestion/run - Feed-Ingestion starten (optional pro Feed)

Datenbank

  • SQLite-Datei unter backend/data/rss_news.db
  • Tabellen werden beim App-Start initialisiert.
  • Tabellen: sources, feeds, runs, articles
  • Dedupe-Strategie Artikel: source_url -> (feed_id, source_article_id) -> source_hash

Policy-Enforcement

  • Ingestion blockiert Feeds automatisch, wenn die zugeordnete Quelle nicht policy-konform ist.
  • Mindestanforderungen: risk_level=green, terms_url, license_name, last_reviewed_at, is_enabled=1.
  • Pro importiertem Artikel wird ein attribution-Block in meta_json gespeichert.

Review-Workflow

  • Statuskette: new -> review -> approved -> published
  • Ablehnung im Review setzt auf rewrite
  • Ungueltige Statuswechsel werden per API blockiert

Verifikation

python -m unittest backend.tests.test_db_repositories
python -m unittest backend.tests.test_ingestion
python -m unittest backend.tests.test_api_auth

CI / Online-Auswertung

  • GitHub Actions Workflow: .github/workflows/test.yml
  • Fuehrt Tests inkl. Coverage auf Push/PR gegen main aus.

Hetzner Smoketest

BASE_URL="https://news.vanityontour.de" \
APP_ADMIN_USERNAME="admin" \
APP_ADMIN_PASSWORD="..." \
bash scripts/smoke_backend.sh

Hinweis

Passwort-Hashing und CSRF/Rate-Limit sind als naechste Ausbaustufe vorgesehen.