docs: Dashboard bleibt Heimnetz-only (Bernd Nr. 3) – ROADMAP-Punkt geschlossen, Doku nachgezogen, Nr.-4-Vermerk am Secrets-Punkt

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bernd Steckmeister
2026-07-05 14:53:27 +02:00
parent 81ec06398f
commit 66bf54bdff
4 changed files with 76 additions and 20 deletions
+8
View File
@@ -1294,3 +1294,11 @@
2026-07-04 19:45 [Edit] /home/steggi/.claude-pyramid/projects/-home-steggi-pyramid/memory/pyramid-arbeitsstand.md 2026-07-04 19:45 [Edit] /home/steggi/.claude-pyramid/projects/-home-steggi-pyramid/memory/pyramid-arbeitsstand.md
2026-07-05 14:51 [Edit] /home/steggi/pyramid/PROGRESS.md 2026-07-05 14:51 [Edit] /home/steggi/pyramid/PROGRESS.md
2026-07-05 14:52 [Edit] /home/steggi/pyramid/PROGRESS.md 2026-07-05 14:52 [Edit] /home/steggi/pyramid/PROGRESS.md
2026-07-05 14:52 [Edit] /home/steggi/pyramid/ROADMAP.md
2026-07-05 14:52 [Edit] /home/steggi/pyramid/ROADMAP.md
2026-07-05 14:52 [Edit] /home/steggi/pyramid/ROADMAP.md
2026-07-05 14:52 [Edit] /home/steggi/pyramid/docs/DASHBOARD_AUTH_HARDENING.md
2026-07-05 14:52 [Edit] /home/steggi/pyramid/docs/DASHBOARD_AUTH_HARDENING.md
2026-07-05 14:52 [Edit] /home/steggi/pyramid/docs/DASHBOARD_AUTH_HARDENING.md
2026-07-05 14:53 [Edit] /home/steggi/pyramid/docs/DASHBOARD_AUTH_HARDENING.md
2026-07-05 14:53 [Edit] /home/steggi/pyramid/PROGRESS.md
+34
View File
@@ -13,6 +13,40 @@ Schritt (und beim Abbruch mitten im Schritt den Zwischenstand). Format:
--- ---
## 2026-07-05 Dashboard-ROADMAP-Punkt GESCHLOSSEN (Bernds Entscheidung 3 nachgezogen)
**Erledigt:** Folge aus Review-Befund (v): Bernds Entscheidungen 3 und 4 aus
`ANTWORTEN_BERND.md` sind jetzt überall nachgezogen, damit keine künftige
Session die geschlossenen Fragen wieder aufmacht:
- **ROADMAP M0 „Dashboard-Admin-Endpoints": abgehakt.** Das Heimnetz-Gate ist
laut Bernd der Endzustand (kein Fernzugriff, unterwegs WireGuard, A/B-Frage
geschlossen). Restrisiken (öffentliche Nutzerlisten-Ansicht, theoretisches
LAN-CSRF) bewusst akzeptiert im ROADMAP-Punkt und in
`docs/DASHBOARD_AUTH_HARDENING.md` vermerkt.
- **`docs/DASHBOARD_AUTH_HARDENING.md`:** Status-Kopf auf „ABGESCHLOSSEN"
umgestellt, „Interims-Gate" heißt jetzt Endzustand, Weg A/B als Archiv
markiert, „bis zur A/B-Entscheidung"-Formulierungen bereinigt.
- **ROADMAP M0 Secrets-Punkt:** Vermerk zu Entscheidung 4 ergänzt Rotation
und History-Rewrite ruhen bewusst (Bernds manuelle Sache, nicht vom
Autopilot anstoßen oder nachfragen); der Punkt bleibt nur als Merkposten
offen. KEINE Code-/Serveränderung in diesem Schritt, nur Doku
`server.py` und das Gate sind unangetastet.
**Offen/Nächster Schritt:** In M0 sind damit nur noch zwei Punkte offen, beide
nicht Pi-bearbeitbar: SQLCipher (PC-/Gerätetest, laut Entscheidung 1 als
Erstes am PC) und der Härtetest (`docs/PC_TESTPLAN.md`). Danach M2 mit
Call-Pilot (Entscheidung 2, Gerätetest nötig). Auf dem Pi bleibt ohne neuen
Anlass nichts sicher Bearbeitbares Session darf sauber enden.
**Stolperfallen:** Keine reine Doku-Angleichung. Lehre aus dem
(v)-Befund: Wenn Entscheidungen in einer eigenen Datei landen
(`ANTWORTEN_BERND.md`), müssen die referenzierten offenen Punkte in
ROADMAP/Docs im SELBEN Zug geschlossen/annotiert werden, sonst stellt die
nächste Session die beantwortete Frage erneut.
---
## 2026-07-05 Fable-5-Review (v)+(w): die zwei PC-Commits geprüft Fix korrekt, 1 Doku-Lücke gefunden ## 2026-07-05 Fable-5-Review (v)+(w): die zwei PC-Commits geprüft Fix korrekt, 1 Doku-Lücke gefunden
**Erledigt:** Review-Pass über die seit (u) dazugekommene Arbeit die zwei am **Erledigt:** Review-Pass über die seit (u) dazugekommene Arbeit die zwei am
+14 -4
View File
@@ -60,8 +60,9 @@ Punkte abhaken (`[x]`), wenn erledigt UND in `PROGRESS.md` protokolliert.
- [x] Geräte-/Sessionverwaltung in den Einstellungen: bereits vorhanden - [x] Geräte-/Sessionverwaltung in den Einstellungen: bereits vorhanden
(`_SessionsSection` in `settings_modal.dart` Liste, Umbenennen, Verifizieren (`_SessionsSection` in `settings_modal.dart` Liste, Umbenennen, Verifizieren
per SAS/QR, Abmelden, Massen-Abmeldung mit Passwort-Reauth) per SAS/QR, Abmelden, Massen-Abmeldung mit Passwort-Reauth)
- [ ] **SICHERHEIT: Dashboard-Admin-Endpoints akutes Loch mit Interims-Gate - [x] **SICHERHEIT: Dashboard-Admin-Endpoints ERLEDIGT: Loch geschlossen,
geschlossen (2026-07-04), Fernzugriffs-Entscheidung offen** (Fable-5-Review (o)). Heimnetz-only ist laut Bernd der Endzustand** (Fable-5-Review (o);
Entscheidung `ANTWORTEN_BERND.md` Nr. 3, 2026-07-05).
`server.py` nimmt `/api/ban`, `/api/unban`, `/api/toggle-registration`, `server.py` nimmt `/api/ban`, `/api/unban`, `/api/toggle-registration`,
`/api/create-invite`, `/api/run-stats` jetzt NUR noch aus Heimnetz/localhost an `/api/create-invite`, `/api/run-stats` jetzt NUR noch aus Heimnetz/localhost an
(Socket-IP + Cloudflare-Header-Check); Fremde aus dem Internet bekommen 403. (Socket-IP + Cloudflare-Header-Check); Fremde aus dem Internet bekommen 403.
@@ -93,8 +94,13 @@ Punkte abhaken (`[x]`), wenn erledigt UND in `PROGRESS.md` protokolliert.
verifiziert inkl. 500-Beweis. verifiziert inkl. 500-Beweis.
Zusatz (Fable-5-Review (u), 2026-07-04): (t)-Fix gegengelesen korrekt, Zusatz (Fable-5-Review (u), 2026-07-04): (t)-Fix gegengelesen korrekt,
kein Befund; die server.py-Härtungskette ist damit KONVERGIERT (alle kein Befund; die server.py-Härtungskette ist damit KONVERGIERT (alle
verbliebenen `str(e)`-Antworten LAN-gegated, absichtlich). Offen bleibt an verbliebenen `str(e)`-Antworten LAN-gegated, absichtlich).
diesem Punkt NUR noch Bernds Fernzugriffs-Entscheidung A/B. **Abschluss (2026-07-05, `ANTWORTEN_BERND.md` Nr. 3): KEIN Fernzugriff
gewünscht die A/B-Frage ist GESCHLOSSEN, das Heimnetz-Gate ist der
Endzustand (unterwegs nutzt Bernd WireGuard). Die Restrisiken des Gates
(öffentliche Nutzerlisten-Ansicht, theoretisches LAN-CSRF) sind bewusst
akzeptiert und in `docs/DASHBOARD_AUTH_HARDENING.md` dokumentiert.
Nicht weiter daran arbeiten.**
- [x] **LiveKit-Token-Route server-seitig gebaut + verifiziert** (Fable-5-Review (n), - [x] **LiveKit-Token-Route server-seitig gebaut + verifiziert** (Fable-5-Review (n),
PROGRESS.md 2026-07-04). `POST /api/livekit-token` läuft live in `server.py` PROGRESS.md 2026-07-04). `POST /api/livekit-token` läuft live in `server.py`
(whoami-Auth, stdlib-HS256-Minting aus `livekit.yaml`), headless geprüft (whoami-Auth, stdlib-HS256-Minting aus `livekit.yaml`), headless geprüft
@@ -121,6 +127,10 @@ Punkte abhaken (`[x]`), wenn erledigt UND in `PROGRESS.md` protokolliert.
Client umgestellt und verifiziert (neuer Token 200, alter Admin-Token 403). Der Client umgestellt und verifiziert (neuer Token 200, alter Admin-Token 403). Der
Admin-Token selbst muss trotzdem noch rotiert werden (steht oben, Bernds Sache). Admin-Token selbst muss trotzdem noch rotiert werden (steht oben, Bernds Sache).
- Optional: Git-History-Rewrite (Bernds Entscheidung, Repo ist auch Backup). - Optional: Git-History-Rewrite (Bernds Entscheidung, Repo ist auch Backup).
- **Stand 2026-07-05 (`ANTWORTEN_BERND.md` Nr. 4): Rotation und
History-Rewrite ruhen BEWUSST beides bleibt Bernds manuelle Sache,
NICHT vom Autopilot anstoßen oder nachfragen. Der Punkt bleibt nur als
Merkposten offen; Autopilot-bearbeitbar ist hier nichts mehr.**
- **ACHTUNG bei „Repo einfach privat schalten":** Der In-App-Updater - **ACHTUNG bei „Repo einfach privat schalten":** Der In-App-Updater
(`lib/core/update_checker.dart`) holt Releases **anonym** über die öffentliche (`lib/core/update_checker.dart`) holt Releases **anonym** über die öffentliche
Gitea-API (`/api/v1/repos/steggi/pyramid/releases`). Repo privat = Utas App Gitea-API (`/api/v1/repos/steggi/pyramid/releases`). Repo privat = Utas App
+20 -16
View File
@@ -1,17 +1,19 @@
# Dashboard-Server absichern: Admin-Endpoints haben KEINE Authentifizierung # Dashboard-Server absichern: Admin-Endpoints haben KEINE Authentifizierung
**Status (aktualisiert 2026-07-04): Das akute Loch ist mit einem INTERIMS-GATE **Status (ABGESCHLOSSEN 2026-07-05): Das Loch ist mit dem Heimnetz-Gate
geschlossen („Weg C", siehe unten)** die fünf Admin-Endpoints akzeptieren nur („Weg C", siehe unten) geschlossen, und Bernd hat entschieden
noch Anfragen aus dem Heimnetz/localhost; alles, was über den Cloudflare-Tunnel (`ANTWORTEN_BERND.md` Nr. 3): KEIN Fernzugriff das Gate ist der ENDZUSTAND.**
kommt, bekommt 403 mit einer Erklärung (die das Dashboard per `alert()` anzeigt). Die fünf Admin-Endpoints akzeptieren nur noch Anfragen aus dem
Bernds Dashboard funktioniert im Heimnetz unverändert unter Heimnetz/localhost; alles, was über den Cloudflare-Tunnel kommt, bekommt 403 mit
`http://192.168.178.71:8080/stats.html`; die öffentliche URL zeigt weiterhin die einer Erklärung (die das Dashboard per `alert()` anzeigt). Bernds Dashboard
Ansicht, nur die Admin-Buttons sind dort gesperrt. **Offen bleibt Bernds funktioniert im Heimnetz unverändert unter
Entscheidung Weg A (Cloudflare Access, empfohlen) oder Weg B (DASH_TOKEN), falls `http://192.168.178.71:8080/stats.html`; unterwegs kommt Bernd per WireGuard ins
er die Admin-Buttons auch von unterwegs braucht** das Gate ersetzt die Heimnetz. Die A/B-Frage (Cloudflare Access vs. `DASH_TOKEN`) ist damit
Entscheidung nicht, es stopft nur das Loch, solange sie aussteht. GESCHLOSSEN die Optionen unten bleiben nur als Archiv stehen, falls sich der
Bedarf je ändert. Die unten dokumentierten Restrisiken des Gates sind bewusst
akzeptiert. **Nicht weiter an diesem Thema arbeiten.**
## Interims-Gate („Weg C", aktiv seit 2026-07-04) ## Heimnetz-Gate („Weg C", aktiv seit 2026-07-04, seit 2026-07-05 Endzustand)
In `server.py` (Konstante `ADMIN_PATHS` + Helfer `lan_denied_reason`): eine In `server.py` (Konstante `ADMIN_PATHS` + Helfer `lan_denied_reason`): eine
Admin-POST-Anfrage wird nur angenommen, wenn (1) **kein** `Cf-Connecting-Ip`/ Admin-POST-Anfrage wird nur angenommen, wenn (1) **kein** `Cf-Connecting-Ip`/
@@ -25,8 +27,8 @@ erreicht (400 bei leerem Nutzer), gespoofter Cf-Header aus dem LAN → 403,
`/api/e2ee-diagnostics` (403 bei falschem Token) unverändert öffentlich `/api/e2ee-diagnostics` (403 bei falschem Token) unverändert öffentlich
erreichbar (die App braucht sie, eigene Auth vorhanden). erreichbar (die App braucht sie, eigene Auth vorhanden).
**Bekannte Restrisiken des Interims-Gates (Gründe, warum Weg A trotzdem kommen **Bekannte Restrisiken des Gates (Bernd bekannt und bewusst akzeptiert,
sollte):** Entscheidung 2026-07-05):**
- Die **öffentliche Ansicht bleibt offen** und zeigt Nutzerliste + Präsenz - Die **öffentliche Ansicht bleibt offen** und zeigt Nutzerliste + Präsenz
(Informations-Preisgabe). Weg A würde auch das schließen. (Informations-Preisgabe). Weg A würde auch das schließen.
- **CSRF aus dem Heimnetz:** Eine bösartige Webseite in Bernds Browser könnte - **CSRF aus dem Heimnetz:** Eine bösartige Webseite in Bernds Browser könnte
@@ -168,6 +170,8 @@ Bernds Richtungsentscheidung. Das später ergänzte Interims-Gate umgeht dieses
Dilemma: Es braucht keinerlei Aktion von Bernd (Heimnetz-Nutzung läuft Dilemma: Es braucht keinerlei Aktion von Bernd (Heimnetz-Nutzung läuft
unverändert weiter, inkl. spontanem Spam-Bann von zu Hause), sperrt aber unverändert weiter, inkl. spontanem Spam-Bann von zu Hause), sperrt aber
Fremde aus dem Internet sofort aus. Einzige Einschränkung: Admin-Buttons über Fremde aus dem Internet sofort aus. Einzige Einschränkung: Admin-Buttons über
die öffentliche URL gehen bis zur A/B-Entscheidung nicht die 403-Meldung im die öffentliche URL gehen nicht die 403-Meldung im Dashboard erklärt das und
Dashboard erklärt das und nennt die Heimnetz-URL. Rückbau = die Gate-Zeilen in nennt die Heimnetz-URL. Mit Bernds Entscheidung vom 2026-07-05 (Heimnetz-only,
`server.py` entfernen (Backup: `server.py.bak-20260704-dashgate`). unterwegs WireGuard) ist genau dieser Zustand der gewollte Endzustand. Rückbau
(falls je nötig) = die Gate-Zeilen in `server.py` entfernen
(Backup: `server.py.bak-20260704-dashgate`).