gwoe-antragspruefer/docs/archive/STATUS-2026-03-28.md

183 lines
4.7 KiB
Markdown
Raw Permalink Normal View History

#62 Phase 1+3: ADRs + Doku-Struktur in webapp/docs/ 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
2026-04-10 01:38:03 +02:00
# 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*