/* ===================================================================== Die eigene Adresse der Modi-App (10.09.2026) crew.dogfather-universe.com WARUM EINE EIGENE ADRESSE. Derselbe Grund, aus dem der Creator Workspace am 06.09.2026 umgezogen ist (siehe workspace-umzug.js): Auf einem Ursprung laesst sich genau EINE App installieren. Zwei Manifeste mit verschachtelten Bereichen sind laut w3c/manifest Nr. 1180 "strongly not recommended", und Chrome haelt sich daran -- der zweite Eintrag erscheint dann nur als Verknuepfung, nie als eigene App. Filipe will fuer die Modis ausdruecklich eine eigene App: "ich will dass es eine eigene app wird." WAS SICH NICHT AENDERT: der Pfad /workspace/, der Dienst (4100), die Datenbank, der Code. Getrennt wird ueber den HOSTNAMEN, nicht ueber einen zweiten Prozess. Genau so machen es Hauptseite und Workspace schon heute. --------------------------------------------------------------------- DREI FALLEN, DIE MAN EINER BEDINGUNG NICHT ANSIEHT --------------------------------------------------------------------- 1. EIN MUSTER STATT EINER LISTE WAERE TOEDLICH. /dogfather-universe\.com$/ passt auch auf workspace.dogfather-universe.com -- und wuerde damit genau die Adresse abschalten, die man schuetzen will. Deshalb hier zwei feste Mengen und kein einziges Muster. (Dieselbe Ueberlegung steht schon in workspace-umzug.js; sie hat dort einen Ausfall verhindert und gilt hier unveraendert.) 2. "ALLES AUSSER crew." IST NICHT DASSELBE WIE "DIE ALTEN ADRESSEN". Der naheliegende Satz waere: "Ein Modi darf ueberall rein, nur nicht auf einer Adresse, die nicht crew heisst." Damit waeren localhost, 127.0.0.1 und jede Pruefadresse eingeschlossen -- und saemtliche Modi-Pruefungen wuerden ab sofort messen, dass ein Modi nirgends hereinkommt, ohne dass irgendwo etwas rot wird. Ein gruener Lauf, der nichts mehr prueft, ist schlimmer als ein roter. Deshalb ist OHNE_MODI_HOSTS eine AUFZAEHLUNG der drei echten Adressen. Wer eine vierte anlegt, traegt sie hier nach -- und pruef-crew-adresse.mjs sagt es ihm, wenn er es vergisst. 3. "FAENGT AN MIT /workspace" TRIFFT AUCH /workspaceXYZ. Beim Workspace-Umzug waere das beinahe passiert. Hier gilt es genauso, deshalb dieselbe Schreibweise: genau "/workspace" oder alles unter "/workspace/", sonst nichts. --------------------------------------------------------------------- WARUM DIE ALTE ADRESSE FUER MODIS ZUGEHT --------------------------------------------------------------------- Ein Modi, der sich weiterhin auf workspace.dogfather-universe.com anmelden koennte, haette zwei Anmeldungen, zwei Sitzungen und zwei Apps auf dem Startbildschirm -- und der verborgene Zugang haette damit eine zweite Spur genau dort, wo alle anderen arbeiten. Er bekommt deshalb auf der alten Adresse KEINE Sitzung, sondern den Hinweis auf die neue. DASS DIESER HINWEIS DIE ADRESSE NENNT, IST KEIN LECK: Er erscheint nur nach Eingabe eines gueltigen Modi-Codes. Wer den hat, ist Modi. Fuer jeden anderen -- auch fuer jeden Manager mit gueltigem eigenen Code -- veraendert sich an der alten Adresse ueberhaupt nichts. --------------------------------------------------------------------- UND WARUM AUF DER NEUEN ADRESSE NUR MODIS HEREINKOMMEN --------------------------------------------------------------------- Sonst waere crew. eine zweite, vollwertige Tuer in den Workspace -- und die erste Person, die sie zufaellig errät und ihren eigenen Code eintippt, wuesste sofort, dass es hier noch etwas gibt. Ein fremder Code bekommt dort deshalb dieselbe Antwort wie ein erfundener: die Zugangswand sieht aus wie immer, und der Code stimmt nicht. ===================================================================== */ export const CREW_ADRESSE = "https://crew.dogfather-universe.com"; /** Die Adresse der Modi-App. Feste Menge, kein Muster -- Falle 1. */ const CREW_HOSTS = new Set(["crew.dogfather-universe.com"]); /** Die echten Adressen, auf denen ein Modi nichts verloren hat. * Aufzaehlung und ausdruecklich NICHT "alles ausser crew" -- Falle 2. */ const OHNE_MODI_HOSTS = new Set([ "dogfather-universe.com", "www.dogfather-universe.com", "workspace.dogfather-universe.com", ]); /** Nur der Name, ohne Port und in Kleinschreibung. * Hostnamen sind laut RFC 4343 gross/klein-unempfindlich; ein Browser * darf "Workspace.Dogfather-Universe.com" schicken. */ function nurHost(hostKopfzeile) { return String(hostKopfzeile || "").toLowerCase().split(":")[0]; } /** Kommt die Anfrage ueber die Adresse der Modi-App? */ export function istCrewAdresse(hostKopfzeile) { return CREW_HOSTS.has(nurHost(hostKopfzeile)); } /** Ist das eine der Adressen, auf denen Modis nicht mehr arbeiten? */ export function istOhneModiAdresse(hostKopfzeile) { return OHNE_MODI_HOSTS.has(nurHost(hostKopfzeile)); } /** Gehoert dieser Pfad zum Workspace-Teil? Genau "/workspace" oder * alles darunter -- aber NICHT /workspaceXYZ (Falle 3). */ export function istWorkspacePfad(pfad) { const p = String(pfad || ""); return p === "/workspace" || p.startsWith("/workspace/"); } /** * Darf diese Person auf dieser Adresse angemeldet sein? * * Die eine Regel, aus der beide Richtungen folgen. Sie steht hier als * eigene Funktion, damit sie ohne laufenden Server pruefbar ist -- und * damit sie an GENAU EINER Stelle steht: sitzungLesen() in * workspace.js. Jedes der 26 Fachmodule geht dort durch. * * @param {string} rolle Rolle der angemeldeten Person * @param {string} hostKopfzeile Inhalt des Host-Kopffeldes */ export function sitzungPasstZurAdresse(rolle, hostKopfzeile) { const modi = rolle === "modi"; if (istCrewAdresse(hostKopfzeile)) return modi; // crew: nur Modis if (istOhneModiAdresse(hostKopfzeile)) return !modi; // echte alte Adressen: keine Modis return true; // localhost, Pruefadressen: unberuehrt } /** * Express-Zwischenschritt fuer die Adresse der Modi-App. * * Er macht zwei Dinge und ausdruecklich nichts mit Rechten -- die * liegen in sitzungLesen(): * * 1. NICHT INDIZIEREN. Die Adresse taucht heute in keinem oeffentlichen * Zertifikatsprotokoll auf (nachgemessen am 10.09.2026: crt.sh * kennt fuer dogfather-universe.com nur den Platzhalter-Eintrag). * Eine Suchmaschine waere der zweite Weg, sie doch zu finden -- * der Kopf schliesst ihn. Er steht hier und nicht nur als * im HTML, weil er dann auch fuer Bilder, Manifest und * jede Antwort ohne HTML gilt. * * 2. NUR DER WORKSPACE. Auf crew. gibt es die Hauptseite nicht -- * sonst laege die komplette Dogfather-Website ein zweites Mal * unter einer zweiten Adresse (doppelter Inhalt, und ein Weg, * die Adresse ueber eine Suchmaschine zu finden). Alles ausserhalb * von /workspace und /assets geht zur Zugangswand. * * Caddy tut Punkt 2 bereits mit derselben Weiche. Dass es hier ein * zweites Mal steht, ist Absicht: Eine Schranke, die nur in einer * Datei ausserhalb des Projekts existiert, faellt beim naechsten * Serverumbau lautlos weg. */ export function crewWeiche(req, res, next) { if (!istCrewAdresse(req.get("host"))) { /* DIE ANDERE RICHTUNG -- und sie war ein echtes Loch. Die zweite Zugangswand liegt als Datei im selben Ordner wie alles andere und wird von express.static ausgeliefert. Ohne diese Zeile kann sie JEDER unter ihrem Dateinamen aufrufen, auch auf workspace.dogfather-universe.com -- und saehe dort eine Anmeldeseite, die es dort gar nicht geben soll. Gefunden hat das nicht ein Gedanke, sondern eine Pruefung: Der Wortleck-Test durchsucht ALLE ausgelieferten Dateien, und dass er diese eine ueberhaupt las, war die Antwort auf eine Frage, die ich mir nicht gestellt hatte -- naemlich wer sie sonst noch abrufen kann. 404 UND KEINE WEITERLEITUNG: "Gibt es nicht" ist die Antwort, die nichts verraet. Eine Weiterleitung wuerde sagen, dass es die Datei gibt, nur woanders. NUR AUF DEN DREI ECHTEN ADRESSEN, nicht "ueberall ausser crew": Sonst waere sie auch auf localhost gesperrt, und die Pruefung, die die Wand im Browser ansieht, koennte sie nicht mehr oeffnen -- sie wuerde gruen bleiben und nichts mehr messen. */ if (istOhneModiAdresse(req.get("host")) && req.path.toLowerCase().replace(/\/{2,}/g, "/") === "/workspace/crew-index.html") { return res.status(404).type("html").send("Nicht gefunden."); } return next(); } res.setHeader("X-Robots-Tag", "noindex, nofollow"); /* DAS MANIFEST MACHT DIE APP (10.09.2026). Beide Adressen liefern dieselben HTML-Dateien aus -- in jeder steht . Auf der Modi-Adresse soll dahinter aber ein anderes Manifest stehen: eigener Name ("Team Dogi"), eigenes Symbol. Sonst hiesse die App auf dem Startbildschirm eines Modis "Creator Workspace" und traege das Zeichen mit der Chili -- die zu Spicy Media gehoert, nicht zu ihnen. WARUM DIE ADRESSE UMGEBOGEN WIRD, STATT IN 30 HTML-DATEIEN EINE ZWEITE ZEILE ZU SETZEN: Eine zweite Zeile muesste jemand bei jeder neuen Seite mitschreiben, und wer sie vergisst, bekommt eine Seite, die still zur falschen App gehoert. Hier steht es einmal. ZWISCHENSPEICHER: Cloudflare nimmt den Hostnamen in den Schluessel auf, die beiden Antworten koennen sich also nicht vermischen. Der Browser ohnehin nicht -- fuer ihn sind es zwei Ursprunge. */ if (req.path === "/workspace/app.webmanifest") { req.url = "/workspace/crew.webmanifest"; return next(); } /* DIE ZUGANGSWAND GEHOERT DOGI UND DEN MODIS (10.09.2026). Filipe: "alles soll auf dogfather und die modis perfektionniert werden auf der neuen modi seite." Bis dahin stand hier die gewohnte Wand: Spicy-Media-Logo, "Creator Workspace", fuenf Rollenkacheln -- fuer einen Modi war davon nichts richtig. Jetzt liefert crew. eine eigene Seite mit eigener Buehne, eigenem Namen und ohne Kachelreihe. DAS KEHRT EINE FRUEHERE ENTSCHEIDUNG UM, und das gehoert hierhergeschrieben: Vorher war die Wand absichtlich identisch -- wer die Adresse errat, sollte etwas Vertrautes sehen und nichts ueber Modis erfahren. Filipe hat anders entschieden. Der Tausch ist damit bewusst: Ein Ratender liest jetzt "Team Dogi". Alles andere bleibt, wie es war -- sein Code funktioniert dort nicht. ZWEI ADRESSEN, EINE DATEI: `/workspace/` und `/workspace/index.html` fuehren beide zur Wand, also muessen beide umgebogen werden. Die zweite zu vergessen waere nicht aufgefallen, denn im Alltag tippt sie niemand. */ if (req.path === "/workspace/" || req.path === "/workspace/index.html") { req.url = "/workspace/crew-index.html"; return next(); } if (istWorkspacePfad(req.path) || req.path.startsWith("/assets/")) return next(); return res.redirect(302, "/workspace/"); }