/* ===================================================================== STEHT DAS WORT IN EINER DATEI, DIE JEDER BEKOMMT? Der verborgene Zugang haelt genau so lange, wie niemand den Rollennamen im Quelltext findet. Alles unter workspace/ wird an JEDEN ausgeliefert, der die Seite oeffnet -- an jeden Manager, jeden Scout, jeden Creator. Ein einziges `if (ich.rolle === '...')` dort, und der ganze Aufwand darueber ist umsonst. WARUM ES DIESE PRUEFUNG GIBT: Weil genau das passiert ist. Am 10.09.2026 habe ich beim Bau der Kategorien SECHS Vergleiche und VIER Kommentare mit dem Rollennamen in zwei ausgelieferte Dateien geschrieben -- waehrend ich an anderer Stelle penibel darauf achtete, ihn herauszuhalten. Gefunden habe ich es durch Nachsehen, nicht durch Nachdenken. Nachdenken hatte ich vorher schon getan. Die Regel ist deshalb ab jetzt keine Absicht mehr, sondern ein Werkzeug: Wer den Namen dort hineinschreibt, bekommt einen roten Lauf, keinen erhobenen Zeigefinger im Kommentar. NICHT BETROFFEN ist die oeffentliche Seite (team-modis.html und Verwandte). Dort steht das Modi-Team seit jeher offen -- das ist gewollt. Verborgen ist nicht das TEAM, sondern dass es einen eigenen Zugang zum Workspace hat. ===================================================================== */ import { readdirSync, readFileSync, statSync } from "node:fs"; import { join, dirname, extname, relative } from "node:path"; import { fileURLToPath } from "node:url"; const HIER = dirname(fileURLToPath(import.meta.url)); const ORDNER = join(HIER, "..", "workspace"); let fehler = 0; let geprueft = 0; const ok = (b, t) => { geprueft++; console.log((b ? " ok " : " FEHL ") + t); if (!b) fehler++; }; /* Alles, was der Server aus diesem Ordner herausgibt. Bewusst eine Liste von Endungen und kein "alles ausser": Kaeme morgen eine neue Art Datei dazu, faellt sie hier auf, statt stillschweigend ungeprueft zu bleiben. */ const ENDUNGEN = new Set([".js", ".html", ".css", ".webmanifest", ".json", ".svg", ".txt"]); /* `\bmodi\b` und nicht `modi`: "modifiziert", "Modul" und "Modus" sollen nicht anschlagen -- eine Pruefung, die staendig Fehlalarm gibt, wird abgeschaltet, und dann faengt sie auch den echten Fall nicht mehr. Nachgemessen: Keines der drei Woerter passt auf dieses Muster, weil nach "modi" dort ein Buchstabe folgt. */ const MUSTER = /\bmodi\b/i; function dateien(pfad, aus = []) { for (const name of readdirSync(pfad)) { const voll = join(pfad, name); if (statSync(voll).isDirectory()) { dateien(voll, aus); continue; } if (ENDUNGEN.has(extname(name).toLowerCase())) aus.push(voll); } return aus; } console.log("\n=== Der Rollenname darf in keiner ausgelieferten Datei stehen ===\n"); /* ===================================================================== DIE EINE DATEI, DIE DEN NAMEN TRAGEN DARF (10.09.2026) crew-index.html ist die Zugangswand von crew.dogfather-universe.com. Filipe: "3 rollen. dogfather. rechte hand und modis." Auf dieser Wand STEHEN die drei Namen -- als Kacheln, sichtbar, so gewollt. WARUM DAS KEIN WIDERSPRUCH ZUR REGEL IST: Die Regel schuetzt nicht den Namen, sondern die Tatsache, dass es einen eigenen Zugang zum WORKSPACE gibt. Diese Datei wird ausserhalb von crew. ueberhaupt nicht ausgeliefert -- der Server antwortet dort mit "gibt es nicht". UND DAS IST DIE BEDINGUNG DER AUSNAHME, nicht ihre Begruendung: Sie gilt nur, solange jene Sperre wirklich haelt. Gemessen wird das nicht hier, sondern in pruef-crew-adresse.mjs ("die zweite Wand gibt es dort nicht", drei Adressen plus doppelter Schraegstrich). Faellt jene Pruefung, ist diese Ausnahme ungueltig -- deshalb steht der Verweis hier und nicht nur in einem Kommentar irgendwo. AUSDRUECKLICH EINE EINZELNE DATEI und kein Muster wie "crew-*": Sonst waere die naechste crew-Datei stillschweigend mit ausgenommen, und niemand haette entschieden, ob sie es sein darf. */ const AUSGENOMMEN = new Set(["crew-index.html"]); const alle = dateien(ORDNER); /* DIE ZAHL GEHOERT IN DIE BEDINGUNG. Faende die Suche keine einzige Datei -- verschobener Ordner, andere Endungen --, waere unten alles gruen, ohne dass irgendetwas angesehen wurde. Genau diese Sorte gruener Haken ist im Haus schon zweimal aufgefallen. */ ok(alle.length >= 30, `${alle.length} ausgelieferte Dateien durchsucht`); const treffer = []; let ausgenommen = 0; for (const datei of alle) { if (AUSGENOMMEN.has(relative(ORDNER, datei))) { ausgenommen++; continue; } const text = readFileSync(datei, "utf8"); const zeilen = text.split("\n"); for (let i = 0; i < zeilen.length; i++) { if (MUSTER.test(zeilen[i])) { treffer.push(`${relative(ORDNER, datei)}:${i + 1} ${zeilen[i].trim().slice(0, 70)}`); } } } ok(treffer.length === 0, treffer.length ? `${treffer.length} Fundstelle(n) -- der verborgene Zugang waere damit auffindbar:\n ` + treffer.slice(0, 12).join("\n ") : "keine einzige Fundstelle"); /* DIE AUSNAHME MUSS AUCH WIRKLICH GEBRAUCHT WERDEN. Waere crew-index.html eines Tages umbenannt oder geloescht, stuende hier eine Ausnahme fuer eine Datei, die es nicht gibt -- und beim naechsten Umbau wuerde jemand annehmen, sie decke etwas ab. Eine Ausnahme, die ins Leere zeigt, ist schlimmer als keine: Sie sieht aus wie ein Schutz. */ ok(ausgenommen === AUSGENOMMEN.size, `${ausgenommen} von ${AUSGENOMMEN.size} ausgenommenen Dateien gibt es wirklich`); /* ---------- Gegenprobe ------------------------------------------------ Findet dieselbe Suche den Namen ueberhaupt, wenn er dasteht? Ohne diesen Schritt bewiese der Haken oben nichts: Er waere auch gruen, wenn das Muster kaputt oder die Dateiliste leer waere. Auf einem Text im Speicher, nicht auf einer echten Datei -- eine Pruefung, die zum Beweisen etwas anlegt, hinterlaesst irgendwann etwas. */ console.log("\n=== Gegenprobe: schlaegt die Suche ueberhaupt an? ===\n"); { const probe = " if (ich.rolle === 'modi') { ziel.hidden = true; return; }"; ok(MUSTER.test(probe), "eine eingebaute Fundstelle wird erkannt"); /* Und die drei Woerter, die NICHT anschlagen duerfen -- sonst waere die Pruefung nach dem ersten Fehlalarm abgeschaltet. */ const harmlos = ["const modifiziert = true;", "/* Modul */", "prefers-reduced-motion", "let modus = 'hell';"]; ok(harmlos.every((z) => !MUSTER.test(z)), `und "modifiziert", "Modul", "motion", "Modus" schlagen nicht an`); } console.log(`\n${fehler ? "FEHLGESCHLAGEN" : "BESTANDEN"} -- ${geprueft} geprueft, ${fehler} Fehler`); process.exit(fehler ? 1 : 0);