# Reverse-Proxy: Pfad-Freigabeliste für DataMetric360

**Vorbereitung, noch nicht in Betrieb.** Gehört zu Phase 12 des
`../UMSETZUNGSPLAN.md`; die Entscheidung dahinter steht in
`../COMPANION_APP_ARCHITECTURE.md` §4.

Ziel: Die App erreicht Home Assistant von unterwegs, **ohne dass Home Assistant
selbst im Internet steht**. Dazu ein Cloudflare-Tunnel (baut nur nach außen auf,
kein Port am Router) auf einen Reverse Proxy, der ausschließlich die unten
aufgeführten Pfade durchlässt.

## Was die App wirklich braucht

Aus dem tatsächlichen Code der Datenschicht (`companion-app/src/api/`)
abgeleitet, nicht geschätzt:

| Methode | Pfad | Wofür |
|---|---|---|
| `GET` | `/api/` | Verbindungsprüfung bei der Ersteinrichtung |
| `GET` | `/api/states/pyscript.audi_dashboard_*` | Profil, Fahrten, Tankvorgänge, Status, Batterieverlauf, Belegergebnis, Updatestatus |
| `GET` | `/api/states/pyscript.reifen_*` | Reifensatz-Kilometerstände |
| `POST` | `/api/services/pyscript/audi_dashboard_*` | alle schreibenden Vorgänge |
| `GET` (Upgrade) | `/api/websocket` | Live-Aktualisierung |

Alles andere wird geblockt, insbesondere `/auth/*`, `/lovelace*`, `/config*`,
`/api/config`, `/api/history*`, `/developer-tools*` und die Oberfläche selbst.

## Ehrliche Einschränkung

**Der WebSocket lässt sich nicht pfadgenau beschneiden.** Nach `auth_ok` kann
über `/api/websocket` grundsätzlich jeder Zustand gelesen werden, nicht nur die
`pyscript.*`-Entitäten. Die Freigabeliste ist an dieser Stelle also grobkörniger
als beim REST-Zugriff.

Was bleibt: Ohne gültigen Token kommt gar keine Verbindung zustande, und ein
verlorenes Gerät wird durch Zurückziehen genau seines Tokens ausgesperrt. Das
ist die im Architekturdokument bewusst akzeptierte Abwägung — sie sollte nur
nicht in Vergessenheit geraten.

Wer sie nicht eingehen will, hat eine Alternative: den WebSocket weglassen und
die App auf regelmäßiges Abfragen umstellen. Kostet Akku und Datenvolumen,
verkleinert die Angriffsfläche aber auf die exakt aufgeführten REST-Pfade.

## Nginx Proxy Manager

Im Add-on unter *Hosts → Proxy Hosts → Edit → Advanced* eintragen. Ziel ist der
interne Name der Home-Assistant-Instanz (im Supervisor-Netz `homeassistant:8123`).

```nginx
# Reihenfolge zählt: die erlaubenden Blöcke stehen vor dem pauschalen Verbot.

location = /api/ {
    proxy_pass http://homeassistant:8123;
    include conf.d/include/proxy.conf;
}

location ~ ^/api/states/pyscript\.(audi_dashboard_[a-z_]+|reifen_[a-z_]+)$ {
    limit_except GET { deny all; }
    proxy_pass http://homeassistant:8123;
    include conf.d/include/proxy.conf;
}

location ~ ^/api/services/pyscript/audi_dashboard_[a-z_]+$ {
    limit_except POST { deny all; }
    proxy_pass http://homeassistant:8123;
    include conf.d/include/proxy.conf;
}

location = /api/websocket {
    proxy_pass http://homeassistant:8123;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;
    include conf.d/include/proxy.conf;
}

# Die Fotos der Fahrzeuge, die die App anzeigt. Nur Lesen, nur Bilder.
location ~ ^/local/bilder/[a-z0-9_-]+\.(webp|png|jpg|svg)$ {
    limit_except GET { deny all; }
    proxy_pass http://homeassistant:8123;
    include conf.d/include/proxy.conf;
}

# Alles Übrige: nicht durchlassen.
location / {
    return 404;
}
```

Wird die App selbst unter derselben Adresse ausgeliefert, braucht sie einen
eigenen Block auf ihr Verzeichnis — sauberer ist ein getrennter Hostname
(`datametric360.app` für die App, `api.datametric360.app` für die
Schnittstelle), dann bleibt diese Liste unverändert.

## Nach der Einrichtung prüfen

Von einem Netz ohne VPN, etwa über Mobilfunk:

```bash
API=https://api.datametric360.app
T=<Zugriffstoken>

# muss gehen
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $T" "$API/api/"
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $T" \
  "$API/api/states/pyscript.audi_dashboard_profil"

# muss 404 oder 403 liefern
curl -s -o /dev/null -w '%{http_code}\n' "$API/auth/authorize"
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $T" "$API/api/config"
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $T" \
  "$API/api/states/sensor.audi_rs_4_avant_mileage"

# ohne Token: 401, nicht 200
curl -s -o /dev/null -w '%{http_code}\n' "$API/api/states/pyscript.audi_dashboard_profil"
```

Zusätzlich: Port 8123 darf von außen **gar nicht** antworten.

## Offen bis zur Einrichtung

- Nameserver von `datametric360.app` auf Cloudflare umstellen („Full setup")
- Entscheidung Nginx Proxy Manager gegen Traefik (die Liste oben ist für NPM
  geschrieben und für Traefik sinngemäß zu übertragen)
- Endgültige Hostnamen festlegen und hier eintragen
