Architektur-Entscheidung aus Issue #62: Diátaxis-Framework für Doku- Pflege ohne Drift. Pflege im Repo, ADRs immutable, Stale-Snapshots explizit als Archiv markiert. Phase 1 — Architecture Decision Records: - docs/README.md — Diátaxis-Index, Erklärung was wo dokumentiert wird - docs/adr/README.md — ADR-Workflow + Index - docs/adr/template.md — Vorlage für neue ADRs - docs/adr/0001-llm-citation-binding.md — Issue #60 Doppel-Fix-Story (A=ENUM-Anker, B=server-seitige Rekonstruktion, warum Option C verworfen) - docs/adr/0002-adapter-architecture.md — ParlamentAdapter-Basisklasse + Registry, Klassen vs. Strategy vs. Modul-pro-Adapter - docs/adr/0003-citation-property-tests.md — Sub-D Strategie, warum Property-Test gegen echte PDFs statt Schema-Tests oder Online-Verify - docs/adr/0004-deployment-workflow.md — Docker-Compose + Volumes Standard-Workflow + SN-XML-Sonderpfad + Container-UTC-Gotcha Phase 3 — Stale Doku archiviert: - DOKUMENTATION.md (24.März, Skript-Architektur vor Webapp-Migrate) → docs/archive/DOKUMENTATION-2026-03-24.md - STATUS-2026-03-28.md (Tagesstand-Snapshot) → docs/archive/STATUS-2026-03-28.md - README.md (28.März, listet nur NRW-Adapter, vor 16 weiteren BLs) → docs/archive/README-2026-03-28.md - docs/archive/README.md erklärt warum die Files da sind und warum niemand sie überschreiben oder ersetzen sollte Plus neue Top-Level-README.md im Project-Root (außerhalb git, da project-root kein Repo ist) als Folder-Index für den User. CLAUDE.md ergänzt um Doku-Sektion mit Verweis auf docs/adr/. Phase 2 (mkdocs Setup) folgt separat — braucht eine Docker-Image- Erweiterung, die ich nicht autark einrollen will ohne Decision. Tests: 194/194 grün (keine Code-Änderung). Refs: #62
183 lines
4.7 KiB
Markdown
183 lines
4.7 KiB
Markdown
# GWÖ-Antragsprüfer — Status 28.03.2026 (Final)
|
|
|
|
## ✅ Heute erledigt (28.03.2026)
|
|
|
|
### Vormittag
|
|
- [x] "Jetzt prüfen" aus Landtag-Suche implementiert
|
|
- [x] Zitat-System mit Wahlprogramm-Seitenreferenzen
|
|
- [x] 5 Original-Wahlprogramme integriert (CDU, SPD, Grüne, FDP, AfD)
|
|
|
|
### Nachmittag/Abend
|
|
- [x] **Security Headers** eingebaut (CSP, X-Frame-Options, etc.)
|
|
- [x] /docs, /redoc, /openapi.json deaktiviert
|
|
- [x] **v5-Prompt** mit Verbesserungsvorschlägen im Redline-Format
|
|
- [x] **Retry-Logik** (3 Versuche) bei JSON-Parse-Fehlern
|
|
- [x] **Partei-Filter** (Dropdown)
|
|
- [x] **Tag-Wolke** mit Multi-Select (Schnittmenge-Filter)
|
|
- [x] **Partei-Durchschnittswerte** in kompakter Stats-Bar
|
|
- [x] **Persistente DB** — Dockerfile gefixt, data/ als Volume
|
|
- [x] JSON-Import deaktiviert (DB ist Source of Truth)
|
|
- [x] 20 Test-Anträge neu analysiert mit v5-Prompt
|
|
- [x] **Git-Repository** auf repo.toppyr.de gepusht
|
|
- [x] **Dokumentation** komplett
|
|
|
|
---
|
|
|
|
## 🌐 Live-System
|
|
|
|
| Was | URL |
|
|
|-----|-----|
|
|
| **Webapp** | https://gwoe.toppyr.de |
|
|
| **Repository** | https://repo.toppyr.de/tobias/gwoe-antragspruefer |
|
|
| **Server** | VServer 152.53.119.77 (`/opt/gwoe-antragspruefer/`) |
|
|
|
|
---
|
|
|
|
## 📊 Aktueller Stand
|
|
|
|
| Metrik | Wert |
|
|
|--------|------|
|
|
| Analysierte Anträge | 20 |
|
|
| Alle mit Verbesserungsvorschlägen | ✅ |
|
|
| Ø GWÖ-Score gesamt | 4.6 |
|
|
| Ø SPD | 7.7 |
|
|
| Ø CDU/GRÜNE | 6.0 |
|
|
| Ø FDP | 4.8 |
|
|
| Ø AfD | 1.5 |
|
|
|
|
---
|
|
|
|
## 🔧 Technische Änderungen heute
|
|
|
|
### Security (main.py)
|
|
```python
|
|
# Middleware hinzugefügt:
|
|
- X-Content-Type-Options: nosniff
|
|
- X-Frame-Options: DENY
|
|
- X-XSS-Protection: 1; mode=block
|
|
- Content-Security-Policy
|
|
- Referrer-Policy: strict-origin-when-cross-origin
|
|
- Permissions-Policy: geolocation=(), microphone=(), camera=()
|
|
|
|
# FastAPI Docs deaktiviert:
|
|
docs_url=None, redoc_url=None, openapi_url=None
|
|
```
|
|
|
|
### Retry-Logik (analyzer.py)
|
|
```python
|
|
# 3 Versuche bei JSON-Parse-Fehlern
|
|
# Temperatur steigt pro Versuch (0.3 → 0.4 → 0.5)
|
|
max_retries = 3
|
|
for attempt in range(max_retries):
|
|
# ... LLM Call ...
|
|
try:
|
|
data = json.loads(content)
|
|
return Assessment.model_validate(data)
|
|
except json.JSONDecodeError:
|
|
continue # Retry
|
|
```
|
|
|
|
### Persistente DB (Dockerfile)
|
|
```dockerfile
|
|
# VORHER (kaputt):
|
|
COPY data/ ./data/
|
|
COPY reports/ ./reports/
|
|
|
|
# NACHHER (korrekt):
|
|
# data/ und reports/ werden als Volumes gemountet
|
|
RUN mkdir -p /app/data /app/reports
|
|
```
|
|
|
|
### Deploy-Workflow
|
|
```bash
|
|
# .tarignore und --exclude verhindern Überschreiben der Server-DB
|
|
tar czf ... --exclude='data' --exclude='reports' ...
|
|
```
|
|
|
|
---
|
|
|
|
## 📁 Repository-Struktur
|
|
|
|
```
|
|
gwoe-antragspruefer/
|
|
├── app/
|
|
│ ├── main.py # FastAPI + Security
|
|
│ ├── analyzer.py # LLM + Retry
|
|
│ ├── database.py # SQLite
|
|
│ ├── models.py # Pydantic
|
|
│ ├── parlamente.py # OPAL-Adapter
|
|
│ ├── report.py # PDF
|
|
│ ├── kontext/ # GWÖ-Matrix, Programme
|
|
│ ├── templates/ # Jinja2 UI
|
|
│ └── static/referenzen/ # Original-PDFs
|
|
├── docker-compose.yml
|
|
├── Dockerfile
|
|
├── requirements.txt
|
|
├── .env.example
|
|
├── .gitignore
|
|
├── LICENSE (MIT)
|
|
└── README.md
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 Offene TODOs
|
|
|
|
### Prio 1
|
|
- [ ] Keycloak SSO aktivieren
|
|
- [ ] Batch-Analyse für viele Anträge optimieren
|
|
|
|
### Prio 2
|
|
- [ ] Weitere Bundesländer (BY, BW)
|
|
- [ ] CSV/Excel-Export
|
|
- [ ] Zitat-Highlighting in PDFs
|
|
|
|
### Nice to have
|
|
- [ ] Historische Trend-Analyse
|
|
- [ ] Newsletter-Integration
|
|
- [ ] API-Rate-Limiting für öffentliche Nutzung
|
|
|
|
---
|
|
|
|
## 🚀 Deployment-Befehle
|
|
|
|
### Standard-Update
|
|
```bash
|
|
# Lokal committen
|
|
cd ~/Nextcloud/dotty/projekte/2026-03-23\ GWÖ-Antragsprüfer\ _WIP_/webapp
|
|
git add . && git commit -m "..." && git push
|
|
|
|
# Server aktualisieren
|
|
ssh vserver 'cd /opt/gwoe-antragspruefer && git pull && docker compose up -d --build'
|
|
```
|
|
|
|
### Manuell (ohne Server-Git)
|
|
```bash
|
|
cd ~/Nextcloud/dotty/projekte/2026-03-23\ GWÖ-Antragsprüfer\ _WIP_/webapp
|
|
tar czf /tmp/gwoe-webapp.tar.gz --exclude='venv' --exclude='__pycache__' --exclude='data' --exclude='reports' --exclude='.env' .
|
|
scp /tmp/gwoe-webapp.tar.gz vserver:/tmp/
|
|
ssh vserver 'cd /opt/gwoe-antragspruefer && tar xzf /tmp/gwoe-webapp.tar.gz && docker compose up -d --build'
|
|
```
|
|
|
|
### Logs prüfen
|
|
```bash
|
|
ssh vserver 'docker logs gwoe-antragspruefer --tail 50'
|
|
```
|
|
|
|
### DB-Status
|
|
```bash
|
|
ssh vserver 'docker exec gwoe-antragspruefer python -c "
|
|
import sqlite3
|
|
conn = sqlite3.connect(\"/app/data/gwoe-antraege.db\")
|
|
cur = conn.cursor()
|
|
cur.execute(\"SELECT COUNT(*) FROM assessments\")
|
|
print(f\"Assessments: {cur.fetchone()[0]}\")
|
|
"'
|
|
```
|
|
|
|
---
|
|
|
|
**Projekt-Status: FUNKTIONSFÄHIG** ✅
|
|
|
|
*Dokumentiert von Dotty, 28.03.2026, 23:58 Uhr*
|