From 61c238b38d64647d267718d87fb400c97a91cdb8 Mon Sep 17 00:00:00 2001 From: DeeCee03 Date: Mon, 19 Oct 2026 17:15:44 +0200 Subject: [PATCH] Freigabe fuer Kollegen, Kopf auf schmalen Fenstern bleibt oben freigabe.sh startet freigabe.py (Passwort, nur lesen, nichts mit Punkt am Anfang) und einen Cloudflare Quick Tunnel. Anleitung fuer Agents in .docs/Freigabe.md, Hinweis darauf in .claude/CLAUDE.md. Das Passwort selbst bleibt in .freigabe-passwort ausserhalb von git. Dashboard: Unter 900 px bleibt die Navigation beim Scrollen stehen, nur das Logo scrollt weg. Co-Authored-By: Claude Opus 5.5 --- .claude/CLAUDE.md | 5 +++ .docs/Freigabe.md | 63 ++++++++++++++++++++++++++++++ .gitignore | 3 ++ Dashboard/stil.css | 5 ++- freigabe.py | 96 ++++++++++++++++++++++++++++++++++++++++++++++ freigabe.sh | 18 +++++++++ 6 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 .claude/CLAUDE.md create mode 100644 .docs/Freigabe.md create mode 100644 freigabe.py create mode 100755 freigabe.sh diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md new file mode 100644 index 0000000..22121ee --- /dev/null +++ b/.claude/CLAUDE.md @@ -0,0 +1,5 @@ +# HiveGrid Marketing + +Das Dashboard lässt sich für Kollegen freigeben, über einen Tunnel mit Passwort und nur zum Lesen. Wenn Dejan darum bittet, die Freigabe oder eine Session für die Kollegen zu starten: nach `.docs/Freigabe.md` vorgehen. Dort stehen auch das Passwort und wie man prüft und beendet. + +Interne Dateien, die Kollegen nicht sehen sollen, gehören in einen Ordner mit Punkt am Anfang (`.docs/`). Alles andere im Hub ist über die Freigabe sichtbar. diff --git a/.docs/Freigabe.md b/.docs/Freigabe.md new file mode 100644 index 0000000..241f659 --- /dev/null +++ b/.docs/Freigabe.md @@ -0,0 +1,63 @@ +# Freigabe für Kollegen + +**Stand:** 19.10.2026. Das Dashboard lässt sich über einen Cloudflare-Tunnel für Kollegen freigeben, mit Passwort und nur zum Lesen. Diese Datei sieht von außen niemand: Die Freigabe liefert nichts aus, was mit einem Punkt beginnt. + +--- + +## Zugang + +- **Passwort:** `attiJia1GXxGeIKg`, der Name ist egal. +- Maßgeblich ist die Datei `.freigabe-passwort` (nicht in git). Wird sie gelöscht, erzeugt der nächste Start ein neues Passwort. Dann hier nachtragen. +- **Die Adresse ist bei jedem Start neu,** zum Beispiel `https://dock-texture-dna-reason.trycloudflare.com`. Kollegen brauchen also nach jedem Neustart den neuen Link. + +--- + +## Für Agents: Freigabe starten + +Wenn Dejan sagt „starte die Freigabe“, „Session für die Kollegen“ oder Ähnliches: + +1. **Läuft sie schon?** `curl -s 127.0.0.1:20241/quicktunnel`. Kommt ein `hostname` zurück, läuft sie. Dann nur Adresse und Passwort nennen, nichts neu starten. Ist Port 4330 belegt (`lsof -iTCP:4330 -sTCP:LISTEN`), aber kein Tunnel da, zuerst beenden (siehe unten). +2. **Starten:** `./freigabe.sh` im Hub-Ordner im Hintergrund laufen lassen. Achtung, der Ordnername endet mit einem Leerzeichen: `"/Users/dejancosic/Documents/GitHub/HiveGrid Marketing "`. +3. **Adresse holen:** ein paar Sekunden warten, dann `curl -s 127.0.0.1:20241/quicktunnel`. In der Ausgabe von `freigabe.sh` steht vorher schon „Requesting new quick Tunnel on trycloudflare.com...“. Das ist noch nicht die Adresse. +4. **Prüfen,** nach weiteren paar Sekunden, bis der neue Name auflöst: + - `curl -s -o /dev/null -w '%{http_code}' https:///` muss `401` sein + - `curl -s -o /dev/null -w '%{http_code}' -u x:$(cat .freigabe-passwort) https:///` muss `200` sein + - `.../.git/config` mit Passwort muss `404` sein +5. **Dejan Adresse und Passwort nennen.** + +**Wichtig:** Eine Freigabe, die ein Agent startet, endet mit dessen Sitzung. Soll sie länger laufen, startet Dejan selbst in einem Terminal: + +``` +cd "/Users/dejancosic/Documents/GitHub/HiveGrid Marketing " && ./freigabe.sh +``` + +**Beenden:** die Hintergrund-Aufgabe stoppen oder Ctrl+C im Terminal. Wenn etwas hängen bleibt: + +``` +pkill -f "cloudflared tunnel --no-autoupdate --url http://127.0.0.1:4330"; pkill -f freigabe.py +``` + +--- + +## Was gesperrt ist + +- **Ohne Passwort** alles (401). +- **Alles mit Punkt am Anfang** (404): `.git`, `.docs`, `.claude`, `.freigabe-passwort`. Interne Dateien, die Kollegen nicht sehen sollen, gehören deshalb in einen solchen Ordner, zum Beispiel hierher. +- **Ordnerlisten** (404). +- **Status setzen, Export, Öffnen** (403). Das Dashboard zeigt dann unten „In der Freigabe lässt sich nichts ändern.“ + +Alles andere im Hub ist für Kollegen sichtbar, auch Dokumente und Daten, die nicht in git stehen. + +## Was bei Kollegen nicht geht + +- PostGrid, das läuft nur auf Dejans Mac. +- Das Online-Deck und andere claude.ai-Links, die sind privat. + +--- + +## Technik + +- `freigabe.py`: derselbe Server wie `serve.py`, aber auf Port 4330, nur 127.0.0.1, mit Passwort und nur zum Lesen. +- `freigabe.sh`: startet `freigabe.py`, dazu `caffeinate` (der Mac schläft nicht ein, mit zugeklapptem Deckel trotzdem) und `cloudflared tunnel --url http://127.0.0.1:4330`. +- `cloudflared` ist über Homebrew installiert (19.10.2026, Version 2026.10.1). Ein Quick Tunnel braucht kein Konto, hat aber keine Garantie auf Erreichbarkeit. +- `127.0.0.1:20241` ist die Statusseite von `cloudflared`. Ist der Port belegt, nimmt es den nächsten bis 20245. diff --git a/.gitignore b/.gitignore index 6b42e27..efb0749 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ webinar/slides/.druck.html # Pakete zum Verschicken, lassen sich jederzeit neu bauen webinar/Paket für Noah/ webinar/Webinar-Entwurf.zip + +# Passwort der Freigabe für Kollegen (freigabe.py) +.freigabe-passwort diff --git a/Dashboard/stil.css b/Dashboard/stil.css index 084c8d4..d5b1b19 100644 --- a/Dashboard/stil.css +++ b/Dashboard/stil.css @@ -385,7 +385,10 @@ mark.fund { background: var(--gold); color: var(--tinte); padding: 0 2px; } } @media (max-width: 900px) { body { grid-template-columns: minmax(0, 1fr); } - .leiste { position: static; height: auto; overflow: visible; padding: 16px 12px 10px; border-right: 0; border-bottom: 1px solid var(--rand); } + /* Die Leiste wird zum Kopf und bleibt beim Scrollen oben. Nur das Logo + scrollt weg (-46px), damit der Kopf auf dem Handy wenig Platz nimmt. */ + .leiste { top: -46px; z-index: 15; height: auto; overflow: visible; padding: 16px 12px 10px; border-right: 0; border-bottom: 1px solid var(--rand); } + html { scroll-padding-top: 100px; } .marke { margin: 0 6px 10px; } .marke img { width: 100px; } .marke span { display: none; } diff --git a/freigabe.py b/freigabe.py new file mode 100644 index 0000000..477b456 --- /dev/null +++ b/freigabe.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +"""Freigabe des Marketing-Dashboards für Kollegen. + +Derselbe Server wie serve.py, aber für den Weg nach draußen über einen +Cloudflare-Tunnel. Gestartet wird alles zusammen mit ./freigabe.sh. + + - jede Anfrage braucht das Passwort, der Name ist egal + - nur lesen: kein Status setzen, kein Export, nichts öffnen + - nichts, was mit einem Punkt beginnt, also weder .git noch .DS_Store + - keine Ordnerlisten + +Das Passwort steht in .freigabe-passwort. Fehlt die Datei, wird beim ersten +Start eins erzeugt. Zum Wechseln die Datei löschen und neu starten. +Anleitung zum Starten, Prüfen und Beenden: .docs/Freigabe.md +""" + +import base64 +import hmac +import secrets +import sys +import urllib.parse + +import serve + +PORT = 4330 +PASSWORTDATEI = serve.HUB / ".freigabe-passwort" + + +def passwort(): + if PASSWORTDATEI.exists(): + return PASSWORTDATEI.read_text(encoding="utf-8").strip() + neu = secrets.token_urlsafe(12) + PASSWORTDATEI.write_text(neu + "\n", encoding="utf-8") + PASSWORTDATEI.chmod(0o600) + return neu + + +PASSWORT = passwort() + + +class Handler(serve.Handler): + def _erlaubt(self): + kopf = self.headers.get("Authorization", "") + if kopf.startswith("Basic "): + try: + _, _, pw = base64.b64decode(kopf[6:]).decode("utf-8").partition(":") + except Exception: + pw = "" + if hmac.compare_digest(pw.encode("utf-8"), PASSWORT.encode("utf-8")): + return True + self.send_response(401) + self.send_header("WWW-Authenticate", 'Basic realm="HiveGrid Marketing", charset="UTF-8"') + self.send_header("Content-Length", "0") + self.end_headers() + return False + + def _versteckt(self): + pfad = urllib.parse.unquote(urllib.parse.urlparse(self.path).path) + if any(t.startswith(".") for t in pfad.split("/") if t): + self.send_error(404) + return True + return False + + def do_GET(self): + if self._erlaubt() and not self._versteckt(): + super().do_GET() + + def do_HEAD(self): + if self._erlaubt() and not self._versteckt(): + super().do_HEAD() + + def do_POST(self): + # Das Dashboard zeigt "fehler" unten als Meldung an. + if self._erlaubt(): + self._json(403, {"fehler": "In der Freigabe lässt sich nichts ändern."}) + + def list_directory(self, path): + # Ordner ohne index.html. Eine Liste würde auch versteckte Dateien und + # alles zeigen, was nicht für die Kollegen gedacht ist. + self.send_error(404) + return None + + +if __name__ == "__main__": + try: + server = serve.Server(("127.0.0.1", PORT), Handler) + except OSError: + print("Port %d ist belegt. Läuft die Freigabe schon?" % PORT, flush=True) + sys.exit(1) + print("Freigabe läuft auf http://127.0.0.1:%d/" % PORT, flush=True) + print("Passwort für die Kollegen: %s (Name egal)" % PASSWORT, flush=True) + with server: + try: + server.serve_forever() + except KeyboardInterrupt: + pass diff --git a/freigabe.sh b/freigabe.sh new file mode 100755 index 0000000..b3a4468 --- /dev/null +++ b/freigabe.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# Gibt das Dashboard für Kollegen frei: mit Passwort, nur lesen, über einen +# Cloudflare-Tunnel ohne Konto. Die Adresse steht weiter unten im Kasten +# (https://....trycloudflare.com) und ist nach jedem Start eine neue. +# Läuft, solange dieses Fenster offen ist. Beenden mit Ctrl+C. +cd "$(dirname "$0")" || exit 1 +command -v cloudflared >/dev/null || { echo "cloudflared fehlt: brew install cloudflared"; exit 1; } + +python3 freigabe.py & +SERVER=$! +trap 'kill $SERVER 2>/dev/null' EXIT INT TERM +sleep 1 +kill -0 $SERVER 2>/dev/null || exit 1 + +# Der Mac schläft nicht ein, solange die Freigabe läuft. +caffeinate -is -w $SERVER & + +cloudflared tunnel --no-autoupdate --url http://127.0.0.1:4330