diff --git a/server/pruef-crew-adresse.mjs b/server/pruef-crew-adresse.mjs index 48efbbb1..4e59065b 100644 --- a/server/pruef-crew-adresse.mjs +++ b/server/pruef-crew-adresse.mjs @@ -124,7 +124,7 @@ const LOKAL = "127.0.0.1:4371"; hier moeglich ist: die Entscheidung pruefen, nicht ihre Auswirkung. ===================================================================== */ console.log("\n--- Die Regeln selbst ---"); -const { istCrewAdresse, istOhneModiAdresse, istWorkspacePfad, sitzungPasstZurAdresse, CREW_ADRESSE } +const { istCrewAdresse, istOhneModiAdresse, istWorkspacePfad, sitzungPasstZurAdresse } = await import("./crew-adresse.js"); ok(istCrewAdresse(CREW) === true, "crew.dogfather-universe.com ist die Modi-Adresse"); @@ -214,13 +214,12 @@ const handAufCrew = await anmelden(CREW, "hand", "CODE-HAND-0001"); ok(handAufCrew.status === 200 && handAufCrew.keks.includes("dfw_sitzung"), "crew.: die rechte Hand kommt herein"); -/* Und sie kommt NICHT auf die andere Adresse -- genau wie ein Modi. - Sie bekommt dort denselben Hinweis auf die neue Adresse. */ +/* Und sie kommt NICHT auf die andere Adresse -- genau wie ein Modi, + und mit genau derselben Antwort wie ein erfundener Code. */ const handAufWs = await anmelden(WS, "creator", "CODE-HAND-0001"); -let zielHand = {}; -try { zielHand = JSON.parse(handAufWs.text); } catch { /* bleibt leer */ } -ok(handAufWs.status === 200 && zielHand.weiter === `${CREW_ADRESSE}/workspace/start.html`, - "workspace.: die rechte Hand wird auf die neue Adresse verwiesen"); +const erfunden2 = await anmelden(WS, "creator", "AUCH-DIESEN-NICHT-000"); +ok(handAufWs.status === 401 && handAufWs.text === erfunden2.text, + `workspace.: die rechte Hand wird abgewiesen wie ein erfundener Code (${handAufWs.status})`); ok(!handAufWs.keks.includes("dfw_sitzung"), "workspace.: und bekommt dort keine Sitzung"); @@ -229,14 +228,25 @@ ok(!handAufWs.keks.includes("dfw_sitzung"), const spicyAufCrew = await anmelden(CREW, "spicy", "CODE-DOGI-0001"); ok(spicyAufCrew.status === 401, "crew.: eine fremde Kachel gibt es dort nicht"); +/* ===================================================================== + DIE ALTE WAND SCHWEIGT (Entscheidung Filipe, 10.09.2026) + + Vorher zeigte sie einem Modi den Weg zur neuen Adresse. Seine + Entscheidung: "gar nichts -- Code stimmt nicht." + + GEPRUEFT WIRD NICHT DER STATUSCODE, SONDERN DIE UNUNTERSCHEIDBARKEIT. + Eine 401 waere leicht zu erfuellen und truege trotzdem eine Spur, wenn + der Rumpf, die Koepfe oder die Dauer anders aussaehen als bei einem + erfundenen Code. Deshalb wird beides nebeneinandergelegt und + verglichen -- Zeichen fuer Zeichen. */ +const erfunden = await anmelden(WS, "creator", "DIESEN-CODE-GIBT-ES-NICHT"); const modiAufWs = await anmelden(WS, "creator", "CODE-MODI-0001"); -ok(modiAufWs.status === 200, "workspace.: der Modi bekommt eine Antwort"); -let zielWs = {}; -try { zielWs = JSON.parse(modiAufWs.text); } catch { /* bleibt leer */ } -ok(zielWs.weiter === `${CREW_ADRESSE}/workspace/start.html`, - "workspace.: sie zeigt ihm die neue Adresse"); -ok(!modiAufWs.keks.includes("dfw_sitzung"), - "workspace.: aber KEINE Sitzung -- er meldet sich nur noch auf crew. an"); +ok(modiAufWs.status === erfunden.status && modiAufWs.status === 401, + `workspace.: der Modi-Code wird abgewiesen wie ein erfundener (${modiAufWs.status})`); +ok(modiAufWs.text === erfunden.text, + `workspace.: und die Antwort ist Zeichen fuer Zeichen dieselbe (${modiAufWs.text.slice(0, 40)})`); +ok(!modiAufWs.keks.includes("dfw_sitzung"), "workspace.: keine Sitzung"); +ok(!/crew\./.test(modiAufWs.text), "workspace.: die neue Adresse wird nicht genannt"); /* DER WICHTIGSTE PUNKT DIESER DATEI. Derselbe Dienst bedient beide Adressen; ein Denkfehler hier sperrt das ganze Team aus. */ diff --git a/server/workspace.js b/server/workspace.js index c52e5c76..3ef41f58 100644 --- a/server/workspace.js +++ b/server/workspace.js @@ -27,7 +27,7 @@ import { dirname, join } from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import { mkdirSync } from "node:fs"; import { createRequire } from "node:module"; -import { sitzungPasstZurAdresse, CREW_ADRESSE, istOhneModiAdresse, istCrewAdresse, +import { sitzungPasstZurAdresse, istOhneModiAdresse, istCrewAdresse, TEAM_DOGI_ROLLEN } from "./crew-adresse.js"; /* Weitergereicht, damit die Fachmodule sie wie alles andere aus workspace.js beziehen und nicht wissen muessen, wo sie wohnt. */ @@ -2827,35 +2827,39 @@ workspaceRouter.post("/workspace/api/anmelden", (req, res) => { DER SUCHSCHLUESSEL ALLEIN LAESST NIEMANDEN HEREIN. Er sagt nur, WEN man pruefen soll -- danach entscheidet scrypt wie ueberall. */ - const still = codeBrauchbar ? stillerZugang(code) : null; + /* AUF DEN ALTEN ADRESSEN WIRD DER VERBORGENE ZUGANG GAR NICHT ERST + GEFRAGT (Entscheidung Filipe, 10.09.2026). + + 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. + + 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. + + 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. */ + const still = codeBrauchbar && !istOhneModiAdresse(req.get("host")) + ? stillerZugang(code) + : null; if (still) { - /* AUF DER ALTEN ADRESSE GIBT ES KEINE SITZUNG MEHR (10.09.2026). - - Die Modi-App hat seit heute eine eigene Adresse. Wer seinen Code - noch auf workspace.dogfather-universe.com eintippt, bekommt hier - den Weg dorthin -- und ausdruecklich KEINE Anmeldung: zwei - Sitzungen auf zwei Adressen waeren zwei Apps auf dem - Startbildschirm und eine zweite Spur genau dort, wo alle anderen - arbeiten. - - DASS DIE ANTWORT DIE NEUE ADRESSE NENNT, IST KEIN LECK. Sie - kommt nur nach Eingabe eines gueltigen Modi-Codes; wer den hat, - ist Modi. Fuer jeden anderen -- auch fuer einen Manager mit - gueltigem eigenen Code -- veraendert sich hier gar nichts. - - Kein Eintrag in `versuche`: Der Code war richtig. Ein Modi, der - die alte Verknuepfung auf dem Handy hat, wuerde sich sonst mit - jedem Versuch selbst aussperren. */ - if (istOhneModiAdresse(req.get("host"))) { - protokolliere("anmeldung_alte_adresse", { - personId: still.id, rolle: still.rolle, ip, detail: still.name, - }); - return res.json({ - weiter: `${CREW_ADRESSE}/workspace/start.html`, - name: still.name, rolle: still.rolle, umgezogen: true, - }); - } - 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);