2026-03-28 22:30:24 +01:00
|
|
|
from pydantic_settings import BaseSettings
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
|
|
|
app_name: str = "GWÖ-Antragsprüfer"
|
2026-04-28 01:10:36 +02:00
|
|
|
app_version: str = "1.0.2"
|
2026-03-28 22:30:24 +01:00
|
|
|
prompt_version: str = "v4.1"
|
|
|
|
|
|
|
|
|
|
# Paths
|
|
|
|
|
base_dir: Path = Path(__file__).resolve().parent.parent
|
|
|
|
|
data_dir: Path = base_dir / "data"
|
|
|
|
|
reports_dir: Path = base_dir / "reports"
|
|
|
|
|
kontext_dir: Path = Path(__file__).resolve().parent / "kontext"
|
|
|
|
|
db_path: Path = data_dir / "gwoe-antraege.db"
|
|
|
|
|
|
|
|
|
|
# LLM
|
|
|
|
|
dashscope_api_key: str = ""
|
|
|
|
|
dashscope_base_url: str = "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
|
|
|
|
|
llm_model_default: str = "qwen-plus-latest"
|
|
|
|
|
llm_model_premium: str = "qwen-max"
|
|
|
|
|
|
feat(#139,#129,#138,#141): v2-Frontend (ECOnGOOD-CD), Login-Modal, Auto-DL, OG-Cards
v2-Frontend (#139, ECOnGOOD CD Manual Juni 2024):
- app/static/v2/: tokens.css, fonts.css, v2.css, Nunito-Sans woff2, Phosphor-Icons (21 SVGs)
- app/templates/v2/: base.html + 11 Screens + 8 Component-Macros
- AppShell mit Sidebar (Lesen/Pruefen/Daten/Admin), v2-Detail mit allen Features
(ScoreHero, MatrixMini, QuoteCard, Redline, Fraktions-Scores)
- v2 ist jetzt Default unter / — classic unter /classic
- Login-Modal in v2-Topbar mit Tabs Anmelden/Registrieren (#129)
- Phosphor-Icons in Sidebar + Topbar mit dynamischem Theme-Toggle
- Keyboard-Shortcuts (j/k/Enter/Esc/?/path), Landtag-Suche, Antrag-Historie,
Sort-Dropdown, Matrix-Feld-Info-Modal, Bookmarks/Comments/Voting/Share/Re-Analyze
Backend-Erweiterungen:
- main.py: ~30 neue Routes (/v2/*, /antrag/{ds}, /api/auth/{login,refresh,logout},
/api/me/merkliste/*, /api/admin/*, /v2/admin/*, OG-Cards, etc.)
- og_card.py + og_template: Open-Graph-Bilder via Playwright (#141)
- wahlprogramm_fetch.py + wahlprogramm-links.yaml: SHA-Gate Auto-DL (#138)
- auswertungen.py: BL-Filter + get_wahlperioden Helper (#137)
- auth.py: Direct-Access-Grant + Refresh-Token-Cookie
Classic-Updates:
- Header-DRY via _header.html, Auswertungen redirected, Batch-Inline raus
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 20:55:57 +02:00
|
|
|
# Embedding-Modell: neue Rows werden immer mit embedding_model_write geschrieben,
|
|
|
|
|
# Lese-Queries filtern nach embedding_model_read. Zwei Settings erlauben einen
|
|
|
|
|
# Zero-Downtime-Switch von v3 auf v4 (siehe Issue #123):
|
|
|
|
|
# Phase 1: write=v4, read=v3 → Prod läuft weiter, Reindex füllt v4-Rows
|
|
|
|
|
# Phase 2: write=v4, read=v4 → Switch aktiv, alte v3-Rows können gelöscht werden
|
|
|
|
|
embedding_model_write: str = "text-embedding-v4"
|
|
|
|
|
embedding_model_read: str = "text-embedding-v3"
|
|
|
|
|
embedding_dimensions: int = 1024
|
|
|
|
|
|
|
|
|
|
# Keycloak
|
2026-03-28 22:30:24 +01:00
|
|
|
keycloak_url: str = ""
|
|
|
|
|
keycloak_realm: str = ""
|
|
|
|
|
keycloak_client_id: str = ""
|
feat(#139,#129,#138,#141): v2-Frontend (ECOnGOOD-CD), Login-Modal, Auto-DL, OG-Cards
v2-Frontend (#139, ECOnGOOD CD Manual Juni 2024):
- app/static/v2/: tokens.css, fonts.css, v2.css, Nunito-Sans woff2, Phosphor-Icons (21 SVGs)
- app/templates/v2/: base.html + 11 Screens + 8 Component-Macros
- AppShell mit Sidebar (Lesen/Pruefen/Daten/Admin), v2-Detail mit allen Features
(ScoreHero, MatrixMini, QuoteCard, Redline, Fraktions-Scores)
- v2 ist jetzt Default unter / — classic unter /classic
- Login-Modal in v2-Topbar mit Tabs Anmelden/Registrieren (#129)
- Phosphor-Icons in Sidebar + Topbar mit dynamischem Theme-Toggle
- Keyboard-Shortcuts (j/k/Enter/Esc/?/path), Landtag-Suche, Antrag-Historie,
Sort-Dropdown, Matrix-Feld-Info-Modal, Bookmarks/Comments/Voting/Share/Re-Analyze
Backend-Erweiterungen:
- main.py: ~30 neue Routes (/v2/*, /antrag/{ds}, /api/auth/{login,refresh,logout},
/api/me/merkliste/*, /api/admin/*, /v2/admin/*, OG-Cards, etc.)
- og_card.py + og_template: Open-Graph-Bilder via Playwright (#141)
- wahlprogramm_fetch.py + wahlprogramm-links.yaml: SHA-Gate Auto-DL (#138)
- auswertungen.py: BL-Filter + get_wahlperioden Helper (#137)
- auth.py: Direct-Access-Grant + Refresh-Token-Cookie
Classic-Updates:
- Header-DRY via _header.html, Auswertungen redirected, Batch-Inline raus
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 20:55:57 +02:00
|
|
|
keycloak_admin_user: str = ""
|
|
|
|
|
keycloak_admin_password: str = ""
|
2026-03-28 22:30:24 +01:00
|
|
|
|
|
|
|
|
# Server
|
|
|
|
|
host: str = "0.0.0.0"
|
|
|
|
|
port: int = 8000
|
|
|
|
|
|
feat(#139,#129,#138,#141): v2-Frontend (ECOnGOOD-CD), Login-Modal, Auto-DL, OG-Cards
v2-Frontend (#139, ECOnGOOD CD Manual Juni 2024):
- app/static/v2/: tokens.css, fonts.css, v2.css, Nunito-Sans woff2, Phosphor-Icons (21 SVGs)
- app/templates/v2/: base.html + 11 Screens + 8 Component-Macros
- AppShell mit Sidebar (Lesen/Pruefen/Daten/Admin), v2-Detail mit allen Features
(ScoreHero, MatrixMini, QuoteCard, Redline, Fraktions-Scores)
- v2 ist jetzt Default unter / — classic unter /classic
- Login-Modal in v2-Topbar mit Tabs Anmelden/Registrieren (#129)
- Phosphor-Icons in Sidebar + Topbar mit dynamischem Theme-Toggle
- Keyboard-Shortcuts (j/k/Enter/Esc/?/path), Landtag-Suche, Antrag-Historie,
Sort-Dropdown, Matrix-Feld-Info-Modal, Bookmarks/Comments/Voting/Share/Re-Analyze
Backend-Erweiterungen:
- main.py: ~30 neue Routes (/v2/*, /antrag/{ds}, /api/auth/{login,refresh,logout},
/api/me/merkliste/*, /api/admin/*, /v2/admin/*, OG-Cards, etc.)
- og_card.py + og_template: Open-Graph-Bilder via Playwright (#141)
- wahlprogramm_fetch.py + wahlprogramm-links.yaml: SHA-Gate Auto-DL (#138)
- auswertungen.py: BL-Filter + get_wahlperioden Helper (#137)
- auth.py: Direct-Access-Grant + Refresh-Token-Cookie
Classic-Updates:
- Header-DRY via _header.html, Auswertungen redirected, Batch-Inline raus
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 20:55:57 +02:00
|
|
|
# SMTP (Issue #124 E-Mail-Benachrichtigung)
|
|
|
|
|
# 1blu: smtp.1blu.de:465 SSL, username = Postfachname (NICHT E-Mail!),
|
|
|
|
|
# z.B. "q294440_0-gwoe-toppyr". Passwort via ENV SMTP_PASSWORD.
|
|
|
|
|
smtp_host: str = ""
|
|
|
|
|
smtp_port: int = 465
|
|
|
|
|
smtp_user: str = ""
|
|
|
|
|
smtp_password: str = ""
|
|
|
|
|
smtp_from_email: str = "noreply@toppyr.de"
|
|
|
|
|
smtp_from_name: str = "GWÖ-Antragsprüfer"
|
|
|
|
|
# URL-Basis für Links in Mails (Unsubscribe, Detail-Ansicht)
|
|
|
|
|
base_url: str = "https://gwoe.toppyr.de"
|
|
|
|
|
# Token für Unsubscribe-Links (HMAC-Secret)
|
|
|
|
|
unsubscribe_secret: str = "change-me-in-prod"
|
|
|
|
|
|
feat(v2): Feedback-Widget mit Audit-Trail + Screenshot + direkter Gitea-Anbindung
- Component v2/components/feedback_widget.html: Button unten links oberhalb der
Queue, Klick oeffnet Modal mit vorausgefuellten Kontext-Feldern (URL,
Drucksache, Viewport, User-Agent, letzte 15 Klicks, letzte 10 Console-Errors,
letzte 5 Page-Loads). Eingaben: Titel, Beschreibung, optional Screenshot
- Audit-Trail-Sammler in localStorage (Ringbuffer 30 Klicks, 10 Errors)
- Screenshot via self-hosted html2canvas 1.4.1 (194 KB unter app/static/v2/lib/)
- Backend POST /api/feedback (rate-limit 5/h):
- validiert + html-strippt Inputs
- erstellt Gitea-Issue per API mit Label 'feedback' (Label wird idempotent angelegt)
- laedt Screenshot als Issue-Asset hoch (Gitea Issue-Attachment-API)
- 4 neue Settings: gitea_token, gitea_api_url, gitea_repo_owner, gitea_repo_name
- Server .env um GITEA_TOKEN ergaenzt
- 10 neue Unit-Tests (mit gemocktem httpx)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 01:00:44 +02:00
|
|
|
# Gitea-API-Token für Feedback-Issues (Issue #feedback-widget)
|
|
|
|
|
# Wert in .env: GITEA_TOKEN=<token>
|
|
|
|
|
# Token-Quelle: cat ~/.claude/.gitea-token
|
|
|
|
|
gitea_token: str = ""
|
|
|
|
|
gitea_api_url: str = "https://repo.toppyr.de/api/v1"
|
|
|
|
|
gitea_repo_owner: str = "tobias"
|
|
|
|
|
gitea_repo_name: str = "gwoe-antragspruefer"
|
|
|
|
|
|
2026-03-28 22:30:24 +01:00
|
|
|
model_config = {"env_file": ".env", "env_file_encoding": "utf-8"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
settings = Settings()
|