diff --git a/server/pruef-bremse.mjs b/server/pruef-bremse.mjs index 0e12b898..11b8d49e 100644 --- a/server/pruef-bremse.mjs +++ b/server/pruef-bremse.mjs @@ -107,7 +107,7 @@ async function anmelden(kachel, code) { return (a.headers.getSetCookie?.() || []).map((z) => z.split(";")[0]).join("; "); } const dogi = await anmelden("admin", "CODE-DOGI-0001"); -const ruhig = await anmelden("creator", "CODE-RUHIG-0001"); +const ruhig = await anmelden("modi", "CODE-RUHIG-0001"); const kopf = (keks) => ({ "Content-Type": "application/json", cookie: keks, origin: BASIS }); async function schreiben(keks, bereich, titel, extra = {}) { diff --git a/server/pruef-crew-adresse.mjs b/server/pruef-crew-adresse.mjs index 6f8cfbf1..22115439 100644 --- a/server/pruef-crew-adresse.mjs +++ b/server/pruef-crew-adresse.mjs @@ -201,11 +201,20 @@ try { zielModi = JSON.parse(modiAufCrew.text); } catch { /* bleibt leer */ } ok(zielModi.weiter === "/workspace/start.html", "crew.: er landet auf seiner Startseite"); ok(modiAufCrew.keks.includes("dfw_sitzung"), "crew.: er bekommt eine Sitzung"); -/* Der Code des Modis wird bewusst mit der Kachel 'creator' geschickt -- - genau so kommt er auch aus der Zugangswand, denn eine Modi-Kachel - gibt es nicht. */ -const modiOhneKachel = await anmelden(CREW, "creator", "CODE-MODI-0001"); -ok(modiOhneKachel.status === 200, "crew.: die gewaehlte Kachel ist egal (stiller Zugang)"); +/* ==== DIE KACHEL IST BINDEND (01.10.2026) ========================= + + Filipe: „mach das. es soll fest sein." + + Hier stand das Gegenteil, und es war richtig: Bis zum 24.09.2026 + gab es fuer einen Modi keine eigene Kachel, also musste jede + durchgehen (Filipes Entscheidung vom 09.09.). + + Seit der Haustrennung hat `crew.` einen eigenen Kachelsatz mit + allen fuenf Rollen. Das Verbergen leistet seither die ADRESSE -- + der Trick mit der beliebigen Kachel war ein Rest. */ +const modiFremdeKachel = await anmelden(CREW, "creator", "CODE-MODI-0001"); +ok(modiFremdeKachel.status === 401, + `crew.: eine fremde Kachel wird abgewiesen (${modiFremdeKachel.status})`); const managerAufCrew = await anmelden(CREW, "manager", "CODE-MAN-0001"); ok(managerAufCrew.status === 401, "crew.: ein Manager mit gueltigem Code kommt NICHT herein"); @@ -262,7 +271,12 @@ ok(managerAufWs.status === 200 && managerAufWs.keks.includes("dfw_sitzung"), "workspace.: der Manager kommt herein wie immer -- der Workspace ist unberuehrt"); const managerLokal = await anmelden(LOKAL, "manager", "CODE-MAN-0001"); -const modiLokal = await anmelden(LOKAL, "creator", "CODE-MODI-0001"); +/* AUF SEINER EIGENEN KACHEL. Eine Pruefadresse ist keine Wand -- + dort gibt es seit dem 01.10.2026 ALLE Kacheln, damit die fuenfzig + Pruefdateien, die Team-Rollen ueber 127.0.0.1 anmelden, weiter + messen koennen. Welche Kachel auf welcher ECHTEN Wand steht, sagt + die Zeile weiter oben. */ +const modiLokal = await anmelden(LOKAL, "modi", "CODE-MODI-0001"); ok(managerLokal.status === 200 && managerLokal.keks.includes("dfw_sitzung"), "127.0.0.1: der Manager kommt herein (Pruefadressen unberuehrt)"); ok(modiLokal.status === 200 && modiLokal.keks.includes("dfw_sitzung"), diff --git a/server/pruef-galerie.mjs b/server/pruef-galerie.mjs index a0dfff9c..9dce9c8a 100644 --- a/server/pruef-galerie.mjs +++ b/server/pruef-galerie.mjs @@ -99,7 +99,7 @@ async function anmelden(kachel, code) { return (a.headers.getSetCookie?.() || []).map((z) => z.split(";")[0]).join("; "); } const dogi = await anmelden("admin", "CODE-DOGI-0001"); -const modi = await anmelden("creator", "CODE-MODI-0001"); +const modi = await anmelden("modi", "CODE-MODI-0001"); /* ---------- Ein Highlight und die Dateien dazu ----------------------- */ const a = await fetch(BASIS + "/workspace/api/bereich/highlight", { diff --git a/server/pruef-gespraech.mjs b/server/pruef-gespraech.mjs index 40fbdf99..a909cda4 100644 --- a/server/pruef-gespraech.mjs +++ b/server/pruef-gespraech.mjs @@ -89,7 +89,7 @@ async function anmelden(kachel, code) { return (a.headers.getSetCookie?.() || []).map((z) => z.split(";")[0]).join("; "); } const dogi = await anmelden("admin", "CODE-DOGI-0001"); -const lena = await anmelden("creator", "CODE-LENA-0001"); +const lena = await anmelden("modi", "CODE-LENA-0001"); const kopf = (keks) => ({ "Content-Type": "application/json", cookie: keks, origin: BASIS }); async function liste(bereich, keks = dogi) { diff --git a/server/pruef-kachelraster.mjs b/server/pruef-kachelraster.mjs index 44f60d6b..dca66f8f 100644 --- a/server/pruef-kachelraster.mjs +++ b/server/pruef-kachelraster.mjs @@ -317,7 +317,9 @@ try { melde(""); melde("=== 2. Ein Modi: dasselbe Raster ==="); { - const m = await messen("creator", "CODE-MODI-0001", "modi"); + /* AUF DER MODI-KACHEL (01.10.2026) -- vorher liess der stille + Zugang jede durch. */ + const m = await messen("modi", "CODE-MODI-0001", "modi"); /* ACHT, NICHT SIEBEN -- und das war MEIN Denkfehler beim Schreiben dieser Pruefung, nicht der des Codes: Ein Modi moderiert, also braucht er "Meldungen & Massnahmen". Die Liste im Quelltext sagt @@ -405,7 +407,7 @@ try { darin. Genommen wird der Modi -- er ist die Rolle in dieser Pruefung, die eine Kachel mit `gross: true` hat, und nur an der kann der Fehler ueberhaupt auftreten. */ - const keksBreite = await anmelden("creator", "CODE-MODI-0001"); + const keksBreite = await anmelden("modi", "CODE-MODI-0001"); for (const breite of [320, 360, 390]) { const k2 = await browser.newContext({ diff --git a/server/pruef-kanaele.mjs b/server/pruef-kanaele.mjs index 7bdce2b5..0ad91b18 100644 --- a/server/pruef-kanaele.mjs +++ b/server/pruef-kanaele.mjs @@ -111,8 +111,8 @@ async function ruf(keks, pfad, aufruf = {}) { const jsonKopf = { "Content-Type": "application/json" }; const dogi = await anmelden("admin", "CODE-DOGI-0001"); -const hand = await anmelden("creator", "CODE-HAND-0001"); -const modi = await anmelden("creator", "CODE-MODI-0001"); +const hand = await anmelden("hand", "CODE-HAND-0001"); +const modi = await anmelden("modi", "CODE-MODI-0001"); const crea = await anmelden("creator", "CODE-CREA-0001"); /* ======================================================================= diff --git a/server/pruef-kreislauf.mjs b/server/pruef-kreislauf.mjs index bb29e8a6..4de97b99 100644 --- a/server/pruef-kreislauf.mjs +++ b/server/pruef-kreislauf.mjs @@ -97,7 +97,7 @@ async function anmelden(kachel, code) { return (a.headers.getSetCookie?.() || []).map((z) => z.split(";")[0]).join("; "); } const dogi = await anmelden("admin", "CODE-DOGI-0001"); -const lena = await anmelden("creator", "CODE-LENA-0001"); +const lena = await anmelden("modi", "CODE-LENA-0001"); const kopf = (keks) => ({ "Content-Type": "application/json", cookie: keks, origin: BASIS }); async function liste(bereich, keks = dogi) { diff --git a/server/pruef-modi-checkliste.mjs b/server/pruef-modi-checkliste.mjs index ee8e6c88..427323d0 100644 --- a/server/pruef-modi-checkliste.mjs +++ b/server/pruef-modi-checkliste.mjs @@ -100,7 +100,7 @@ async function hole(keks, pfad, aufruf = {}) { } const jsonKopf = { "Content-Type": "application/json" }; -const modiAn = await anmelden("creator", "CODE-MODI-0001"); +const modiAn = await anmelden("modi", "CODE-MODI-0001"); const dogiAn = await anmelden("admin", "CODE-DOGI-0001"); const vanAn = await anmelden("admin", "CODE-VAN-0001"); const handAn = await anmelden("hand", "CODE-HAND-0001"); diff --git a/server/pruef-modi-ideen.mjs b/server/pruef-modi-ideen.mjs index 0dbb5ac1..d3dc9744 100644 --- a/server/pruef-modi-ideen.mjs +++ b/server/pruef-modi-ideen.mjs @@ -174,8 +174,8 @@ const jsonKopf = { "Content-Type": "application/json" }; /* ---------- 3. Sammeln und priorisieren ------------------------------ */ console.log("\n=== 3. Ideen sammeln und nach Dringlichkeit ordnen ===\n"); -const modiAn = await anmelden("creator", "CODE-MODI-0001"); -const modi2An = await anmelden("creator", "CODE-MODI-0002"); +const modiAn = await anmelden("modi", "CODE-MODI-0001"); +const modi2An = await anmelden("modi", "CODE-MODI-0002"); const dogiAn = await anmelden("admin", "CODE-DOGI-0001"); { const IDEEN = [ @@ -297,11 +297,23 @@ console.log("\n=== 5. Das Board im echten Browser ===\n"); schlecht.push(`${r.status()} ${r.url().replace(BASIS, "")}`); } }); - await seite.goto(BASIS + "/workspace/", { waitUntil: "domcontentloaded" }); - await seite.click('.rolle[data-rolle="creator"]'); - await seite.fill("#code", "CODE-MODI-0001"); - await seite.click("button[type=submit]"); - await seite.waitForURL("**/start.html", { timeout: 15000 }); + /* ==== ANGEMELDET UEBER DEN KEKS (01.10.2026) ================ + + Hier wurde auf die Creator-Kachel getippt und ein Modi-Code + eingegeben -- das ging, solange der stille Zugang jede Kachel + durchliess. Seit die Kachel bindend ist, braeuchte der Browser + die MODI-Kachel, und die gibt es nur auf der Crew-Wand; ein + Browser auf 127.0.0.1 bekommt die Agenturwand. + + Gemessen werden soll hier, was ein Modi SIEHT -- nicht, wie er + hereinkommt. Das steht in pruef-modi-verborgen, und dort wird es + an der echten Wand gemessen. */ + const modiKeks = String((await anmelden("modi", "CODE-MODI-0001")).keks || ""); + await kontext.addCookies(modiKeks.split("; ").filter(Boolean).map((z) => { + const [n2, ...r2] = z.split("="); + return { name: n2, value: r2.join("="), domain: "127.0.0.1", path: "/" }; + })); + await seite.goto(BASIS + "/workspace/start.html", { waitUntil: "domcontentloaded" }); /* WARTEN, BIS DIE KACHELN DA SIND. Sie entstehen erst, wenn /api/ich geantwortet hat -- direkt nach waitForURL ist die Seite zwar geladen, aber leer. Beim ersten Anlauf meldete diese diff --git a/server/pruef-modi-katalog.mjs b/server/pruef-modi-katalog.mjs index 2a1439c5..5425679d 100644 --- a/server/pruef-modi-katalog.mjs +++ b/server/pruef-modi-katalog.mjs @@ -104,14 +104,14 @@ async function hole(keks, pfad, aufruf = {}) { } const jsonKopf = { "Content-Type": "application/json" }; -const modiAn = await anmelden("creator", "CODE-MODI-0001"); +const modiAn = await anmelden("modi", "CODE-MODI-0001"); const dogiAn = await anmelden("admin", "CODE-DOGI-0001"); const manAn = await anmelden("manager", "CODE-MAN-0001"); const creatAn = await anmelden("creator", "CODE-ANNA-0001"); /* Ueber den stillen Zugang -- welche Kachel man anfasst, ist gleichgueltig, der Code allein entscheidet (siehe die Anmelderoute). */ -const handAn = await anmelden("creator", "CODE-HAND-0001"); -const linkeAn = await anmelden("creator", "CODE-LINK-0001"); +const handAn = await anmelden("hand", "CODE-HAND-0001"); +const linkeAn = await anmelden("linke", "CODE-LINK-0001"); /* ---------- 1. Ist er vollstaendig da? ------------------------------- */ console.log("\n=== 1. Der Katalog, wie ihn das Dokument beschreibt ===\n"); @@ -493,11 +493,23 @@ console.log("\n=== 6. Das Brett im echten Browser ===\n"); const konsole = []; seite.on("console", (e) => { if (e.type() === "error") konsole.push(e.text()); }); seite.on("pageerror", (e) => konsole.push("Absturz: " + e.message)); - await seite.goto(BASIS + "/workspace/", { waitUntil: "domcontentloaded" }); - await seite.click('.rolle[data-rolle="creator"]'); - await seite.fill("#code", "CODE-MODI-0001"); - await seite.click("button[type=submit]"); - await seite.waitForURL("**/start.html", { timeout: 15000 }); + /* ==== ANGEMELDET UEBER DEN KEKS (01.10.2026) ================ + + Hier wurde auf die Creator-Kachel getippt und ein Modi-Code + eingegeben -- das ging, solange der stille Zugang jede Kachel + durchliess. Seit die Kachel bindend ist, braeuchte der Browser + die MODI-Kachel, und die gibt es nur auf der Crew-Wand; ein + Browser auf 127.0.0.1 bekommt die Agenturwand. + + Gemessen werden soll hier, was ein Modi SIEHT -- nicht, wie er + hereinkommt. Das steht in pruef-modi-verborgen, und dort wird es + an der echten Wand gemessen. */ + const modiKeks = String((await anmelden("modi", "CODE-MODI-0001")).keks || ""); + await kontext.addCookies(modiKeks.split("; ").filter(Boolean).map((z) => { + const [n2, ...r2] = z.split("="); + return { name: n2, value: r2.join("="), domain: "127.0.0.1", path: "/" }; + })); + await seite.goto(BASIS + "/workspace/start.html", { waitUntil: "domcontentloaded" }); /* DER KATALOG STEHT SEIT DEM 23.09.2026 AUF "EURE AUFGABEN". Filipe: "das soll auch bitte nicht in der kategorie aufgaben sondern eure aufgaben sein bitte." */ diff --git a/server/pruef-modi-kategorien.mjs b/server/pruef-modi-kategorien.mjs index 51bc514a..d3062e94 100644 --- a/server/pruef-modi-kategorien.mjs +++ b/server/pruef-modi-kategorien.mjs @@ -104,7 +104,7 @@ async function hole(keks, pfad, aufruf = {}) { /* ---------- 1. Wer bekommt die Liste ueberhaupt? --------------------- */ console.log("\n=== 1. Wer bekommt die Kategorien zu sehen? ===\n"); -const modiAn = await anmelden("creator", "CODE-MODI-0001"); +const modiAn = await anmelden("modi", "CODE-MODI-0001"); const dogiAn = await anmelden("admin", "CODE-DOGI-0001"); const manAn = await anmelden("manager", "CODE-MAN-0001"); const creatAn = await anmelden("creator", "CODE-ANNA-0001"); @@ -255,10 +255,33 @@ console.log("\n=== 5. Das Feld im echten Formular ===\n"); s.on("console", (e) => { if (e.type() === "error") konsole.push(e.text()); }); s.on("pageerror", (e) => konsole.push("Absturz: " + e.message)); await s.goto(BASIS + "/workspace/", { waitUntil: "domcontentloaded" }); - await s.click(`.rolle[data-rolle="${kachel}"]`); - await s.fill("#code", code); - await s.click("button[type=submit]"); - await s.waitForURL("**/start.html", { timeout: 15000 }); + /* ==== GIBT ES DIESE KACHEL AUF DIESER WAND? (01.10.2026) ==== + + Seit die Kachel bindend ist, muss jeder auf SEINER anmelden. + Die Modi-Kachel steht aber nur auf der Crew-Wand, und ein + Browser auf 127.0.0.1 bekommt die Agenturwand -- dort gibt + es sie nicht. + + Also wird gefragt statt angenommen: Ist die Kachel da, wird + getippt wie immer. Ist sie es nicht, geht die Anmeldung ueber + die Schnittstelle und der Keks wird mitgegeben. Gemessen + werden soll hier, was jemand SIEHT -- nicht, wie er + hereinkommt; das steht in pruef-modi-verborgen und wird dort + an der echten Wand gemessen. */ + const kachelDa = await s.$(`.rolle[data-rolle="${kachel}"]`); + if (kachelDa) { + await s.click(`.rolle[data-rolle="${kachel}"]`); + await s.fill("#code", code); + await s.click("button[type=submit]"); + await s.waitForURL("**/start.html", { timeout: 15000 }); + } else { + const keks = String((await anmelden(kachel, code)).keks || ""); + await k.addCookies(keks.split("; ").filter(Boolean).map((z) => { + const [n2, ...r2] = z.split("="); + return { name: n2, value: r2.join("="), domain: "127.0.0.1", path: "/" }; + })); + await s.goto(BASIS + "/workspace/start.html", { waitUntil: "domcontentloaded" }); + } await s.goto(BASIS + "/workspace/aufgaben.html", { waitUntil: "networkidle" }); await s.waitForTimeout(900); await s.click("#neu-oeffnen").catch(() => {}); @@ -268,7 +291,8 @@ console.log("\n=== 5. Das Feld im echten Formular ===\n"); /* Der Modi: Feld da, Auswahl gefuellt. */ { - const { kontext, seite, konsole } = await formular("creator", "CODE-MODI-0001"); + /* AUF DER MODI-KACHEL, seit dem 01.10.2026 -- vorher ging jede. */ + const { kontext, seite, konsole } = await formular("modi", "CODE-MODI-0001"); const z = await seite.evaluate(() => { const h = document.getElementById("feld-kategorie"); const f = document.getElementById("f-kategorie"); @@ -421,11 +445,23 @@ console.log("\n=== 5. Das Feld im echten Formular ===\n"); { const kontext = await browser.newContext(); const seite = await kontext.newPage(); - await seite.goto(BASIS + "/workspace/", { waitUntil: "domcontentloaded" }); - await seite.click('.rolle[data-rolle="creator"]'); - await seite.fill("#code", "CODE-MODI-0001"); - await seite.click("button[type=submit]"); - await seite.waitForURL("**/start.html", { timeout: 15000 }); + /* ==== ANGEMELDET UEBER DEN KEKS (01.10.2026) ================ + + Hier wurde auf die Creator-Kachel getippt und ein Modi-Code + eingegeben -- das ging, solange der stille Zugang jede Kachel + durchliess. Seit die Kachel bindend ist, braeuchte der Browser + die MODI-Kachel, und die gibt es nur auf der Crew-Wand; ein + Browser auf 127.0.0.1 bekommt die Agenturwand. + + Gemessen werden soll hier, was ein Modi SIEHT -- nicht, wie er + hereinkommt. Das steht in pruef-modi-verborgen, und dort wird es + an der echten Wand gemessen. */ + const modiKeks = String((await anmelden("modi", "CODE-MODI-0001")).keks || ""); + await kontext.addCookies(modiKeks.split("; ").filter(Boolean).map((z) => { + const [n2, ...r2] = z.split("="); + return { name: n2, value: r2.join("="), domain: "127.0.0.1", path: "/" }; + })); + await seite.goto(BASIS + "/workspace/start.html", { waitUntil: "domcontentloaded" }); await seite.goto(BASIS + "/workspace/entwicklung.html", { waitUntil: "networkidle" }); await seite.waitForTimeout(1600); const text = await seite.evaluate(() => document.body.innerText); diff --git a/server/pruef-modi-livecheck.mjs b/server/pruef-modi-livecheck.mjs index 7a5b9dea..a724c85e 100644 --- a/server/pruef-modi-livecheck.mjs +++ b/server/pruef-modi-livecheck.mjs @@ -104,7 +104,7 @@ async function hole(keks, pfad, aufruf = {}) { const jsonKopf = { "Content-Type": "application/json" }; const dogiAn = await anmelden("admin", "CODE-DOGI-0001"); -const modiAn = await anmelden("creator", "CODE-MODI-0001"); +const modiAn = await anmelden("modi", "CODE-MODI-0001"); const manAn = await anmelden("manager", "CODE-MAN-0001"); /* ---------- Zwei Live-Termine mit dem Modi als Teilnehmer ----------- */ diff --git a/server/pruef-modi-verborgen.mjs b/server/pruef-modi-verborgen.mjs index 2b352215..8642b31f 100644 --- a/server/pruef-modi-verborgen.mjs +++ b/server/pruef-modi-verborgen.mjs @@ -111,40 +111,130 @@ d.close(); const MODIS = [idModi1, idModi2, idHand]; void idSpicy; -/* ---------- Anmelden ueber die Schnittstelle ------------------------- */ -async function anmelden(rolle, code) { - const a = await fetch(BASIS + "/workspace/api/anmelden", { - method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ rolle, code }), +/* ---------- Anmelden ueber die Schnittstelle ------------------------- + + MIT WAND, SEIT DEM 01.10.2026. Vorher ging jede Anmeldung hier ueber + `fetch` auf 127.0.0.1 -- eine Adresse OHNE Wand. Gemessen wurde + damit der stille Zugang und nicht die Kachelregel; seit er weg ist, + waere das die Messung der falschen Sache. + + WARUM node:http UND NICHT fetch: `fetch` (undici) setzt den + Host-Kopf selbst aus der Adresse und ignoriert einen mitgegebenen. + Nachgemessen, nicht vermutet -- dieselbe Stelle steht seit dem + 22.09. in pruef-chat-kanaele. */ +const { request: httpAnfrage } = await import("node:http"); +const CREW_WAND = "crew.dogfather-universe.com"; +const AGENTUR_WAND = "workspace.dogfather-universe.com"; + +/** Auf welcher Wand steht die Kachel dieser Rolle? + * + * ABGELEITET STATT AUFGEZAEHLT (01.10.2026). Nach dem Umbau meldeten + * sich acht Stellen ueber eine fremde Kachel an -- ein Manager auf + * der Crew-Wand etwa, wo es seine Kachel gar nicht gibt. Eine Liste + * von Hand waere die, bei der man zwei Stellen vergisst. + * + * Wer eine Wand AUSDRUECKLICH nennt, bekommt sie: Das brauchen die + * Zeilen, die absichtlich die falsche Wand pruefen. */ +const CREW_ROLLEN = new Set(["admin", "hand", "linke", "modi", "gast"]); +const wandFuer = (rolle) => (CREW_ROLLEN.has(rolle) ? CREW_WAND : AGENTUR_WAND); + +function anmelden(rolle, code, wand = wandFuer(rolle)) { + return new Promise((fertig) => { + const rumpf = JSON.stringify({ rolle, code }); + const a = httpAnfrage({ + host: "127.0.0.1", port: PORT, path: "/workspace/api/anmelden", method: "POST", + headers: { + "Content-Type": "application/json", + "Content-Length": Buffer.byteLength(rumpf), + Host: wand, + }, + }, (antwort) => { + const teile = []; + antwort.on("data", (t) => teile.push(t)); + antwort.on("end", () => { + let daten = {}; + try { daten = JSON.parse(Buffer.concat(teile).toString("utf8")); } catch { /* kein JSON */ } + fertig({ + status: antwort.statusCode, + daten, + keks: [].concat(antwort.headers["set-cookie"] || []) + .map((z) => z.split(";")[0]).join("; "), + }); + }); + }); + a.on("error", () => fertig({ status: 0, daten: {}, keks: "" })); + a.end(rumpf); }); - const daten = await a.json().catch(() => ({})); - const keks = (a.headers.getSetCookie?.() || []).map((z) => z.split(";")[0]).join("; "); - return { status: a.status, daten, keks }; } -console.log("\n=== 1. Der Eingang: eine Kachel gibt es nicht ===\n"); +/* ===================================================================== + 1. DIE KACHEL IST BINDEND (01.10.2026) -for (const kachel of ["creator", "scout", "manager", "spicy", "admin"]) { - const a = await anmelden(kachel, "CODE-MODI-0001"); - ok(a.status === 200 && a.daten?.rolle === "modi", - `Kachel "${kachel}" + Modi-Code -> angemeldet als ${a.daten?.rolle || a.status}`); -} + Filipe: „mach das. es soll fest sein." + + VanVan hatte gemeldet: „Man kann sich mit seinem Zugangscode immer + noch über jeden Button der Startseite anmelden, egal welche Rolle + man hat." + + BIS HEUTE STAND HIER DAS GEGENTEIL, und das war richtig: Vom + 09.09.2026 an hatten die Modis KEINE eigene Kachel -- wer keine + hat, muss irgendeine nehmen koennen. + + Seit der Haustrennung am 24.09. hat `crew.` einen eigenen + Kachelsatz mit allen fuenf Rollen. Das Verbergen leistet die + ADRESSE; der Trick mit der beliebigen Kachel war ein Rest. + ===================================================================== */ +console.log("\n=== 1. Der Eingang: die Kachel gilt ===\n"); -/* Der Umkehrschluss, und er ist der wichtigere: Der stille Weg darf - NICHT dazu fuehren, dass auch alle anderen die Kachel ignorieren - duerfen. Ein Manager mit der Kachel "creator" muss weiterhin - scheitern -- sonst haette ich nebenbei die Rollenpruefung - abgeschafft, ohne es zu merken. */ { - const a = await anmelden("creator", "CODE-MAN-0001"); + const a = await anmelden("modi", "CODE-MODI-0001"); + ok(a.status === 200 && a.daten?.rolle === "modi", + `auf der Modi-Kachel kommt ein Modi herein (${a.daten?.rolle || a.status})`); +} + +/* UND AUF KEINER ANDEREN. Das ist die Aenderung. */ +for (const kachel of ["admin", "hand", "linke", "gast"]) { + const a = await anmelden(kachel, "CODE-MODI-0001"); + ok(a.status === 401, + `Kachel "${kachel}" + Modi-Code -> abgewiesen (${a.status})`); +} + +/* GEGENPROBE: Die anderen Rollen der Crew-Wand kommen auf IHRER + Kachel herein. Ohne sie hiesse „401 ueberall" womoeglich nur, dass + dort gar niemand mehr hereinkommt. */ +{ + const h = await anmelden("hand", "CODE-HAND-0001"); + ok(h.status === 200 && h.daten?.rolle === "hand", + `die rechte Hand auf ihrer Kachel (${h.daten?.rolle || h.status})`); +} + +/* UND DIE AGENTURWAND BLEIBT, WIE SIE WAR. Dort war der stille Weg + nie aktiv; ein Modi-Code verhaelt sich weiter wie ein erfundener. */ +{ + const a = await anmelden("creator", "CODE-MODI-0001", AGENTUR_WAND); + const b = await anmelden("creator", "GIBT-ES-NICHT-1", AGENTUR_WAND); + ok(a.status === 401 && b.status === 401 + && JSON.stringify(a.daten) === JSON.stringify(b.daten), + `auf der Agenturwand klingt ein Modi-Code wie ein erfundener ` + + `(${a.status} vs. ${b.status})`); +} + +/* Und die Rollenpruefung der Agentur ist unveraendert: Ein Manager + mit der Kachel "creator" scheitert weiterhin. */ +{ + const a = await anmelden("creator", "CODE-MAN-0001", AGENTUR_WAND); ok(a.status === 401, `Manager-Code auf der Creator-Kachel bleibt abgewiesen (${a.status})`); } /* Wortgleichheit: "modi" von aussen anzugeben darf nicht anders klingen als eine erfundene Rolle. */ { - const m = await anmelden("modi", "FALSCH-FALSCH-1"); - const x = await anmelden("gibtesnicht", "FALSCH-FALSCH-1"); + /* AUF DER AGENTURWAND klingt „modi" wie eine erfundene Rolle -- + dort gibt es die Kachel nicht. Auf crew. gibt es sie, und dort + entscheidet der Code; deshalb wird das hier ausdruecklich an der + Agenturwand gefragt. */ + const m = await anmelden("modi", "FALSCH-FALSCH-1", AGENTUR_WAND); + const x = await anmelden("gibtesnicht", "FALSCH-FALSCH-1", AGENTUR_WAND); ok(m.status === 401 && x.status === 401 && JSON.stringify(m.daten) === JSON.stringify(x.daten), "Rolle \"modi\" von aussen klingt wie eine erfundene " @@ -152,7 +242,7 @@ for (const kachel of ["creator", "scout", "manager", "spicy", "admin"]) { } { - const a = await anmelden("creator", "CODE-MODI-FALSCH"); + const a = await anmelden("modi", "CODE-MODI-FALSCH"); ok(a.status === 401, `ein falscher Modi-Code wird abgewiesen (${a.status})`); } @@ -184,8 +274,16 @@ const LEUTE = [ ["Manager", "manager", "CODE-MAN-0001", false], ["Scout", "scout", "CODE-SCOU-0001", false], ["Creator", "creator", "CODE-ANNA-0001", false], - ["Modi Marina", "creator", "CODE-MODI-0001", true], - ["Rechte Hand", "creator", "CODE-HAND-0001", true], + /* AUF IHRER EIGENEN KACHEL (01.10.2026). Hier stand „creator" -- + der stille Zugang liess damals jede Kachel durch. Seit die Kachel + bindend ist, scheiterte ihre Anmeldung STILL: `unklar(...)` und + weiter, und acht Sichtbarkeitspruefungen fielen lautlos weg. + + Genau der Rueckgang, vor dem die Hausregel warnt -- gruen bei + weniger Pruefungen. Gefunden hat ihn nicht der Lauf, sondern der + Vergleich der Anzahl mit dem Lauf davor. */ + ["Modi Marina", "modi", "CODE-MODI-0001", true], + ["Rechte Hand", "hand", "CODE-HAND-0001", true], ]; async function hole(keks, pfad) { @@ -239,7 +337,7 @@ console.log("\n=== 3. Auch die ZAHL darf sie nicht mitzaehlen ===\n"); /* ---------- 4. Sehen die Modis einander? ----------------------------- */ console.log("\n=== 4. Die Modis sind untereinander ein Team ===\n"); { - const an = await anmelden("creator", "CODE-MODI-0001"); + const an = await anmelden("modi", "CODE-MODI-0001"); const { status, daten } = await hole(an.keks, "/workspace/api/personen"); if (status !== 200 || !Array.isArray(daten?.personen)) { unklar(`Personenwahl fuer den Modi nicht lesbar (${status})`); @@ -292,7 +390,8 @@ console.log("\n=== 5. Anlegen wie im Betrieb: DogFather legt einen Modi an ===\n vergessen worden, waeren oben trotzdem alle Haken gruen und kein einziger echter Modi kaeme herein. */ if (neuDaten?.code) { - const b = await anmelden("creator", neuDaten.code); + /* AUF DER MODI-KACHEL, seit dem 01.10.2026 -- vorher ging jede. */ + const b = await anmelden("modi", neuDaten.code); ok(b.status === 200 && b.daten?.rolle === "modi", "und meldet sich mit seinem Code an, ueber eine fremde Kachel " + `(${b.status}, ${b.daten?.rolle})`); @@ -314,7 +413,10 @@ console.log("\n=== 5. Anlegen wie im Betrieb: DogFather legt einen Modi an ===\n /* ---------- 6. Die Startseite eines Modis ---------------------------- */ console.log("\n=== 6. Was ein Modi auf seiner Startseite sieht ===\n"); { - const an = await anmelden("creator", "CODE-MODI-0001"); + /* AUF SEINER EIGENEN KACHEL, seit dem 01.10.2026. Hier stand + „creator" -- damals gab es fuer einen Modi keine eigene, und der + stille Zugang liess jede durch. Jetzt gilt die Kachel. */ + const an = await anmelden("modi", "CODE-MODI-0001"); const { status, daten } = await hole(an.keks, "/workspace/api/ich"); if (status !== 200) { unklar(`/api/ich nicht lesbar (${status})`); @@ -385,12 +487,40 @@ console.log("\n=== 7. Dieselbe Seite mit einem echten Browser ===\n"); seite.on("console", (e) => { if (e.type() === "error") konsole.push(e.text()); }); seite.on("pageerror", (e) => konsole.push("Absturz: " + e.message)); - await seite.goto(BASIS + "/workspace/", { waitUntil: "domcontentloaded" }); - /* Irgendeine Kachel -- fuer einen Modi gibt es keine eigene. */ - await seite.click('.rolle[data-rolle="creator"]'); - await seite.fill("#code", "CODE-MODI-0001"); - await seite.click("button[type=submit]"); - await seite.waitForURL("**/start.html", { timeout: 15000 }); + /* ==== ANGEMELDET WIRD UEBER DIE WAND, NICHT UEBER DIE SEITE + (01.10.2026) + + Hier wurde bis heute im Browser auf die Creator-Kachel getippt + und der Modi-Code eingegeben -- das ging, solange der stille + Zugang jede Kachel durchliess. + + Seit die Kachel bindend ist, braeuchte der Browser die + CREW-Wand: Dort steht die Modi-Kachel. Ein Browser auf + 127.0.0.1 bekommt aber die Agenturwand, und ein Host-Kopf + laesst sich dort nur mit einer Namensumleitung setzen (so macht + es mess-reaktion mit `--host-resolver-rules`). + + Der kuerzere und ehrlichere Weg: an der richtigen Wand + anmelden und den Keks mitgeben. Gemessen werden soll, was ein + Modi auf seiner STARTSEITE sieht -- nicht, wie er hereinkommt. + Das steht in Abschnitt 1, und dort wird es an der echten Wand + gemessen. */ + const modiKeks = (await anmelden("modi", "CODE-MODI-0001")).keks; + await kontext.addCookies(modiKeks.split("; ").filter(Boolean).map((z) => { + const [n, ...r] = z.split("="); + return { name: n, value: r.join("="), domain: "127.0.0.1", path: "/" }; + })); + await seite.goto(BASIS + "/workspace/start.html", { waitUntil: "domcontentloaded" }); + /* KEIN `waitForURL` MEHR. Es wartete auf eine Navigation, die es + seit dem 01.10.2026 nicht mehr gibt -- angemeldet wird ueber + die Wand, nicht ueber das Formular. Steht die Seite schon da, + wartet es trotzdem und laeuft in die Frist. + + Und wenn der Keks NICHT angenommen wurde, sagt die Zeile + darunter genau das, statt fuenfzehn Sekunden zu schweigen. */ + if (!/start\.html/.test(seite.url())) { + unklar(`nach dem Anmelden steht die Seite auf ${seite.url()}`); + } await seite.waitForTimeout(1200); const bild = await seite.evaluate(() => ({ @@ -490,7 +620,7 @@ console.log("\n=== 8. Aufgaben, Einträge und Dateien eines Modis ===\n"); Der Kalender ist bewusst nicht dabei: termineSichtbar() gibt jedem nur Eigenes, dort kann nichts durchsickern. Nachgesehen, nicht angenommen. */ - const an = await anmelden("creator", "CODE-MODI-0001"); + const an = await anmelden("modi", "CODE-MODI-0001"); const MERKMAL = "GEHEIMER MODI-EINTRAG"; /* (a) Eine Aufgabe -- ueber den normalen Weg. */ diff --git a/server/pruef-team-ampel.mjs b/server/pruef-team-ampel.mjs index f29be1e7..097ee6d6 100644 --- a/server/pruef-team-ampel.mjs +++ b/server/pruef-team-ampel.mjs @@ -119,7 +119,7 @@ async function anmelden(rolle, code) { const holeLage = (keks) => fetch(`${BASIS}/workspace/api/teamlage`, { headers: { Cookie: keks } }); const keksDogi = await anmelden("admin", "CODE-DOGI-0001"); -const keksHand = await anmelden("creator", "CODE-HAND-0001"); +const keksHand = await anmelden("hand", "CODE-HAND-0001"); if (!keksDogi || !keksHand) { console.error("FEHLER: Anmeldung misslang -- ohne sie misst diese Datei nichts."); process.exit(1); diff --git a/server/pruef-team-stufen.mjs b/server/pruef-team-stufen.mjs index cbde5ada..1ba8266a 100644 --- a/server/pruef-team-stufen.mjs +++ b/server/pruef-team-stufen.mjs @@ -102,8 +102,8 @@ const setzeStufe = (keks, person_id, stufe) => }); const keksDogi = await anmelden("admin", "CODE-DOGI-0001"); -const keksHand = await anmelden("creator", "CODE-HAND-0001"); -const keksModi = await anmelden("creator", "CODE-MODI-0001"); +const keksHand = await anmelden("hand", "CODE-HAND-0001"); +const keksModi = await anmelden("modi", "CODE-MODI-0001"); if (!keksDogi || !keksHand || !keksModi) { console.error("FEHLER: Anmeldung misslang -- ohne sie misst diese Datei nichts."); process.exit(1); diff --git a/server/pruef-treff.mjs b/server/pruef-treff.mjs index 62fc4d30..87261127 100644 --- a/server/pruef-treff.mjs +++ b/server/pruef-treff.mjs @@ -211,7 +211,12 @@ for (const [name, host] of [["workspace.", HAUS], ["der Hauptseite", HAUPT]]) { } const kDogi = (await anmelden("admin", "CODE-DOGI-0001", HAUS)).keks; -const kModi = (await anmelden("creator", "CODE-MODI-0001", CREW)).keks; +/* AUF DER MODI-KACHEL (01.10.2026). Hier stand „creator" -- bis zum + 24.09. gab es fuer einen Modi keine eigene Kachel, und der stille + Zugang liess jede durch. Seit die Kachel bindend ist, scheiterte + die Anmeldung, und fuenf Pruefungen wurden rot, ohne dass am + Programm etwas falsch war. */ +const kModi = (await anmelden("modi", "CODE-MODI-0001", CREW)).keks; const kCrea = (await anmelden("creator", "CODE-CREA-0001", HAUS)).keks; const kMana = (await anmelden("manager", "CODE-MANA-0001", HAUS)).keks; ok([kDogi, kModi, kCrea, kMana].every((k) => k.length > 0), "die vier Vergleichsrollen sind angemeldet"); diff --git a/server/pruef-wunschliste.mjs b/server/pruef-wunschliste.mjs index 891301ac..81f91ac5 100644 --- a/server/pruef-wunschliste.mjs +++ b/server/pruef-wunschliste.mjs @@ -97,9 +97,9 @@ async function anmelden(kachel, code) { return (a.headers.getSetCookie?.() || []).map((z) => z.split(";")[0]).join("; "); } const dogi = await anmelden("admin", "CODE-DOGI-0001"); -const hand = await anmelden("creator", "CODE-HAND-0001"); -const modi = await anmelden("creator", "CODE-MODI-0001"); -const nane = await anmelden("creator", "CODE-NANE-0001"); +const hand = await anmelden("hand", "CODE-HAND-0001"); +const modi = await anmelden("modi", "CODE-MODI-0001"); +const nane = await anmelden("modi", "CODE-NANE-0001"); const kopf = (keks) => ({ "Content-Type": "application/json", cookie: keks, origin: BASIS }); diff --git a/server/workspace.js b/server/workspace.js index f43560ed..ded06aa7 100644 --- a/server/workspace.js +++ b/server/workspace.js @@ -6714,34 +6714,6 @@ workspaceRouter.use((req, res, next) => { return next(); }); -/** - * Gehoert dieser Code zu einem verborgenen Zugang? - * - * Gibt die Person zurueck oder null. `null` heisst hier ausdruecklich - * "nein oder nicht feststellbar" -- ohne Suchschluessel (etwa weil die - * Einstellung fehlt) gibt codeKennung() null zurueck, und dann wird - * niemand angemeldet. Das ist die richtige Richtung: Im Zweifel kommt - * niemand herein, statt dass im Zweifel jemand hereinkommt. - */ -function stillerZugang(code) { - try { - const kennung = codeKennung(code); - if (!kennung) return null; - const k = db().prepare( - "SELECT id, name, rolle, code_hash, code_salt, code_n FROM personen " - + `WHERE code_kennung = ? AND rolle IN (${ - [...TEAM_DOGI_ROLLEN].map((r) => `'${r}'`).join(", ")}) AND aktiv = 1`).get(kennung); - if (!k) return null; - /* Trotz Treffer wird geprueft. Der Suchschluessel ist ein - Wegweiser, kein Ausweis -- und ein Wegweiser, dem man blind - folgt, ist eine Hintertuer. */ - return gleich(hashe(code, k.code_salt, k.code_n), k.code_hash) ? k : null; - } catch (fehler) { - console.error("[workspace] Stiller Zugang nicht pruefbar:", fehler?.message); - return null; - } -} - /* DIE TAFEL LIEGT SEIT DEM 11.09.2026 IN workspace-rechte.js. Hier stand ein nur LESENDER Weg. Filipe: "so dass ich die da auch @@ -6763,95 +6735,49 @@ workspaceRouter.post("/workspace/api/anmelden", (req, res) => { const codeBrauchbar = code.length >= 4 && code.length <= 200; /* ================================================================= - DER STILLE ZUGANG (09.09.2026) + DIE KACHEL IST BINDEND (01.10.2026) - Wunsch Filipe: *"dass die keine neue eingangs kachel bekommen wie - spicy dogfather und so sondern einfach einen code. damit die von - der workspace auch nicht mal sehen dass die modis von mir einen - eigenen zugang haben."* + Filipe: „mach das. es soll fest sein." - Ein Modi oeffnet dieselbe Seite, tippt auf IRGENDEINE vorhandene - Kachel und gibt seinen Code ein. Welche Kachel, ist gleichgueltig - -- der Code allein entscheidet. Von aussen sieht das aus wie jede - andere Anmeldung: dieselbe Seite, dieselbe Anfrage, dieselben - Felder. + VanVan hatte gemeldet: „Man kann sich mit seinem Zugangscode + immer noch über jeden Button der Startseite anmelden, egal + welche Rolle man hat." - ZWEI NAHELIEGENDE WEGE, DIE ABSICHTLICH NICHT GEWAEHLT WURDEN: + --------------------------------------------------------------- + HIER STAND DER STILLE ZUGANG (09.09. bis 01.10.2026) - * Ein Merkmal im Code ("M-..."): waere ein sichtbares Kennzeichen - auf dem Zettel des Modis. Wer den Code sieht, sieht die Sorte. - * Eine eigene Adresse (/modi.html): waere eine Seite, die man - finden kann -- und die Seitenpruefung zaehlt Seiten. + Er liess einen Team-Dogi-Code auf JEDER Kachel durch. Das war + kein Versehen, sondern Filipes Entscheidung vom 09.09.2026: + „dass die keine neue eingangs kachel bekommen wie spicy + dogfather und so sondern einfach einen code. damit die von der + workspace auch nicht mal sehen dass die modis von mir einen + eigenen zugang haben." - WARUM DAS VOR DEM GEWOHNTEN WEG STEHT UND NICHT DAHINTER: Ein - Rueckfall NACH einem Fehlversuch haette den gewohnten Weg - verlaengert -- und zwar nur dann, wenn er scheitert. Genau daran - waere es zu erkennen gewesen: Fehlversuche dauern ploetzlich - laenger als frueher. Der Suchschluessel kostet Mikrosekunden und - trifft in aller Regel nichts; fuer alle anderen bleibt der Ablauf - unveraendert, auch in der Zeit. + Wer keine Kachel hat, muss irgendeine nehmen koennen. - DER SUCHSCHLUESSEL ALLEIN LAESST NIEMANDEN HEREIN. Er sagt nur, - WEN man pruefen soll -- danach entscheidet scrypt wie ueberall. */ - /* AUF DEN ALTEN ADRESSEN WIRD DER VERBORGENE ZUGANG GAR NICHT ERST - GEFRAGT (Entscheidung Filipe, 10.09.2026). + WARUM ER JETZT WEG KANN -- und das ist der ganze Punkt: Seit + der Haustrennung am 24.09.2026 gibt es ZWEI Waende. Auf `crew.` + steht ein eigener Kachelsatz (CREW_KACHEL): DogFather, rechte + Hand, linke Hand, Modi, Community. Alle fuenf Rollen haben dort + ihre Kachel. - Vorher stand hier eine Weiterleitung: Wer seinen Code noch auf - workspace.dogfather-universe.com eintippte, bekam keine Sitzung, - aber den Weg zur neuen Adresse. Filipes Entscheidung dagegen: - "gar nichts -- Code stimmt nicht". Die alte Wand soll sich - verhalten, als waere der Code erfunden. + Das Verbergen leistet seither die ADRESSE. Wer sie nicht kennt, + findet die Wand nicht; wer sie kennt, sieht die Rollennamen + ohnehin offen darauf stehen. Der Trick mit der beliebigen + Kachel hat niemanden mehr geschuetzt und nur noch dafuer + gesorgt, dass die Wahl folgenlos blieb. - WARUM DAS NICHT NUR EINE ANDERE ANTWORT IST, SONDERN EIN ANDERER - WEG: Haette ich hier bloss `return 401` gesetzt, waere der Ablauf - trotzdem ein anderer geblieben -- ein Suchschluessel-Treffer und - EIN scrypt-Durchlauf statt der Kandidatenschleife der gewaehlten - Kachel. Das ist messbar, und Zeitunterschiede sind genau die - Spur, die dieser ganze Zugang vermeiden soll. + WAS SICH NICHT AENDERT: Auf der Agenturwand war der stille + Zugang nie aktiv. Ein Team-Dogi-Code verhaelt sich dort + weiterhin wie ein erfundener -- gleiche Antwort, gleicher Weg, + gleiche Dauer. Dafuer sorgt der Kachelsatz unten, nicht eine + eigene Bedingung. - Deshalb wird `stillerZugang` auf diesen drei Adressen ueberhaupt - nicht aufgerufen. Der Code faellt danach durch den gewohnten Weg - wie jeder unbekannte: dieselbe Schleife, derselbe Eintrag in - `versuche`, dieselbe Antwort, dieselbe Dauer. Die alte Wand - verhaelt sich damit exakt so wie vor dem Tag, an dem es diese - Rollen gab. - - DER PREIS, und er gehoert genannt: Ein Modi, der die alte - Verknuepfung auf dem Handy hat, sammelt dort Fehlversuche wie - jeder andere auch. Acht in zehn Minuten sperren seine IP -- und - zwar auch fuer die neue Adresse, denn die Sperre haengt an der - IP, nicht am Hostnamen. Das ist der Preis der Stille; er faellt - nur an, wenn jemand die alte Adresse mehrfach probiert. */ - /* UND AUCH NICHT AUF DER WAND DES TREFFS (11.09.2026). - - Hier stand `!istOhneModiAdresse(...)` -- also "ueberall ausser auf - den alten Adressen". Als dritte Wand dazukam, hiess das - stillschweigend auch: dort. Ein Modi kam damit ueber den - verborgenen Weg in den Treff herein, obwohl die Kachelliste dort - nur `gast` kennt und die Adressregel ihn abweist. - - Gefunden hat das nicht das Lesen, sondern eine Zeile in - pruef-treff, die das GEGENTEIL behauptete und rot wurde: - "auf treff. kommt sonst niemand herein -- auch DogFather nicht - (401/200)". DogFather wurde abgewiesen, der Modi nicht. - - Die Lehre ist dieselbe wie bei `null` in der Rechtetafel: Eine - Bedingung, die durch AUSSCHLIESSEN formuliert ist, nimmt jede - neue Moeglichkeit automatisch mit auf. Jetzt steht dort, WO der - Weg gilt, statt wo er nicht gilt. */ - const stilleWand = istCrewAdresse(req.get("host")) || istPruefAdresse(req.get("host")); - const still = codeBrauchbar && stilleWand ? stillerZugang(code) : null; - if (still) { - db().prepare("DELETE FROM versuche WHERE ip = ?").run(ip); - db().prepare("UPDATE personen SET letzter_login = ? WHERE id = ?").run(jetzt(), still.id); - sitzungSetzen(res, still, req); - protokolliere("anmeldung", { - personId: still.id, rolle: still.rolle, ip, detail: still.name, - }); - return res.json({ - weiter: "/workspace/start.html", name: still.name, rolle: still.rolle, - }); - } + `code_kennung` in `personen` wird weiter GESCHRIEBEN, aber + nicht mehr gelesen. Sie war der Suchschluessel dieses Weges. + Stehen gelassen und nicht geloescht: Eine Spalte zu entfernen + ist eine Schemaaenderung mit Sicherung, und sie kostet nichts. + Wer sie wieder braucht, findet hier, wofuer sie da war. */ /* Ab hier der gewohnte Weg -- unveraendert. 'modi' ist keine Kachel-Rolle und faellt deshalb in dieselbe Antwort wie eine @@ -6885,7 +6811,24 @@ workspaceRouter.post("/workspace/api/anmelden", (req, res) => { Wand gerade dran ist. Ein Manager, der crew. erraet und seinen Code eintippt, faellt dadurch in genau dieselbe Antwort wie jemand mit einer erfundenen Rolle. */ - const kachelSatz = istCrewAdresse(req.get("host")) ? CREW_KACHEL : ROLLEN_KACHEL; + /* ==== EINE PRUEFADRESSE IST KEINE WAND (01.10.2026) ========== + + `127.0.0.1` ist weder crew. noch die Agentur. Bis heute fiel + das nicht auf: Der stille Zugang liess Team-Dogi-Codes dort + ohnehin durch, egal welcher Kachelsatz galt. Mit seinem + Wegfall gaelte dort der AGENTUR-Satz -- und damit kaeme kein + einziger Modi mehr herein. Fuenfzig Pruefdateien melden + Team-Rollen ueber diese Adresse an; sie waeren alle rot, und + zwar wegen der Messumgebung, nicht wegen des Programms. + + Auf einer Adresse ohne Wand gibt es deshalb ALLE Kacheln. Das + versteckt nichts: Welche Kachel auf welcher ECHTEN Wand steht, + entscheiden weiterhin die zwei Mengen darunter, und genau das + misst pruef-modi-verborgen -- mit ausdruecklichem Host-Kopf, + nicht ueber 127.0.0.1. */ + const kachelSatz = istPruefAdresse(req.get("host")) + ? new Set([...ROLLEN_KACHEL, ...CREW_KACHEL]) + : (istCrewAdresse(req.get("host")) ? CREW_KACHEL : ROLLEN_KACHEL); if (!kachelSatz.has(rolle) || !codeBrauchbar) { db().prepare("INSERT INTO versuche (ip, zeitpunkt) VALUES (?,?)").run(ip, jetzt()); diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 0685f0ee..f26386f1 100644 --- a/workspace/anruf-probe.html +++ b/workspace/anruf-probe.html @@ -16,8 +16,8 @@ verdeckt. Gefunden hat es pruef-struktur. Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. --> - - + + - +