From ede34fe386f909ec632104022582337e04f359ea Mon Sep 17 00:00:00 2001 From: Dogfather Date: Thu, 10 Sep 2026 01:05:01 +0200 Subject: [PATCH] Der Rollenname stand in zwei Dateien, die jeder bekommt SELBST EINGEBAUT, EINE STUNDE VORHER. Beim Bau der Kategorien habe ich SECHS Vergleiche und VIER Kommentare mit dem Rollennamen nach assets/js/aufgaben.js und assets/js/start.js geschrieben -- waehrend ich an anderer Stelle penibel darauf achtete, ihn herauszuhalten. Alles unter workspace/ geht an JEDEN, der die Seite oeffnet. Ein Blick in den Quelltext, und der ganze verborgene Zugang waere gefunden gewesen: nicht wer ein Modi ist, aber dass es die Rolle ueberhaupt gibt -- und genau das war Filipes Bedingung ("damit die von der workspace auch nicht mal sehen dass die modis von mir einen eigenen zugang haben"). Gefunden habe ich es durch Nachsehen, nicht durch Nachdenken. Nachgedacht hatte ich vorher schon, und zwar richtig -- beim Anzeigenamen und bei der Rollenauswahl habe ich es sauber ueber den Server geloest. Eine Stunde spaeter habe ich dieselbe Regel dreimal gebrochen, ohne es zu merken. WAS AN DIE STELLE TRITT, dreimal derselbe Gedanke: * Das Vorlagenbrett: /workspace/api/vorlagen liefert den Katalog jetzt schlicht nicht an die Betroffenen. `if (!vorlagen) return` laesst das Brett dann verborgen -- dieselbe Wirkung, ohne eine Zeile, die verraet, fuer wen sie gilt. * Das Kategorie-Feld: statt `ich.rolle === '...'` kommt vom Server `kategorie_fuer` -- NUMMERN statt eines Rollennamens. Aus Nummern laesst sich nichts schliessen; wer keine bekommt, sieht eine leere Liste, und eine leere Liste sagt nichts. `null` heisst "gilt immer" und muss `null` bleiben: Ein `|| []` daraus zu machen waere der stille Fehler, aus "gilt immer" wuerde "gilt nie". * Die Kommentare sagen jetzt, WAS gilt, ohne zu sagen, FUER WEN. UND EINE SPERRE DAGEGEN: pruef-modi-wortleck durchsucht alle 73 ausgelieferten Dateien nach dem Rollennamen. Die Regel ist damit kein Vorsatz mehr, sondern ein Werkzeug -- wer ihn dort hineinschreibt, bekommt einen roten Lauf statt eines erhobenen Zeigefingers im Kommentar. Mit Gegenprobe in beide Richtungen: Eine eingebaute Fundstelle MUSS erkannt werden, und "modifiziert", "Modul", "Modus" duerfen NICHT anschlagen -- eine Pruefung, die staendig Fehlalarm gibt, wird abgeschaltet und faengt dann auch den echten Fall nicht mehr. Die Dateizahl steht in der Bedingung, nicht nur im Meldetext: Faende die Suche keine einzige Datei, waere sonst alles gruen, ohne dass etwas angesehen wurde. AUSSERDEM BELEGT statt behauptet: Dass das Kategorie-Feld bei DogFather nur erscheint, wenn er wirklich einen Modi eintraegt, steht jetzt in der Pruefung -- erst ein Creator (Feld bleibt weg), dann ein Modi (Feld kommt). Ohne den zweiten Schritt waere "bleibt weg" auch dann gruen, wenn es NIE kaeme. GEPRUEFT: pruef-modi-wortleck (4, neu), pruef-modi-kategorien (25), pruef-modi-verborgen (57), pruef-vorlagen, pruef-aufgabenbrett. Co-Authored-By: Claude Opus 5 --- server/pruef-modi-kategorien.mjs | 38 +++++++++++ server/pruef-modi-wortleck.mjs | 105 +++++++++++++++++++++++++++++++ server/workspace-aufgaben.js | 6 +- server/workspace-vorlagen.js | 23 ++++++- server/workspace.js | 30 +++++++++ workspace/app.webmanifest | 8 +-- workspace/assets/js/aufgaben.js | 68 ++++++++++---------- workspace/assets/js/start.js | 8 ++- workspace/aufgaben.html | 22 +++---- workspace/automation.html | 24 +++---- workspace/bereich.html | 32 +++++----- workspace/calls.html | 26 ++++---- workspace/chat.html | 24 +++---- workspace/content.html | 28 ++++----- workspace/dateien.html | 24 +++---- workspace/index.html | 8 +-- workspace/kalender.html | 26 ++++---- workspace/leistung.html | 24 +++---- workspace/personen.html | 24 +++---- workspace/profil.html | 26 ++++---- workspace/report.html | 26 ++++---- workspace/scouting.html | 24 +++---- workspace/start.html | 22 +++---- workspace/startcheck.html | 26 ++++---- workspace/steckbrief.html | 24 +++---- workspace/team.html | 24 +++---- workspace/uebersicht.html | 24 +++---- workspace/wissen.html | 24 +++---- 28 files changed, 484 insertions(+), 284 deletions(-) create mode 100644 server/pruef-modi-wortleck.mjs diff --git a/server/pruef-modi-kategorien.mjs b/server/pruef-modi-kategorien.mjs index b4430794..82efc979 100644 --- a/server/pruef-modi-kategorien.mjs +++ b/server/pruef-modi-kategorien.mjs @@ -284,6 +284,44 @@ console.log("\n=== 5. Das Feld im echten Formular ===\n"); await kontext.close(); } + /* DOGFATHER: das Feld folgt der gewaehlten Person. + + Er sieht die Kategorien -- aber an einer Creator-Aufgabe haben + sie nichts zu suchen. Ohne diesen Abschnitt waere "nur bei den + Modis" eine Behauptung: Das Feld koennte bei ihm dauerhaft + dastehen, und oben waere trotzdem alles gruen. */ + { + const { kontext, seite } = await formular("admin", "CODE-DOGI-0001"); + const start = await seite.evaluate(() => { + const h = document.getElementById("feld-kategorie"); + return !!h && !h.hidden; + }); + ok(!start, "bei DogFather steht das Feld zunaechst nicht da"); + + /* Einen Creator eintragen -- es muss weg bleiben. */ + const mitCreator = await seite.evaluate((id) => { + const f = document.getElementById("f-verant"); + f.value = String(id); + f.dispatchEvent(new Event("change", { bubbles: true })); + const h = document.getElementById("feld-kategorie"); + return !!h && !h.hidden; + }, idCreat); + ok(!mitCreator, "auch nicht, wenn er einen Creator eintraegt"); + + /* Und jetzt einen Modi -- jetzt muss es kommen. Das ist die + Gegenprobe zu den beiden Zeilen darueber: Ohne sie waere "steht + nicht da" auch dann gruen, wenn es NIE kaeme. */ + const mitModi = await seite.evaluate((id) => { + const f = document.getElementById("f-verant"); + f.value = String(id); + f.dispatchEvent(new Event("change", { bubbles: true })); + const h = document.getElementById("feld-kategorie"); + return !!h && !h.hidden; + }, idModi); + ok(mitModi, "sobald er einen Modi eintraegt, erscheint es"); + await kontext.close(); + } + /* GEGENPROBE ZUM BROWSERTEIL: Findet die Suche die Namen ueberhaupt, wenn sie dastehen? Ohne diesen Schritt bewiese der Haken oben nichts -- er waere auch gruen, wenn innerText leer waere. */ diff --git a/server/pruef-modi-wortleck.mjs b/server/pruef-modi-wortleck.mjs new file mode 100644 index 00000000..1d419f36 --- /dev/null +++ b/server/pruef-modi-wortleck.mjs @@ -0,0 +1,105 @@ +/* ===================================================================== + 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"); + +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 = []; +for (const datei of alle) { + 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"); + +/* ---------- 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); diff --git a/server/workspace-aufgaben.js b/server/workspace-aufgaben.js index 54472efc..5c9763f3 100644 --- a/server/workspace-aufgaben.js +++ b/server/workspace-aufgaben.js @@ -12,7 +12,7 @@ import express from "express"; import { db, protokolliere, echteIp, sitzungLesen, betreutWo, istLeitung, ohneDogFather, heuteLokal, ROLLEN_SORTIERUNG, betreuteIds, externPruefen, externSql, sichtbarePersonenIds, sichtbareCreatorIds, - MODI_KATEGORIEN, kategorienFuer, + MODI_KATEGORIEN, kategorienFuer, kategoriePersonen, } from "./workspace.js"; export const aufgabenRouter = express.Router(); @@ -219,6 +219,10 @@ aufgabenRouter.get("/workspace/api/aufgaben", (req, res) => { kann. Wer sie nicht benutzen darf, bekommt eine leere Liste -- und die Oberflaeche zeigt dann gar kein Feld. */ kategorien: kategorienFuer(req.person), + /* Fuer wessen Aufgaben sie gilt -- als Nummern, nicht als + Rollenname. Im Browser darf nichts stehen, woraus sich auf eine + verborgene Rolle schliessen laesst. */ + kategorie_fuer: kategoriePersonen(req.person), }); } catch (fehler) { console.error("[workspace] Aufgaben lesen:", fehler?.message); diff --git a/server/workspace-vorlagen.js b/server/workspace-vorlagen.js index aed88e9a..3675e119 100644 --- a/server/workspace-vorlagen.js +++ b/server/workspace-vorlagen.js @@ -1099,13 +1099,34 @@ export const AUFGABEN_VORLAGEN_FLACH = Object.entries(AUFGABEN_VORLAGEN) vorlagenRouter.use("/workspace/api/vorlagen", angemeldet); vorlagenRouter.get("/workspace/api/vorlagen", (req, res) => { + /* ===================================================================== + WER DIESEN KATALOG NICHT BEKOMMT (10.09.2026) + + `AUFGABEN_VORLAGEN` sind 80 Aufgaben fuer den Aufbau eines KANALS -- + Ton einstellen, Sendeplan festlegen, Verweildauer vergleichen. Wer + moderiert, statt zu senden, kann damit nichts anfangen; ein + Vorschlag, der nicht passt, ist schlimmer als keiner. + + WARUM DIE ENTSCHEIDUNG HIER FAELLT UND NICHT IM BROWSER: Beim + ersten Anlauf stand im Browser `if (ich.rolle === 'modi')`. Das ist + zwar richtig gedacht, steht aber in assets/js/aufgaben.js -- einer + Datei, die JEDER bekommt, der die Seite oeffnet. Ein Blick in den + Quelltext, und die verborgene Rolle waere gefunden gewesen. Ich + habe mir das selbst eingebaut und beim Nachsehen gefunden; seither + wacht pruef-modi-wortleck darueber, dass das Wort in keiner + ausgelieferten Datei steht. + + `null` statt einer leeren Liste: Die Oberflaeche prueft `if + (!vorlagen) return;` und laesst das Brett dann verborgen -- ohne + eine einzige Zeile, die verraet, fuer wen. */ + const ohneKatalog = req.person?.rolle === "modi"; res.json({ content: CONTENT_IDEEN, live: LIVE_PUNKTE, community: COMMUNITY_PUNKTE, technik: TECHNIK_PUNKTE, calls: CALL_LEITFAEDEN, - aufgaben: AUFGABEN_VORLAGEN, + aufgaben: ohneKatalog ? null : AUFGABEN_VORLAGEN, }); }); diff --git a/server/workspace.js b/server/workspace.js index fafcddcd..a2804c32 100644 --- a/server/workspace.js +++ b/server/workspace.js @@ -345,6 +345,36 @@ export function kategorienFuer(person) { return person.rolle === "modi" || person.rolle === "admin" ? MODI_KATEGORIEN : []; } +/** + * FUER WESSEN AUFGABEN gilt die Kategorie? (10.09.2026) + * + * null -> fuer alle eigenen; die Oberflaeche zeigt das Feld immer + * [Nummern] -> nur wenn eine dieser Personen gewaehlt ist + * [] -> nie + * + * WARUM DAS DER SERVER BEANTWORTET UND NICHT DER BROWSER: Die + * Oberflaeche muesste sonst `p.rolle === 'modi'` vergleichen -- und + * assets/js/aufgaben.js bekommt JEDER, der die Seite oeffnet. Genau so + * stand es beim ersten Anlauf da, an sechs Stellen. Mit Nummern statt + * einem Rollennamen steht im Browser nichts, woraus sich etwas + * schliessen laesst: Wer keine bekommt, sieht eine leere Liste, und + * eine leere Liste sagt nichts. + */ +export function kategoriePersonen(person) { + if (!person) return []; + /* Ein Modi arbeitet ausschliesslich an eigenen Aufgaben -- dort gilt + sie immer, unabhaengig davon, wen er eintraegt. */ + if (person.rolle === "modi") return null; + if (person.rolle !== "admin") return []; + try { + return db().prepare( + "SELECT id FROM personen WHERE rolle = 'modi' AND aktiv = 1").all().map((z) => z.id); + } catch { + /* Ohne Datenbank lieber kein Feld als ein falsches. */ + return []; + } +} + export function rollentextFuer(person) { return person?.rolle === "modi" ? MODI_ROLLENTEXT : null; } diff --git a/workspace/app.webmanifest b/workspace/app.webmanifest index f9928569..5855f0cb 100644 --- a/workspace/app.webmanifest +++ b/workspace/app.webmanifest @@ -13,25 +13,25 @@ "theme_color": "#06090f", "icons": [ { - "src": "/assets/img/app-symbole/workspace-192.png?v=202609100051", + "src": "/assets/img/app-symbole/workspace-192.png?v=202609100105", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/workspace-512.png?v=202609100051", + "src": "/assets/img/app-symbole/workspace-512.png?v=202609100105", "sizes": "512x512", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609100051", + "src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609100105", "sizes": "192x192", "type": "image/png", "purpose": "maskable" }, { - "src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609100051", + "src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609100105", "sizes": "512x512", "type": "image/png", "purpose": "maskable" diff --git a/workspace/assets/js/aufgaben.js b/workspace/assets/js/aufgaben.js index 19c14578..549e91ca 100644 --- a/workspace/assets/js/aufgaben.js +++ b/workspace/assets/js/aufgaben.js @@ -699,10 +699,18 @@ die Frage auf, fuer wen sie da ist. Genau die soll niemand stellen. ===================================================================== */ let kategorien = []; - /* Wer ein Modi ist -- gefuellt aus der Personenliste, die ohnehin - geladen wird. Sie enthaelt Modis nur fuer den, der sie sehen darf; - fuer alle anderen bleibt diese Menge leer. */ - const modis = new Set(); + /* FUER WESSEN AUFGABEN die Kategorie gilt. Kommt fertig vom Server: + + null -> fuer alle eigenen (das Feld steht immer da) + [Nummern] -> nur wenn eine dieser Personen gewaehlt ist + [] -> nie + + ALS NUMMERN UND NICHT ALS ROLLENNAME, und das ist kein Zufall: Beim + ersten Anlauf stand hier ein Vergleich auf einen Rollennamen -- in + einer Datei, die JEDER bekommt, der die Seite oeffnet. Aus Nummern + laesst sich nichts schliessen; wer keine bekommt, sieht eine leere + Liste, und eine leere Liste sagt nichts. */ + let kategorieFuer = []; function kategorienEinsetzen() { if (!kategorien.length) return; @@ -718,22 +726,24 @@ } } - /* Gehoert diese Aufgabe zu einem Modi? + /* Braucht diese Aufgabe eine Kategorie? - Fuer einen Modi immer (es sind seine eigenen). Fuer die - DogFather-Rolle nur dann, wenn die gewaehlte Person eine ist -- - sonst stuende das Feld auch an jeder Creator-Aufgabe, und genau das - wollte Filipe nicht ("nur bei den Modis"). */ - function gehoertModi(creatorId, verantId) { - if (ich?.rolle === 'modi') return true; - return modis.has(Number(creatorId)) || modis.has(Number(verantId)); + `null` heisst "immer" -- dann arbeitet die angemeldete Person + ausschliesslich an eigenen Aufgaben, und dort gilt sie unabhaengig + davon, wen sie eintraegt. Sonst entscheidet die gewaehlte Person. + Wer eine leere Liste bekommt, sieht das Feld nie. */ + function kategorieNoetig(creatorId, verantId) { + if (kategorieFuer === null) return true; + if (!Array.isArray(kategorieFuer) || !kategorieFuer.length) return false; + return kategorieFuer.includes(Number(creatorId)) + || kategorieFuer.includes(Number(verantId)); } function kategorieFeldZeigen(praefix) { const huelle = $(praefix === 'f' ? 'feld-kategorie' : 'b-feld-kategorie'); if (!huelle) return; const zeigen = kategorien.length - && gehoertModi($(`${praefix}-creator`)?.value, $(`${praefix}-verant`)?.value); + && kategorieNoetig($(`${praefix}-creator`)?.value, $(`${praefix}-verant`)?.value); huelle.hidden = !zeigen; /* Verborgen heisst auch: nichts mitschicken. Ein Wert, der in einem unsichtbaren Feld stehenbleibt, wandert sonst beim naechsten @@ -748,6 +758,10 @@ const daten = await antwort.json(); alleAufgaben = daten.aufgaben || []; kategorien = daten.kategorien || []; + /* `null` muss `null` BLEIBEN -- ein `|| []` daraus zu machen waere + der stille Fehler: Aus "gilt immer" wuerde "gilt nie", und das + Feld verschwaende fuer genau die, die es brauchen. */ + kategorieFuer = daten.kategorie_fuer === undefined ? [] : daten.kategorie_fuer; kategorienEinsetzen(); kategorieFeldZeigen('f'); lageZeigen(alleAufgaben); @@ -905,11 +919,6 @@ Das laesst sich nicht rueckgaengig machen. Erledigte Aufgaben sollten normalerwe try { const { personen } = await (await hole('/workspace/api/personen')).json(); for (const p of personen) { - /* Wer ein Modi ist, entscheidet spaeter, ob das Kategorie-Feld - ueberhaupt erscheint. Die Liste enthaelt Modis nur fuer den, - der sie sehen darf -- fuer alle anderen bleibt die Menge - leer, und das Feld bleibt weg. */ - if (p.rolle === 'modi') modis.add(Number(p.id)); for (const ziel of ['f-creator', 'f-verant', 'b-creator', 'b-verant']) { const o = el('option', null, `${p.name} (${p.rolle})`); o.value = String(p.id); @@ -1010,23 +1019,14 @@ Das laesst sich nicht rueckgaengig machen. Erledigte Aufgaben sollten normalerwe async function vorlagenbrettZeigen() { const ziel = $('vorlagenbrett'); if (!ziel || !ich) return; - /* NICHT FUER EINEN MODI (10.09.2026). + /* WER DIESEN KATALOG BEKOMMT, ENTSCHEIDET DER SERVER. - Das Vorlagenbrett haelt 80 fertige Aufgaben in vier Bereichen und - vier Stufen bereit -- den Begleitplan fuer einen CREATOR, von - "Ton aufnehmen und anhoeren" bis "Monatsbericht mit drei festen - Zahlen". Fuer einen Modi ist davon nichts gedacht: Er moderiert, - er baut keinen Kanal auf. - - Aufgefallen ist das auf dem Bildschirmfoto der Browserpruefung, - nicht im Code -- die Kachel laedt fehlerfrei, sie zeigt nur das - Falsche. Ein Vorschlag, der nicht passt, ist schlimmer als - keiner: Man raeumt ihn nicht weg, man arbeitet um ihn herum. - - SEIN Katalog steht in Teil 2 des Anforderungsdokuments (die 60+ - Aufgaben aus Phase 1 bis 6). Bis der da ist, steht hier nichts -- - das ist ehrlicher als etwas Fremdes. */ - if (ich.rolle === 'modi') { ziel.hidden = true; return; } + Hier stand kurzzeitig ein Vergleich auf einen Rollennamen -- in + einer Datei, die JEDER bekommt, der die Seite oeffnet. Jetzt + liefert /workspace/api/vorlagen fuer die Betroffenen schlicht + nichts, und `if (!vorlagen) return` weiter unten laesst das Brett + verborgen. Dieselbe Wirkung, ohne eine Zeile, die verraet, fuer + wen sie gilt. */ if (!vorlagen) { try { const a = await hole('/workspace/api/vorlagen'); diff --git a/workspace/assets/js/start.js b/workspace/assets/js/start.js index dac122ab..dd242b25 100644 --- a/workspace/assets/js/start.js +++ b/workspace/assets/js/start.js @@ -722,9 +722,11 @@ fuenf bekannten Rollen nichts. */ /* DIE ZIERZEILE UEBER DEM TITEL (10.09.2026). - Sie nennt den Betrieb -- fest "Spicy Media" in start.html. Fuer - einen Modi stimmt das nicht, er gehoert zu Team Dogi; der Server - schickt dann den passenden Namen mit. + Sie nennt den Betrieb -- fest "Spicy Media" in start.html. Das + stimmt nicht fuer jeden, der hier arbeitet; wo es nicht stimmt, + schickt der Server den passenden Namen mit. WER das ist, steht + ausdruecklich nicht in dieser Datei: Sie bekommt jeder, der die + Seite oeffnet. ERSETZT WIRD NUR DER TEXTKNOTEN, nicht der ganze Inhalt: In dem Element sitzen zwei als Zierrauten links und diff --git a/workspace/aufgaben.html b/workspace/aufgaben.html index d2dc01a4..71db8113 100644 --- a/workspace/aufgaben.html +++ b/workspace/aufgaben.html @@ -12,12 +12,12 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - + + + + + + @@ -245,10 +245,10 @@ - - - - - + + + + + diff --git a/workspace/automation.html b/workspace/automation.html index c0d428f9..ad8f867c 100644 --- a/workspace/automation.html +++ b/workspace/automation.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -140,10 +140,10 @@ - - - - - + + + + + diff --git a/workspace/bereich.html b/workspace/bereich.html index 7b655f8b..240a9b2c 100644 --- a/workspace/bereich.html +++ b/workspace/bereich.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -149,14 +149,14 @@ - - - - - - - - - + + + + + + + + + diff --git a/workspace/calls.html b/workspace/calls.html index fe6af1f3..8a8658ce 100644 --- a/workspace/calls.html +++ b/workspace/calls.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -82,11 +82,11 @@ - - - - - - + + + + + + diff --git a/workspace/chat.html b/workspace/chat.html index 8734a6b4..c96800de 100644 --- a/workspace/chat.html +++ b/workspace/chat.html @@ -12,19 +12,19 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - + + + + - - - + + + @@ -247,10 +247,10 @@ - - - - - + + + + + diff --git a/workspace/content.html b/workspace/content.html index 154a196b..41ecc6c8 100644 --- a/workspace/content.html +++ b/workspace/content.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -172,12 +172,12 @@ - - - - - - - + + + + + + + diff --git a/workspace/dateien.html b/workspace/dateien.html index 9ea98cca..5bac82e6 100644 --- a/workspace/dateien.html +++ b/workspace/dateien.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -101,10 +101,10 @@ - - - - - + + + + + diff --git a/workspace/index.html b/workspace/index.html index 822a0823..29f678af 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -30,9 +30,9 @@ - - - + + + @@ -401,6 +401,6 @@ - + diff --git a/workspace/kalender.html b/workspace/kalender.html index f054e2c3..a322e4bf 100644 --- a/workspace/kalender.html +++ b/workspace/kalender.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -370,11 +370,11 @@ - - - - - - + + + + + + diff --git a/workspace/leistung.html b/workspace/leistung.html index db2e9e59..f0eebd53 100644 --- a/workspace/leistung.html +++ b/workspace/leistung.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -217,10 +217,10 @@ - - - - - + + + + + diff --git a/workspace/personen.html b/workspace/personen.html index 0df13d5b..cccd1002 100644 --- a/workspace/personen.html +++ b/workspace/personen.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -335,10 +335,10 @@ - - - - - + + + + + diff --git a/workspace/profil.html b/workspace/profil.html index f85459b1..dd891c55 100644 --- a/workspace/profil.html +++ b/workspace/profil.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -207,11 +207,11 @@ - - - - - - + + + + + + diff --git a/workspace/report.html b/workspace/report.html index c8968446..a5c25bde 100644 --- a/workspace/report.html +++ b/workspace/report.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -99,11 +99,11 @@ - - - - - - + + + + + + diff --git a/workspace/scouting.html b/workspace/scouting.html index 545ab78b..81708418 100644 --- a/workspace/scouting.html +++ b/workspace/scouting.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -132,10 +132,10 @@ - - - - - + + + + + diff --git a/workspace/start.html b/workspace/start.html index e28252e4..9da8af96 100644 --- a/workspace/start.html +++ b/workspace/start.html @@ -12,14 +12,14 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - + + + + - - + + @@ -667,10 +667,10 @@

- - - - - + + + + + diff --git a/workspace/startcheck.html b/workspace/startcheck.html index 3e9c365b..6445e49b 100644 --- a/workspace/startcheck.html +++ b/workspace/startcheck.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -78,11 +78,11 @@ - - - - - - + + + + + + diff --git a/workspace/steckbrief.html b/workspace/steckbrief.html index 69ad87e3..a5c31ee2 100644 --- a/workspace/steckbrief.html +++ b/workspace/steckbrief.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -119,10 +119,10 @@ - - - - - + + + + + diff --git a/workspace/team.html b/workspace/team.html index 27cff631..c96517e8 100644 --- a/workspace/team.html +++ b/workspace/team.html @@ -7,13 +7,13 @@ - - - - - - - + + + + + + + @@ -103,10 +103,10 @@ - - - - - + + + + + diff --git a/workspace/uebersicht.html b/workspace/uebersicht.html index f54c6aaf..cb376c81 100644 --- a/workspace/uebersicht.html +++ b/workspace/uebersicht.html @@ -12,15 +12,15 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - + + + + - - - + + + @@ -142,11 +142,11 @@ - + - - - - + + + + diff --git a/workspace/wissen.html b/workspace/wissen.html index 17b0e500..ee067569 100644 --- a/workspace/wissen.html +++ b/workspace/wissen.html @@ -12,13 +12,13 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + @@ -183,10 +183,10 @@ - - - - - + + + + +