Eine Kampagne gehoert zur Agentur -- auch wenn DogFather ueberall admin ist

Aufgefallen beim Nachweis auf der echten Adresse, nicht beim Bauen:
Der Kasten haengt an `bereich === "agentur"` und an der Rolle. DogFather
ist aber in BEIDEN Haeusern `admin`. Oeffnet er auf
crew.dogfather-universe.com von Hand `bereich.html?b=agentur`, dann
stimmt der Bereich, die Rolle stimmt -- und `hausFuerNeuenEintrag` gaebe
der Kampagne das Haus "crew". Eine Agentur-Kampagne staende im Rudel,
und die Trennung waere an genau der Stelle unterlaufen, an der niemand
nachsieht. Bauplan, Teil 11: "Nichts im Haus Team Dogi."

ZWEI FRAGEN, ZWEI SCHWELLEN -- und das ist Absicht:

  /api/ich (ZEIGEN)     haus !== "crew"
  Route    (SCHREIBEN)  haus === "agentur"

Der Unterschied betrifft genau einen Fall: `null`. Den gibt es nur auf
einer PRUEFADRESSE -- `sitzungLesen` vergibt dort seit dem 24.09.2026
bewusst kein Haus, und die Begruendung dort nennt den Schaden:
Als 127.0.0.1 einmal ein Haus bekam, fiel pruef-chat-kanaele mit 13
Fehlschlaegen um, und die naechsten Pruefungen waeren still gruen
geblieben, ohne noch etwas zu messen. Eine echte Anfrage hat immer eine
der beiden Waende; eine Sitzung zu einer dritten lehnt
`sitzungPasstZurAdresse` ohnehin ab.

Beim SCHREIBEN wird trotzdem streng gefragt: Ein Eintrag mit
`haus = null` waere in BEIDEN Haeusern sichtbar -- genau das, was Teil
11 ausschliesst.

WAS ICH DABEI ZWEIMAL FALSCH VERSUCHT HABE
  Zuerst sollte das Bildwerkzeug ueber die Agenturwand kommen, damit
  es den Kasten weiter messen kann. Den Host-Kopf beim Durchreichen zu
  ueberschreiben wirkt nicht -- gemessen: /api/ich meldete weiter
  `darf: false`, der Wirt blieb "127.0.0.1:4338". Chromium laesst
  `Host` nicht ueberschreiben.

  Dann den Namen wirklich aufloesen (--host-resolver-rules). Das
  funktioniert, bringt aber die Anmeldemaske der echten Wand mit einer
  Tuer davor, die ein Bildwerkzeug nicht aufmachen soll. Gemessen
  werden soll die KACHEL, nicht der Zugang.

  Deshalb bleibt bild-kampagne auf der Pruefadresse -- und genau
  deshalb fragt /api/ich `!== "crew"` statt `=== "agentur"`. Beide
  Zeilen tragen jetzt die Begruendung bei sich, damit sie niemand
  "vereinheitlicht": Das macht entweder die Pruefungen blind oder
  laesst eine Kampagne ins Rudel.

Zwei Gegenproben gefahren, beide schlagen an: Route nimmt jede Wand an
-> 2 rot. /api/ich fragt nicht nach dem Haus -> 1 rot.

GEPRUEFT: pruef-kampagne 98 -> 99 gruen · bild-kampagne 20 Messungen
gruen · pruef-struktur, pruef-haus-trennung 107, pruef-agentur 62,
pruef-eventkarte 94, pruef-alle-wege, pruef-schranke, pruef-zeichen 8

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-10-07 17:31:11 +02:00
co-authored by Claude Opus 5
parent 10e24b0c93
commit 8cde56bd96
4 changed files with 122 additions and 8 deletions
+21
View File
@@ -753,6 +753,15 @@ melde("=== 11. Kampagnen anlegen dürfen DogFather und die Manager ===");
&& ichLuna.darf_kampagne_einlesen === false,
"/api/ich sagt der Oberfläche dasselbe wie die Schranke der Route");
/* UND AUF DER CREW-ADRESSE SAGT SIE NEIN. Das ist der Fall, den
es in der Wirklichkeit gibt: DogFather ist dort ebenfalls
`admin`, und ohne diese Antwort stuende der Kasten im Rudel. */
const ichCrew = JSON.parse((await roh("/workspace/api/ich",
{ keks: keksDogiCrew, wirt: CREW_HOST })).text);
ok(ichCrew.rolle === "admin" && ichCrew.darf_kampagne_einlesen === false,
`auf der Crew-Adresse sagt sie nein (Rolle ${ichCrew.rolle},`
+ ` darf ${ichCrew.darf_kampagne_einlesen})`);
/* FREMDE HERKUNFT. Die Wache steht in index.js, VOR diesem Router. */
const fremd = await new Promise((f, s) => {
const daten = Buffer.from(JSON.stringify({ text: "x" }));
@@ -795,6 +804,18 @@ melde("=== 12. Team Dogi bleibt unberührt ===");
ok((wsBrett.eintraege || []).some((e) => e.id === kachelId),
"Gegenprobe: auf der Agentur-Adresse schon");
/* UND VON DER CREW-ADRESSE AUS LAESST SIE SICH GAR NICHT ANLEGEN.
DogFather ist in beiden Haeusern `admin` -- die Rollenfrage
allein laesst ihn also durch. Ohne diese Schranke bekaeme die
Kampagne das Haus "crew", und die Trennung waere an genau der
Stelle unterlaufen, an der niemand nachsieht. */
const vonCrew = await einlesen(`Klick: ${TIK}/t/gipfel`, keksDogiCrew, CREW_HOST);
ok(vonCrew.code === 403,
`von der Crew-Adresse: HTTP ${vonCrew.code} — „${vonCrew.j.fehler}“`);
ok(/[Aa]gentur/.test(vonCrew.j.fehler || ""),
" und die Meldung sagt, wo es hingehoert");
const crewNachher = dbLesen("SELECT COUNT(*) AS n FROM eintraege WHERE haus = 'crew'")[0].n;
ok(crewVorher === crewNachher,
`und die Zahl der Crew-Einträge ist unverändert (${crewVorher} = ${crewNachher})`);