Filipe: "ich will das alles auch so perfekt dass ich es ganz einfach
und easy mit obs oder mit tiktok studio verbinden kann. also so dass
man dan nur die kamera und das video sieht."
WARUM OHNE ANMELDUNG -- nachgesehen, nicht angenommen
OBS speichert die Anmeldung einer Browser-Quelle NICHT zuverlaessig;
im OBS-Forum stehen dazu Meldungen bis in die aktuelle Fassung 31.
Eine Quelle, bei der man sich nach jedem Programmstart neu anmelden
muss, ist mitten in einer Sendung unbrauchbar.
Deshalb ein SCHLUESSEL in der Adresse -- derselbe Weg, den jedes
Alert-Werkzeug im Netz geht. 32 Byte aus dem Zufall des Systems,
verglichen wird zeitgleich (`timingSafeEqual`): Ein gewoehnlicher
Vergleich bricht beim ersten falschen Zeichen ab, und aus den
Bruchteilen einer Millisekunde laesst sich ein Schluessel Zeichen
fuer Zeichen erraten.
DREI QUELLEN, WEIL DREI DINGE VERSCHIEDEN SIND
buehne.html Das laufende YouTube-Video, auf die Sekunde genau wie
bei allen anderen. Stumm (der Ton kommt aus dem
Mischpult) und ohne jede Bedienung -- was hier zu
sehen ist, geht in den Stream.
DIE EIGENE KAMERA IST ABSICHTLICH NICHT DRIN. Sie ist
in OBS direkt als Geraet verfuegbar, in besserer
Qualitaet und frei in Groesse und Lage -- genau das,
was Filipe will ("meine kamera groesser machen video
kleiner"). Den Umweg ueber den Browser zu nehmen
hiesse, Qualitaet gegen nichts einzutauschen und die
Groesse festzulegen statt sie freizugeben.
tafel.html Nur die Spendenkarten, auf DURCHSICHTIGEM Grund.
Groesse und Lage stehen in der Adresse (`&g=1.6`,
`&pos=or`): Wer in OBS eine Quelle einrichtet, hat die
Adresse ohnehin vor sich -- ein Wert, den man
stattdessen im Regiepult suchen muesste, waere ein
Fensterwechsel mitten im Einrichten. Alles rechnet in
`rem`, ein Wert nimmt Schrift, Bild und Polsterung
gleichmaessig mit.
Buehnenmodus `reaktion.html?nur=buehne` -- dieselbe Seite, nur ohne
alles Bedienbare. Fuer den Fall, dass GAESTE im Bild
sind: Deren Kameras kommen ueber eine
Direktverbindung an, und die braucht eine angemeldete
Seite. Diese eine wird als Fenster aufgenommen.
ES IST DIESELBE SEITE UND NICHT EINE ZWEITE. Eine
eigene muesste Video, Kameras, Verbindungsaufbau und
Nachfuehrung noch einmal enthalten -- und beim
naechsten Umbau saehe eine von beiden anders aus.
WAS HERAUSKOMMT, IST DIE EIGENTLICHE FRAGE
Wer den Schluessel hat, sieht genau das, was ohnehin im Stream
steht: Video, Stand, Sekunde, Titel -- und die Spendenkarten. Kein
Chat, keine Namen von Zusehenden, keine Zahlen ueber das Haus. Die
Pruefung zaehlt die Felder der Auskunft EINZELN auf und weist jedes
verbotene namentlich nach; eine Auskunft, die "ungefaehr das
Richtige" enthaelt, ist bei einem Weg ohne Anmeldung keine.
Ein neuer Schluessel macht die alten Adressen sofort tot -- und
schliesst die laufenden Quellen. Sonst liefe eine mit dem alten
weiter, obwohl er zurueckgezogen ist, und man haelt sich fuer
sicher, ohne es zu sein.
SIE MUESSEN TAGE LAUFEN, OHNE DASS JEMAND HINSIEHT
Das ist der Unterschied zu einer Seite im Browser: Wer eine Seite
offen hat, merkt, wenn sie haengt. Eine Quelle in OBS laeuft im
Hintergrund, und ein Stillstand faellt erst auf, wenn die erste
Spende nicht erscheint -- mitten in der Sendung. Deshalb ein
Lebenszeichen alle 25 Sekunden, eine eigene Wache (70 Sekunden ohne
alles = neu verbinden) und ein sofortiger Neuaufbau, wenn der
Rechner aus dem Ruhezustand kommt.
Und: Ein Fehler wird angezeigt, aber nur der, der etwas bedeutet --
ein falscher Schluessel. Alles andere bleibt still, weil jede
Flaeche hier im Stream zu sehen waere.
ZWEI EIGENE FEHLER, BEIDE VON DER MESSUNG GEFUNDEN
1. Die Quellen kamen mit 401 zurueck, obwohl die Seiten laengst
geladen waren: `aufgabenRouter` haengt eine Schranke ueber ALLE
Pfade unter /workspace/api. Genau dafuer stehen `sicherungRouter`
und der Weg fuers Profilbild schon davor -- die Buehne ist der
dritte Fall derselben Art und steht jetzt dort.
2. `waitUntil: "networkidle"` auf einer Seite mit Ereignisstrom. Der
Strom endet absichtlich nie; die Messung wartete auf einen
Zustand, der nicht eintreten kann, und brach nach 30 Sekunden ab.
Dieselbe Falle wie am 06.09. beim Regressionslauf.
ZWEI PRUEFUNGEN WURDEN DABEI GENAUER
`pruef-struktur` verlangte von den zwei OBS-Quellen ein Symbol fuer
den Startbildschirm, ein Manifest und eine Leistenfarbe. Sie
laufen in einem Programmfenster und werden nie installiert -- sie
fallen aus dieser Frage heraus, benannt und mit Grund.
Die Namensstreit-Regel zaehlte jede Klasse, die irgendwo in einem
Selektor vorkommt. Damit galt auch
`body[data-nur="buehne"] .kopfleiste { display: none }` als eigene
Klasse -- dabei ist das das Gegenteil: eine absichtliche
Bezugnahme, um sie im Buehnenmodus wegzunehmen. Gezaehlt wird
jetzt nur, was am ANFANG einer Regel steht, also als eigenes
Bauteil gemeint ist. Mit Gegenprobe in beide Richtungen -- sonst
haette ich eine Regel nur so lange geschaerft, bis sie schweigt.
GEMESSEN
mess-buehne (neu) Ein Browserfenster OHNE jeden Keks: beide
Quellen arbeiten, 0 Kekse, Grund durchsichtig
(rgba(0,0,0,0)), Karte laeuft an (25 EUR,
Rudel-Legende, 348x178). Falscher Schluessel: kein
Inhalt, Grund im Bild. Neuer Schluessel: alter 404,
neuer 200. Buehnenmodus: Kopf, Chat, Pult und
Schild weg, Leinwand da, Saal 720 von 720.
pruef-buehne (neu) 36 Punkte, 0 Fehler
pruef-reaktion 156 (war 154), spenden 46, haus-trennung 100,
haus-seiten 38, struktur 35, css-klassen 33,
verborgen 25, rechtetafel 19, portnummern 15,
ports 8 -- alle 0 Fehler.
835 lines
40 KiB
JavaScript
835 lines
40 KiB
JavaScript
/* =====================================================================
|
||
DIE RECHTETAFEL — was jede Rolle sehen darf, an einer Stelle
|
||
=====================================================================
|
||
|
||
Filipe, 11.09.2026:
|
||
|
||
"egal welche rolle oder person hinzugefuegt wird soll immer nur
|
||
das sehen wass ich erlaube. mehr nicht. soll nichts so sein dass
|
||
wenn mann eine rolle oder jemanden hinzufuegt dass er dan alles
|
||
sieht, soll jede rolle immer nur das sehen was sie sehen sollen."
|
||
|
||
---------------------------------------------------------------------
|
||
DAS IST EINE UMKEHRUNG DER BAUWEISE, KEINE EINSTELLUNG
|
||
|
||
Vorher galt: erlauben, ausser es steht etwas dagegen. Die Tabelle
|
||
der geschuetzten Seiten hiess sogar so -- "GESCHUETZT ist die
|
||
Ausnahme, nicht die Regel" -- und sie kannte zwei Wege, auf denen
|
||
etwas durchfiel:
|
||
|
||
1. `null` als Wert hiess "jede angemeldete Rolle". NEUN von zwanzig
|
||
Seiten standen darauf: Start, Uebersicht, Aufgaben, Chat,
|
||
Kalender, Dateien, Calls, Start-Check, Wissen. Eine neue Rolle
|
||
erbte sie alle, ohne dass jemand etwas erlaubt haette.
|
||
|
||
2. Eine Seite, die GAR NICHT in der Tabelle stand, fiel durch
|
||
dieselbe Bedingung (`if (erlaubt && ...)`) und war damit
|
||
ebenfalls fuer jeden offen. Das betraf am 11.09.2026 keine
|
||
einzige Seite -- gemessen, nicht gehofft --, aber jede neue
|
||
waere so entstanden.
|
||
|
||
Ab hier gilt das Gegenteil: WAS NICHT IN DIESER TAFEL STEHT, IST
|
||
VERBOTEN. Kein `null`, kein `undefined`, kein Zweig, der etwas
|
||
durchlaesst. `darfSeite()` kennt genau zwei Antworten.
|
||
|
||
---------------------------------------------------------------------
|
||
WARUM DAS NICHT "DIE LISTE EINMAL DURCHGEHEN" IST
|
||
|
||
Das waere die naheliegende Antwort und die falsche. Die Rolle wird
|
||
im Haus an 74 Stellen in 20 Modulen abgefragt (gezaehlt, nicht
|
||
geschaetzt). Drei Gruende, und alle drei sind hier schon eingetreten:
|
||
|
||
* Eine Liste ALTERT. Am 09.09. war `content.html` fuer eine neue
|
||
Rolle offen -- nicht aus Nachlaessigkeit, sondern weil die Seite
|
||
spaeter dazukam als die Ueberlegung.
|
||
* Eine vergessene Erlaubnis SCHWEIGT. Sie faellt nur dem auf, der
|
||
hindurchgeht, und der merkt nichts: Die Seite laedt ja. In der
|
||
anderen Richtung ist es schlimmer -- eine Seite, die zu viel
|
||
zeigt, sieht aus wie eine Seite, die funktioniert.
|
||
* Bei 74 Stellen ist "ich gehe sie alle durch" kein Verfahren,
|
||
sondern ein Vorsatz.
|
||
|
||
Deshalb steht die Antwort nicht in einem Kommentar, sondern in
|
||
`pruef-rechtetafel.mjs`: Eine Rolle ohne Eintrag macht den Prueflauf
|
||
rot. Eine Seite ohne Eintrag macht den Prueflauf rot. Man KANN es
|
||
nicht mehr vergessen.
|
||
|
||
---------------------------------------------------------------------
|
||
DIESE DATEI HAENGT VON NICHTS AB
|
||
|
||
Kein Import aus workspace.js -- sonst gaebe es einen Ring, und die
|
||
Tafel muesste warten, bis das grosse Modul geladen ist. Sie ist
|
||
damit auch ohne laufenden Server pruefbar, genau wie crew-adresse.js.
|
||
===================================================================== */
|
||
|
||
/** Alle Rollen, die es gibt. Muss zu ROLLEN in workspace.js passen --
|
||
* pruef-rechtetafel vergleicht die beiden und wird rot, wenn eine
|
||
* Rolle nur in einer der beiden Listen steht. */
|
||
export const ALLE_ROLLEN = [
|
||
"spicy", "admin", "manager", "scout", "creator", "hand", "modi",
|
||
/* DIE LINKE HAND (21.09.2026). Dieselbe Liste wie ROLLEN in
|
||
workspace.js -- pruef-rechtetafel haelt beide gegeneinander und
|
||
wird rot, sobald eine Rolle nur in einer steht. Genau das ist
|
||
beim Bauen passiert und hat den Eintrag hier gefunden. */
|
||
"linke",
|
||
/* DIE COMMUNITY (11.09.2026). Zuschauer mit einem Zugang, die den
|
||
Treff sehen -- und sonst nichts. Sie steht hier NICHT in `ALLE`
|
||
(siehe unten): Wer neu dazukommt, bekommt genau die zwei Seiten,
|
||
die weiter unten ausdruecklich seinen Namen tragen. */
|
||
"gast",
|
||
];
|
||
|
||
/* Kurzform fuer die Tafel unten. `ALLE` heisst hier ausdruecklich
|
||
"alle Rollen, die es GIBT" -- nicht "alle, die es geben wird".
|
||
Genau darin liegt der Unterschied zum alten `null`. */
|
||
/* ACHTUNG: `ALLE` ist NICHT ALLE_ROLLEN.
|
||
|
||
Es ist die Abkuerzung fuer "alle Rollen, die diese Seiten am
|
||
11.09.2026 schon hatten" -- die sieben des Hauses. Die Community
|
||
gehoert ausdruecklich nicht dazu; sie bekommt ihre Seiten einzeln.
|
||
|
||
Wuerde hier ALLE_ROLLEN stehen, haette jede kuenftige Rolle wieder
|
||
automatisch neun Seiten geerbt -- genau der Fehler, gegen den diese
|
||
Datei gebaut ist, nur mit einem anderen Namen. */
|
||
const ALLE = ["spicy", "admin", "manager", "scout", "creator", "hand", "modi"];
|
||
|
||
/* Schutz der angemeldeten Seiten. Serverseitig, nicht nur im Browser --
|
||
sonst könnte man die Seite einfach direkt aufrufen. */
|
||
/* Pfad -> erlaubte Rollen. `null` heisst: jede angemeldete Rolle.
|
||
|
||
Die Rolle wird hier mitgeprueft und nicht nur in der Schnittstelle.
|
||
Sonst bekommt z. B. ein Creator die Verwaltungsseite zwar ausgeliefert
|
||
(HTTP 200) und sieht ihr Geruest, auch wenn sie danach leer bleibt und
|
||
das Skript ihn wegschickt. Sichtbar sein soll sie gar nicht. */
|
||
|
||
export const SEITEN = {
|
||
/* AUS `null` WURDE EINE LISTE (11.09.2026).
|
||
|
||
Filipe: "egal welche rolle oder person hinzugefuegt wird soll
|
||
immer nur das sehen wass ich erlaube."
|
||
|
||
Diese neun Seiten standen auf `null` -- das hiess "jede
|
||
angemeldete Rolle", also auch jede Rolle, die es noch gar nicht
|
||
gibt. Jetzt stehen die sieben, die es wirklich gibt.
|
||
|
||
FUER DIE VORHANDENEN ROLLEN AENDERT SICH DAMIT NICHTS. Das ist
|
||
Absicht: Eine Umkehrung, die nebenbei Rechte entzieht, waere
|
||
zwei Aenderungen in einer -- und man wuesste hinterher nicht,
|
||
welche der beiden etwas kaputtgemacht hat. Wer hier enger
|
||
stellen will, macht das als eigenen Schritt. */
|
||
/* Die Community sieht hier ihre sieben Kacheln und sonst nichts --
|
||
welche das sind, entscheidet bereicheFuer() in workspace.js. */
|
||
"/workspace/start.html": [...ALLE, "gast"],
|
||
"/workspace/uebersicht.html": [...ALLE],
|
||
/* AUSDRUECKLICH OHNE 'modi' (10.09.2026). Vorher stand hier `null`
|
||
("jede angemeldete Rolle") -- und mit der neuen Rolle hiess das
|
||
auch: sie. Die Seite laedt dann zwar, ihre Schnittstelle antwortet
|
||
ihm aber mit 404, weil `content` nicht zu seinen Bereichen gehoert.
|
||
Eine Seite, die man oeffnen kann und die dann leer bleibt, sieht
|
||
aus wie ein Fehler -- und ist einer.
|
||
|
||
Das ist die Kehrseite von "geschuetzt ist die Regel, nicht die
|
||
Ausnahme": Eine NEUE ROLLE erbt jedes `null` automatisch. Wer eine
|
||
Rolle hinzufuegt, muss diese Liste durchgehen -- der Kachel-Durchgang
|
||
in pruef-rollen findet die Faelle, die dabei auffallen. */
|
||
"/workspace/content.html": ["spicy", "admin", "manager", "scout", "creator"],
|
||
"/workspace/aufgaben.html": [...ALLE],
|
||
/* Chat (06.09.2026): jede Rolle. WEN man erreicht, entscheidet
|
||
schreibbareIds() -- nicht der Zugang zur Seite. Ein Creator, der
|
||
die Seite nicht öffnen dürfte, könnte auch nicht antworten, und
|
||
genau das Antworten ist der Zweck.
|
||
|
||
SEIT DEM 19.09.2026 AUCH DIE COMMUNITY. Sie bekommt genau EINEN
|
||
Raum -- den Treff -- und sonst keinen: `schreibbareIds` liefert
|
||
ihr weiterhin eine leere Liste (ohneAussen), ein Zweier-Gespraech
|
||
entsteht also nicht. Was sie sieht, ist der Kanal, in dem sie
|
||
Mitglied ist.
|
||
|
||
Und sie telefoniert nicht: Der Riegel dafuer sitzt am
|
||
Anruf-Router, nicht hier (Filipe: "die sollen nicht anrufen
|
||
koennen. nur schreiben"). */
|
||
"/workspace/chat.html": [...ALLE, "gast"],
|
||
/* NUR DogFather (07.09.2026). Wunsch Filipe: "nimm die kategorie
|
||
zahlen bei jedem weg, nur die rolle dogfather soll die sehen."
|
||
|
||
Bis heute stand hier `null` -- jede Rolle durfte die Seite oeffnen,
|
||
und WESSEN Zahlen jemand sah, entschied sichtbareCreatorIds().
|
||
Die Begruendung dafuer war gut (es sind SEINE Zahlen), sie ist
|
||
jetzt aber nicht mehr meine Entscheidung.
|
||
|
||
WICHTIG: Die Kachel wegzunehmen haette NICHT gereicht. Eine Kachel
|
||
ist ein Weg, keine Schranke -- wer die Adresse kennt oder ein altes
|
||
Lesezeichen hat, waere weiterhin hineingekommen. Beides gehoert
|
||
zusammen: bereiche.js zeigt sie nur noch DogFather, diese Zeile
|
||
laesst nur ihn hinein. */
|
||
/* JETZT WIEDER FUER ALLE (11.09.2026). Filipe, mit der Kachel im
|
||
Bild: "jetzt soll jede rolle diese kachel sehen. spicy, dogfather,
|
||
manager, scout und creator. aber die creator kriegen dan quasi nur
|
||
ihre daten zu sehen und der manager scout dogfather oder spicy
|
||
koennen eintragen."
|
||
|
||
Die Zeile stand seit dem 07.09.2026 auf ["admin"] -- erst "nimm
|
||
die kategorie zahlen bei jedem weg", dann die Praezisierung, dass
|
||
auch Spicy Media sie nicht sieht. Beides ist damit aufgehoben.
|
||
|
||
AUSDRUECKLICH ALS LISTE, NICHT ALS `null`. `null` hiesse "jede
|
||
angemeldete Rolle" -- und damit automatisch auch jede Rolle, die
|
||
es noch gar nicht gibt. Genau das ist am 10.09. bei content.html
|
||
schiefgegangen. Hier stehen die fuenf, die Filipe genannt hat.
|
||
|
||
WER WAS DARF, steht NICHT hier. Diese Zeile oeffnet nur die Tuer.
|
||
Dahinter gilt weiterhin: sichtbareCreatorIds() entscheidet, WESSEN
|
||
Zahlen jemand sieht (ein Creator sieht genau sich selbst), und
|
||
darfEintragen() entscheidet, wer schreiben darf (Leitung + Scout,
|
||
also NICHT der Creator). Beides war schon vorher so gebaut und
|
||
bleibt unangetastet -- es war nur niemand da, der es benutzen
|
||
konnte. */
|
||
"/workspace/leistung.html": ["spicy", "admin", "manager", "scout", "creator"],
|
||
/* NUR DogFather (02.09.2026). Die Rollenauswahl verspricht das seit
|
||
jeher ("Manager -- dieselben Rechte, ausser der
|
||
Personenverwaltung"), die Schranke hielt sich nur nicht daran.
|
||
Wunsch: "die manager sollen diese kategorien garnicht sehen". */
|
||
/* PERSONEN & ZUGAENGE: jetzt auch fuer Manager und Spicy Media
|
||
(07.09.2026).
|
||
|
||
Filipe: "die manager sehen immer noch nicht die kachel personen &
|
||
zugangscode, wo sie dan die neuen creator hinzufuegen koennen ...
|
||
und die sollen in der kategorie wo die jetzt sehen werden auch noch
|
||
das mit den hinzufuegen sehen, alles andere auf der seite sollen die
|
||
weiterhin nicht sehen."
|
||
|
||
DIE SEITE OEFFNET SICH, DIE SCHNITTSTELLEN NICHT. Das ist der ganze
|
||
Trick und der Grund, warum das hier ungefaehrlich ist: Alles unter
|
||
/workspace/api/verwaltung haengt weiterhin an `nurAdmin` -- Rollen
|
||
aendern, Codes neu setzen, sperren, loeschen, Protokoll lesen
|
||
bleiben zu und antworten mit 404. Wer die Seite oeffnet, bekommt
|
||
also genau die Teile zu sehen, fuer die es auch einen Weg gibt.
|
||
|
||
Eine Seite ist kein Schutz, sie ist ein Weg. Der Schutz steht in den
|
||
Schnittstellen, und der ist unveraendert. */
|
||
/* 'hand' kam am 10.09.2026 dazu. Filipe: "ich will dass die rechte
|
||
Hand auch alle sieht."
|
||
|
||
ES WAR DIE DRITTE SCHICHT, DIE ZUSTIMMEN MUSSTE. Die Kachel stand
|
||
da, die Schnittstelle liess sie lesen -- und die Seite selbst warf
|
||
sie auf die Startseite zurueck. Gefunden hat das nicht das Auge,
|
||
sondern pruef-rollen: Sie geht jede Kachel jeder Rolle ab und
|
||
schaut, wo man landet ("Rechte Hand Kachel personen.html LANDET
|
||
AUF start.html").
|
||
|
||
Dass die Seite aufgeht, gibt ihr nichts, was die Schnittstellen ihr
|
||
nicht ohnehin geben: Alles unter /workspace/api/verwaltung ausser
|
||
der Liste antwortet ihr weiterhin mit 404. Eine Seite ist kein
|
||
Schutz, sie ist ein Weg. */
|
||
"/workspace/personen.html": ["spicy", "admin", "manager", "hand"],
|
||
"/workspace/profil.html": ["spicy", "admin", "manager", "scout", "creator"],
|
||
/* Der eigene Steckbrief -- jede Rolle hat einen. Ein Creator wird
|
||
dort nicht hingeschickt (er sieht seinen auf profil.html), darf die
|
||
Seite aber aufrufen: Sie zeigt ihm dasselbe, nur ohne die Akte. */
|
||
/* 'modi' kam am 10.09.2026 dazu. Der Steckbrief ist die EIGENE Seite
|
||
("Dein Bild und deine Kanäle"); profil.html daneben ist der
|
||
Entwicklungsplan eines Creators und fuer ihn sinnlos. Der erste
|
||
Anlauf hatte genau das verwechselt -- die Kachel hiess "Mein
|
||
Profil" und fuehrte auf eine Seite, deren Schnittstelle mit 404
|
||
antwortet, weil sie ausdruecklich nur Creator kennt. Gefunden vom
|
||
neuen Kachel-Durchgang in pruef-rollen. */
|
||
/* JEDER MIT EINEM ZUGANG HAT EINEN STECKBRIEF (19.09.2026).
|
||
|
||
Filipe: "jeder soll ein steckbrief haben, jeder der ein account
|
||
hat, rechte hand, modis und community, jeder soll genau wie ich
|
||
foto und so hinzufuegen koennen."
|
||
|
||
Vorher fehlte hier "gast" -- und damit ausgerechnet die groesste
|
||
Gruppe. Die Seite selbst konnte es die ganze Zeit: `/mein` fragt
|
||
nach `req.person.id` und kennt gar keine Rolle. Es fehlte nur die
|
||
Tuer.
|
||
|
||
WAS EIN MITGLIED DORT SIEHT, ENTSCHEIDET NICHT DIESE ZEILE,
|
||
sondern `sichtbareIds` in workspace-steckbrief.js: Der eigene
|
||
Eintrag, DogFather, und was die Sichtbarkeitsregeln sonst
|
||
hergeben. Eine Seite ist ein Weg, keine Schranke. */
|
||
"/workspace/steckbrief.html": ["spicy", "admin", "manager", "scout", "creator", "hand", "modi", "gast"],
|
||
"/workspace/kalender.html": [...ALLE],
|
||
"/workspace/dateien.html": [...ALLE],
|
||
/* 'modi' kam am 10.09.2026 dazu -- und es war ein echter Fund: Ohne
|
||
diese Zeile leiteten VIER seiner Kacheln (Live-Ablauf, Community,
|
||
Technik, Ideen-Board) wortlos auf die Startseite zurueck. Der
|
||
Rollen-Rundgang meldete sie trotzdem als "ok": Eine Umleitung ist
|
||
kein Fehler, die Seite laedt ja -- nur eben eine andere. Seither
|
||
prueft pruef-rollen fuer JEDE Rolle, dass jede Kachel, die sie
|
||
bekommt, auch wirklich dort ankommt.
|
||
|
||
WELCHE Bereiche ein Modi oeffnen darf, entscheidet die Liste
|
||
seiner Kacheln (MODI_BEREICHE_ERLAUBT) -- sonst kaeme er ueber die
|
||
Adresszeile auch in die Agentur-Ablage. */
|
||
/* Die sieben Bretter des Treffs laufen ueber dieselbe Seite wie alle
|
||
anderen Bereiche. WELCHE ein Gast oeffnen darf, entscheidet die
|
||
Bereichsliste in workspace-bereiche.js -- diese Zeile oeffnet nur
|
||
die Tuer. Eine Seite ist ein Weg, keine Schranke. */
|
||
"/workspace/bereich.html": ["spicy", "admin", "manager", "scout", "creator", "hand", "modi", "gast"],
|
||
"/workspace/report.html": ["spicy", "admin", "manager", "scout", "creator"],
|
||
"/workspace/scouting.html": ["spicy", "admin", "manager", "scout"],
|
||
/* DIE ARBEITSLAGE DES TEAMS (09.09.2026).
|
||
|
||
Filipe: "so eine kategorie wie ueber die creator will ich dass nur
|
||
fuer die spicy und dogfather rolle auch ueber manager und scouts
|
||
gibt."
|
||
|
||
Nur diese beiden Rollen. Ein Manager sieht seine eigene Zeile hier
|
||
ausdruecklich NICHT -- das ist kein Versehen: Eine Uebersicht ueber
|
||
die Arbeit der Kollegen gehoert der Leitung, nicht der Reihe. Der
|
||
Schutz steht ohnehin in der Schnittstelle (workspace-team.js);
|
||
diese Zeile sorgt nur dafuer, dass niemand vor einer leeren Seite
|
||
steht. */
|
||
"/workspace/team.html": ["spicy", "admin"],
|
||
"/workspace/calls.html": [...ALLE],
|
||
"/workspace/startcheck.html": [...ALLE],
|
||
"/workspace/wissen.html": [...ALLE],
|
||
/* Ebenfalls nur DogFather: Was von allein passiert, bestimmt, was
|
||
allen anderen zugeschoben wird. */
|
||
/* AUTOMATIONEN BLEIBEN BEI DogFather (07.09.2026). Ausdruecklich:
|
||
"bei automationen sollen die nicht sehen." Dahinter liegen
|
||
Sicherungen, die KI und der Zustand des Servers -- das ist Betrieb,
|
||
nicht Betreuung. */
|
||
"/workspace/automation.html": ["admin"],
|
||
/* Die gemeinsame Lage des Teams -- nur die DogFather-Rolle, also
|
||
Filipe und VanVan (10.09.2026). Fuer alle anderen leitet die
|
||
Schranke auf die Startseite; die Schnittstelle dahinter antwortet
|
||
zusaetzlich mit 404. Zwei Schloesser, absichtlich: Faellt eines
|
||
weg, haelt das andere. */
|
||
/* Der Eingang: DogFather und seine rechte Hand. Blueprint 3.1 --
|
||
"Kann im Alltag vertretend Entscheidungen treffen." Genau das
|
||
passiert auf dieser Seite. */
|
||
"/workspace/teamlage.html": ["admin", "hand"],
|
||
|
||
/* DIE REGELN DES TREFFS (11.09.2026). Fuer die Community und fuer
|
||
die, die sie durchsetzen — ein Modi, der die Regeln nicht sehen
|
||
kann, moderiert nach Gefuehl.
|
||
|
||
AUSDRUECKLICH NICHT fuer Manager, Scouts, Creator und Spicy: Sie
|
||
haben mit dem Treff nichts zu tun, und die Seite nennt Fristen,
|
||
Stufen und die Bedingungen des Ausschlusses. */
|
||
/* WILLKOMMEN (21.09.2026). Die Orientierungsseite. Sie erklaert nur,
|
||
was die Person ohnehin hat -- deshalb ist sie fuer JEDE gueltige
|
||
Rolle offen, genau wie die Startseite. Wer sie sperrt, sperrt die
|
||
Erklaerung, nicht den Zugang. */
|
||
"/workspace/willkommen.html": [...ALLE, "gast"],
|
||
|
||
/* MATERIAL (22.09.2026). Dieselben Rollen wie der Treff: Das Team
|
||
stellt ein, die Community holt sich etwas. WER was darf, steht
|
||
nicht hier, sondern in workspace-material.js -- diese Tafel
|
||
entscheidet nur, wer die Seite oeffnen darf. */
|
||
"/workspace/material.html": ["gast", "modi", "hand", "linke", "admin"],
|
||
|
||
"/workspace/treff-regeln.html": ["gast", "modi", "hand", "admin"],
|
||
/* DIE ANRUF-PROBE (19.09.2026). Sie sagt einem Menschen in seinem
|
||
eigenen Browser, warum es nicht klingelt -- die Frage, die sich
|
||
von aussen nicht beantworten laesst. Sie ruft niemanden an und
|
||
zeigt nichts ueber andere.
|
||
|
||
ERWEITERT AM 19.09.2026, nachmittags, nach einer Messung: Von
|
||
elf Zugaengen hatten SIEBEN kein einziges Geraet angemeldet -- bei
|
||
ihnen klingelt nichts und es kommt keine Erinnerung an, solange
|
||
die Seite zu ist. Fuenf der sieben sind Creator, Scout oder Spicy
|
||
Media und durften diese Seite gar nicht oeffnen.
|
||
|
||
Das war die falsche Einschraenkung: Die Seite prueft nicht nur
|
||
Anrufe, sondern die ganze Kette bis zur angemeldeten Geraete-Kennung
|
||
-- und die traegt auch jede Aufgaben- und Terminerinnerung. Wer
|
||
Erinnerungen bekommen kann, muss nachsehen koennen, warum sie
|
||
ausbleiben.
|
||
|
||
OHNE "gast". Die Community bekommt keine Erinnerungen, und eine
|
||
Seite mit sieben Prueftpunkten ueber etwas, das es fuer sie nicht
|
||
gibt, waere nur Verwirrung. */
|
||
"/workspace/anruf-probe.html": [...ALLE],
|
||
|
||
/* DIE ANFRAGE FUER MODI (17.09.2026).
|
||
|
||
NUR "gast" -- und das ist keine Schlamperei, sondern die Aussage.
|
||
Wer schon im Team ist, hat hier nichts zu beantworten; und ein
|
||
Formular, das auch Modis sehen, waere die Einladung, es als
|
||
Beurteilungsbogen zu benutzen.
|
||
|
||
Der Server sagt dasselbe noch einmal (SCHICKEN_ROLLEN). Zwei
|
||
Schloesser an derselben Tuer, weil die Tafel umstellbar ist:
|
||
Wer sie versehentlich oeffnet, bekommt trotzdem keine Anfrage
|
||
von einem Modi in den Eingang. */
|
||
"/workspace/bewerben.html": ["gast"],
|
||
|
||
|
||
/* DIE ENTWICKLUNGSKARTE (11.09.2026).
|
||
|
||
DogFather und die rechte Hand fuehren sie ueber das Team. Ein Modi
|
||
kommt ebenfalls auf die Seite -- aber er sieht dort AUSSCHLIESSLICH
|
||
Block 5, die sechs Fragen ueber sich selbst. Das entscheidet nicht
|
||
diese Tafel, sondern workspace-entwicklung.js: Hier steht nur, wer
|
||
die Tuer oeffnen darf, nicht was dahinter liegt.
|
||
|
||
ZWEI SCHLOESSER, ABSICHTLICH. Faellt die Rechtepruefung im Modul
|
||
weg, steht immer noch diese Zeile; faellt diese Zeile weg, steht
|
||
immer noch das Modul. */
|
||
/* WIE GEHT'S DIR? -- dieselben Rollen wie die Entwicklungsseite, und
|
||
das ist kein Zufall: Es sind die Menschen, ueber die dort etwas
|
||
steht. Wer beobachtet wird, darf auch ueber sich selbst sprechen.
|
||
Die Agentur hat diese Seite nicht -- sie hat auch keine
|
||
Entwicklungskarte. */
|
||
/* DAS ZIEL DES TEILEN-MENÜS (17.09.2026).
|
||
|
||
DIESELBEN ROLLEN WIE DIE VIDEO-ROUTE, nicht mehr: Wer ein Video
|
||
nicht eintragen darf, soll auch nicht auf einer Seite landen, die
|
||
ihm einen Knopf dafür zeigt. Ein Knopf, der mit 403 antwortet, ist
|
||
schlimmer als kein Knopf.
|
||
|
||
Die Seite selbst legt nichts an -- das tut die Route, und die
|
||
prüft ihrerseits. Das hier ist der Riegel davor, nicht statt. */
|
||
"/workspace/teilen.html": ["admin", "hand", "modi"],
|
||
"/workspace/befinden.html": ["admin", "hand", "modi"],
|
||
"/workspace/entwicklung.html": ["admin", "hand", "modi"],
|
||
|
||
/* DIE AUSWERTUNG (19.09.2026) -- Kachel "Entwicklung".
|
||
|
||
MIT "modi", obwohl die Liste aller Karten nur die Leitung sieht.
|
||
Die Seite hat zwei Gesichter: Wer das Team fuehrt, sieht die
|
||
Karten; wer dazugehoert, sieht ausschliesslich die Bewegung in der
|
||
EIGENEN -- ohne Namen, ohne Anlass, ohne wer-hat-was.
|
||
|
||
Dass die Person ihren eigenen Fortschritt sieht, ist kein
|
||
Zugestaendnis, sondern der Punkt: Sichtbarer Fortschritt ist nach
|
||
der Forschung der staerkste einzelne Treiber guter Arbeit. Die
|
||
Schranke dahinter sitzt in der Route (`/werdegang/liste` und
|
||
`/werdegang/person/:id` antworten einem Modi mit 404), nicht hier.
|
||
Das hier ist der Riegel davor, nicht statt. */
|
||
"/workspace/werdegang.html": ["admin", "hand", "modi"],
|
||
|
||
/* TALENTE. Hier stehen Namen von Menschen, die nichts davon wissen --
|
||
ausdruecklich OHNE "modi": Wer beobachtet wird, ohne es zu wissen,
|
||
hat ein Recht darauf, dass der Kreis klein bleibt. */
|
||
"/workspace/talente.html": ["admin", "hand"],
|
||
|
||
/* DER EINGANG FUER DIE ANFRAGEN -- dieselben zwei wie bei den
|
||
Talenten, und aus demselben Grund: Hier stehen Saetze, die
|
||
jemand ueber sich selbst geschrieben hat, im Vertrauen darauf,
|
||
dass zwei Menschen sie lesen.
|
||
|
||
Filipes Entscheidung vom 17.09.2026 auf die Rueckfrage, wer
|
||
entscheiden darf: "Du und die rechte Hand." */
|
||
"/workspace/bewerbungen.html": ["admin", "hand"],
|
||
|
||
|
||
/* MELDUNGEN & MASSNAHMEN. Nur wer moderiert -- ausdruecklich OHNE
|
||
"gast": Dort stehen die Namen derer, die gemeldet haben. Eine
|
||
Meldung, die der Gemeldete lesen kann, ist keine Meldung mehr,
|
||
sondern eine Einladung zur Vergeltung. */
|
||
"/workspace/treff-moderation.html": ["modi", "hand", "admin"],
|
||
|
||
/* UNSERE SEITEN (19.09.2026). Die Website und VanVans Shop, mit dem
|
||
Rabattcode fuer die Community.
|
||
|
||
GENAU DIE VIER ROLLEN DES TREFFS -- also MIT "gast", anders als die
|
||
Moderationsseite eine Zeile darueber. Sie ist ausdruecklich FUER die
|
||
Community gebaut; ohne "gast" waere die Kachel bei jedem Mitglied
|
||
sichtbar und beim Antippen zu. Genau diese Sorte toter Weg hat die
|
||
Sichtpruefung am 18.09. zehnmal gefunden.
|
||
|
||
Die Agentur steht bewusst nicht dabei (siehe TREFF_ROLLEN in
|
||
workspace.js): Creator, Scouts und Spicy Media haben mit dem Treff
|
||
nichts zu tun. */
|
||
"/workspace/unsere-seiten.html": ["gast", "modi", "hand", "admin"],
|
||
|
||
/* DER VERTRAULICHE MELDEWEG (19.09.2026).
|
||
|
||
Filipe: "es soll auch eine kategorie also eine hauptkachel geben wo
|
||
die community leute sich anonym melden koennen wenn sie probleme
|
||
haben ... rechte hand und dogfather sollen zugriff auf diese
|
||
anonyme nachrichten haben."
|
||
|
||
DREI ROLLEN, UND MODIS AUSDRUECKLICH NICHT. Sehr oft geht es in
|
||
diesen Meldungen um eine Moderationsentscheidung -- wer beteiligt
|
||
ist, darf die Beschwerde ueber sich nicht lesen. Das ist keine
|
||
Geringschaetzung der Modis, sondern dieselbe Regel, die auch
|
||
anderswo gilt: Niemand prueft sich selbst.
|
||
|
||
WAS AUF DER SEITE ZU SEHEN IST, entscheidet nicht diese Zeile,
|
||
sondern `fallFuer` in workspace-hilfe.js: Ein Mitglied sieht seine
|
||
eigenen Faelle, die Leitung alle. */
|
||
"/workspace/hilfe.html": ["gast", "hand", "admin"],
|
||
|
||
/* DER SUPPORT: WIRKLICH JEDER (24.09.2026).
|
||
|
||
Filipe: „da fehlt auch eine support kachel. die jeder sieht.
|
||
jeder benutzen kann."
|
||
|
||
Das ist der Unterschied zum vertraulichen Meldeweg eine Zeile
|
||
darueber: Der gilt nur fuer gast, hand und admin -- Modis,
|
||
Creator, Scouts, Manager und die linke Hand hatten gar keinen
|
||
Weg, einen kaputten Knopf zu melden.
|
||
|
||
ALLE ROLLEN AUSGESCHRIEBEN und nicht „* " oder ein Weglassen:
|
||
Diese Tafel ist die Stelle, an der man nachsieht, wer wohin darf.
|
||
Eine Abkuerzung hier hiesse, dass der Support in der Uebersicht
|
||
„Wer sieht was" als Luecke erscheint. */
|
||
"/workspace/support.html": ["gast", "modi", "creator", "scout", "manager",
|
||
"linke", "hand", "spicy", "admin"],
|
||
|
||
/* UNTERSTÜTZEN (24.09.2026).
|
||
|
||
Filipe: „jeder soll diese kachel sehen aber nur dogfather soll sie
|
||
verändern können oder vieles mehr sehen. alle anderen, rechte und
|
||
linke hand, modis und community sollen supporten können."
|
||
|
||
Die Seite steht damit JEDER Rolle offen — was jemand darauf tun
|
||
darf, entscheidet workspace-unterstuetzung.js und nicht diese
|
||
Tafel. Sie beantwortet nur, wer die Tür aufbekommt.
|
||
|
||
ALLE ROLLEN AUSGESCHRIEBEN, dieselbe Überlegung wie beim Support
|
||
eine Zeile darüber: Diese Tafel ist die Stelle, an der man
|
||
nachsieht, wer wohin darf. Eine Abkürzung hier hieße, dass die
|
||
Seite in „Wer sieht was" als Lücke erscheint. */
|
||
"/workspace/unterstuetzen.html": ["gast", "modi", "creator", "scout", "manager",
|
||
"linke", "hand", "spicy", "admin"],
|
||
|
||
/* WER SIEHT WAS. DogFather und die rechte Hand (Filipe, 11.09.2026:
|
||
"ich will die kategorie auch auf der team dogi seite fuer die
|
||
dogfather und rechte hand rollen").
|
||
|
||
ANSEHEN BEIDE, UMSTELLEN NUR ER. Sie fuehren das Team zusammen;
|
||
wer mitentscheidet, muss nachsehen koennen. Wer aber Rechte
|
||
vergeben kann, kann sich Rechte vergeben -- und diese eine Tuer
|
||
bleibt bei ihm. Durchgesetzt wird das in workspace-rechte.js, nicht
|
||
hier: Diese Tafel beantwortet, wer die SEITE oeffnen darf, nicht
|
||
was er darauf tun kann.
|
||
|
||
Weiterhin ausdruecklich NICHT fuer die Agentur und nicht fuer die
|
||
Modis: Die Seite ist eine vollstaendige Karte dieses Hauses -- jede
|
||
Seite, jede Rolle. Wer sie hat, weiss, wo er es versuchen muesste. */
|
||
/* DER NOTIZBLOCK (26.09.2026).
|
||
|
||
Filipe: „fuer die modis, rechte und linke hand und dogfather
|
||
eine kachel hinzufuegst, sie soll: Notizen, heissen."
|
||
|
||
GENAU DIESE VIER, und die linke Hand steht ausdruecklich dabei
|
||
statt sich aus der Schleife weiter unten zu ergeben: Sie ist
|
||
hier namentlich genannt, und eine namentliche Nennung gehoert
|
||
in die Tafel, die man liest, wenn man wissen will, wer wohin
|
||
darf.
|
||
|
||
WAS AUF DER SEITE ZU SEHEN IST, entscheidet nicht diese Zeile:
|
||
In workspace-notizen.js hat jede Abfrage `person_id = ?` fest
|
||
eingebaut. Es gibt keine Rolle, die mehr sieht -- auch
|
||
DogFather nicht. Diese Tafel beantwortet nur, wer die Tuer
|
||
aufbekommt.
|
||
|
||
DIE AGENTUR STEHT NICHT DABEI, und die Adresse auch nicht: Die
|
||
Seite gehoert zum Haus von Team Dogi und ist auf der
|
||
Agenturadresse ein 404 (GEHOERT_ZU_ADRESSE in crew-adresse.js). */
|
||
"/workspace/notizen.html": ["admin", "hand", "linke", "modi"],
|
||
/* Die Reaction ist fuer ALLE im Haus -- Filipes Notiz sagt
|
||
woertlich „fuer alle sichtbar". Die Community steht deshalb
|
||
ausdruecklich mit drin; wer nicht Host ist, sieht dort die
|
||
Zuschauerseite. */
|
||
"/workspace/reaktion.html": ["admin", "hand", "linke", "modi", "gast"],
|
||
|
||
"/workspace/rechte.html": ["admin", "hand"],
|
||
};
|
||
|
||
/* =====================================================================
|
||
DIE LINKE HAND BEKOMMT DIE SEITEN DER RECHTEN -- ABGELEITET
|
||
===================================================================== (21.09.2026)
|
||
|
||
Filipe: *"Die linke Hand erhaelt grundsaetzlich dieselben Rechte wie
|
||
die rechte Hand in allen Bereichen, die die Modis, Aufgaben,
|
||
Aufgabenzuweisungen, Uebersichten, Kommunikation und Auswertungen
|
||
betreffen."*
|
||
|
||
WARUM ABGELEITET UND NICHT SIEBZEHNMAL "linke" HINGESCHRIEBEN: Die
|
||
naechste Seite, die jemand der rechten Hand gibt, bekaeme die linke
|
||
sonst nicht -- und das faellt niemandem auf, weil eine fehlende
|
||
Seite aussieht wie eine Seite, die es nicht gibt. Diese Schleife
|
||
kann das nicht vergessen.
|
||
|
||
DIE AUSNAHMEN STEHEN EINZELN DA, MIT GRUND. Eine Ausnahme ohne
|
||
Begruendung ist beim naechsten Umbau eine, die jemand fuer ein
|
||
Versehen haelt und wegnimmt. */
|
||
const LINKE_NICHT = {
|
||
/* Personen anlegen -- ausdruecklich im Auftrag ausgeschlossen. Die
|
||
LISTE der Leute braucht sie trotzdem, um Aufgaben zu verteilen;
|
||
die kommt aus /api/personen/liste und ist dort eigens geoeffnet. */
|
||
"/workspace/personen.html": "legt Personen an",
|
||
/* Der Weg, auf dem neue Leute ueberhaupt hereinkommen. */
|
||
"/workspace/bewerbungen.html": "fuehrt zu neuen Personen",
|
||
"/workspace/talente.html": "fuehrt zu neuen Personen",
|
||
/* Der vertrauliche Meldeweg. Das Empfindlichste im Haus -- Meldungen
|
||
ueber Menschen. Im Zweifel das kleinere Recht: Ein Wort von Filipe
|
||
oeffnet es, eine versehentlich gelesene Meldung laesst sich nicht
|
||
zurueckholen. Ein Modi darf ihn uebrigens auch nicht. */
|
||
"/workspace/hilfe.html": "vertraulicher Meldeweg",
|
||
/* Wer die Rechtetafel bedient, verwaltet Konten -- nicht Aufgaben. */
|
||
"/workspace/rechte.html": "Rechteverwaltung",
|
||
};
|
||
|
||
for (const [seite, rollen] of Object.entries(SEITEN)) {
|
||
if (!Array.isArray(rollen) || !rollen.includes("hand")) continue;
|
||
if (LINKE_NICHT[seite]) continue;
|
||
if (rollen.includes("linke")) continue;
|
||
/* EINE KOPIE, KEINE AENDERUNG AM ORIGINAL. Mehrere Seiten teilen
|
||
sich dieselbe Liste (`ALLE`). Wer die an Ort und Stelle aendert,
|
||
gibt die Rolle allen Seiten, die dieselbe Liste benutzen -- auch
|
||
denen, die gerade eine Ausnahme sind. Das faellt nicht auf,
|
||
solange keine Ausnahme `ALLE` benutzt, und knallt an dem Tag, an
|
||
dem eine es tut.
|
||
Direkt hinter die rechte Hand -- die Reihenfolge in diesen Listen
|
||
ist an einigen Stellen die Anzeigereihenfolge. */
|
||
const kopie = rollen.slice();
|
||
kopie.splice(kopie.indexOf("hand") + 1, 0, "linke");
|
||
SEITEN[seite] = kopie;
|
||
}
|
||
|
||
/** Welche Seiten der rechten Hand die linke NICHT bekommt -- und warum.
|
||
* Exportiert, damit die Pruefung die Begruendung mitlesen kann statt
|
||
* eine eigene Liste zu fuehren. */
|
||
export const LINKE_AUSNAHMEN = LINKE_NICHT;
|
||
|
||
/* Die Zugangswaende. Sie haben keine Rolle, weil sich dort noch
|
||
niemand angemeldet hat -- sie sind der Ort, an dem das passiert.
|
||
Sie stehen hier nur, damit die Pruefung "jede Datei hat einen
|
||
Eintrag" sie nicht als Luecke meldet. */
|
||
export const OHNE_ANMELDUNG = [
|
||
"/workspace/index.html",
|
||
"/workspace/crew-index.html",
|
||
/* ==== DIE ZWEI BUEHNENQUELLEN (28.09.2026) ====================
|
||
|
||
OBS speichert die Anmeldung einer Browser-Quelle nicht
|
||
zuverlaessig -- eine Quelle, bei der man sich nach jedem
|
||
Programmstart neu anmelden muss, ist mitten in einer Sendung
|
||
unbrauchbar. Beide Seiten pruefen stattdessen einen SCHLUESSEL
|
||
in der Adresse und zeigen ohne ihn nichts.
|
||
|
||
WAS SIE ZEIGEN, STEHT OHNEHIN IM STREAM: das laufende Video und
|
||
die Spendenkarten. Keine Namen von Zusehenden, kein Chat, keine
|
||
Bedienung. */
|
||
"/workspace/buehne.html",
|
||
"/workspace/tafel.html",
|
||
];
|
||
|
||
/* =====================================================================
|
||
DIE EINE FRAGE, DIE ALLES BEANTWORTET
|
||
===================================================================== */
|
||
|
||
/**
|
||
* Darf diese Person diese Seite oeffnen?
|
||
*
|
||
* Zwei Antworten, keine dritte:
|
||
* - Die Seite steht in der Tafel UND die Rolle steht darin -> ja.
|
||
* - Alles andere -> nein. Auch eine Seite, die es in der Tafel gar
|
||
* nicht gibt. Das ist die eigentliche Aenderung.
|
||
*
|
||
* @param {{rolle?: string}|null} person
|
||
* @param {string} pfad z. B. "/workspace/start.html"
|
||
*/
|
||
/* =====================================================================
|
||
DIE TAFEL IST SEIT DEM 11.09.2026 VERAENDERBAR — aber nur auf EINE Art
|
||
=====================================================================
|
||
|
||
Filipe: *"so dass ich die da auch manuel wechseln und speichern kann."*
|
||
|
||
WAS OBEN STEHT, IST AB JETZT DER GRUNDSTAND, nicht mehr die ganze
|
||
Wahrheit. Was DogFather auf der Seite "Wer sieht was" umstellt, liegt
|
||
in der Datenbank und wird hier darübergelegt.
|
||
|
||
DREI ENTSCHEIDUNGEN, DIE MAN DEM CODE NICHT ANSIEHT:
|
||
|
||
1. GESPEICHERT WIRD NUR DER UNTERSCHIED. In der Datenbank steht eine
|
||
Zeile nur dann, wenn sie vom Grundstand ABWEICHT. Damit bedeutet
|
||
der Code oben weiterhin etwas -- man sieht, was gedacht war, und
|
||
daneben, was jemand daraus gemacht hat. Eine vollstaendige Kopie
|
||
in der Datenbank waere nach einer Woche die einzige Wahrheit, und
|
||
der Code oben wuerde still veralten.
|
||
|
||
2. DER GRUNDSTAND IST DER RUECKFALL, wenn die Abweichungen nicht
|
||
gelesen werden koennen. Das ist die richtige Richtung: Er ist der
|
||
geprüfte Zustand, nicht der zufaellige. Ein Fehlschlag wird laut
|
||
protokolliert -- eine Tafel, die still auf etwas anderes
|
||
zurueckfaellt, waere die schlimmste Sorte Fehler in dieser Datei.
|
||
|
||
3. GEAENDERT WIRD NICHT HIER. Diese Datei kennt keine Datenbank; sie
|
||
nimmt eine fertige Tafel entgegen. Wer sie setzt und wer das darf,
|
||
steht in workspace-rechte.js. Zwei Dateien, zwei Fragen -- und die
|
||
Rechtepruefung bleibt ohne laufenden Server pruefbar.
|
||
===================================================================== */
|
||
|
||
/** Die Tafel, die gerade gilt. Am Anfang der Grundstand. */
|
||
let TAFEL = SEITEN;
|
||
|
||
/** Setzt die geltende Tafel. "null" stellt den Grundstand wieder her. */
|
||
export function tafelSetzen(neu) {
|
||
TAFEL = neu && typeof neu === "object" ? neu : SEITEN;
|
||
}
|
||
|
||
/** Die Tafel, die gerade gilt -- fuer die Anzeige und fuer Pruefungen. */
|
||
export function tafelJetzt() {
|
||
return TAFEL;
|
||
}
|
||
|
||
/** Weicht diese Seite/Rolle vom Grundstand ab? Fuer die Anzeige: Man
|
||
* soll sehen, was jemand von Hand geaendert hat. */
|
||
export function weichtAb(pfad, rolle) {
|
||
const grund = Array.isArray(SEITEN[pfad]) && SEITEN[pfad].includes(rolle);
|
||
const jetzt = Array.isArray(TAFEL[pfad]) && TAFEL[pfad].includes(rolle);
|
||
return grund !== jetzt;
|
||
}
|
||
|
||
export function darfSeite(person, pfad) {
|
||
const rolle = person?.rolle;
|
||
if (!rolle) return false;
|
||
const erlaubt = TAFEL[String(pfad || "")];
|
||
/* Kein Eintrag heisst NEIN. Vorher hiess es ja -- und genau darin
|
||
lag das Loch, das man einer neuen Seite nicht ansieht. */
|
||
if (!Array.isArray(erlaubt)) return false;
|
||
return erlaubt.includes(rolle);
|
||
}
|
||
|
||
/**
|
||
* Die Tafel aus der anderen Richtung: Rolle -> Seiten.
|
||
*
|
||
* Fuer die Uebersichtsseite ("Wer sieht was") und fuer Pruefungen.
|
||
* ABGELEITET, nicht zweitgeschrieben -- eine zweite Liste waere die
|
||
* Stelle, an der die beiden auseinanderlaufen.
|
||
*/
|
||
export function seitenFuer(rolle) {
|
||
return Object.entries(TAFEL)
|
||
.filter(([, r]) => r.includes(rolle))
|
||
.map(([p]) => p)
|
||
.sort();
|
||
}
|
||
|
||
/** Alle Seiten der Tafel -- fuer die Pruefung gegen die Platte. */
|
||
export function alleSeiten() {
|
||
/* AUS DEM GRUNDSTAND, nicht aus der geltenden Tafel.
|
||
|
||
Die Liste der SEITEN aendert sich durch eine Umstellung nicht --
|
||
nur, wer sie oeffnen darf. Wer hier TAFEL naehme, bekaeme bei einem
|
||
Fehler in der Zusammenfuehrung eine kuerzere Liste, und
|
||
pruef-rechtetafel ("jede Datei hat einen Eintrag") wuerde dann
|
||
stillschweigend weniger pruefen. */
|
||
return Object.keys(SEITEN).sort();
|
||
}
|
||
|
||
/** Nur DogFather darf die Tafel umstellen -- und selbst er nicht alles.
|
||
*
|
||
* DIESE DREI SEITEN KANN ER SICH NICHT SELBST WEGNEHMEN. Ohne
|
||
* "rechte.html" koennte er die Aenderung nicht zuruecknehmen, ohne
|
||
* "personen.html" keinen Zugang mehr vergeben, ohne "start.html"
|
||
* nirgends mehr hin. Eine Sperre, aus der man sich aussperren kann,
|
||
* ist keine Einstellung, sondern eine Falle -- und sie waere genau
|
||
* einen Fehlklick entfernt.
|
||
*
|
||
* Fuer JEDE andere Rolle darf er jede Seite umstellen. Das ist der
|
||
* Sinn der Sache: "soll jede rolle immer nur das sehen was sie sehen
|
||
* sollen" -- wer das entscheidet, ist er. */
|
||
export const UNANTASTBAR = [
|
||
{ pfad: "/workspace/rechte.html", rolle: "admin" },
|
||
{ pfad: "/workspace/personen.html", rolle: "admin" },
|
||
{ pfad: "/workspace/start.html", rolle: "admin" },
|
||
];
|
||
|
||
/* =====================================================================
|
||
WAS DIE RECHTE HAND NICHT ANFASSEN DARF (24.09.2026)
|
||
|
||
Filipe: „die rechte hand soll das auch sehen. und die selben rechte
|
||
da haben wie dogfather. das einzige was sie nicht kann ist die
|
||
dogfather rolle oder leute anfassen. also da kann sie nichts
|
||
verändern."
|
||
|
||
SEHEN KONNTE SIE DIE TAFEL SCHON -- `nurLeitung` liess sie herein,
|
||
und die Kachel steht in ihrer Liste. Was ihr fehlte, war das
|
||
Umstellen: Jeder Knopf antwortete mit „Umstellen kann das nur
|
||
DogFather."
|
||
|
||
ZWEI SPERREN, und beide stehen hier statt in der Route -- damit die
|
||
Oberflaeche dieselbe Auskunft bekommt und den Knopf gar nicht erst
|
||
als Knopf zeigt:
|
||
|
||
1. DIE SPALTE „DogFather". Sie entscheidet, was er selbst sieht.
|
||
Wer sie aendern kann, kann ihm Seiten wegnehmen.
|
||
2. DIE ZEILE „Personen & Zugaenge" -- „leute anfassen". Wer
|
||
personen.html fuer eine Rolle freischaltet, hat damit
|
||
Zugaenge vergeben, ohne einen einzigen anzulegen.
|
||
|
||
DRITTENS, UND DAS HAT ER NICHT GESAGT: Sie kann sich auch selbst
|
||
nicht aussperren. Dieselbe Ueberlegung wie bei UNANTASTBAR fuer
|
||
DogFather -- eine Sperre, aus der man sich aussperren kann, ist
|
||
keine Einstellung, sondern eine Falle. Haette ich es weggelassen,
|
||
waere der erste Fehlklick auf „rechte.html / Rechte Hand" das Ende
|
||
ihres Zugangs zu dieser Seite gewesen.
|
||
===================================================================== */
|
||
|
||
/** Die Spalte, die nur DogFather selbst aendern darf. */
|
||
const NUR_DOGFATHER_SPALTE = "admin";
|
||
/** Die Zeile, die nur DogFather aendern darf -- fuer JEDE Rolle. */
|
||
const NUR_DOGFATHER_ZEILE = "/workspace/personen.html";
|
||
/** Und was die rechte Hand sich selbst nicht wegnehmen kann. */
|
||
const HAND_BRAUCHT = ["/workspace/rechte.html", "/workspace/start.html"];
|
||
|
||
/** Darf DIESE PERSON dieses Feld anfassen? -- unabhaengig davon, ob
|
||
* sie es an- oder abwaehlen will.
|
||
*
|
||
* Getrennt von `darfUmstellen`, weil die Oberflaeche genau diese
|
||
* Frage stellt, bevor sie ein Feld zeichnet: Ein Knopf, der eine
|
||
* Absage bringt, ist schlimmer als keiner.
|
||
*
|
||
* @returns {string|null} Grund -- oder null, wenn es geht. */
|
||
export function darfFeldAnfassen(person, pfad, rolle) {
|
||
const wer = person?.rolle;
|
||
if (wer === "admin") return null;
|
||
if (wer !== "hand") return "Umstellen kann das nur DogFather und die rechte Hand.";
|
||
|
||
if (rolle === NUR_DOGFATHER_SPALTE) {
|
||
return "Was DogFather sieht, stellt nur er selbst um.";
|
||
}
|
||
if (pfad === NUR_DOGFATHER_ZEILE) {
|
||
return "Wer Zugänge vergeben darf, entscheidet nur DogFather.";
|
||
}
|
||
if (rolle === "hand" && HAND_BRAUCHT.includes(pfad)) {
|
||
return "Diese Seite kannst du dir nicht selbst wegnehmen – "
|
||
+ "sonst kämst du an die Rechte nicht mehr heran.";
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/** Alle Felder, die diese Person nicht anfassen darf -- fuer die
|
||
* Oberflaeche, damit sie sie als fest zeichnet.
|
||
*
|
||
* ABGELEITET AUS `darfFeldAnfassen`, nicht danebengeschrieben: Zwei
|
||
* Listen fuer dieselbe Regel waeren die, die beim naechsten Umbau
|
||
* auseinanderlaufen -- und die in der Oberflaeche waere die, die
|
||
* jeder herunterlaedt. */
|
||
export function festeFelder(person, pfad) {
|
||
const aus = UNANTASTBAR.filter((u) => u.pfad === pfad).map((u) => u.rolle);
|
||
for (const r of ALLE_ROLLEN) {
|
||
if (aus.includes(r)) continue;
|
||
if (darfFeldAnfassen(person, pfad, r)) aus.push(r);
|
||
}
|
||
return aus;
|
||
}
|
||
|
||
/** @returns {string|null} Grund, warum das nicht geht -- oder null. */
|
||
export function darfUmstellen(pfad, rolle, erlaubt, person) {
|
||
if (!Object.prototype.hasOwnProperty.call(SEITEN, pfad)) return "Diese Seite gibt es nicht.";
|
||
if (!ALLE_ROLLEN.includes(rolle)) return "Diese Rolle gibt es nicht.";
|
||
/* ZUERST DIE PERSON, DANN DER INHALT. Wer ein Feld gar nicht
|
||
anfassen darf, bekommt denselben Grund -- egal ob er an- oder
|
||
abwaehlen wollte. Stuende diese Frage nach `if (erlaubt) return
|
||
null`, koennte die rechte Hand DogFather jede Seite ZUSCHALTEN
|
||
und nur nicht wegnehmen; das waere dieselbe Tuer, nur andersherum. */
|
||
const nein = person ? darfFeldAnfassen(person, pfad, rolle) : null;
|
||
if (nein) return nein;
|
||
if (erlaubt) return null;
|
||
const fest = UNANTASTBAR.find((u) => u.pfad === pfad && u.rolle === rolle);
|
||
if (fest) {
|
||
return "Diese Seite kannst du dir nicht selbst wegnehmen – sonst käme "
|
||
+ "niemand mehr an die Rechte, an die Zugänge oder auf die Startseite.";
|
||
}
|
||
return null;
|
||
}
|