Der Treff zieht in Team Dogi ein — die dritte Adresse ist wieder weg

Filipe, nachdem er die dritte Wand gesehen hatte: "das soll keine app
für sich sein, dass soll in der crew seite adaptiert werden, da rein
perfektionniert."

WAS VERSCHWINDET: treff.dogfather-universe.com samt Weiche
(treff-adresse.js), Zugangswand, Manifest und acht Bühnenbildern. Kein
DNS-Eintrag, kein zweiter Caddy-Block, kein zweites App-Symbol.

Die Gründe, die DAFÜR sprachen, stehen jetzt als Kommentar in
crew-adresse.js statt als Code -- sie gelten weiter, und beim nächsten
Mal wird jemand dieselbe Idee haben: eine App je Ursprung, und ein
Schloss mehr zwischen der Community und den Daten der Agentur.

WAS DER VERZICHT KOSTET, benannt statt übersehen:
 · Die Community steht vor derselben Wand wie das Team und liest dort
   die Namen der drei Team-Rollen. Filipes Entscheidung auf die Frage:
   vierte Kachel "Community" statt gar keiner Kacheln.
 · Ein Schloss weniger. Was vorher die Adresse getrennt hat, muss jetzt
   jede einzelne Regel halten -- deshalb prüft pruef-treff-werkzeuge
   seit heute zehn Dinge mehr (70 statt 60).

EINE LÜCKE, DIE DABEI AUFGEFALLEN IST -- und die es schon vorher gab:
Ein Mitglied der Community stand in der Auswahl, wen man zu einem
Termin einlädt, wem man eine Aufgabe gibt und mit wem man einen Chat
anfängt. Für DogFather bedeutet fast jede Liste "alle". Jetzt zu, über
eine Hülle (ohneAussen) um die fünf Listen, die von Zusammenarbeit
handeln -- damit sie auch für die Listen gilt, die es noch nicht gibt.
Die Verwaltungsliste in "Personen & Zugänge" zeigt sie weiterhin, sonst
legt er einen Zugang an und der verschwindet im selben Moment.

DREI BEFUNDE AUS DEN PRÜFUNGEN, wieder keiner vom Lesen:
 · Mein eigener Kommentar auf der Wand nannte eine Rolle der Agentur --
   in einer Datei, die jedes Community-Mitglied im Quelltext liest.
   Zum zweiten Mal an einem Tag, und zum zweiten Mal ausgerechnet in
   einem Kommentar, der erklärt, warum man das nicht tut.
 · Die Prüfung "der Satz nennt die Modis" durchsuchte den QUELLTEXT und
   wäre grün geblieben, obwohl der Satz auf dem Bildschirm längst ein
   anderer ist -- sie fand ihn in einem Kommentar. Sie misst jetzt die
   sichtbare Unterzeile.
 · Der erste Entwurf der Adressregel sperrte die Community auch auf
   localhost aus -- eine Bedingung durch AUSSCHLUSS, zum dritten Mal an
   einem Tag. Jede Zeile nennt jetzt die Adresse, FÜR DIE sie gilt.

Und zwei feste Zahlen weniger: Die Kachelreihe wird nicht mehr gezählt,
sondern beim Namen genannt (admin, hand, modi, gast) -- eine Zahl war
dort schon zweimal rot, ohne dass etwas kaputt war. Der App-Name wird
nicht nur geprüft, sondern der UNTERSCHIED zur Agenturadresse.

Die App heißt auf crew. jetzt "DogFather Universe" statt "Team Dogi" --
sie gehört ab heute beiden (Entscheidung Filipe).

Geprüft: rollen 312 · crew-adresse 132 · kalender 104 · sicht 84 ·
modi-verborgen 80 · chat-kanaele 79 · treff-werkzeuge 70 · haus-trennung
62 · treff 58 · chat 48 · treff-seiten 42 · bereiche-lesend 37 ·
start-ansicht 147 · css-klassen 30 · zwischenspeicher 21 · alle-wege 19 ·
rechtetafel 19 -- alles grün.

Die 58 bei pruef-treff sind elf weniger als gestern: Mit der dritten
Adresse fallen ihre 26 Weichen-Prüfungen weg, ersetzt durch 10 für die
eine Wand plus die neuen in 7b.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-11 18:38:05 +02:00
co-authored by Claude Opus 5
parent 1ebaf8a864
commit 39dd666b17
47 changed files with 856 additions and 987 deletions
+96 -14
View File
@@ -32,7 +32,7 @@ import { darfSeite, OHNE_ANMELDUNG, SEITEN, ALLE_ROLLEN } from "./rechte.js";
obwohl workspace-treff.js seinerseits aus dieser Datei importiert.
Begruendung im Kopf von treff-tabellen.js. */
import { treffTabellen, treffSperreLesen } from "./treff-tabellen.js";
import { sitzungPasstZurAdresse, istOhneModiAdresse, istCrewAdresse, istTreffAdresse, istPruefAdresse, AUSSEN_ROLLEN,
import { sitzungPasstZurAdresse, istOhneModiAdresse, istCrewAdresse, istPruefAdresse, AUSSEN_ROLLEN,
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. */
@@ -100,8 +100,22 @@ const ROLLEN_KACHEL = new Set(["spicy", "admin", "manager", "scout", "creator"])
*
* DogFather steht auf BEIDEN Waenden. Er ist die einzige Person, die
* in beiden Welten arbeitet; das ist keine Ausnahme von der Trennung,
* sondern ihr Sinn. */
const CREW_KACHEL = new Set(["admin", "hand", "modi"]);
* sondern ihr Sinn.
*
* VIER, SEIT DER TREFF HIER WOHNT (Entscheidung Filipe, 11.09.2026:
* "das soll keine app fuer sich sein, das soll in der crew seite
* adaptiert werden" -- und auf die Frage, wie die Community durch
* diese Wand kommt: "vierte Kachel Community").
*
* WAS DAS KOSTET, und es gehoert hierhin und nicht in eine Fussnote:
* Ein Mitglied der Community liest vor seiner Anmeldung die Namen der
* drei Team-Rollen. Die Alternative waere gewesen, die Kachelreihe
* ganz abzuschaffen und allein den Code entscheiden zu lassen -- dann
* haette niemand eine Rolle gesehen, aber Filipes Entscheidung vom
* 10.09. waere wieder umgeworfen worden. Er hat sich fuer die vierte
* Kachel entschieden; der Preis ist damit bewusst bezahlt und nicht
* uebersehen. */
const CREW_KACHEL = new Set(["admin", "hand", "modi", "gast"]);
/** Die Rollen mit einer Kachel auf der Zugangswand von treff.
*
@@ -114,7 +128,7 @@ const CREW_KACHEL = new Set(["admin", "hand", "modi"]);
* Die Menge steht trotzdem hier: Die Anmeldung prueft gegen sie, und
* eine Wand ohne Kacheln darf nicht heissen, dass jede Rolle
* durchkommt. */
const TREFF_KACHEL = new Set(["gast"]);
/* Als SQL-Ausdruck fuer ORDER BY. "ORDER BY rolle" waere alphabetisch
(admin, creator, manager, scout, spicy) -- also fast genau falsch
@@ -3288,7 +3302,7 @@ export function sitzungLesen(req) {
(sichtPerson) das auch nicht tut. Wer hier etwas anderes einbaut,
macht aus einer Anzeigefrage eine Rechtefrage. */
const haus = istCrewAdresse(req.get?.("host")) ? "crew"
: istTreffAdresse(req.get?.("host")) ? "treff" : "agentur";
: "agentur";
/* DER AUSSCHLUSS WIRKT HIER -- an derselben Stelle wie alles andere
(11.09.2026).
@@ -3676,9 +3690,7 @@ workspaceRouter.post("/workspace/api/anmelden", (req, res) => {
Wand gerade dran ist. Ein Manager, der crew. erraet und seinen
Code eintippt, faellt dadurch in genau dieselbe Antwort wie
jemand mit einer erfundenen Rolle. */
const kachelSatz = istTreffAdresse(req.get("host")) ? TREFF_KACHEL
: istCrewAdresse(req.get("host")) ? CREW_KACHEL
: ROLLEN_KACHEL;
const kachelSatz = istCrewAdresse(req.get("host")) ? CREW_KACHEL : ROLLEN_KACHEL;
if (!kachelSatz.has(rolle) || !codeBrauchbar) {
db().prepare("INSERT INTO versuche (ip, zeitpunkt) VALUES (?,?)").run(ip, jetzt());
@@ -4865,7 +4877,21 @@ export function protokollLesen(anzahl = 20) {
Die Reihenfolge ist egal (beide verkleinern nur), die Trennung nicht.
===================================================================== */
const HAUS_TEAM_ROLLEN = new Set(["admin", "hand", "modi"]);
/* WER AUF DER TEAM-ADRESSE UEBERHAUPT VORKOMMT.
*
* Die Community steht seit dem 11.09.2026 mit drin (Filipe: "das soll
* keine app fuer sich sein, das soll in der crew seite adaptiert
* werden"). Der Treff wohnt jetzt hier, also muessen seine Mitglieder
* hier auch verwaltet werden koennen -- sonst legt DogFather einen
* Zugang an und er verschwindet im selben Moment aus der Liste.
*
* DAS MACHT SIE NICHT ZU KOLLEGEN. Diese Menge beantwortet nur "wer
* kommt auf dieser Adresse vor". Ob jemand in eine Einladung, eine
* Aufgabe oder einen Chat darf, beantwortet ohneAussen() weiter unten
* -- und das sagt bei der Community ueberall Nein. Zwei verschiedene
* Fragen, zwei verschiedene Funktionen; wer sie in eine legt, kann
* spaeter nicht mehr sagen, welche gerade zugeschlagen hat. */
const HAUS_TEAM_ROLLEN = new Set(["admin", "hand", "modi", "gast"]);
function nurHaus(ids, person) {
if (person?.haus !== "crew") return ids;
@@ -4971,10 +4997,66 @@ function nurEigene(ids, person) {
return person?.id ? [person.id] : [];
}
export const sichtbareCreatorIds = (person) => nurEigene(nurCreatorIds(nurHaus(ohneVerborgene(sichtbareCreatorIdsRoh(person), person), person)), person);
/* =====================================================================
WER VON AUSSEN IST, STEHT IN KEINER ARBEITSLISTE (11.09.2026)
=====================================================================
nurEigene() beantwortet "was sieht ein Mitglied der Community?".
Diese Huelle beantwortet die andere Richtung: "steht ein Mitglied der
Community in der Liste, die jemand ANDERS bekommt?"
DER ANLASS: Seit es die Rolle gibt, taucht sie in jeder Liste auf,
die "alle" bedeutet -- und fuer DogFather bedeutet fast jede Liste
"alle" (siehtAlles). Ein Mitglied der Community stand damit in der
Auswahl, wen man zu einem Termin einlaedt, wem man eine Aufgabe gibt
und mit wem man einen Chat anfaengt. Nichts davon ist vorgesehen, es
gab dafuer nie eine Entscheidung, und aufgefallen waere es zum ersten
Mal, wenn jemand versehentlich einen Zuschauer zu einer internen
Besprechung einlaedt.
WARUM ALS HUELLE UND NICHT IN DEN VIER FUNKTIONEN: Weil sie dann auch
fuer die Listen gilt, die es noch nicht gibt. Dieselbe Ueberlegung
steht schon bei nurHaus() und bei der Modi-Huelle in
workspace-bereiche.js -- und beide Male war der erste Anlauf ein
einzelner geflickter Fall, der den naechsten offen liess.
NULL HEISST "ALLE" -- und sobald hier etwas herausfaellt, darf es das
nicht mehr heissen. Die Liste wird deshalb AUSGESCHRIEBEN, so wie
ohneVerborgene() und nurHaus() es auch tun.
EIN FEHLSCHLAG SCHLIESST. Bei einer Datenbankstoerung eine
ungefilterte Liste zurueckzugeben hiesse, die Community genau dann in
die Einladungsauswahl zu setzen, wenn ohnehin gerade etwas nicht
stimmt. Eine leere Liste ist sichtbar falsch, eine zu volle nicht.
AUSDRUECKLICH NICHT ANGEWENDET auf sichtbarePersonenIds(): Das ist
die Verwaltungsliste, in der DogFather Zugaenge anlegt und Codes neu
setzt. Dort MUSS die Community stehen. Die Einladungsliste leitet
sich zwar davon ab -- aber sie bekommt diese Huelle aussen herum,
und damit ist die Verwaltung offen und die Zusammenarbeit zu. */
function ohneAussen(ids) {
const rollen = [...AUSSEN_ROLLEN];
if (!rollen.length) return ids;
try {
const platz = rollen.map(() => "?").join(", ");
const aussen = db().prepare(
`SELECT id FROM personen WHERE rolle IN (${platz})`).all(...rollen).map((z) => z.id);
if (!aussen.length) return ids;
if (ids === null) {
return db().prepare(
`SELECT id FROM personen WHERE rolle NOT IN (${platz})`).all(...rollen).map((z) => z.id);
}
const menge = new Set(aussen);
return ids.filter((i) => !menge.has(i));
} catch {
return [];
}
}
export const sichtbareCreatorIds = (person) => ohneAussen(nurEigene(nurCreatorIds(nurHaus(ohneVerborgene(sichtbareCreatorIdsRoh(person), person), person)), person));
export const sichtbarePersonenIds = (person) => nurEigene(nurHaus(ohneVerborgene(sichtbarePersonenIdsRoh(person), person), person), person);
export const betreuerIds = (person) => nurEigene(nurHaus(ohneVerborgene(betreuerIdsRoh(person), person), person), person);
export const einladbareIds = (person) => nurEigene(nurHaus(ohneVerborgene(einladbareIdsRoh(person), person), person), person);
export const betreuerIds = (person) => ohneAussen(nurEigene(nurHaus(ohneVerborgene(betreuerIdsRoh(person), person), person), person));
export const einladbareIds = (person) => ohneAussen(nurEigene(nurHaus(ohneVerborgene(einladbareIdsRoh(person), person), person), person));
/* SICH SELBST NICHT -- UND ZWAR AUCH DANN NICHT, WENN DIE LISTE
AUSGESCHRIEBEN WIRD (10.09.2026).
@@ -4996,7 +5078,7 @@ export const einladbareIds = (person) => nurEigene(nurHaus(ohneVerborgene(einlad
seit es ueberhaupt jemanden zu verbergen gibt; vorher konnte es ihn
nicht geben. */
export const schreibbareIds = (person) => {
const ids = nurHaus(ohneVerborgene(schreibbareIdsRoh(person), person), person);
const ids = ohneAussen(nurHaus(ohneVerborgene(schreibbareIdsRoh(person), person), person));
return ids === null ? null : ids.filter((i) => i !== person?.id);
};
export const pipelineIds = (person) => nurHaus(ohneVerborgene(pipelineIdsRoh(person), person), person);
export const pipelineIds = (person) => ohneAussen(nurHaus(ohneVerborgene(pipelineIdsRoh(person), person), person));