From 24ef154a2cd2379905d1e6943d1b7efcc703cc20 Mon Sep 17 00:00:00 2001 From: Dogfather Date: Wed, 23 Sep 2026 00:32:48 +0200 Subject: [PATCH] pruef-haus-seiten: zwei gepflegte Seitenlisten durch eine Ableitung ersetzt GEFUNDEN BEIM NACHGEHEN DER ALTLASTEN FEHL calls.html ist auf crew. noch offen (200) FEHL alle 8 Agenturseiten sind auf der Team-Adresse zu Richtig gemessen und trotzdem kein Befund: Die Seite SOLL dort offen sein. Am 22.09. hat Team Dogi die Kachel "Calls & Protokolle" bekommen; seither gehoert calls.html zum Team. Rot war die Liste, nicht das Haus. Es waren ZWEI Listen von Hand -- neun Agenturseiten in Abschnitt 2, fuenfzehn Teamseiten in Abschnitt 3 -- und in beiden fehlte dieselbe Aenderung. Zwei gepflegte Listen fuer dieselbe Frage sind zwei Gelegenheiten, eine zu vergessen. ABGELEITET STATT GEPFLEGT Welche Seiten es auf einer Adresse gibt, entscheidet `gehoertAufDieseAdresse`: Eine Seite gehoert hierher, wenn sie unter den KACHELN dieser Person steht. Die Pruefung fragt jetzt dieselben Kacheln (`bereicheFuer` + `zusatzBereicheFuer`) und misst danach ueber HTTP. Das beweist NICHT, dass die Regel richtig gedacht ist -- das steht in der Regel selbst. Es beweist, dass die Schranke tut, was die Kacheln versprechen, und dass keine Seite durchrutscht, die auf keiner Kachel steht. Und es gibt keine Zahl mehr, die morgen falsch ist. ZWEI SORTEN GEHOEREN WEDER DEM EINEN NOCH DEM ANDEREN HAUS Beim ersten Anlauf zaehlte die Ableitung `crew-index.html`, `index.html` und `start.html` als Agenturseiten -- und verlangte damit etwa, dass crew-index.html auf der Agenturadresse steht, wo sie zu Recht ein 404 ist. 1. DIE EINGANGSWAENDE (OHNE_ANMELDUNG): jede gehoert zu IHRER Adresse, auf der anderen gibt es sie nicht. 2. DIE SEITEN OHNE KACHEL (OHNE_KACHEL_UEBERALL): der eigene Steckbrief, die Regeln des Treffs -- sie gehoeren dem Menschen, nicht dem Haus. Mein erster Versuch las beide Listen mit einem regulaeren Ausdruck aus dem Quelltext. Das ging schief (leere Mengen, vier neue Fehlalarme) und war auch der falsche Gedanke: Eine Liste, die man PARST, ist eine Abschrift mit Zwischenschritt. `OHNE_KACHEL_UEBERALL` ist jetzt ausgeleitet, beide werden importiert. Gemessen: 10 Seiten gehoeren nicht zu Team Dogi (automation, content, leistung, profil, report, scouting, startcheck, team, teilen, uebersicht), 21 gehoeren dorthin. 38 Pruefungen, 0 Fehler. Dazu eine Gegenprobe zur Ableitung selbst: `calls.html` darf nicht mehr unter den Agenturseiten stehen. Stuende es dort, waere die Ableitung kaputt -- und die Pruefung wuerde denselben Fehlalarm wie zuvor melden, nur mit mehr Umweg. NEBENBEI GEKLAERT: team.html schickt einen admin auf der Team-Adresse auf start.html. Am 22.09. als "auffaellig, nicht untersucht" notiert -- nachgesehen ist es RICHTIG: team.html ist die Teamuebersicht der Agentur, Team Dogi hat teamlage.html. Die Umleitung ist die Haustrennung bei der Arbeit, kein Fehler. Sie steht jetzt in der abgeleiteten Liste der zehn. Co-Authored-By: Claude Opus 5 --- server/pruef-haus-seiten.mjs | 116 ++++++++++++++++++++++++++++++++--- server/workspace.js | 5 +- 2 files changed, 111 insertions(+), 10 deletions(-) diff --git a/server/pruef-haus-seiten.mjs b/server/pruef-haus-seiten.mjs index dcc3972e..1d7a71f8 100644 --- a/server/pruef-haus-seiten.mjs +++ b/server/pruef-haus-seiten.mjs @@ -26,7 +26,7 @@ Aufrufen mit: node server/pruef-haus-seiten.mjs ===================================================================== */ -import { mkdtempSync, rmSync, readdirSync } from "node:fs"; +import { mkdtempSync, rmSync, readdirSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { request as httpAnfrage } from "node:http"; @@ -58,6 +58,12 @@ const ok = (b, t) => { geprueft++; console.log((b ? " ok " : " FEHL ") + t); const CREW = "crew.dogfather-universe.com"; const HAUS = "workspace.dogfather-universe.com"; +/* DIE NUMMER VON DOGFATHER. Die abgeleiteten Seitenlisten (Abschnitt + 2 und 3) brauchen eine PERSON, nicht nur einen Keks: `bereicheFuer` + fragt Rolle und Haus, und zwar an derselben Stelle wie der Server. + Ein zweiter Nachbau hier waere die zweite Wahrheit. */ +let idDogi = 0; + const { DatabaseSync } = await import("node:sqlite"); const { scryptSync, randomBytes, createHmac } = await import("node:crypto"); const ws = await import("./workspace.js"); @@ -77,7 +83,7 @@ const jetzt = new Date().toISOString(); + " VALUES (?,?,?,?,?,?,1,?)") .run(name, rolle, hash, salt, 32768, createHmac("sha256", s).update(code).digest("hex"), jetzt); }; - anlegen("Filipe", "admin", "CODE-DOGI-0001"); + idDogi = anlegen("Filipe", "admin", "CODE-DOGI-0001"); anlegen("Rieke", "hand", "CODE-HAND-0001"); anlegen("Frida", "modi", "CODE-MODI-0001"); anlegen("Mara", "manager", "CODE-MANA-0001"); @@ -159,10 +165,96 @@ melde("=== 1. Der Start-Check ==="); 2. ALLE AGENTURSEITEN, NICHT NUR DIESE EINE ======================================================================= */ melde(""); -melde("=== 2. Die übrigen neun ==="); +melde("=== 2. Die übrigen Agenturseiten ==="); { - const AGENTUR = ["automation.html", "calls.html", "content.html", "leistung.html", - "profil.html", "report.html", "scouting.html", "team.html", "uebersicht.html"]; + /* ===================================================================== + DIE LISTE WIRD ABGELEITET, NICHT GEPFLEGT (23.09.2026) + ===================================================================== + + Hier stand eine Liste von neun Dateinamen, und daneben in + Abschnitt 3 eine zweite mit fünfzehn. Am 22.09. hat Filipe die + Kachel „Calls & Protokolle" für Team Dogi bekommen — `calls.html` + gehört seither zum Team. In KEINER der beiden Listen wurde das + nachgezogen, und die Prüfung meldete: + + FEHL calls.html ist auf crew. noch offen (200) + + Das war richtig gemessen und trotzdem kein Befund: Die Seite SOLL + dort offen sein. Rot war die Liste, nicht das Haus. + + Dieselbe Krankheit wie die abgeschriebene Spaltenliste beim + Datenumbau und die Portnummern: Eine Liste, die jemand pflegen + muss, wird beim nächsten Umbau vergessen. + + --------------------------------------------------------------------- + WORAUS JETZT ABGELEITET WIRD — und was das beweist + + Welche Seiten es auf einer Adresse gibt, entscheidet + `gehoertAufDieseAdresse`: Eine Seite gehört hierher, wenn sie + unter den KACHELN dieser Person steht (oder in der kurzen Liste + der Seiten ohne Kachel). Die Kacheln kommen aus `bereicheFuer`, + die Erreichbarkeit aus der Schranke in workspace.js — zwei + getrennte Wege. + + Diese Prüfung fragt die Kacheln und misst danach über HTTP. Sie + beweist damit NICHT, dass die Regel richtig gedacht ist — das + steht in der Regel selbst. Sie beweist, dass die Schranke tut, + was die Kacheln versprechen, und dass keine Seite durchrutscht, + die auf keiner Kachel steht. + + Und sie hat keine Zahl mehr, die morgen falsch ist. + ===================================================================== */ + const { bereicheFuer, zusatzBereicheFuer } = await import("./workspace.js"); + const alleSeiten = readdirSync(new URL("../workspace/", import.meta.url)) + .filter((f) => f.endsWith(".html")); + + const dogiAufCrew = { id: idDogi, rolle: "admin", haus: "crew" }; + const seinsAufCrew = new Set( + [...(bereicheFuer(dogiAufCrew) || []), ...(zusatzBereicheFuer(dogiAufCrew) || [])] + .map((k) => String(k?.ziel || "").split("?")[0]) + .filter(Boolean)); + + /* ZWEI SORTEN, DIE WEDER DEM EINEN NOCH DEM ANDEREN HAUS GEHOEREN + -- und die beim ersten Anlauf faelschlich als Agenturseiten + gezaehlt wurden: + + 1. DIE EINGANGSWAENDE (OHNE_ANMELDUNG in rechte.js): + index.html und crew-index.html. Jede gehoert zu IHRER + Adresse und ist dort ohne Anmeldung offen; auf der anderen + gibt es sie nicht. Sie als "Agenturseite" zu fuehren hiesse + zu verlangen, dass crew-index.html auf der Agenturadresse + steht -- dort ist sie zu Recht ein 404. + + 2. DIE SEITEN OHNE KACHEL (OHNE_KACHEL_UEBERALL in + workspace.js): der eigene Steckbrief, die Regeln des Treffs + und Verwandtes. Sie gehoeren dem Menschen, nicht dem Haus. + + BEIDE LISTEN WERDEN GELESEN, nicht abgeschrieben -- sonst waeren + es zwei weitere Listen, die jemand pflegen muss, und genau das + sollte hier ja aufhoeren. */ + const { OHNE_KACHEL_UEBERALL } = await import("./workspace.js"); + const { OHNE_ANMELDUNG } = await import("./rechte.js"); + const nurName = (p2) => String(p2).replace("/workspace/", ""); + const ohneKachel = new Set([...OHNE_KACHEL_UEBERALL].map(nurName)); + const eingaenge = new Set(OHNE_ANMELDUNG.map(nurName)); + ok(eingaenge.size >= 2 && ohneKachel.size >= 3, + `${eingaenge.size} Eingangswaende, ${ohneKachel.size} Seiten ohne Kachel` + + " -- beide Listen kommen aus dem Quelltext, nicht von hier"); + + const AGENTUR = alleSeiten.filter((f) => + !seinsAufCrew.has(f) && !ohneKachel.has(f) && !eingaenge.has(f)); + + ok(AGENTUR.length >= 5, + `${AGENTUR.length} Seiten gehoeren NICHT zu Team Dogi (${AGENTUR.join(", ")})`); + ok(seinsAufCrew.size >= 5, + `und ${seinsAufCrew.size} gehoeren dorthin`); + /* DIE GEGENPROBE ZUR ABLEITUNG SELBST: calls.html steht seit dem + 22.09. auf der Team-Seite. Stuende es hier wieder unter AGENTUR, + waere die Ableitung kaputt -- und die Pruefung wuerde denselben + Fehlalarm wie zuvor melden, nur mit mehr Umweg. */ + ok(!AGENTUR.includes("calls.html"), + "calls.html zaehlt als Teamseite -- die Ableitung folgt der Kachel von gestern"); + let zu = 0; for (const s of AGENTUR) { const a = await seite(s, CREW, kDogiCrew); @@ -190,10 +282,16 @@ melde("=== 2. Die übrigen neun ==="); melde(""); melde("=== 3. Und was bleibt ==="); { - const TEAM = ["start.html", "aufgaben.html", "chat.html", "dateien.html", - "kalender.html", "wissen.html", "bereich.html", "entwicklung.html", - "befinden.html", "talente.html", "personen.html", "teamlage.html", - "treff-regeln.html", "treff-moderation.html", "rechte.html"]; + /* AUCH HIER ABGELEITET (23.09.2026) -- aus denselben Kacheln wie in + Abschnitt 2. Diese Liste war die zweite, in der `calls.html` + gefehlt hat. Zwei gepflegte Listen fuer dieselbe Frage sind zwei + Gelegenheiten, eine zu vergessen. */ + const { bereicheFuer: bf, zusatzBereicheFuer: zbf } = await import("./workspace.js"); + const aufCrew = { id: idDogi, rolle: "admin", haus: "crew" }; + const TEAM = [...new Set( + [...(bf(aufCrew) || []), ...(zbf(aufCrew) || [])] + .map((k) => String(k?.ziel || "").split("?")[0]) + .filter((z) => z && z.endsWith(".html") && !/^https?:/i.test(z)))]; let da = 0; for (const s of TEAM) { const a = await seite(s, CREW, kDogiCrew); diff --git a/server/workspace.js b/server/workspace.js index 8e060dbc..00190de7 100644 --- a/server/workspace.js +++ b/server/workspace.js @@ -5500,7 +5500,10 @@ function schrankenPfad(roh) { ===================================================================== */ /** Seiten, die in JEDEM Haus dazugehoeren und keine Kachel haben. */ -const OHNE_KACHEL_UEBERALL = new Set([ +/* AUSGELEITET (23.09.2026), damit pruef-haus-seiten sie LESEN kann + statt sie abzuschreiben. Sie hatte dort eine eigene Liste von + Dateinamen -- und die war beim ersten Umbau veraltet. */ +export const OHNE_KACHEL_UEBERALL = new Set([ /* Die Startseite selbst -- sie ist das Ziel der Umleitung. */ "/workspace/start.html", /* Die Regeln des Treffs. Sie gehoeren der Community und dem Team. */