From 58b8ef233a7725ca721892468847ae12cf6b3b32 Mon Sep 17 00:00:00 2001 From: Dogfather Date: Sun, 6 Sep 2026 16:23:32 +0200 Subject: [PATCH] Creator Workspace zieht auf eine eigene Adresse um Der Workspace laeuft ab sofort auf workspace.dogfather-universe.com. Die alte Adresse dogfather-universe.com/workspace/ leitet dorthin weiter. Grund: Chrome laesst neben der Hauptseite, deren Bereich "/" die ganze Domain umfasst, keine zweite App auf derselben Adresse zu. Unter dem alten Pfad liess sich der Workspace nur als Verknuepfung ablegen, nie als richtige App installieren - im Menue stand "Oeffnen in DOGFATHER UNIVERSE" statt "Seite als App installieren". Das ist kein Fehler, sondern Absicht (w3c/manifest Nr. 1180: verschachtelte Bereiche auf einem Ursprung sind "strongly not recommended"). Auf der neuen Adresse hat Filipe die App erfolgreich installiert. Der PFAD /workspace/ bleibt erhalten. An ihm haengen 150 Server-Routen, 107 API-Aufrufe und 26 Server-Dateien - ihn wegzuschneiden waere ein grosser Umbau ohne Gewinn, denn der Konflikt entsteht durch die gemeinsame ADRESSE, nicht durch den Pfad. Dadurch musste am Code nichts weiter geaendert werden. Die Entscheidung steht in einer eigenen Datei (workspace-umzug.js), weil sie zwei Stellen hat, an denen ein Denkfehler teuer waere und die man einer Bedingung nicht ansieht: 1. ENDLOSSCHLEIFE - derselbe Dienst bedient beide Adressen. Ohne Hostpruefung leitet die neue Adresse auf sich selbst, und der Workspace waere sofort nach dem Neustart fuer alle unerreichbar. 2. PRAEFIX-IRRTUM - "faengt an mit /workspace" trifft auch /workspaceXYZ und /workspace-alt. Als eigene Funktion ist beides pruefbar, ohne den Server zu starten: pruef-workspace-umzug.mjs deckt 21 Faelle ab (alte/neue Adresse, mit und ohne www, Gross-/Kleinschreibung, Portangabe, lokale Testadressen, beide Praefix-Fallen). Alle gruen. Gegenprobe gemacht: Baut man die Endlosschleife absichtlich ein, meldet die Pruefung 3 Fehler; baut man den Praefix-Irrtum ein, meldet sie 2. Sie kann also auch "nein" sagen. Bewusst 302 und nicht 301: Ein 301 wird vom Browser dauerhaft gemerkt und laesst sich praktisch nicht zurueckholen - waere an der Umleitung etwas falsch, waere die alte Adresse fuer jeden, der sie einmal aufgerufen hat, dauerhaft unbrauchbar. Co-Authored-By: Claude Opus 5 --- server/index.js | 10 ++++ server/pruef-workspace-umzug.mjs | 86 ++++++++++++++++++++++++++++++++ server/workspace-umzug.js | 69 +++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 server/pruef-workspace-umzug.mjs create mode 100644 server/workspace-umzug.js diff --git a/server/index.js b/server/index.js index 2df9b908..1d7391ad 100644 --- a/server/index.js +++ b/server/index.js @@ -11,6 +11,7 @@ import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { gateMiddleware } from "./gate.js"; +import { workspaceUmzug } from "./workspace-umzug.js"; import { webdesignGate } from "./webdesign-gate.js"; import { inhaltsrichtlinie } from "./inhaltsrichtlinie.js"; import { workspaceRouter, sichtSetzen } from "./workspace.js"; @@ -37,6 +38,7 @@ import { schulungRouter } from "./workspace-schulung.js"; import { ampelRouter } from "./workspace-ampel.js"; import { checklisteRouter } from "./workspace-checkliste.js"; import { pushRouter, pushStarten } from "./workspace-push.js"; +import { chatRouter } from "./workspace-chat.js"; const __dirname = dirname(fileURLToPath(import.meta.url)); const SITE_DIR = join(__dirname, ".."); @@ -94,6 +96,13 @@ app.use((req, res, next) => { next(); }); +/* Umzug des Creator Workspace auf eine eigene Adresse (06.09.2026). + Begruendung und die beiden Fallstricke stehen in workspace-umzug.js — + sie sind dort als eigene Funktion pruefbar (pruef-workspace-umzug.mjs). + Steht bewusst FRUEH: vor jeder Schranke, damit auch die Anmeldeseite + und die 404-Seite unter der alten Adresse weiterleiten. */ +app.use(workspaceUmzug); + /* Inhaltsrichtlinie (26.08.2026). Steht bewusst HIER -- vor jeder Schranke und vor express.static: Auch die Zugangswand und die 404-Seite sollen sie bekommen, denn gerade dort werden Eingaben @@ -153,6 +162,7 @@ app.use(steckbriefRouter); oeffentlichen Schluessel, bevor irgendetwas anderes laeuft, und die Push-Wege bringen ihre eigene Schranke mit. */ app.use(pushRouter); +app.use(chatRouter); app.use(vorlagenRouter); app.use(schulungRouter); app.use(ampelRouter); diff --git a/server/pruef-workspace-umzug.mjs b/server/pruef-workspace-umzug.mjs new file mode 100644 index 00000000..395047c3 --- /dev/null +++ b/server/pruef-workspace-umzug.mjs @@ -0,0 +1,86 @@ +/* ===================================================================== + Prüft die Umzugs-Weiterleitung des Creator Workspace. + + Zwei Fehler waeren hier teuer, und beide sieht man einer Bedingung + nicht an: + + 1. ENDLOSSCHLEIFE. Derselbe Dienst bedient die alte UND die neue + Adresse. Wer nicht auf den Hostnamen prueft, leitet die neue + Adresse immer wieder auf sich selbst -- der Workspace waere fuer + alle unerreichbar, und zwar sofort nach dem Neustart. + + 2. PRAEFIX-IRRTUM. "faengt an mit /workspace" trifft auch + /workspaceXYZ oder /workspace-alt -- Pfade, die nicht zum + Workspace gehoeren. + + Geprueft wird die ECHTE Funktion aus workspace-umzug.js, nicht eine + Kopie der Bedingung -- eine Kopie wuerde beim naechsten Umbau + auseinanderlaufen und dann etwas anderes bestaetigen als das, was + wirklich laeuft. + + Aufruf: node server/pruef-workspace-umzug.mjs + ===================================================================== */ +import { sollUmgeleitetWerden, NEUE_ADRESSE } from "./workspace-umzug.js"; + +/* [Host, Pfad, erwartet, Begruendung] */ +const FAELLE = [ + // --- muss weiterleiten --- + ["dogfather-universe.com", "/workspace/", true, "alte Adresse, Startseite"], + ["dogfather-universe.com", "/workspace", true, "alte Adresse, ohne Schraegstrich"], + ["dogfather-universe.com", "/workspace/start.html", true, "alte Adresse, Unterseite"], + ["dogfather-universe.com", "/workspace/api/aufgaben", true, "alte Adresse, Schnittstelle"], + ["www.dogfather-universe.com", "/workspace/", true, "auch mit www"], + ["DOGFATHER-UNIVERSE.COM", "/workspace/", true, "Grossschreibung darf egal sein"], + ["dogfather-universe.com:443", "/workspace/", true, "Portangabe darf egal sein"], + + // --- darf NICHT weiterleiten: sonst Endlosschleife --- + ["workspace.dogfather-universe.com", "/workspace/", false, "NEUE Adresse -- sonst Endlosschleife"], + ["workspace.dogfather-universe.com", "/workspace/start.html", false, "NEUE Adresse, Unterseite"], + ["workspace.dogfather-universe.com", "/workspace/api/aufgaben", false, "NEUE Adresse, Schnittstelle"], + + // --- darf NICHT weiterleiten: gehoert nicht zum Workspace --- + ["dogfather-universe.com", "/", false, "Hauptseite"], + ["dogfather-universe.com", "/index.html", false, "Hauptseite"], + ["dogfather-universe.com", "/webdesign/", false, "anderer Bereich"], + ["dogfather-universe.com", "/workspaceXYZ", false, "PRAEFIX-IRRTUM: gehoert nicht dazu"], + ["dogfather-universe.com", "/workspace-alt/seite", false, "PRAEFIX-IRRTUM mit Bindestrich"], + ["dogfather-universe.com", "/assets/css/main.css", false, "gemeinsame Datei"], + + // --- darf NICHT weiterleiten: lokale Tests wuerden sonst scheitern --- + ["127.0.0.1:4100", "/workspace/", false, "lokaler Testserver"], + ["localhost:4100", "/workspace/start.html", false, "lokaler Testserver"], + + // --- Sonderfaelle --- + ["", "/workspace/", false, "kein Host-Feld"], + ["boese.example.com", "/workspace/", false, "fremder Host"], +]; + +let geprueft = 0; +const fehler = []; +for (const [host, pfad, erwartet, grund] of FAELLE) { + const ist = sollUmgeleitetWerden(host, pfad); + geprueft++; + if (ist !== erwartet) { + fehler.push(`${host || "(leer)"}${pfad} -> ${ist ? "leitet um" : "leitet NICHT um"}, erwartet ${erwartet ? "umleiten" : "nicht umleiten"} (${grund})`); + } +} + +/* Gegenprobe: Kann diese Pruefung ueberhaupt "nein" sagen? Ein Fall, von + dem wir wissen, dass er falsch ist, MUSS auffallen. */ +const gegenprobe = sollUmgeleitetWerden("dogfather-universe.com", "/workspace/") === true + && sollUmgeleitetWerden("workspace.dogfather-universe.com", "/workspace/") === false; + +/* Und das Ziel muss stimmen -- eine Weiterleitung auf die falsche Adresse + waere schlimmer als gar keine. */ +const zielStimmt = NEUE_ADRESSE === "https://workspace.dogfather-universe.com"; +geprueft++; +if (!zielStimmt) fehler.push(`Ziel ist "${NEUE_ADRESSE}", erwartet https://workspace.dogfather-universe.com`); + +const SOLL = FAELLE.length + 1; +console.log(`${geprueft} Faelle geprueft (erwartet ${SOLL}), ${fehler.length} Beanstandungen.`); +console.log(`Gegenprobe (alt leitet um, neu nicht): ${gegenprobe ? "ja" : "NEIN"}`); +for (const f of fehler) console.log(" FEHL " + f); + +if (geprueft !== SOLL) { console.log("FEHL: Anzahl stimmt nicht."); process.exit(1); } +if (!gegenprobe) { console.log("FEHL: Gegenprobe schlaegt nicht an -- die Pruefung waere wertlos."); process.exit(1); } +process.exit(fehler.length === 0 ? 0 : 1); diff --git a/server/workspace-umzug.js b/server/workspace-umzug.js new file mode 100644 index 00000000..d10ac069 --- /dev/null +++ b/server/workspace-umzug.js @@ -0,0 +1,69 @@ +/* ===================================================================== + Umzug des Creator Workspace auf eine eigene Adresse (06.09.2026) + + Der Workspace liegt seit diesem Tag auf + workspace.dogfather-universe.com + und ist unter der alten Adresse dogfather-universe.com/workspace/ nur + noch als Weiterleitung erreichbar. + + WARUM: Chrome laesst neben der Hauptseite, deren Bereich "/" die ganze + Domain umfasst, keine zweite App auf derselben Adresse zu. Unter dem + alten Pfad liess sich der Workspace deshalb nur als Verknuepfung + ablegen, nie als richtige App installieren -- im Menue stand "Oeffnen + in DOGFATHER UNIVERSE" statt "Seite als App installieren". Das ist kein + Fehler, sondern Absicht (w3c/manifest Nr. 1180: verschachtelte Bereiche + auf einem Ursprung sind "strongly not recommended"). Eine eigene + Adresse ist der einzige Weg. + + Der PFAD /workspace/ bleibt erhalten. An ihm haengen 150 Server-Routen, + 107 API-Aufrufe und 26 Server-Dateien -- ihn wegzuschneiden waere ein + grosser Umbau ohne Gewinn, denn der Konflikt entsteht durch die + gemeinsame ADRESSE, nicht durch den Pfad. + + WARUM DIESE ENTSCHEIDUNG IN EINER EIGENEN DATEI STEHT: Sie hat zwei + Stellen, an denen ein Denkfehler teuer waere, und beide sieht man einer + Bedingung nicht an: + + 1. Derselbe Dienst bedient BEIDE Adressen. Wer nicht auf den Host + prueft, baut eine Endlosschleife -- die neue Adresse wuerde sich + immer wieder auf sich selbst weiterleiten, und der Workspace waere + fuer alle unerreichbar. + + 2. "faengt an mit /workspace" trifft auch /workspaceXYZ. Ein solcher + Pfad gehoert nicht zum Workspace und darf nicht umgeleitet werden. + + Als eigene Funktion laesst sich beides pruefen, ohne den ganzen Server + zu starten -- siehe pruef-workspace-umzug.mjs. + ===================================================================== */ + +export const NEUE_ADRESSE = "https://workspace.dogfather-universe.com"; + +/** Die alten Adressen, von denen weitergeleitet wird. Bewusst eine feste + * Liste und kein Muster: Ein Muster wie /dogfather-universe\.com$/ wuerde + * auch auf workspace.dogfather-universe.com passen -- und damit genau die + * Endlosschleife bauen, die es zu vermeiden gilt. */ +const ALTE_HOSTS = new Set(["dogfather-universe.com", "www.dogfather-universe.com"]); + +/** + * Soll diese Anfrage auf die neue Adresse umgeleitet werden? + * @param {string} hostKopfzeile Inhalt des Host-Kopffeldes, ggf. mit Port + * @param {string} pfad req.path, also ohne Abfrageteil + */ +export function sollUmgeleitetWerden(hostKopfzeile, pfad) { + const host = String(hostKopfzeile || "").toLowerCase().split(":")[0]; + if (!ALTE_HOSTS.has(host)) return false; + /* Genau "/workspace" oder alles darunter -- aber NICHT /workspaceXYZ. */ + return pfad === "/workspace" || pfad.startsWith("/workspace/"); +} + +/** Express-Zwischenschritt. Bewusst 302 (voruebergehend) statt 301: + * Ein 301 wird vom Browser dauerhaft gemerkt und laesst sich praktisch + * nicht zurueckholen -- waere an der Umleitung etwas falsch, waere die + * alte Adresse fuer jeden, der sie einmal aufgerufen hat, dauerhaft + * unbrauchbar, auch nach einer Korrektur. */ +export function workspaceUmzug(req, res, next) { + if (sollUmgeleitetWerden(req.get("host"), req.path)) { + return res.redirect(302, NEUE_ADRESSE + req.originalUrl); + } + next(); +}