Commit Graph
23 Commits
Author SHA1 Message Date
DogFatherGitandClaude Opus 5 3e1e0810ba Agentur-Events: die Karte als Aushang, Aufgaben zum Abhaken
Filipe, mit einem Bildschirmfoto des Oktober-Events: "ich will das viel
geiler viel perfekter. und auch wenn man die eintraegt und so soll viel
mehr perfektioniert und uebersichtlicher sein."

VORHER GEMESSEN (1280 px, eine einzige Eventkarte):

  Kartenhoehe            1196 px   -- das Fenster ist 900 px
  davon Banner            638 px   -- 53 %, ohne einen Buchstaben
  Titel steht bei        1482 px   -- zweimal scrollen bis zum Namen
  Titelgroesse          15,36 px   -- 1,4 px mehr als der Fliesstext
  Etikett               10,88 px   -- unter der eigenen Grenze (11,5)
  Datum                     3 x    -- in drei Zeilen untereinander
  Knoepfe              4 x gleich  -- "loeschen" wie "zur Aufgabe"

NACHHER, dieselbe Messung: Karte 618 px, Buehne 203 px, Titel 75 px
unter der Kartenkante und 24,8 px gross, Etikett 12 px, das Datum
einmal, "loeschen" abgesetzt.

DIE KARTE
Das Banner ist nicht mehr ein Anhang ueber dem Titel, sondern die
Buehne dahinter -- Hoehe gedeckelt, Titel darauf. Dazu die Frage, die
bei einem Wettbewerb wirklich zaehlt und bisher nirgends beantwortet
wurde: "noch 12 Tage", mit Zeitbalken. Ein Knopf "Banner ganz" holt das
vollstaendige Bild zurueck, das beim Umbau sonst verloren gegangen
waere -- bei Filipes Banner steht die Ansage IM Bild.

DIE AUFGABEN
Aus Fliesstext wird eine Liste, und jeder hakt fuer sich ab (neue
Tabelle event_punkte, Schluessel aus dem Zeilentext). Umsortieren
laesst den Haken, wo er ist; wird die Bedingung selbst umgeschrieben,
faellt er -- beides nachgemessen. Die Leitung sieht, wer wie weit ist,
eine Creatorin sieht diese Liste gar nicht erst.

DAS FORMULAR
Ein Feld je Zeile statt eines leeren Textfeldes. Im echten Event stand
".Jeden Tag Live gehen" neben ". 33k Diamanten erreichen" -- einmal mit
Leerzeichen, einmal ohne. Das ist die zwangslaeufige Folge davon, dass
die Aufzaehlungszeichen von Hand getippt werden; jetzt setzt sie das
Formular. Dazu "Laeuft 14 Tage.", eine Warnung bei verdrehtem Zeitraum
und eine Vorschau, die dieselbe Funktion benutzt wie die echte Karte.

NEBENBEI GEFUNDEN UND BEHOBEN
* Das Banner kam bei Creatorn mit 404 zurueck -- also an genau der
  Karte, die fuer sie gemacht ist. Die Regel "wer das Brett sieht,
  sieht das Bild" galt nur fuer die sieben Community-Bretter. Jetzt
  fragt der Bildweg dieselbe Regel wie das Brett (darfEintragSehen);
  die Gegenprobe zeigt, dass ein fremder Eintrag weiterhin 404 gibt.
* Zwei Stellen setzten das Formular zurueck, die kuerzere liess
  Vorschau und Zeilen-Editor stehen -- beim naechsten "Neuer Eintrag"
  standen die Aufgaben des vorigen Events noch da.
* Der Schriftgrund ragte auf dem Handy 6 px ueber die Karte (feste
  -20 px gegen 14 px Polsterung); jetzt an die Polsterung gekoppelt.

GEPRUEFT
pruef-eventkarte.mjs (neu): 77 Pruefungen, 0 Fehler -- mit Gegenproben
zu jeder Zusage und einer Kontrastmessung am Bildpunkt auf einem
weissen Banner (14,7:1; ohne den Schriftgrund 1,05:1).
pruef-agentur.mjs auf die neuen Bausteine nachgezogen, Zahl unveraendert
bei 62. pruef-eintrag-bild.mjs 24/0.

OFFEN, NICHT AUS DIESEM UMBAU: Das Brett `agentur` ist auf der
Crew-Adresse erreichbar. Zweimal gemessen, mit und ohne diese
Aenderung -- gleiches Ergebnis. Gehoert zur Trennungsregel vom
24.09.2026 und wird getrennt entschieden.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-03 19:02:05 +02:00
DogFatherGitandClaude Opus 5 4324547eb3 Teilanfragen: Sprachnachrichten kommen jetzt auch auf dem iPhone an
Filipe: „zeurst schaust du mal ob es im system liegt dass miss, die modi,
keine sprachnachrichten hoeren kann oder ob es an ihr liegt weil bei allen
anderen klappt nur bei ihr nicht"

ES LAG AM SYSTEM.

WAS GEMESSEN WURDE (nicht vermutet)

1. An ihrer Rolle liegt es nicht. Der Weg `/workspace/api/chat/anhang/:id`
   fragt drei Dinge: gibt es die Nachricht, ist die Person im Raum, hat sie
   das Gespraech weggeraeumt. Keine Rollenpruefung. Gegen eine Wegwerf-
   Datenbank gemessen: `anmelden admin=200 modi=200`, Anhang als modi
   HTTP 200, 40018 Bytes -- genau wie als admin.

2. Sie ist in allen drei Raeumen mit Sprachnachrichten, geloescht_bis = 0,
   alle sechs Tondateien liegen auf der Platte. (Live-Datenbank, nur
   gelesen, auf einer Kopie, Kopie danach geloescht.)

3. Sie ist die EINZIGE im Haus mit Safari. Aus dem Caddy-Protokoll, ueber
   IP und Minute mit ihren Protokolleintraegen abgeglichen: iPhone,
   iOS 18.7, Safari 26.6.1. Alle anderen Geraete der letzten zwei Wochen:
   Android-Chrome 3900 Anfragen, Windows-Chrome/Edge/Firefox 2646.
   Neun von zehn iPhone-IP-Praefixen sind ihre.

4. DER FEHLER: Der Anhang-Weg beantwortete eine Teilanfrage
   (`Range: bytes=0-1`) mit einer vollen HTTP 200 -- ohne `Accept-Ranges`,
   ohne `Content-Length`, als `chunked`. Zum Vergleich dieselbe Anfrage an
   `express.static`: HTTP 206, `accept-ranges: bytes`,
   `content-range: bytes 0-1/2480`.

   Safari verlangt fuer <audio> und <video> zwingend Teilanfragen und
   verweigert die Wiedergabe bei einer 200. Chrome und Firefox nehmen die
   ganze Datei klaglos. Bilder brauchen das nicht -- deshalb sah sie Fotos
   und hoerte nichts, und deshalb fiel es sieben Tage lang nur ihr auf.

WAS GEAENDERT IST

A) EIN GEMEINSAMER AUSLIEFERWEG (server/helfer-ausliefern.mjs)

   Im Haus gaben ZEHN Stellen eine Datei mit `createReadStream(pfad)
   .pipe(res)` hinaus: Chat-Anhang, Chat-GIF, Dateiablage (ansehen und
   laden), Material (ansehen und laden), Steckbriefbild, Buehnenbild,
   Supportbild, Wissens-PDF. Nur eine davon zu reparieren hiesse, eine
   Liste zu fuehren, welche Stelle schon richtig ist -- und die naechste
   neue macht es wieder falsch. Alle zehn gehen jetzt ueber
   `liefereDatei(req, res, pfad)`: `Accept-Ranges`, `Content-Length`,
   206 mit `Content-Range`, 416 mit `bytes */groesse`. Mehrere Bereiche in
   einer Anfrage werden absichtlich nicht bedient (das darf ein Server);
   die Antwort ist dann die GANZE Datei, nie eine falsche Teilmenge.

   WAS ES AUSSER SAFARI BRINGT, gemessen: Eine MP4-Sprachnachricht meldete
   in Chromium ohne Teilanfragen 0,23 s statt 1,96 s Laenge -- der Kopf
   einer MP4 steht am Ende der Datei. Eine Ogg-Datei meldete „Infinity"
   statt 2,02 s. Und ein PDF-Betrachter springt jetzt zu einer Seite, ohne
   die ganze Datei zu holen.

B) AUFGENOMMEN WIRD AAC IN MP4 (workspace/assets/js/chat.js)

   Die Reihenfolge der Behaelter beantwortete bisher die Frage „was kann
   DIESES Geraet am liebsten". Richtig ist „was koennen die ANDEREN
   abspielen" -- die hoeren es.

   Gemessen mit echten Aufnahmen aus echten Browsern, danach in beiden
   Engines abgespielt:
     Chromium nimmt auf: webm/opus, mp4(AAC), mp4(Opus)
     Firefox  nimmt auf: webm/opus, ogg/opus -- MP4 gar nicht
     Beide spielen alle vier Behaelter vollstaendig ab (2 s rein, 2 s raus)

   ZWEI FALLEN, die die Messung gezeigt hat:
   - Ein blankes `audio/mp4` ist nicht AAC: Chromium meldet darauf
     `audio/mp4;codecs=opus` zurueck -- MP4 aussen, Opus innen, fuer Safari
     genauso unbrauchbar wie WebM. Deshalb steht `audio/mp4;codecs=mp4a.40.2`
     VOR dem blanken `audio/mp4`.
   - Firefox kann kein MP4 aufnehmen und faellt sauber auf WebM/Opus
     zurueck. Kein Rueckschritt -- das ist der heutige Stand.

   Die Pruefung nimmt jetzt im echten Browser ueber den echten Knopf auf,
   und der Server erkennt: audio/mp4, 45583 Bytes, 2734 ms.

   BERICHTIGT: In zwei Kommentaren stand „Safari und das iPhone koennen
   nur MP4". Das stimmt nicht. An Miss' eigener Aufnahme nachgemessen:
   Behaelter WebM, Mux-Programm „WebKit", Tonspur A_OPUS. Safari NIMMT
   WebM auf -- ob es WebM abspielt, ist eine andere Frage.

C) EIN AUSWEG STATT EINER VERTROESTUNG (chat.js, chat.css)

   Vorher stand im Fehlerfall „Sprachnachricht laesst sich gerade nicht
   laden". Das war fuer Miss die ganze Auskunft, und es stimmte nicht
   einmal: Die Datei kam an, ihr Browser konnte den Behaelter nicht.
   „Gerade" heisst „gleich nochmal versuchen" -- bei einem fremden
   Behaelter hilft kein Versuch mehr.

   Jetzt wird unterschieden (Fehlercode 4 = Format, alles andere = Laden)
   und daneben steht ein Weg, der wirklich zum Ton fuehrt: Herunterladen,
   44 px hoch, in der Farbe der Blase, mit eigenem Vorlesewort. Nur im
   Fehlerfall -- ein Knopf an jeder Sprachnachricht waere Unordnung fuer
   alle, damit einer Person geholfen ist.

WAS JETZT NACHGEZAEHLT WIRD

- pruef-chat-anhaenge: 119 -> 146 Pruefungen. Dreizehn davon messen
  Teilanfragen am Foto (0-9, -8, 5-, ueber das Ende hinaus, 416, mehrere
  Bereiche, unverstandener Kopf) und vergleichen jeden Abschnitt BYTEWEISE
  mit der vollen Datei -- eine 206 mit den falschen Bytes waere schlimmer
  als keine. Drei Gegenproben legen dieselbe Messlatte an erfundene
  Antworten (die alte volle 200, falsche Gesamtgroesse, falsche Bytes) und
  muessen durchfallen. Neun weitere pruefen die Sprachnachricht selbst und
  den Ausweg.
- pruef-wissen-neu: +6. Der Weg zur PDF war der EINZIGE der zehn, den nie
  eine Pruefung abgerufen hat -- genau der, bei dem eine Umstellung
  unbemerkt danebengeht. Jetzt beide Spielarten (ansehen und laden).
- pruef-struktur: +6. Wer kuenftig wieder `createReadStream(...).pipe(res)`
  schreibt, bekommt einen Befund. Mit Gegenproben in beide Richtungen; die
  Probetexte sind zusammengesetzt, sonst meldet die Wache ihre eigene
  Begruendung als Fund. Pruefdateien sind ausgenommen, weil sie an niemanden
  ausliefern -- dort ist ein Weg ohne Teilanfragen die Gegenprobe.
  (Beim ersten Lauf hat die Wache sofort meine eigene Messdatei gefunden.)

WAS NICHT NACHGESEHEN WERDEN KONNTE

Ob iOS-Safari WebM/Opus ueberhaupt abspielt. Playwrights WebKit startet auf
diesem Rechner nicht (`icuuc77.dll`, auch nach Neuinstallation), und ein
iPhone habe ich nicht. Der dritte Ausgang: konnte nicht nachsehen. Deshalb
sind A, B und C drei Sicherungen hintereinander statt einer Wette auf eine.

GEPRUEFT (alles einzeln, kein Gesamtlauf)

  pruef-chat-anhaenge   146 ok   pruef-material     159 ok
  pruef-wissen-neu       33 ok   pruef-spenden      172 ok
  pruef-struktur         85 ok   pruef-support       63 ok
  pruef-video            74 ok   pruef-steckbrief    65 ok
  pruef-galerie          26 ok   pruef-eintrag-bild  24 ok
  pruef-chat             63 ok   pruef-chat-optik    62 ok
  pruef-haus-trennung   100 ok

Die beiden Haeuser bleiben getrennt (pruef-haus-trennung, 100 ok). Der
Ausliefer-Weg gehoert beiden gleichermassen und traegt nichts Haus-
spezifisches; die Aufnahme betrifft faktisch nur Team Dogi, weil nur dort
der Mikrofonknopf steht („also nur die modis rechte linke hand und
dogfather").

NICHT VON MIR, SCHON VORHER ROT: pruef-gifs meldet zwei Fehler („das GIF
steht danach wirklich im Verlauf", „die Tafel geht zu"). Gegen den
unveraenderten Stand von HEAD nachgemessen -- dieselben zwei Fehler, mit
denselben Zahlen. Ein eigener Befund, kein Nebenschaden dieser Arbeit.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 03:41:18 +02:00
DogFatherGitandClaude Opus 5 9863645952 Die zwei Häuser sind getrennt -- und die Tür geht in beide Richtungen
Filipe: "ich will dass du zuerst die komplette site vn der workspace
seite trennst. da soll nichts verknüpft sein. wenn ich bei der einen
was mache soll nichts bei der anderen passieren. … es soll nur für
dogfather eine kachel geben wo er mit einem einfachen klick von der
einen auf die anderen seite kommt aber sonst garnichts."

Das kehrt die Entscheidung vom 10.09.2026 um ("getrennt wird das
AUSSEHEN, nicht der Bestand"). Wer den alten Kommentar liest, liest
einen überholten Stand -- das steht jetzt an jeder betroffenen Stelle.

WAS GEMESSEN WAR, BEVOR ETWAS GEBAUT WURDE
  * Nur drei Module trennten nach Haus (Aufgaben, Bereiche, Dateien).
    Chat, Kalender, Wissen, Material, Personenlisten und der Rest nicht.
  * Die Trennung war EINSEITIG: nurHaus() griff nur auf crew.
  * siehtModis() hebelte sie für DogFather auf der Agenturseite aus --
    in seiner Gesprächsliste standen dort beide Häuser nebeneinander.
  * Keine haus-Spalte in der Datenbank.
  * Der Bestand kreuzte aber kaum: 0 von 86 Terminen gemischt, 0 von 7
    Zweier-/Gruppengesprächen, genau EIN Kanal.

WAS JETZT DASTEHT
  * Drei Rollenmengen in crew-adresse.js (crew / agentur / beide) und
    hausVonRolle(); eine unbekannte Rolle bekommt null, kein Haus.
  * Spalte `haus` an acht Wurzeltabellen, nachgetragen aus Belegen:
    238 Zeilen eindeutig, die Wissensablage geschlossen der Agentur,
    vier Restzeilen namentlich, der gemischte Kanal aufgelöst
    (die zwei Scouts gehen heraus, die 7 Nachrichten sind alle vom
    Team). Offen bleiben: null.
  * nurHaus, hausBedingung und darfAnlegen gelten in BEIDE Richtungen.
  * Der siehtModis-Durchgriff ist weg -- aber in DREI Fällen, nicht
    zwei: Prüfadressen bekommen gar kein Haus und verhalten sich exakt
    wie vorher. Die erste Fassung hatte das übersehen und 19 Prüfungen
    umgeworfen, an denen nichts kaputt war.
  * Kalender: getrennt, aber "belegt" bleibt (Filipes Entscheidung).
    Die Blöcke tragen NUR Beginn und Dauer -- kein Titel, keine Person.
    Gebaut als Gegenstück zur Liste (meine Termine MINUS die sichtbaren),
    damit beide nicht auseinanderlaufen können.
  * Die Wissens-Kachel ist auf der Team-Adresse weg UND die Route
    antwortet dort mit 404 -- eine fehlende Kachel ist nur eine Bitte.
  * Die Wechsel-Kachel für DogFather geht jetzt in beide Richtungen.

GEPRÜFT: pruef-haus-trennung 97 statt 81, 0 Fehler (vorher 7, alle
haben die alte Regel behauptet). Die neuen Abschnitte sind DORT
eingezogen statt in eine zweite Datei -- `pruef-haustrennung.mjs` hätte
sich von `pruef-haus-trennung.mjs` um einen Bindestrich unterschieden.
Dazu grün: haus-seiten, crew-adresse, chat, chat-kanaele,
kanal-besetzung, kalender, serien, treffchat, wissen-neu,
modi-checkliste, modi-katalog, rechtetafel, personen-liste, sicht,
verborgen, fremde-sicht, alle-wege.

NICHT VON MIR: pruef-treff (3) und pruef-kachel-universum (2) waren
schon vorher rot -- beim Treff auf dem Stand 40b48e89 nachgemessen,
bei den Farben steht dieselbe Zahl im Kopf der Prüfung selbst.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-24 20:40:20 +02:00
DogFatherGitandClaude Opus 5 4b14906371 Stufe 5: Highlights als Galerie -- und ein enger Weg fuer Bilder
Aus dem Plan im Vault. "Eure Clips und Bilder" zeigte Textkarten mit
einem Anhang darunter. Ein Bild als Anhang unter einer Ueberschrift ist
kein Highlight -- dieser Bereich lebt vom Sehen. Jetzt steht das Bild
OBEN, der Text ist Bildunterschrift.

ZWEI DINGE WAREN ANDERS ALS IM PLAN

1. "Anhaenge sind schon da" stimmte nicht. Sie hingen an AUFGABEN
   (`dateien.aufgabe_id`); ein Eintrag konnte gar kein Bild tragen.
   Neue Spalte `eintrag_id`.

2. UND DER WICHTIGE, ein Sicherheitsthema: Alles in dieser Ablage geht
   bewusst als DOWNLOAD hinaus (`application/octet-stream`,
   `Content-Disposition: attachment`). Eine hochgeladene HTML- oder
   SVG-Datei wuerde sonst im Browser als Seite DIESER Domain laufen --
   mit Zugriff auf die Sitzung. Eine Galerie braucht also einen
   eigenen, engen Weg, keine Lockerung der alten Regel.

DIE FRAGE "IST DAS EIN BILD?" DARF NICHT `dateien.typ` BEANTWORTEN.
Diese Spalte traegt den vom Browser BEHAUPTETEN Typ
(`req.get("content-type")`) -- wer hochlaedt, bestimmt ihn selbst. Eine
Galerie, die ihm glaubt, liefert auf Zuruf alles inline aus. Erkannt
wird deshalb an den ERSTEN BYTES: PNG, JPEG, GIF, WEBP.

SVG IST AUSDRUECKLICH NICHT DABEI. Es ist ein Bildformat UND kann
Skript enthalten -- genau die Luecke, gegen die die Regel gebaut wurde.
Ein Format, das beides ist, gehoert nicht in die Ausnahme.

Kein Bild heisst 404, nicht 415: Eine eigene Antwort waere die Auskunft
"diese Nummer gibt es, sie ist nur kein Bild", und die laesst sich
durchzaehlen.

WESSEN REGEL GILT: Ein Bild am Community-Beitrag folgt dem BEITRAG,
nicht der Dateiablage. Deren Regel haengt an Creator-Zuordnungen, und
ein Gast hat keine -- er saehe sonst nie ein Highlight, obwohl es fuer
ihn gemacht ist.

NEU: pruef-galerie (26 Pruefungen)
Der Beweis steht in zwei Zeilen: Am Beitrag haengen VIER Dateien --
zwei echte PNGs, ein SVG und eine HTML-Datei, die sich als
"image/png" ausgibt. Im Raster stehen ZWEI. Die anderen beiden holt
der Browser, bekommt 404, und der error-Handler raeumt sie weg: kein
leerer Rahmen, kein kaputtes Symbol.

Dazu die Gegenprobe in die andere Richtung -- ein echtes PNG, das sich
als "text/plain" ausgibt, geht durch. Ohne sie hiesse "404" nur, dass
der Weg immer ablehnt. Und die Konsolenpruefung laesst genau die zwei
gewollten 404 zu und nichts sonst; ein pauschales "Konsole egal" haette
jeden echten Fehler mitversteckt.

EIN EIGENER FEHLER: Mein Test-PNG war kein dekodierbares Bild, nur ein
Dateikopf. Der Browser konnte es nicht zeichnen, der error-Handler
raeumte es weg, und die Pruefung fand im Raster nichts. Fehler in der
Pruefung, nicht im Haus -- aber ein nuetzlicher: Er hat nebenbei
gezeigt, dass ein kaputtes Bild keinen leeren Rahmen hinterlaesst.

pruef-anhaenge 37, pruef-treff 66, pruef-bereiche-lesend,
pruef-css-klassen: gruen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-17 11:43:40 +02:00
DogFatherGitandClaude Opus 5 1386534051 Anhaenge an Aufgaben -- ohne eine zweite Dateiablage
Stufe 9 aus dem Plan. Eine Aufgabe "Vertrag pruefen" ohne den Vertrag
daneben ist eine Aufforderung zum Suchen.

KEIN ZWEITER HOCHLADEWEG

Dateien leben in der Dateiablage -- mit ihrer Sichtbarkeit, ihren
Freigaben, ihren Fassungen und ihrem Protokoll. Ein eigener Weg an der
Aufgabe waere eine zweite Ablage mit einer zweiten Rechtelogik gewesen,
und die zweite ist immer die, die etwas durchlaesst.

Deshalb nur eine Spalte: Die Datei WEISS, zu welcher Aufgabe sie
gehoert. Hochgeladen wird ueber denselben Weg wie immer, mit einem Kopf
mehr. Alles andere bleibt, wo es schon richtig ist -- die Anhaenge
tragen deshalb auch ihre Fassungsnummer und die Warnung "nicht mehr
aktuell" mit, ohne dass dafuer eine Zeile geschrieben werden musste.

DER RIEGEL

Waere `x-aufgabe` ungeprueft, waere der Kopf ein Weg, die Existenz
fremder Aufgaben zu erfahren -- man muesste nur Zahlen durchprobieren.
Geprueft wird deshalb gegen dieselbe Schranke wie fuer die Datei
selbst: `darfCreator`, die eine Stelle im Haus, an der diese Frage
beantwortet wird. Eine eigene Herleitung hier waere eine zweite Meinung
darueber gewesen. (Erster Anlauf: genau so eine Herleitung, mit einer
Funktion, die gar nicht importiert war.)

Gemessen: Ein Scout darf an die Aufgabe SEINER Creatorin, an die eines
fremden Creators nicht -- mit wortgleicher Absage wie bei einer
erfundenen Nummer. Der Unterschied waere sonst die Auskunft. Und es
bleibt auch keine lose Datei liegen: Die Pruefung findet vor dem ersten
Byte statt.

ON DELETE SET NULL, NICHT CASCADE

Der wichtigste Teil der Spalte: Wer eine Aufgabe loescht, will die
Aufgabe loeschen, nicht den Vertrag, der daran hing. Die Datei verliert
nur ihren Bezug und steht danach wieder in der Ablage. Gemessen.

EIN EIGENER FEHLER, GEFUNDEN BEIM MESSEN

Der Verweis am Anhang zeigte auf /workspace/api/dateien/:id -- den es
gar nicht gibt, der Weg heisst /inhalt. Die Pruefung ruft ihn jetzt
wirklich auf und erwartet 200, statt nur die Adresse zu vergleichen.

PRUEFUNGEN: pruef-anhaenge neu mit 37, davon 8 im Browser.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-15 13:12:41 +02:00
DogFatherGitandClaude Opus 5 478a2895b5 Dateifassungen: die alte Fassung sieht man ihr an
Stufe 9 aus dem Plan: "Dateiversionen statt Ueberschreiben".

GEMESSEN, BEVOR ETWAS GEBAUT WURDE -- DER PLAN LAG DANEBEN

Ueberschrieben wurde nie: `name_datei` ist eindeutig und zufaellig,
jedes Hochladen legt eine neue Zeile an. Der wirkliche Mangel ist ein
anderer, und er ist gefaehrlicher als Ueberschreiben:

  Zwei Dateien gleichen Namens standen BEZIEHUNGSLOS nebeneinander. Die
  alte kann "freigegeben" sein, die neue "entwurf" -- und wer die Liste
  ansieht, laedt die freigegebene herunter. Also die falsche. Kein
  Fehler, keine Meldung, nur die alte Fassung in der Hand.

WAS JETZT PASSIERT

Beim Hochladen erkennt der Server die Vorgaengerin selbst: gleicher
Originalname, gleicher Creator-Bezug, und sie darf nicht schon ersetzt
sein. An der Datei steht danach "Fassung 2"; an der alten steht "nicht
mehr aktuell".

  AUTOMATISCH, NICHT GEFRAGT -- eine Abwaegung: Wer die Verknuepfung
  vergisst, hat zwei Dateien ohne Zusammenhang, und irgendwann laedt
  jemand die alte herunter. Wer sie faelschlich bekommt, SIEHT das
  sofort und loest sie mit einem Klick. Der stille Schaden ist groesser
  als der sichtbare.

  BEI ZWEIFEL WIRD NICHT GERATEN. Gibt es zwei unersetzte Dateien
  gleichen Namens, bleibt die neue eigenstaendig.

  LOESEN GEHT NUR AN DER AKTUELLEN FASSUNG. Wer eine ueberholte loest,
  macht daraus eine zweite aktuelle -- und hat das Problem zurueck.

  DIE NUMMER IST GERECHNET, NICHT GESPEICHERT. Eine Spalte "version"
  muesste beim Loeschen einer mittleren Fassung nachgezogen werden, und
  genau das vergisst man. Faellt die erste weg, zaehlt die zweite
  wieder als erste -- richtig, denn mehr weiss das System dann nicht.

  EIN RING IN DEN DATEN HAELT DIE SEITE NICHT AN. Kann ueber die Wege
  hier nicht entstehen, aber ein Fehler anderswo koennte ihn erzeugen,
  und ein Stillstand ist schlimmer als ein Fehler. Gemessen: 1 ms.

ZWEI SITZUNGEN IM SELBEN VERZEICHNIS

Der vorige Commit (d2210fd, aus einer anderen Sitzung) hat mit
`git add -A` meine damals noch unfertige Spalte `dateien.ersetzt_id`
mitgenommen -- sie steht dort unter einer Ueberschrift, die nichts
damit zu tun hat. Niemand hat etwas falsch gemacht; die Sitzungen
konnten voneinander nicht wissen. Aufgefallen ist es, weil der
Versionsstempel ploetzlich 347 statt 372 Verweise meldete und ich dem
Rueckgang nachgegangen bin.

PRUEFUNGEN: pruef-fassungen neu mit 37, davon 6 im Browser.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-15 12:58:26 +02:00
DogFatherGitandClaude Opus 5 d2210fdd77 Der Erklaerkasten auf jeder Seite ist weg
Filipe, mit dem Kasten im Bild: "das muss sofort weg. ueberall das ist
scheisse."

Entfernt, nicht ausgeblendet:
  - workspace/assets/js/erklaerung.js
  - server/workspace-erklaerung.js samt Router-Einbindung in index.js
  - server/pruef-erklaerung.mjs
  - der Stilblock in start.css
  - die Skript-Zeile auf allen 25 Seiten

AUSGEBLENDET WAERE KEIN ENTFERNEN. Der Weg haette weiter geantwortet,
das Skript waere weiter geladen worden, und beim naechsten Umbau waere
der Kasten irgendwo wieder aufgetaucht. Was weg soll, wird weggenommen.

NACHGEMESSEN STATT ANGENOMMEN:
  - kein Verweis auf die geloeschten Dateien mehr im Repo,
  - der Server startet ohne Fehler (frische Datenbank, Protokoll leer),
  - keine Reste (erkl__, erklaerung.js) in Seiten oder Stilvorlagen.

Vier andere Pruefungen nennen ebenfalls "Erklaerung" -- sie meinen
ANDERE: den Satz im Neu-Fenster des Chats, die Stufen-Seite, die
Rollenkarten. Die bleiben unberuehrt; nachgesehen, nicht vermutet.

pruef-workspace-seiten, pruef-css-klassen und pruef-lesbarkeit laufen
gruen. Die Zahl der Pruefungen sinkt um die der geloeschten Datei --
das ist hier richtig: Sie prueften etwas, das es nicht mehr gibt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-15 12:52:13 +02:00
DogFatherGitandClaude Opus 5 9c99a5b9c3 Zwei Haeuser auf einer Datenbank -- die Team-Adresse zeigt nur das Team
Filipe, mit Bildschirmfoto der Zentrale: "die daten von dieser seite
sollen nichts mit den daten am hut haben von der workspace seite bitte,
die hier soll ihre eigene daten haben und komplett von der anderen
getrennt sein. dogfather soll die daten auch auf der anderen seite
sehen in der team dogi kategorie aber auch nur er und vanvan."

GETRENNT WIRD DER AUSSCHNITT, NICHT DER BESTAND. Eine zweite Datenbank
haette den zweiten Satz unmoeglich gemacht -- er will dieselben Daten
auf beiden Adressen sehen. Es bleibt also alles an einem Ort, und die
ADRESSE entscheidet, welcher Ausschnitt davon herauskommt.

ALLES HAENGT AN EINEM WERT: `person.haus`, gesetzt in sitzungLesen()
aus dem Hostnamen. Von dort reist er mit der Person durch jede
Sichtbarkeitsregel im Haus. Der Grund ist ein praktischer: Die Regeln
bekommen ueberall dieselbe Person gereicht -- sichtbar(person),
sichtbareCreatorIds(person), bereicheFuer(person). Ein zusaetzliches
Argument haette an ueber dreissig Aufrufstellen mitgeschleift werden
muessen, und die eine vergessene waere das Loch gewesen.

RECHTE AENDERT ES NICHT. Es entscheidet, WAS jemand sieht, nicht, was
er darf -- wie die Sicht eines anderen (sichtPerson) das auch nicht tut.

DER FILTER IST DER SPIEGEL EINES VORHANDENEN. Es gab schon
`ohneTeamDogi` ("alles ausser dem Team") fuer Spicy Media. Dazu kommt
jetzt `ohneAgentur` -- gleiche Bauweise, andere Rollenmenge, GEMEINSAME
Implementierung. In der steckt die NULL-Falle (`IS NULL OR NOT IN`,
denn `NULL NOT IN (...)` ist weder wahr noch falsch), und die sieht man
einer Abschrift nicht an.

WARUM NICHT "MINDESTENS EINE SPALTE ZEIGT AUF TEAM DOGI": Das waere die
naheliegende Formulierung und sie waere falsch. Eine Aufgabe, die
DogFather fuer einen Creator anlegt, haette ueber `erstellt_von` (er
gehoert zum Haus) trotzdem gepasst und stuende auf der Team-Seite.
Andersherum stimmt es: Sobald IRGENDEINE Spalte auf Creator, Scout,
Manager oder Spicy Media zeigt, gehoert die Zeile ins andere Haus.

VIER TUEREN, EINE FORM. Aufgaben, Bereiche, Dateien und der Kalender
haben je eine eigene sichtbar()-Funktion. Alle vier bekommen dieselbe
Bedingung an derselben Stelle, in derselben Schreibweise -- damit keine
davon anders aussieht als die anderen. Beim Kalender steht sie in
termineSichtbar() in workspace.js und nicht im Kalendermodul: Sonst
haetten Termine, Wiederholungen und der ICS-Abruf sie einzeln
gebraucht, und der ICS-Abruf ist der, den man vergisst -- er laeuft
ohne Bildschirm.

ZWEI ABFRAGEN GEHEN ABSICHTLICH NICHT DURCH DIE LISTENFUNKTIONEN, und
genau die standen im Bildschirmfoto: der Ring der Zentrale ("9 IM
TEAM", obwohl das Team drei Leute hat -- gezaehlt wurde das ganze Haus)
und die Hinweiszeile darunter ("Creator-Profile sind noch leer"). Im
Quelltext der Zentrale steht sogar ausdruecklich, dass sie die einzige
solche Stelle ist; gefunden habe ich sie trotzdem erst, weil ich der
Zahl im Bild nachgegangen bin. Beide bekommen die Bedingung jetzt aus
derselben Funktion (`hausBedingung`), nicht aus einer zweiten
Rollenliste.

Die Hinweis-Bedingung sitzt am BLOCK und nicht an den vier Abfragen
darin: Wer eine fuenfte hinzufuegt, bekommt sie dadurch mit, ohne daran
zu denken.

DIE KACHELN: Auf crew. liefert der Server dieselbe Liste wie der
rechten Hand -- nicht eine dritte. Fuenfundzwanzig Kacheln, von denen
zwei Drittel Creator und Agentur betreffen, waeren dort Fenster in ein
Haus, in dem er gerade nicht ist, und hinter jedem stuende seit heute
eine leere Liste. Auf workspace. bleibt alles, wie es war: Dort schickt
der Server weiterhin `bereiche: null` ("nimm die Liste aus der Datei").

JEDE MESSUNG STEHT ZWEIMAL DA. Die Trennung kann auf zwei Arten falsch
sein: Sie greift nicht (dann steht die Agentur weiter auf der
Team-Seite, und niemand merkt es, weil alles funktioniert), oder sie
greift zu weit (dann verschwindet auf der Agenturseite etwas -- der
gefaehrlichere Fall, denn eine zu kurze Liste sieht aus wie "nichts zu
tun"). Deshalb folgt auf jede Messung auf crew. dieselbe Messung auf
workspace., mit DERSELBEN Sitzung; der einzige Unterschied ist der
Host-Kopf. Dazu zwei Gegenproben zur Regel selbst: 127.0.0.1 bleibt
unberuehrt (sonst waeren alle Pruefungen im Haus stillschweigend blind
geworden), und eine erfundene Adresse oeffnet kein drittes Haus.

NEBENBEI ZWEI EIGENE FEHLER BEHOBEN: pruef-chat-kanaele und
pruef-rueckmeldung liefen auf Ports, die schon vergeben waren (4359
neben pruef-modi-verborgen, 4371 neben pruef-crew-adresse). Beide sind
umgezogen. Fuenf weitere Doppelungen zwischen fremden Pruefdateien
(4186, 4188, 4189, 4193, 4198) bleiben stehen und sind gemeldet -- an
Dateien zu greifen, an denen gerade eine zweite Sitzung arbeitet, waere
genau der Fehler, den diese Doppelungen ohnehin schon zeigen.

pruef-haus-trennung 32 (neu) · pruef-rollen 277 · pruef-modi-verborgen
78 · pruef-chat gruen · pruef-rueckmeldung 30 · pruef-modi-ideen 30 ·
pruef-crew-adresse 129 · pruef-start-ansicht gruen ·
pruef-zwischenspeicher 21 · pruef-modi-wortleck 5.

BERICHTIGUNG zum vorigen Commit: Dort steht "pruef-rueckmeldung 34".
Es sind 30. Ich hatte die Zeilen geschaetzt statt sie zu lesen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 23:24:34 +02:00
DogFatherGitandClaude Opus 5 63b3ace3fa Die rechte Hand -- drei Rollen auf der Adresse des Teams
Filipe: "3 rollen. dogfather. rechte hand und modis. perfektionier das."

DIE RECHTE MUSSTE ICH NICHT ERFINDEN. Sie stehen im Blueprint V3.0,
Kapitel 3.1 und in der Sichtbarkeitsmatrix 3.2: "Gleicher Ueberblick wie
Owner. Kann Modis im Alltag koordinieren. Verwaltungsrechte optional
durch Owner freischaltbar." Also: alle Aufgaben, Ideen und Angebote des
Teams, der Eingang samt Entscheidungen, die Checklisten der Modis zum
Ansehen -- aber keine Personenverwaltung (laut Blueprint "optional",
also standardmaessig aus) und keine privaten Kalender oder Einzelchats.

DER EIGENTLICHE UMBAU WAR NICHT DIE ROLLE, SONDERN EINE MENGE.
Bis heute hiess "verborgen" im Code `rolle === "modi"` -- an acht
Stellen. Bei ZWEI verborgenen Rollen ist das genau die Sorte Stelle, die
man an sieben von acht Orten nachzieht; die achte faellt niemandem auf,
weil dort dann einfach jemand sichtbar ist, der es nicht sein sollte.
Ein vergessener Rechteschutz meldet sich nie.

Jetzt lesen alle Regeln aus TEAM_DOGI_ROLLEN: die SQL-Ausblendung
(ohneModi heisst deshalb jetzt ohneTeamDogi), die verborgenen Nummern,
die Marke, die Adressregel, die Schranke beim Anlegen. Eine dritte
verborgene Rolle waere eine Zeile.

Die Menge wohnt in crew-adresse.js und nicht bei den uebrigen Rollen:
workspace.js importiert jene Datei. Andersherum waere es ein Kreis --
Node loest ihn auf, aber mit halb gefuellten Modulen, und das faellt
erst zur Laufzeit auf.

ZWEI LOECHER, GEFUNDEN BEIM SYSTEMATISCHEN NACHLESEN
1. Die Bereichsschranke griff nur bei Modis -- die rechte Hand waere
   ueber die Adresszeile in die Agentur-Ablage gekommen.
2. Ihr Ideen-Board und ihr Angebote-Brett waeren LEER geblieben: Sie
   fiel durch den Team-Zweig hindurch in die Betreuungsregel, die fuer
   sie nichts findet. Derselbe Fehler wie am 01.09. beim Manager und am
   09.09. beim Modi -- und er meldet sich nie, weil ein leeres Brett
   nicht nach Fehler aussieht.

NEBENBEI EINE ALTE SCHWACHSTELLE WEG
gate.js hatte eine zweite Namensliste fuer die Rollen, mit dem Kommentar
daneben, sie sei "genau die Stelle, die beim naechsten Mal wieder
vergessen wird" -- was schon passiert war. Mit zwei Zugangswaenden
haette sie die Namen BEIDER tragen muessen, in einer Datei, die jeder
bekommt. Sie liest den Namen jetzt aus der Kachel, wo er ohnehin steht.

Die Zugangswand hat drei Kacheln: DogFather (Husky), Rechte Hand
(Pfote, neu) und Modi (derselbe Husky, Wunsch vom 09.09.). Die Pfote
liegt am naechsten an "rechte Hand", ohne eine Hand zu sein.

GEMESSEN
pruef-rollen           274 (statt 245; 128 statt 112 Durchgaenge)
pruef-crew-adresse     114   pruef-modi-verborgen     78 (statt 75)
pruef-modi-checkliste   59   pruef-crew-wand-bild     45
pruef-modi-ideen        30   pruef-personen-formular  27 (statt 25)
pruef-modi-katalog      29   pruef-modi-kategorien    25
pruef-zwischenspeicher  21   pruef-modi-livecheck     16
pruef-modi-wortleck      5   pruef-start-ansicht, pruef-bereiche-lesend

Jede gestiegene Zahl hat einen Grund: Die neue Rolle laeuft in DENSELBEN
Listen mit wie die Modis, nicht in eigenen. pruef-modi-verborgen war
vorher gruen, ohne sie ein einziges Mal angesehen zu haben.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 15:18:26 +02:00
DogFatherGitandClaude Opus 5 138bcce80b Spicy Media sah die Zeilen der Modis -- drei Tabellen, ein Loch
GEMESSEN, NICHT VERMUTET, und es war live: Aufgaben, Bereichs-Eintraege
und Dateien eines Modis waren fuer Spicy Media sichtbar. Die NAMEN der
Modis waren ueberall sauber verborgen -- ihre ZEILEN nicht. Eine halbe
Verborgenheit ist keine.

WARUM ES PASSIEREN KONNTE: Fuer Personen gibt es die Regel EINMAL
zentral (verborgeneIds). Fuer Zeilen gibt es sie DREIMAL -- in
workspace-aufgaben.js, workspace-bereiche.js und workspace-dateien.js --
und alle drei geben Spicy Media dasselbe: "alles ausser dem, was
DogFather gehoert" (ohneDogFather). Ein Modi-Eintrag gehoert ihm nicht,
also fiel er durch.

Manager, Scout und Creator waren nie betroffen, ihre Regeln sind enger.
Der Kalender auch nicht: termineSichtbar() gibt jedem nur Eigenes.
Beides nachgesehen, nicht angenommen.

GEFUNDEN HAT ES KEINE UEBERLEGUNG, sondern eine Pruefung, die etwas
ANLEGT und danach mit fremden Augen nachsieht. Vorher hatte ich nur
Namenslisten geprueft -- und die waren die ganze Zeit gruen. Der Anlass
war nicht einmal Misstrauen gegen diese Stelle: Ich wollte ein
Ideen-Board auf die Eintraege setzen und dabei wissen, wer sie sieht.

BEHOBEN mit ohneModi() als Gegenstueck zu ohneDogFather -- und zwar als
UMHUELLUNG um die drei Regeln, nicht als Flicken darin. Ein Flicken
haette den einen bekannten Zweig geschlossen und den naechsten
Rollenzweig wieder offen gelassen; gemerkt haette es niemand, weil an
der geaenderten Stelle nichts davon steht.

Dazu die `fuerAlle`-Ausnahme bei den Eintraegen: Sie haengt ein ODER an
und haette die Bedingung sonst wieder aufgemacht. Heute hat kein Modi
eine Kachel in einen solchen Bereich -- ein Aufruf an der Oberflaeche
vorbei braucht sie aber nicht. Eine Regel, die nur im Formular gilt,
ist keine Regel.

Nachgesehen, dass die Umhuellung nirgends das falsche Tabellenkuerzel
setzt: Alle Aufrufstellen in workspace-hinweise.js und workspace-suche.js
fuehren die Tabellen als a, d und e -- genau so, wie es dasteht.

NEBENBEI: Das Modi-Team teilt sich jetzt auch die Bereichs-Eintraege,
nicht nur die Aufgaben (Entscheidung Filipe, 09.09.2026: "sie sind
untereinander ein Team"). Ohne diesen Zweig saehe jeder Modi nur, was er
selbst geschrieben hat -- eine gemeinsame Sammlung waere keine.

ZWEI EIGENE FEHLER AUF DEM WEG DAHIN, beide festgehalten:

  * Die neue Messung stand HINTER der Gegenprobe. Die macht eine Person
    absichtlich zur Creatorin -- die Messung bekam 403 und meldete
    "kann nichts anlegen". Gemessen wurde ein Zustand, den es im
    Betrieb nicht gibt. Genau davor warnt der Kommentar, den ich selbst
    zwei Tage vorher an diese Gegenprobe geschrieben hatte.
  * Das "konnte nicht nachsehen" nannte KEINEN Grund. Damit ist der
    dritte Ausgang nur dem Namen nach da -- man weiss danach so wenig
    wie vorher. Erst mit der Fehlermeldung im Text kam ich auf die Spur.

GEPRUEFT: pruef-modi-verborgen (75, davon 18 neu ueber drei Tabellen und
fuenf Rollen), pruef-spicy (60), pruef-bereiche-lesend,
pruef-aufgabenbrett, pruef-modi-katalog (29).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 01:34:02 +02:00
DogFatherGitandClaude Opus 5 e8478c9cae Spicy sieht DogFathers Sachen nicht mehr -- und sechs Fehler dazu
VIER DINGE AUS DEN BILDSCHIRMFOTOS, jedes ein echter Fehler:

1. SPICY MEDIA SAH DOGFATHERS DATEN. Beim ersten Anlauf bekam die Rolle
   dieselbe Regel wie DogFather (`1=1`) -- damit stimmte der Ueberblick
   ueber Manager, Scouts und Creator, und nebenbei standen seine eigenen
   Termine, Aufgaben, Dateien und Eintraege mit drin. Jetzt gibt es
   ohneDogFather() als EINE Stelle dafuer: Zwei Spalten werden geprueft,
   `creator_id` (um wen geht es) und `erstellt_von` (wer hat es
   geschrieben) -- ein Termin, den er sich selbst anlegt, haengt nur an
   der zweiten. `IS NULL OR NOT IN` und nicht bloss `NOT IN`: In SQL ist
   `NULL NOT IN (...)` weder wahr noch falsch, die Zeile fiele
   stillschweigend heraus.

2. "PERSOENLICHER ZUGANGSCODE · undefined" auf der Anmeldeseite. Eine
   zweite Namensliste im Browser, die beim Hinzufuegen der Rolle
   niemand gepflegt hat. Ein unbekannter Schluessel faellt jetzt auf
   sich selbst zurueck statt auf `undefined` -- haesslich, aber
   sichtbar.

3. SPICY KAM NICHT IN DIE PERSONENVERWALTUNG. Der Server liess sie
   herein, das Skript warf sie wieder hinaus: zwei Listen fuer dieselbe
   Frage, gepflegt wurde nur die erste.

4. DIE ANMELDEKARTE WAR ZU KLEIN FUER FUENF ROLLEN. Der Kommentar an
   genau dieser Stelle warnt woertlich davor -- und ich habe getan,
   wovor er warnt: eine Rolle eingefuegt und die Zahl daneben nicht
   angefasst. Gemessen: Inhalt 573 px in einer 526 px hohen Tafel, die
   Fusszeile stand unter dem Rahmen. Schrift kleiner half nicht (sie lag
   schon auf dem Anschlag), also sind die Abstaende an neun Stellen
   enger. Nachgemessen auf fuenf Groessen: passt ueberall.

DIE ZEIT WAR WIRKLICH FALSCH. Nicht nur in meinem Satz: `datum()` in
personen.js schnitt die ISO-Zeichenkette ab -- und die ist UTC. Im
Protokoll stand 03:00, wo 05:00 war. Das Tueckische daran ist, dass es
nie kaputt aussieht: Eine Uhrzeit ist immer plausibel.

PROFILBILDER WERDEN JETZT GEZEICHNET. Der Server lieferte sie seit
gestern mit, gezeichnet wurden sie nirgends -- deshalb aenderte sich
nichts. Jetzt in der Personenauswahl (Aufgaben, Termine, Dateien,
Bereiche), in der Gespraechsliste und an jeder Nachricht. Der
Anfangsbuchstabe bleibt als Unterlage LIEGEN: Faellt das Bild aus, steht
dort weiter etwas Sinnvolles.

DER CHAT: Gesichter mit Rollenfarbe, Blasen mit Richtung (die erste
einer Folge eckig, die naechsten rund -- so sieht man, wo ein Gedanke
anfaengt), das offene Gespraech mit Schiene, Ungelesenes hervorgehoben,
und das Eingabefeld in einer eigenen Leiste, die sich beim Schreiben
hebt.

ZWEI EIGENE PATZER, beide von Pruefungen gefunden:
  - `o is not defined`: Mein Suchmuster hat die zwei Zeilen fuer das
    Bild ans DATEIENDE gesetzt statt in die Schleife -- und in
    kalender.js an einen <span> statt ans <option>. Gemeldet von
    pruef-sicht, das die Browserkonsole mitliest.
  - Ein Kommentar mit `bild` in schraegen Anfuehrungszeichen stand INNEN
    in einer Vorlagenzeichenkette und hat sie geschlossen. Die halbe SQL
    wurde zu Programmtext.
Dazu: `.chat-neu` gibt es nicht (heisst `.chat__eingabe`), und der
Rollenknopf hatte fuer den Manager keinen sichtbaren Fokus -- ein
box-shadow wird von `overflow: hidden` abgeschnitten, ein outline nicht.

Gruen: spicy (43), creator-anlegen (29), personen-liste (33), sicht (48),
chat (48), chat-optik (24), buehne (38), struktur (32), css-klassen (15),
handy (59), breiten (23), formulare (19), start-ansicht (136),
lesbarkeit (14), barrierefrei (18), tempo (8), kopf-messen (3),
glocke (26), haerte (20), manager-sicht (43), alle-wege (19),
aufgabenbrett (44), kalender (84).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-07 05:46:19 +02:00
DogFatherGitandClaude Opus 5 68bc116c36 Die Rolle "Spicy Media" -- und drei Fehler, die nur ihre Pruefung fand
DIE PERSONENTABELLE WURDE NEU GEBAUT. Eine Rolle ist ein erlaubter Wert
in einer Spalte, und der steckt in einem CHECK -- den kann SQLite nicht
aendern. Auf `personen` zeigen ZWEIUNDFUENFZIG Fremdschluessel.

Deshalb wird der Bauplan NICHT abgeschrieben, sondern gelesen: Der
CREATE-Text kommt aus sqlite_master, darin wird ausschliesslich die
Rollenliste ersetzt, und die Kopierliste kommt aus PRAGMA table_info.
Die beiden aelteren Umstellungen schreiben ihre Spalten von Hand ab --
`personen` hat seit damals SIEBEN dazubekommen (bild, ueber_mich,
tiktok ...). Wer hier abschreibt, verliert alle Profilbilder.

ZWEI FRAGEN, DIE MAN AUSEINANDERHALTEN MUSS:
  siehtAlles()   = DogFather ODER Spicy Media -> Listen, Uebersichten
  istDogFather() = nur DogFather              -> loeschen, Rollen, Codes
Es waere weniger Arbeit gewesen, istDogFather() um "spicy" zu erweitern
-- und genau das waere der Fehler: Spicy Media koennte dann DogFather
loeschen.

DER CHAT BRAUCHTE NICHTS. Er haengt allein an der Teilnehmerliste und
kennt kein "das Management sieht alles". Spicy Media sieht fremde
Gespraeche nicht, weil es dafuer keinen Weg gibt -- nicht, weil eine
Abfrage es verbietet.

DREI ECHTE FEHLER, alle von pruef-spicy gefunden, keiner vorher sichtbar:

1. MEIN EIGENER KOMMENTAR STAND IM BAUPLAN. SQLite hebt den CREATE-Text
   woertlich auf, samt Kommentaren. Ich hatte "'spicy' steht HIER mit
   drin" hineingeschrieben -- und die Erkennung suchte genau dieses Wort
   im ganzen Text. Ergebnis: Die Umstellung hielt die Tabelle fuer
   erledigt, obwohl die CHECK-Regel noch die alte war. Jetzt wird die
   Regel herausgeschnitten und NUR darin gesucht; der Kommentar steht
   ausserhalb des SQL.

2. DER SICHERUNGSNAME HATTE NUR MINUTEN. `VACUUM INTO` weigert sich, eine
   vorhandene Datei zu ueberschreiben -- zu Recht. Zwei Umstellungen in
   derselben Minute wollten in dieselbe Datei, die zweite scheiterte, und
   weil ohne Sicherung nicht umgestellt wird, blieb sie aus. Es sah nach
   "lief" aus (die Datei lag ja da) und war keine. Jetzt mit Sekunden.

3. EINE FRISCHE DATENBANK LEGTE DIE ALTE ROLLENLISTE AN und stellte beim
   allerersten Start sofort um -- Tabelle neu bauen, Sicherung schreiben,
   fuer nichts. Ein Bauplan, der sofort umgebaut werden muss, ist der
   falsche.

Und ein vierter in der Pruefung selbst: Der Chat-Aufbau benutzte einen
falschen Weg, das Gespraech entstand gar nicht -- "Spicy Media sieht 0
Gespraeche" war trotzdem gruen, weil es keine gab. Jetzt ist das Anlegen
selbst eine Pruefung, und eine Gegenprobe zeigt, dass Max es sehr wohl
sieht.

DAZU: Manager sehen die Kachel "Personen & Zugaenge" -- die SEITE geht
auf, die Schnittstellen nicht. Alles unter /verwaltung haengt weiter an
`nurAdmin` und antwortet 404; sie sehen genau den Teil, fuer den es
einen Weg gibt. Spicy Media legt Creator UND Manager an (zweite enge
Tuer, Rolle steht auch dort nicht im Aufruf; ein Manager kommt durch
sie nicht). Der Rollentext des Managers stimmte nicht mehr -- er legt
jetzt Creator an.

pruef-spicy: 36 Pruefungen, alle gruen. Ausserdem gruen: personen-liste
(33), creator-anlegen (29), sicht (48), css-klassen (15), alle-wege (19),
haerte (20), manager-sicht (43).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-07 04:56:07 +02:00
DogFatherGitandClaude Opus 5 0404f8c0c1 Dreizehn Lecks: eine Managerin sah die Creator aller anderen
Wunsch: "jeder manager soll auch immer nur seine und die seiner scouts
zugeteilten creator und creator daten sehen. und nicht die der anderen."

DIE KETTE WAR GEBAUT -- SIE WURDE NUR NICHT BENUTZT
Manager -> seine Scouts -> deren Creator steht seit dem 01.09.2026 an
genau einer Stelle (betreuteIds). Die Frage war eine andere: Benutzt sie
auch JEDER Weg, der Creator-Daten herausgibt? Ueber zwanzig Stellen
prueften die ROLLE statt der ZUTEILUNG -- "ist Leitung? dann alles".

NICHT GELESEN, SONDERN GEMESSEN
server/pruef-manager-sicht.mjs baut zwei Managerinnen mit vollstaendig
getrennten Creators. Bei der fremden heisst ALLES "GEHEIM..." -- Aufgabe,
Termin, Bereichseintrag, Datei, Steckbrief, Content-Saeule. Danach wird
jede der 31 Leseschnittstellen abgefragt und die ganze Antwort danach
durchsucht. Ein Leck faellt damit auf, egal wo es sitzt und egal, ob ich
es beim Lesen uebersehen haette.

GEFUNDEN: DREIZEHN. Alle geschlossen:

  Kalender          fremde Fristen -- besonders unangenehm, weil es
                    nicht wie ein Leck aussieht: eine kleine orange
                    Marke mit einem Titel, in dem fremde Vorhaben stehen
  Personenauswahl   alle Namen im Zuweisungsfeld
  Dateien           alle Namen in der Freigabe-Auswahl
  Uebersicht        Gesamtuebersicht ueber ALLE Creator
  Report            Auswahl UND Auswertung ueber den ganzen Bestand
  Start-Check       alle Creator zur Auswahl
  Steckbriefe       Bild, Kanaele, "ueber mich" von allen
  Profile           alle Profile, samt interner Notiz
  Schulung          Schulungsstand aller Creator
  Suche             Creator-Profile aller -- die unauffaelligste Stelle:
                    Man sucht etwas anderes und bekommt fremde Namen
  Content-Balance   Themensaeulen fremder Kanaele (die Abfrage daneben
                    war korrekt eingeschraenkt, DIESE hatte eine eigene
                    Bedingung)
  darfCreator       eine einzige Zeile -- sie hing an Profil,
                    Start-Check und Uebersicht gleichzeitig. Es reichte,
                    eine Nummer in die Adresse zu schreiben.

Die Antwort steht jetzt an EINER Stelle: sichtbareCreatorIds und
sichtbarePersonenIds in workspace.js. Rueckgabe null heisst "alle" und
gilt allein DogFather -- bewusst kein leeres Feld: Eine leere Liste
bedeutet "niemand", und die Verwechslung der beiden macht aus einer
Sperre eine Freigabe.

ZWEI DINGE, DIE ICH MIR SELBST NACHTRAGEN MUSS

1. Beim Stopfen fehlte einmal ein Import. Der Weg warf einen Fehler,
   antwortete 503 -- und weil in einer Fehlermeldung kein "GEHEIM" steht,
   meldete die Pruefung "kein Leck". Sie war gruen, weil der Weg KAPUTT
   war. Die Pruefung zaehlt jetzt beides: nichts durchsickern UND
   antworten.

2. Ein Fehlalarm: Die Suche gibt den SUCHBEGRIFF in ihrer Antwort
   zurueck. Wer nach "GEHEIM" sucht, findet das Wort zwangslaeufig --
   auch bei null Treffern. Ich haette um ein Haar ein Leck "repariert",
   das es nie gab. Das Echo wird jetzt entfernt, bevor gemessen wird.

FOLGEN, bewusst in Kauf genommen:
  * Ein Manager ohne Zuteilung sieht keinen Creator. Die Uebersicht sagt
    ihm das jetzt in einem Satz, statt leer zu bleiben.
  * Er kann nur noch IN SEINEN Creator-Bereichen schreiben (darfCreator).

ZWEI PRUEFUNGEN UMGEDREHT statt geloescht -- eine geloeschte Pruefung
hinterlaesst keine Spur davon, dass hier einmal etwas anderes galt:
pruef-uebersicht ("Manager sieht dasselbe" -> "nur seine zugeteilten",
mit beiden Faellen) und pruef-scout-zuteilung ("sieht die ganze
Personenliste" -> "landet auf der Startseite").

GEPRUEFT: 43 neue Pruefungen, dazu 23 bestehende Laeufe gruen --
Startansicht 133, Rollen 97, Kalender 84, Serien 67, Steckbrief 65,
Handy 50, Sicht 48, Ampel 47, Content 45, Aufgabenbrett 44, Schulung 41,
Bereiche 37, Scout-Zuteilung 36, Uebersicht 35, Personenliste 33,
Freie Namen 32, Team 30, Protokoll-Loeschen 20, Personenformular 20,
Formulare 19, Betreuung 18, Code 17, Grosscheck 15.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-03 01:01:00 +02:00
DogFatherGitandClaude Opus 5 540b5d8838 Freie Namen, ein Call-Knopf, und drei Seiten, die fuer Scouts kaputt waren
DREI SACHEN AUF EINMAL, alle aus derselben Sitzung.

1. AUSSUCHEN ODER SELBST EINTRAGEN
   Wunsch: "ich will da auch sachen selber noch eintragen koennen, also
   aussuchen und selbst eintragen."

   Jede Personenauswahl (Kalender, Aufgaben, Bereiche, Content, Dateien)
   nimmt jetzt auch einen getippten Namen an -- eine Agentur, eine Marke,
   einen Gast ohne Konto. Dazu bekommt JEDE Auswahl ab acht Eintraegen
   ein Suchfeld: tippen statt scrollen.

   Gebaut IM vorhandenen Auswahl-Bauteil (wahl.js), nicht daneben. Der
   erste Anlauf war ein zweites Bauteil -- es hat sich prompt mit dem
   ersten gebissen, beide haben denselben <select> eingepackt. Ein
   zweites haette ausserdem anders ausgesehen und waere beim naechsten
   Umbau nur an einer von zwei Stellen nachgezogen worden.

   Der freie Name steht in einer EIGENEN Spalte je Feld; die Verknuepfung
   bleibt leer. Entweder eine Person ODER ein Name, nie beides.

   Filipe hat ausdruecklich auch bei den Creator-Feldern freie Namen
   gewollt, nachdem der Nachteil benannt war: Der Eintrag gehoert dann zu
   keinem Konto. Damit daraus kein STILLER Ausfall wird, faellt jede
   Abfrage, die bisher den Namen der verknuepften Person las, jetzt auf
   den freien Text zurueck (externSql) -- gekennzeichnet als "(extern)".
   Der Eintrag verschwindet dadurch aus keiner Liste, keiner Suche und
   keiner Uebersicht.

2. WO FUEHRE ICH DEN CALL?
   Den Knopf gab es, aber nur wenn jemand von Hand einen Link ins
   Ortsfeld getippt hatte UND das Gespraech noch bevorstand. Stand dort
   "Hier", war nichts zum Anklicken da.

   Jetzt hat das Team einen festen Call-Raum (Discord-Sprachkanal), den
   das Management einmal hinterlegt. Danach hat JEDER Call den Knopf --
   und er bleibt, solange das Gespraech laufen kann, nicht nur bis zur
   Startzeit. Ein eigener Link am Termin schlaegt den festen Raum.

3. WAS EINE ROLLE SIEHT, MUSS AUCH FUNKTIONIEREN
   Gemeldet: "cigdem kriegt als manager gewisse sachen nicht auf die sie
   sieht, check jede rolle ab."

   Neue Pruefung server/pruef-rollen.mjs schickt SECHS Rollen-Zustaende
   ueber alle 16 Seiten und misst Konsolenfehler, fehlgeschlagene
   Serveraufrufe, tote Verweise, haengende Ladeanzeigen und wortlos leere
   Seiten. 96 Durchgaenge.

   Der sechste Zustand ist der wichtige: eine Rolle OHNE zugeteilte
   Creator -- der Normalfall am ersten Tag und Cigdems echte Lage.
   Genau dort fielen die Seiten durch, waehrend dieselben Seiten MIT
   Zuteilung tadellos waren.

   VIER ECHTE FEHLER GEFUNDEN UND BEHOBEN:

   a) Eine Aufgabe, die eine Managerin ohne Creator anlegte, war fuer sie
      im selben Moment unsichtbar -- creator_id und verantwortlich_id
      leer, und "von mir selbst angelegt" stand in keiner
      Sichtbarkeitsregel. Nur DogFather sah sie noch. Kein Fehler, keine
      Meldung, die Aufgabe war einfach weg. Dasselbe bei den
      Bereichseintraegen. Beide Regeln kennen jetzt erstellt_von.
      Niemand sieht dadurch etwas Fremdes -- nur das Eigene.

   b) Ein Scout ohne zugeteilten Creator bekam auf die GESAMTE
      Report-Seite 404, obwohl sie fuer ihn verlinkt ist. Die Seite
      antwortet jetzt sauber und leer, statt sich zu verweigern.

   c) Start-Check und Report blieben fuer immer auf "wird geladen"
      stehen, wenn es nichts zu laden gab.

   d) Das Creator-Profil war fuer Scouts ohne Zuteilung wortlos leer --
      der erklaerende Satz stand nur in der grauen Unterzeile.

   Ausserdem meldete die bestehende Lesbarkeitspruefung zwei neue
   Beschriftungen von mir als zu klein fuers Handy (10,88 statt 11,5 px).
   Behoben, und dieselbe Groesse an der Serien-Karte gleich mit -- dort
   waere es erst aufgefallen, sobald jemand eine Wiederholung anlegt.

GEPRUEFT: pruef-rollen 97, pruef-freie-namen 32 (mit Gegenproben:
Ben sieht Cigdems Aufgabe NICHT; die Saeulen-Zuordnung nimmt
ausdruecklich KEINEN freien Namen). Alle bestehenden Laeufe gruen:
Startansicht 133, Kalender 84, Serien 67, Protokoll 52, Handy 50, Sicht
48, Ampel 47, Content 45, Aufgabenbrett 44, Sprung 43,
Personen-Loeschen 40, Bereiche 37, Uebersicht 33, Workspace-Seiten 32,
Formulare 19, Betreuung 18, Grosscheck 15, Lesbarkeit 14.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-02 20:10:09 +02:00
DogFatherGitandClaude Opus 5 da49a227f1 Aufgabenbrett fuer alle Rollen -- und nur DogFather sieht alles
Wunsch vom 01.09.2026: "verbessere die Aufgabenseite auch bei Manager,
Scout und Creator. Die Scouts und Manager sollen vielleicht ein bisschen
mehr Optionen haben, wie ihre zugeteilten Creator. Aber auch die Creator
sollen es besser und detaillierter sehen. ABER NUR DIE ROLLE DOGFATHER
SOLL WIRKLICH WEITERHIN ALLEINE ALLES SEHEN KOENNEN."
(Nachgereicht: "die Seite Aufgabe auch bei DogFather machen bitte.")

ZWEI FEHLER IN DEN RECHTEN, die beim Nachsehen herausfielen:

  1. Ein MANAGER sah auf dem Aufgabenbrett GAR NICHTS. Die Regel kannte
     nur admin, creator und scout; er fiel in den Zweig "unbekannte
     Rolle sieht nichts". Ein leeres Brett sieht aus wie "nichts zu
     tun", nicht wie ein Fehler -- deshalb ist das lange niemandem
     aufgefallen.

  2. In Kalender, Dateien, Bereichen und Content sah derselbe Manager
     dagegen ALLES (istLeitung). Zwei entgegengesetzte Antworten auf
     dieselbe Frage, in einem Programm.

Jetzt gilt ueberall dasselbe: NUR DogFather sieht alles. Manager und
Scout sehen ihre eigenen Sachen plus die Creator, die ihnen zugeteilt
sind. Dafuer arbeitet betreuteIds() jetzt auch fuer Manager -- die
Datenbank konnte das laengst (in `betreuung` steht eine beliebige
Person), nur diese eine Funktion hat alle ausser Scouts abgewiesen.

GEAENDERT WURDE NUR, WER WAS SIEHT. Was ein Manager DARF -- freigeben,
aendern, Personen verwalten -- haengt weiterhin an istLeitung und ist
unberuehrt. Ohne diese Trennung haette ein Wunsch nach weniger Sicht
stillschweigend die halben Rechte mitgenommen; die Pruefung haelt beides
ausdruecklich fest.

DIE SEITE SELBST bekommt drei Zeilen ueber dem Brett, und die
Reihenfolge ist die Aussage:
  1. WAS BRENNT -- ein Satz beim Reinkommen. Ein Brett aus vier Spalten
     beantwortet das nicht; man muesste alle vier durchsehen, um zu
     wissen, dass nichts brennt.
  2. AUSSCHNITTE -- "Nur meine", "Heute faellig", "Ueberfaellig", jeder
     mit seiner Zahl am Knopf. Ein Filter, der sich erst nach dem Klick
     als leer herausstellt, kostet zweimal Aufmerksamkeit. Sie filtern
     das Brett, statt eine zweite Liste aufzumachen: Vier Spalten
     nebeneinander sind der Wert dieser Seite.
  3. DIE CREATOR -- fuer Betreuer und DogFather, je mit offener Anzahl
     und einer Warnzahl fuer Ueberfaelliges. Bei DogFather heisst die
     Reihe "Alle Creator", sonst "Deine Creator": "deine" waere bei ihm
     eine falsche Auskunft.

Ein Creator bekommt weder "Nur meine" noch die Creator-Reihe -- bei ihm
ist ohnehin alles seins, und ein Filter mit einem einzigen Eintrag ist
ein Knopf, der nichts tut. Die Liste der Creator stammt aus den
Aufgaben selbst und nicht aus einer Personenabfrage: Dann stehen dort
genau die, die man ohnehin sehen darf, und niemals einer mehr.

NEBENBEI (Screen 1): In der Betreuer-Auswahl stand "Dogfather
(DogFather)" -- zweimal dasselbe Wort, nur anders geschrieben. Die
Klammer entfaellt jetzt, wenn sie dasselbe sagt wie der Name.

pruef-aufgabenbrett.mjs prueft die ABGRENZUNG zuerst und an konkreten
Aufgaben, deren Titel verraten, wem sie gehoeren -- eine huebschere
Filterleiste ist eine Annehmlichkeit, eine Rechteregel, die zu viel
zeigt, ist ein Schaden. Dazu eine Gegenprobe zur alten Regel (der
Manager sieht ueberhaupt etwas) und die ausdrueckliche Bestaetigung,
dass er weiterhin anlegen darf.

Ein Fehler steckte in der Pruefung selbst: Sie erwartete beim Creator
eine feste Zahl und haing damit von ihrer eigenen Reihenfolge ab -- der
Abschnitt davor legt eine weitere Aufgabe an. Sie vergleicht jetzt gegen
die Schnittstelle. Das ist ohnehin die bessere Frage: nicht "sind es
drei", sondern "verschluckt die Seite etwas".

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-01 21:38:38 +02:00
DogFatherGitandClaude Opus 5 1c00770ec5 Lesbarere Kaesten, und DogFather kann durch fremde Augen sehen
SCREEN 1 -- "die Kachel ganz leicht dunkler, so dass man den Text besser
gelesen bekommt, aber nicht zu viel, so dass man den Hasen noch sieht."

Die Erklaerkaesten stehen jetzt auf 88 statt 78 Prozent Deckung. Zehn
Punkte sind gemessen der Unterschied zwischen muehsam und ruhig lesbar
und lassen zwoelf Prozent Bild durch -- das Motiv bleibt sichtbar.

"und die von wichtigen und neuen PDFs sollen auch staerker sein."
Das war kein Geschmack, sondern ein Fehler: `background` ist eine
Eigenschaft, keine Schicht. Die Zeile
`background: rgba(232,192,125,.045)` hat die Flaeche nicht getoent,
sondern ERSETZT -- uebrig blieben viereinhalb Prozent Deckung. Damit war
ausgerechnet die Anleitung, die jeder lesen soll, die am schwersten
lesbare der Seite. Die Toenung liegt jetzt als Schicht darueber.
Gemessen: 88 % gegen 78 % bei einer gewoehnlichen.

pruef-lesbarkeit.mjs misst das an ECHTEN PIXELN (Text kurz unsichtbar
machen, Flaeche fotografieren, WCAG-Formel) und kennt ZWEI Grenzen --
lesbar genug UND durchsichtig genug. Mit nur einer haette sie eine
schwarze Flaeche am besten gefunden, und das wollte niemand.

SCREEN 2 -- "ich will alles von den Scouts und Managern einsehen
koennen, auswaehlen, was und von wem. Ueberall, auf jeder Seite.
NUR WIR BEIDE SOLLEN DIESE OPTION HABEN."

Die naheliegende Loesung waere ein Filter je Seite gewesen -- also eine
zweite Rechteregel in zwoelf Modulen, und eine Rechteregel an zwoelf
Stellen stimmt irgendwann an elf. Stattdessen wird die PERSON getauscht,
nicht die Regel: Waehlt DogFather einen Scout, laufen alle vorhandenen
Sichtbarkeitsregeln unveraendert mit diesem Scout. Er sieht exakt dessen
Arbeitsplatz -- nicht mehr, nicht weniger. Keine neue Rechteregel.

Im Browser genauso: EIN Ort statt vierzehn. fetch wird einmal umgeleitet
und haengt den Wert an jede lesende Abfrage an. Neue Seiten sind damit
von selbst dabei; man kann es nicht vergessen.

Drei Sicherungen: nur admin (auf dem SERVER geprueft, nicht in der
Oberflaeche), nur lesend (geschrieben wird immer im eigenen Namen --
sonst staende im Protokoll der falsche Name), nur aktive Personen.

Und ein Rahmen um die Seite, solange eine fremde Sicht laeuft. Der
gefaehrlichste Fall ist nicht, dass man nicht umschalten kann, sondern
dass man vergisst, dass man umgeschaltet hat -- und drei Aufgaben statt
dreissig fuer den Bestand haelt.

FUENF FEHLER, DIE DIE PRUEFUNGEN GEFUNDEN HABEN:

1. steckbrief.html hat die Kopfleiste NIE gefuellt -- dort stand
   monatelang "…" statt des eigenen Namens. Aufgefallen, weil der
   Umschalter dort fehlte. Jetzt zusaetzlich ein Netz darunter: Meldet
   sich nach kurzer Zeit niemand, holt der Kopf sich selbst, wer
   angemeldet ist. Die naechste neue Seite kann es nicht mehr vergessen.

2. Der Umschalter sprengte die Kopfleiste (46 px am Rechner, 117 px am
   Handy) und drueckte den Abmelden-Knopf hinaus.

3. Ich habe das <select> gestaltet -- wahl.js ersetzt aber jedes
   Auswahlfeld durch einen eigenen Knopf und schrumpft das echte Feld
   auf einen Pixel. Meine Regeln haben es wieder auf 20 x 44 aufgeblasen,
   wo es als unsichtbares Hindernis ueber dem Knopf lag. Gestaltet wird
   jetzt der Knopf.

4. Ein Wettlauf: Auf profil.html rufen zwei Dateien werZeigen() auf.
   Beide kamen an "gibt es den Umschalter schon?" vorbei, bevor eine ihn
   angehaengt hatte -- zwei Umschalter uebereinander. Die Sperre gehoert
   vor das erste await.

5. Die Handy-Pruefung bemaengelte ein Schild, das dort per display:none
   gar nicht erscheint. Sie sieht jetzt nur noch sichtbaren Text an --
   eine Pruefung, die Unsichtbares anmahnt, gewoehnt man sich ab zu
   lesen.

Dazu zwei Messfehler in den Pruefungen selbst: getComputedStyle liefert
ein LEBENDES Objekt (die Farbe wurde gelesen, nachdem der Text
unsichtbar gemacht war -- gemeldet wurden 1,17:1 fuer tadellos lesbaren
Text), und ein Vergleich lief still ins Leere, weil die Vergleichsdaten
fehlten.

pruef-sicht.mjs stellt den MISSBRAUCH an den Anfang: Scout, Manager und
Creator haengen ?sicht= an und muessen ignoriert werden; erfundene
Nummern, Buchstaben und ein Einschleusversuch fallen auf die eigene
Sicht zurueck; eine abgeschaltete Person liefert keine Sicht mehr; und
was DogFather bei fremder Sicht anlegt, steht unter SEINEM Namen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-01 21:20:23 +02:00
DogFatherGit 389d8c1213 Workspace: neue Rolle Manager, feste Rollenreihenfolge, echte Rollenwahl
DREI TEILE.

1) ROLLE "MANAGER"

Ein Manager darf alles, was DogFather darf -- mit genau zwei
Vorbehalten: Er kann keine Leitung ANLEGEN und an keiner Leitung etwas
AENDERN. Sonst koennte er sich einen zweiten Vollzugang schaffen oder
DogFather aussperren. "Nur DogFather hat alle endgueltigen Rechte"
heisst genau das.

Umgesetzt ueber istLeitung() an EINER Stelle statt 44 einzelner
Vergleiche auf "admin" im Server und 26 im Browser.

DATENBANK-UMSTELLUNG: CREATE TABLE IF NOT EXISTS fasst eine vorhandene
Tabelle nicht an -- die CHECK-Regel stand also weiter auf den alten drei
Rollen, und ein Manager waere daran gescheitert, obwohl der Code stimmt.
SQLite kann eine CHECK-Regel nicht aendern, also: neue Tabelle, Daten
hinueber, alte weg, umbenennen. Davor schreibt der Server eine
vollstaendige Sicherung (VACUUM INTO, in sich konsistent). Ohne
Sicherung wird NICHT umgestellt.

Geprueft nach der Umstellung: alle 13 Tabellen mit gleicher Zeilenzahl,
PRAGMA integrity_check ok, keine verwaisten Verweise. Die einzige
Abweichung war eine Sitzung mehr -- die eigene Anmeldung, die die
Umstellung ausgeloest hat.

2) EIN SICHERHEITSLOCH, DAS DER TEST GEFUNDEN HAT

Der erste Entwurf sicherte "Person anlegen" und "Person sperren" ab --
und liess "neuer Zugangscode" offen. Ein Manager konnte DogFather einen
neuen Code ausstellen, bekam ihn angezeigt und haette ihn damit aus
seinem eigenen Konto ausgesperrt. Im Test aufgefallen, weil ich den
negativen Fall durchgespielt habe.

Behoben nicht durch eine dritte Einzelpruefung, sondern durch eine
Schranke an JEDEM Weg mit einer :id. Der naechste Weg, der dazukommt,
ist damit automatisch mitgeschuetzt.

Nachgeprueft: Manager bekommt 403 beim Code-Erneuern und Sperren von
DogFather UND von sich selbst, darf aber Creator und Scouts verwalten.

3) FOLGEFEHLER DER MASSENERSETZUNG

Die Regel "niemals den letzten aktiven DogFather sperren" hatte durch
die Umstellung auf istLeitung() ploetzlich auch Manager blockiert --
gezaehlt werden aber nur DogFather-Zugaenge. Jetzt istDogFather().
Geprueft: DogFather kann einen Manager sperren, sich selbst nicht.

4) REIHENFOLGE UND ROLLENWAHL

Ueberall DogFather, Manager, Scout, Creator. "ORDER BY rolle" waere
alphabetisch gewesen (admin, creator, manager, scout) -- also fast genau
falsch herum. Jetzt ein gemeinsamer Sortierausdruck aus workspace.js.

Das Auswahlmenue fuer die Rolle ist weg. Es kam als weisses
Windows-Menue mitten in einer dunklen Oberflaeche und schnitt "Creator"
zu "Crea" ab -- gestalten laesst sich ein aufgeklapptes Systemmenue
nicht. Ersetzt durch vier sichtbare Schalter mit Symbol, Farbe je Rolle
und einer Zeile, was die Rolle bedeutet. Bei "Manager" gegen
"DogFather" ist das der Unterschied zwischen Raten und Wissen.

DogFather und Manager stehen dort nur zur Wahl, wenn DogFather selbst
davorsitzt -- ein Knopf, der immer scheitert, gehoert nicht hin.

Nebenbei: Das Namensfeld war auf eine von zwoelf Spalten gequetscht, weil
seine Umgebung keine .feld-Klasse trug. Alle Formulare daraufhin
durchsucht, keine weiteren Faelle.
2026-08-31 11:32:22 +02:00
DogFatherGit 1f217041ae Workspace: hellere Kategoriekacheln + Dateien gezielt an mehrere Personen
ZWEI WUENSCHE VON FILIPE.

1) KACHELN BESSER SICHTBAR

Erster Versuch war zu zaghaft: die Flaeche ging nur von RGB(17,24,37)
auf (27,36,51), der sichtbare Gewinn kam fast nur vom staerkeren Rand.
Nachgemessen an echten Bildpunkten -- Seite liegt bei RGB(5,7,13).
Jetzt RGB(38,49,67), dazu kraeftigerer Rand und hellerer Symbolring.

Der Beschreibungstext stand auf --text-still und lag damit bei 3,6:1 auf
der neuen Flaeche -- zu blass fuer laufenden Text. Jetzt --text-leise,
gemessen 6,2:1.

Leere Kategorien waren mit opacity .55 fast unlesbar. Jetzt .82 -- sie
sollen erkennbar bleiben, nur zurueckhaltender.

2) DATEIEN AN MEHRERE PERSONEN GEZIELT FREIGEBEN

Bisher hatte eine Datei genau EINEN Bereich (creator_id). Damit liess
sie sich nicht zweien geben, ohne sie zweimal hochzuladen.

Neue Tabelle datei_personen (datei_id + person_id). creator_id bleibt
und behaelt seine Bedeutung: Es sagt, zu wessen BEREICH eine Datei
gehoert -- die neue Tabelle sagt, WER sie sehen darf. Zwei verschiedene
Fragen, deshalb zwei Felder.

Auswahl als einzelne Schalter, nicht als <select multiple>: Dort
verliert man mit einem Fehlklick die ganze Auswahl, und auf dem Handy
ist sie kaum bedienbar. Jeder Name ist ein Schalter, der sichtbar an
oder aus ist, eingefaerbt nach Rolle -- man sieht auf einen Blick, ob
eine Datei an Creator, Scouts oder beide geht.

Wer wen auswaehlen darf:
- DogFather jeden aktiven Menschen ausser sich selbst
- ein Scout NUR die Creator, die er betreut -- sonst koennte er sich
  ueber eine Freigabe Zugang zu fremden Bereichen verschaffen
- ein Creator gar niemanden

Jede Id wird beim Speichern erneut gegen die erlaubte Auswahl geprueft.
Geprueft: Sam schickt die Ids 3, 6 und 7 mit (alles Creator, die er
NICHT betreut) -- die Datei landet bei niemandem. Kein Fehler, kein
Zugang: die Ids fallen still durch das Raster.

Weiter geprueft:
- Chef sieht alle drei Testdateien, Luna nur ihre, Sam nur seine,
  Patrick keine
- Creator bekommt 403 beim Aendern von Freigaben
- Freigaben sind an jeder Datei sichtbar ("Sichtbar fuer ..."), auch
  fuer die, die sie nicht aendern duerfen -- niemand soll raten muessen
- Die Auswahl wird nach dem Hochladen geleert, sonst bekaeme die
  naechste Datei stillschweigend dasselbe Publikum
2026-08-28 13:14:11 +02:00
DogFatherGit 1c3e642f12 Workspace: Rolle "Management" heisst jetzt "DogFather"
Auf Wunsch von Filipe. Betrifft ausschliesslich die Anzeige.

Der Rollenschluessel bleibt "admin". Er steckt in der CHECK-Regel der
Datenbank, in jeder bestehenden Sitzung und in jeder Rechteabfrage --
ihn umzubenennen haette alle drei gebrochen, und bestehende Anmeldungen
waeren ungueltig geworden. Umbenannt wird nur, was man LIEST.

Der Anzeigename steht jetzt an EINER Stelle (ROLLEN_NAME in
workspace.js) und kommt ueber /workspace/api/ich als rolle_name mit.
Stand er in elf Dateien, waere er beim naechsten Mal in zehn davon
geaendert.

Dabei aufgefallen: In der Kopfleiste stand auf JEDER Seite der rohe
Rollenschluessel -- "Chef · admin". Das war schon vorher unschoen, faellt
aber jetzt erst richtig auf. Alle elf Seiten zeigen jetzt "Chef ·
DogFather". Geprueft: kein rohes "admin" mehr in der Oberflaeche.

Geaendert: Rollenkachel und Untertitel auf der Anmeldeseite, Kopfleiste
aller Seiten, Rollentext auf dem Dashboard, Rollenmarken und Auswahl in
der Personenverwaltung, die Betreuungs-Auswahl ("nur DogFather"), der
Hinweis auf der Dateienseite, die Erklaerung zur internen Notiz im
Profil, die Hinweise fuer Scouts ohne Zuteilung -- und vier
Fehlermeldungen vom Server.

Schreibweise "DogFather" wie von Filipe geschrieben; das ist auch auf
der oeffentlichen Website die haeufigste Form (717 von 1216).

In den Code-Kommentaren der Fachmodule heisst die Rolle weiterhin "das
Management". Das bleibt bewusst so -- eine Massenaenderung an vierzig
Kommentaren waere reines Risiko ohne sichtbaren Nutzen. Ein Hinweis an
der ROLLEN_NAME-Zuordnung erklaert den Zusammenhang.
2026-08-28 11:55:05 +02:00
DogFatherGit 5684ff87f1 Workspace: "Was ist dran" -- erster Baustein der Automationen (Phase 4)
Bis hierher musste man selbst daran denken, in den richtigen Bereich zu
schauen. Das dreht die Uebersicht auf dem Dashboard jetzt um: Das System
sagt, was liegen bleibt.

Drei Regeln, an die sich das haelt:

1. KEINE eigenen Daten. Ein Hinweis ist immer nur eine Sicht auf etwas,
   das ohnehin existiert. Wird die Aufgabe erledigt, verschwindet der
   Hinweis von selbst -- es gibt nichts zu quittieren, nichts zu pflegen
   und nichts, was veralten kann. Genau daran scheitern die meisten
   Erinnerungssysteme.

2. JEDER HINWEIS FUEHRT IRGENDWOHIN. Ein Hinweis ohne Ziel ist nur ein
   schlechtes Gewissen. Jeder traegt deshalb einen Link zu der Stelle,
   an der sich die Sache tatsaechlich erledigen laesst. Geprueft: Ziel
   erreichbar, keine Umleitung.

3. DIESELBE SICHTBARKEIT WIE UEBERALL. Die Regeln werden aus den
   Fachmodulen importiert, nicht abgeschrieben (workspace-aufgaben,
   -kalender, -dateien, -bereiche exportieren sie jetzt). Ein Hinweis
   darf nie etwas verraten, das die zugehoerige Seite verbergen wuerde
   -- sonst waere ausgerechnet die Uebersicht das Leck.

Dreizehn Hinweisarten, in drei Stufen. Nur die oberste ist farbig:
waere alles hervorgehoben, waere nichts hervorgehoben. Liegt nichts an,
verschwindet der ganze Block.

Steht bewusst VOR den Zahlen. Die Zahlen sagen, WIE VIEL anliegt --
diese Liste sagt, WAS zu tun ist.

Steuerungswissen bleibt beim Management: Review-Termine, Creator ohne
zustaendige Person und leere Profile erscheinen weder bei Creator noch
bei Scouts -- genau wie die zugehoerigen Profilfelder. Geprueft mit
einem eigenen Leck-Test ueber alle drei Rollen.

Zwei Hinweise, die es ohne diese Uebersicht gar nicht gaebe:
- Aufgaben, die im Review haengen. Sie warten auf jemanden -- die Sorte
  Stillstand, die niemandem auffaellt, weil nichts ueberfaellig wird.
- Uebergebene Leads, aus denen nie ein Creator wurde. Sonst ist die
  Uebergabe eine Sackgasse, die niemand bemerkt.

Nebenbei: Der Fusstext auf dem Dashboard stammte noch vom ersten Tag
("Die Bereiche werden nach dem Phasenplan gebaut") -- inzwischen sind
Phase 1 bis 3 fertig. Ersetzt durch eine Erklaerung, wie die Uebersicht
funktioniert.
2026-08-28 11:23:07 +02:00
DogFatherGit fa8fbab410 Workspace: Scouts betreuen Creator wie das Management
Bisher hatten Scouts mit der Creator-Betreuung nichts zu tun -- keine
Profile, keine Betreuungsbereiche, keine Reports. Das aendert sich, mit
zwei bewusst gesetzten Grenzen.

GRENZE 1: nur zugeteilte Creator, keine Rollenregel.

Neue Tabelle betreuung (creator_id PRIMARY KEY -> betreuer_id). Ein
Creator hat genau EINE zustaendige Person, damit nie unklar ist, wer
gefragt ist. Das Management sieht ohnehin alle und braucht keinen
Eintrag. Wer nichts zugeteilt bekommt, sieht weiterhin nichts -- kein
Recht entsteht automatisch aus der Rolle.

Zugeteilt wird in "Personen & Zugaenge", direkt in der Personenzeile:
Betreuung ist eine Eigenschaft der Person, kein eigener Vorgang. Nur das
Management darf zuteilen -- koennte ein Scout sich selbst Creator geben,
haette er die Rechtevergabe in der Hand, die ihn begrenzen soll.
Zustaendig koennen nur aktive Scouts sein, kein Admin (der sieht alles)
und kein anderer Creator.

Bei der Uebergabe aus der Pipeline passiert die Zuteilung von selbst:
Wer jemanden gefunden hat, betreut ihn weiter. Genau darum geht es bei
"Creator-Onboarding starten". Umhaengen kann das Management jederzeit.

GRENZE 2: betreuen, nicht verwalten.

Profile, die fuenf Bereiche und Reports wie ein Manager. ABER:
- keine Zugangscodes, kein Sperren von Personen (personen.html bleibt
  admin-only, unveraendert)
- keine management-internen Felder. Der Scout bekommt admin_notiz,
  plan_start und naechster_review NICHT -- die Felder fehlen in der
  Antwort komplett, nicht nur in der Anzeige. Eine Notiz UEBER die
  Betreuung gehoert nicht in die Hand dessen, der betreut. Geprueft: Ein
  Scout, der admin_notiz mitschickt, aendert sie nicht.

Die Regel steht an EINER Stelle (betreuteIds / betreutWo / darfCreator
in workspace.js) und wird von sechs Modulen benutzt. Eine Rechteregel,
die an sechs Stellen steht, ist eine Rechteregel, die irgendwann an
fuenf Stellen stimmt.

Genau das ist beim Bauen auch passiert: workspace-calls.js hatte eine
wortgleiche Kopie der Kalender-Sichtbarkeit. Erweitert wurde nur der
Kalender -- Scouts sahen die Termine ihrer Creator, dieselben Termine
als Call aber nicht. Die Kopie ist jetzt weg, calls.js importiert die
Regel aus workspace-kalender.js.

Zwei Fehler, die die Aenderung selbst erzeugt haette, vorher gefunden:
- Report-Entscheidung: ein Scout haette eine Aufgabe angelegt, deren
  "Creator" er selbst ist -- die waere in jeder Auswertung falsch
  mitgelaufen. Zeigt jetzt auf einen seiner Creator.
- Bereichseintrag: derselbe Fehler. Ein Scout hat gar keinen eigenen
  Betreuungsbereich. Ein Eintrag ohne oder mit fremder Zuordnung landet
  beim ersten zugeteilten Creator, nie bei einem fremden. Geprueft:
  Mikas Bereich bleibt bei jedem Versuch unberuehrt.
2026-08-28 11:18:56 +02:00
DogFatherGit 516a003dc8 Dateien: Hochladen nur fuer Management und Scouts
Wunsch vom 28.08.2026: "die dateien sollen nur die manager oder scout
hochladen koennen aber nicht die creator."

Serverseitig ueber DARF_HOCHLADEN. Die Pruefung steht bewusst VOR
express.raw -- wer nicht darf, wird abgewiesen, bevor auch nur ein Byte
entgegengenommen wird. Sonst wanderten bis zu 25 MB durch die Leitung,
nur um danach verworfen zu werden.

Ein Creator sieht und oeffnet weiterhin die Dateien seines Bereichs.
Statt des Ablegefeldes steht dort jetzt, warum es fehlt -- ein einfach
verschwundenes Feld wirkt wie ein Fehler.

Geprueft: Management 201, Scout 201, Creator 403 mit klarer Meldung;
Creator sieht und laedt weiterhin.

--------------------------------------------------------------------
Dabei ein Fehler aufgefallen, der mehrere Seiten betraf:

Das hidden-Attribut blendet nur ueber eine sehr schwache Browserregel
aus -- JEDE eigene display-Angabe schlaegt sie. Betroffen waren:
  * das Ablegefeld fuer Dateien (display: grid) -> ein Creator sah es
    trotz hidden weiterhin
  * die Verwaltungsfelder "Plan-Start" und "Naechster Review" im
    Creator-Profil (ebenfalls grid) -> ein Creator sah sie ebenfalls
  * der Zurueck-Knopf (inline-flex) -> waere vor dem Laden des Skripts
    kurz sichtbar gewesen

Behoben mit einer Regel in gate.css: [hidden] { display: none !important }

Beim Profil waren nie Daten betroffen -- der Server schickt die Felder
an einen Creator gar nicht erst mit, sie waren leer. Sichtbar sein
sollten sie trotzdem nicht.

Aufgefallen ist es erst im Screenshot. Der vorige Test hatte auf das
hidden-ATTRIBUT geprueft, und das war ja gesetzt. Die Pruefung schaut
jetzt auf die tatsaechliche Sichtbarkeit (isVisible).

Ausserdem: In der Regex zum Saeubern von Dateinamen standen die
Steuerzeichen als rohe Bytes statt als Escape-Sequenz. Die Funktion
arbeitete korrekt, aber die Datei galt dadurch als binaer -- grep
verweigerte sie, und Editoren haetten sie zerstoeren koennen. Jetzt
steht dort \x00-\x1f als Text.
2026-08-28 01:25:53 +02:00
DogFatherGit 81b51ab94f Workspace: Dateiablage mit Freigabe-Ablauf (Phase 1 vollstaendig)
/workspace/dateien.html -- Ablegen per Ziehen oder Auswaehlen,
Entwurf -> Review -> Freigabe, Filter je Zustand.

OHNE NEUE ABHAENGIGKEIT. Uploads laufen ueblicherweise ueber multer.
Hier schickt der Browser die Datei roh im Rumpf, der Name steht im Kopf
(URI-kodiert, damit Umlaute heil ankommen). express.raw() bringt den
passenden Empfaenger schon mit -- kein Zerlegen von multipart/form-data
von Hand, was gerade hier heikel waere.

Die drei Punkte, an denen Dateiablagen typischerweise scheitern:

1. Die Dateien liegen AUSSERHALB des Repos (workspace-daten/dateien/).
   Lagen sie darin, wuerde express.static sie ungeprueft ans Netz geben.
2. Auf der Platte traegt jede Datei einen erzeugten Zufallsnamen, der
   Originalname steht nur in der Datenbank. Geprueft mit dem Dateinamen
   "../../etc/passwd": gespeichert wurde "passwd", auf der Platte ein
   Zufallsname IM Ordner -- nichts ist ausgebrochen.
3. Ausgeliefert wird immer als Download mit neutralem Typ, dazu
   nosniff und CSP sandbox. Geprueft mit einer hochgeladenen
   boese.html: kommt als application/octet-stream zurueck, kann also
   keinen Code im Namen der Domain ausfuehren.

Freigabe nach Konzept: Der Zustand "freigegeben" ist eine Abnahme und
bleibt dem Management vorbehalten. Geprueft -- Luna kann Entwurf ->
Review, aber nicht freigeben (403); eine freigegebene Datei kann sie
weder aendern noch loeschen.

Sichtbarkeit wie ueberall: Chef 2 Dateien, Luna 1, Mika 0. Zugriff auf
eine fremde Datei: 404, nicht 403.

Ein Fehler beim Testen gefunden: Bei zu grosser Datei brach express.raw
ab, BEVOR der eigene Code lief -- der Fehler landete im allgemeinen
Behandler als HTTP 500. Fuer die Nutzerin sah das aus wie ein kaputter
Server statt wie "Datei zu gross". Jetzt faengt ein eigener
Fehlerbehandler am Ende des Routers das ab und antwortet mit 413 und
einer verstaendlichen Meldung.

Damit ist Phase 1 aus dem Konzept vollstaendig.
2026-08-28 01:14:00 +02:00