Commit Graph
70 Commits
Author SHA1 Message Date
DogFatherGitandClaude Opus 5 70039714c5 Die Sicherung war zwei Loecher gross -- gefunden, weil sie zum ersten Mal wirklich zurueckgespielt wurde
"Wir haben eine Sicherung" war bis heute ein Satz, kein Nachweis. Die
taegliche Kopie ausserhalb des Servers prueft `PRAGMA integrity_check`
und meldet seit dem 31.08. jeden Tag "in Ordnung". Das heisst: die Datei
ist nicht zerschossen. Es heisst NICHT, dass man damit weiterarbeiten
kann.

tools/wiederherstellung-proben.mjs geht den Weg jetzt wirklich: juengste
Sicherung in ein Wegwerf-Verzeichnis kopieren, die echte Anwendung
dagegen starten (damit laufen alle Schemawanderungen durch), vorher und
nachher zaehlen, anmelden, jede Seite aufrufen. Drei Ausgaenge, nicht
zwei -- "konnte nicht nachsehen" ist weder Erfolg noch Fehler.

BEIM ERSTEN LAUF BLIEB GENAU EINE VON ACHTZEHN SEITEN ROT: der
Steckbrief, mit einem 404 fuer ein Bild. Daran hingen zwei echte Luecken:

  1. PROFILBILDER WAREN NIE GESICHERT. sicherung-holen.sh holte
     dateien/ und wissen/ -- die Bilder liegen aber in einem dritten
     Ordner (profilbilder/, siehe workspace-steckbrief.js). Nach einem
     Plattenausfall waeren alle Profilbilder weg gewesen, waehrend die
     taegliche Meldung weiter "in Ordnung" sagte. Sie hat ja nie
     behauptet, vollstaendig zu sein.

  2. DIE RUECKMELDUNG AN DEN SERVER LIEF INS LEERE. Das Skript meldete
     sich bei dogfather-universe.com/workspace/... -- seit dem Umzug am
     06.09. antwortet diese Adresse mit 410 "Gone". Der Server erfuhr
     also seit dem Umzug nicht mehr, dass die Kopie laeuft; auf der
     Automationen-Seite waere sie mit jedem Tag aelter erschienen,
     obwohl sie taeglich lief. Ein 410 wird jetzt eigens gemeldet -- es
     heisst etwas anderes als "Netz kaputt", naemlich "die Adresse
     stimmt nicht mehr".

Beides behoben. Und damit es kein drittes Mal passiert, vergleicht die
Probe die Ordnerliste des Sicherungsskripts gegen die Ordner, die der
Server im Quelltext wirklich benutzt (`join(DATEN_ORDNER, "...")`). Wer
morgen einen vierten Datenordner anlegt und ihn nicht sichert, bekommt
hier einen Fehler statt eines stillen Lochs -- mit Gegenprobe, dass der
Vergleich einen fehlenden Ordner auch wirklich erkennt.

Ergebnis nach den Reparaturen: 18 Pruefungen, alle gruen,
"DIE SICHERUNG LAESST SICH ZURUECKSPIELEN." Der Lauf traegt sich mit
Datum in die Sicherungsablage ein -- sonst weiss beim naechsten Mal
niemand, wann zuletzt wirklich zurueckgespielt wurde.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-06 23:20:10 +02:00
DogFatherGitandClaude Opus 5 233cd76d78 Der Handy-Durchgang: drei echte Bedienfehler, alle vom selben Ursprung
Filipe: "ich will dass du die komplette seite auf dem handy abcheckst.
ich will dass alles perfekt aussieht und bedienbar ist."

DER SCHWERSTE FUND: Auf ZWOELF Seiten war der "Meine Sicht"-Umschalter
nicht bedienbar -- wer darauf tippte, landete im Chat.

Bei 412 px (der haeufigsten Android-Breite ueberhaupt) brach die
Kopfleiste nicht um, der Umschalter wurde auf 50 px zusammengedrueckt,
sein Knopf behielt aber seine 104 px Mindestbreite und lag damit quer
ueber dem Chat-Knopf. Sichtbar war davon nichts.

Und die Ursache steht seit dem 05.09. woertlich im Kommentar daneben:
"Die Rechnung ging genau auf, solange rechts VIER Dinge standen. Mit der
Glocke sind es FUENF, und bei 320 px passte es nicht mehr." Am 06.09.
habe ich den Chat-Knopf dazugesetzt -- SECHS -- und die Schwelle bei 380
gelassen. Derselbe Fehler, eine Position weiter.

Die Lehre ist nicht "380 auf 430 erhoehen"; das waere er ein drittes
Mal, nur mit einer anderen Zahl. Eine feste Schwelle ist eine Rechnung,
die jemand einmal aufgestellt hat und die beim naechsten Knopf still
falsch wird. `flex-wrap: wrap` OHNE Schwelle rechnet nicht, sondern
misst -- es bricht genau dann um, wenn der Platz nicht reicht.

DASSELBE NOCH EINMAL, am anderen Ende: Bei 1280 px brauchte die Leiste
1235 px (Marke 375 + Bedienelemente 844 + Abstand 16) und hatte 1200.
Auch hier war der Chat-Knopf der Tropfen. Sie brach um, sobald das
Skript die Bedienelemente eingehaengt hatte, und schob die ganze Seite
52 px nach unten -- CLS 0,94. Jetzt gibt die MARKE nach (sie darf
gekuerzt werden, ein Knopf nicht), und umgebrochen wird nur noch auf
sehr schmalen Geraeten.

WEITERE ECHTE FUNDE:
  * /workspace/api/chat/ungelesen wurde auf JEDER Seite ZWEIMAL geholt:
    einmal beim Laden, einmal Millisekunden spaeter beim Aufgehen des
    Ereignisstroms. Der 'open'-Zuhoerer war fuer Wiederverbindungen
    gedacht und feuerte auch beim ersten Mal.
  * Drei Kacheln teilten sich einen Farbton mit einer anderen (18 Farben
    auf 21 Kacheln). Filipe wollte ausdruecklich, dass jede ihre eigene
    hat. Nicht eine Farbe dazuerfunden -- der ganze Farbkreis ist mit
    tools/kachel-farben.mjs neu in 21 geteilt; kleinster Abstand zweier
    Nachbarn jetzt 120 Grad (vorher 106). Dabei fiel eine feste 16 in
    der Mischschleife auf: Bei 18 Kacheln wurden die letzten beiden nie
    mitgemischt.
  * Der Agentur-Untertitel wurde auf dem Handy abgeschnitten.
  * Ein zugeklappter <details>-Kasten (Kalender-Abo) verdeckte einen
    Filter-Chip: Chromium versteckt dessen Inhalt ueber
    `content-visibility`, nicht ueber `display` -- die Kaesten behalten
    eine Groesse. Dieselbe Falle wie bei den Zeitbloecken, dieselbe
    Loesung.

UND DREI PRUEFUNGEN, DIE SELBST FALSCH LAGEN:
  * "achtzehn Kacheln" stand als feste Zahl im Test. Eine Pruefung, die
    bei jeder neuen Kachel rot wird, erzieht dazu, ihr Rotwerden zu
    ignorieren. Sie zaehlt jetzt aus bereiche.js.
  * "das Licht der Kalender-Kachel (tuerkis) muss mehr Blau als Rot
    haben" -- Wissen von aussen, und nach dem Neurechnen war der
    Kalender rosa. Gemessen wird jetzt gegen den Ton der Kachel selbst.
  * pruef-workspace-umzug meldete sein Ergebnis in eigenen Worten. Der
    Gesamtlauf las daraus NULL Pruefungen und schrieb bei JEDEM Lauf ein
    FEHL, obwohl alle 31 Punkte bestanden. Ein Fehlalarm, der immer
    kommt, macht den einen echten unsichtbar.

Und weil "BUTTON 'Meine Sicht' verdeckt" mich eine Stunde gekostet hat,
sagen pruef-handy und pruef-tempo jetzt DAZU, was verdeckt und was
springt -- mit Elternkette und Koordinaten. Ein Befund, den man nicht
verorten kann, ist ein halber.

NEU: der Kalender zum Abonnieren (Stufe 3.2). Persoenlicher, jederzeit
widerrufbarer Link fuer Google, Apple und Outlook. 36 Pruefungen, die
das ICS ZURUECKLESEN statt es anzusehen -- entfaltet, entschluesselt,
verglichen. Wichtigster Punkt: Der Weg ohne Anmeldung darf nichts
zeigen, was der Weg mit Anmeldung nicht zeigt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-06 23:15:37 +02:00
DogFatherGitandClaude Opus 5 bede91921d Der sechste Bereich, und zwei Pruefungen, die den Lauf lahmgelegt haben
DER AGENTUR-BEREICH (Stufe 4 des Plans)
Kernprinzip 04 des Konzepts lautet woertlich "Die Agentur bleibt
angebunden" -- und dafuer gab es bis heute nichts. Fuenf Bereiche
standen, der sechste fehlte vollstaendig. Damit stand nirgends, welche
Kampagne laeuft, welche Schulung ansteht und wie ein Anliegen an die
Agentur ausgegangen ist. Das lief ueber private Nachrichten: nicht
auffindbar, nicht nachvollziehbar, beim naechsten Mal von vorn.

Vier Arten, und die vierte ist der Punkt: kampagne, schulung, anliegen
und ZUSTAENDIGKEIT. Die letzte ist keine Verlegenheit, sondern das, was
das Konzept ausdruecklich fordert -- Betreuung und Umsetzung sind unsere
Seite, offizielle Wege sind Agenturseite. Solange das nur im Kopf steht,
wird es bei jedem Streitfall neu verhandelt.

Der Umbau war das eigentliche Risiko, nicht der Bereich: Ein CHECK
laesst sich in SQLite nicht aendern, die Tabelle muss neu gebaut werden
-- und dabei werden ALLE vorhandenen Eintraege umgeschrieben. Deshalb
geht pruef-agentur.mjs (31 Pruefungen) den Weg wirklich: Sie baut eine
Datenbank im ALTEN Stand nach, fuellt sie mit allen fuenf Bereichen,
laesst die echte Anwendung darueberlaufen und zaehlt danach jede Zeile
UND jedes Feld nach -- auch die seltenen Spalten (hook, creator_extern),
die man beim Abschreiben des Bauplans vergisst. Wichtigste Gegenprobe:
Der CHECK muss danach noch BEISSEN. Eine Umstellung, die nebenbei die
Schranke entfernt, sieht aus wie ein Erfolg und ist der schlimmere
Ausgang.

Nebenbei drei abgeschriebene Bereichslisten beseitigt (Wochenbericht,
Suche, Report-Ziele). Im Wochenbericht waere der neue Bereich sonst
schlicht nicht vorgekommen -- ohne Fehler, ohne Luecke, einfach nicht da.

ZWEI PRUEFUNGEN, DIE DEN GESAMTLAUF ZUM STILLSTAND BRACHTEN

pruef-call-kategorien.mjs hing DREI STUNDEN. Ursache war ein Zeitzuender
in ihr selbst: Sie legte Calls auf "heute 18:00" und erwartete zwei
davon unter "Heute". Ab 18 Uhr sind die vorbei, der Server schiebt sie
nach "Protokoll fehlt", und die Oberflaeche unterteilt erst ab FUENF
anstehenden. Uebrig blieben vier, die Bloecke verschwanden, und die
Pruefung wartete auf einen Klick auf einen Block, den es nicht gab.
Genau die Sorte Fehler, vor der die Projektnotiz vom 06.09. warnt: Sie
war um 17:59 gruen und um 18:01 rot, ohne dass sich am Code etwas
geaendert hatte. Jetzt liegen alle Zeiten RELATIV zu jetzt, und die
Erwartung wird mit derselben Vorschrift gerechnet, die calls.js benutzt
-- statt Zahlen, die nur zu einer bestimmten Tageszeit stimmen.

Und der Grund, warum daraus ein Stillstand statt eines Fehlers wurde:
index.js setzt bewusst zwei Auffangnetze (uncaughtException,
unhandledRejection). Fuer den Betrieb richtig -- ein Fehler darf die
Website nicht offline nehmen. Fuer eine Pruefung fatal: Sie importiert
index.js in denselben Prozess und erbt die Netze. Ihr eigener Absturz
wird dann nur protokolliert, und der Express-Server haelt den Prozess
danach ewig am Leben. Kein Fehler, kein Ergebnis, kein Ende.

Deshalb zwei Abhilfen, die zusammengehoeren:
  * server/helfer-notbremse.mjs -- haengt eigene Zuhoerer DANEBEN
    (process.on ergaenzt, es ersetzt nicht) und beendet den Lauf mit
    Fehler; dazu ein Wecker. In alle 42 Browserpruefungen eingebaut.
    Der Betrieb bleibt unveraendert.
  * tools/alles-pruefen.mjs gibt jeder Datei eine Frist von 600 s. Wer
    sie reisst, wird abgebrochen und ZAEHLT ALS FEHLGESCHLAGEN, mit der
    letzten Ausgabe davor als Beleg. Einzelne Dateien nachzuruesten hilft
    nur bis zur naechsten ohne Notbremse -- deshalb sitzt sie dort, wo
    sie fuer alle gilt, auch fuer die, die es noch nicht gibt.

AUSSERDEM: pruef-breiten.mjs pruefte 16 Seiten aus einer Liste von Hand,
chat.html und leistung.html fehlten darin. Der Chat war bei keiner
einzigen der neun Breiten je gemessen worden. Wie bei pruef-handy kommt
die Liste jetzt aus dem Verzeichnis.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-06 22:06:49 +02:00
DogFatherGitandClaude Opus 5 80a8aac774 Der ganze Prueflauf blieb am Chat-Strom stehen -- behoben
BEFUND. Seit der Chat am 06.09. dazukam, LIEF DER GESAMTE
REGRESSIONSLAUF NICHT MEHR DURCH. Nicht "er wurde rot" -- er blieb
einfach stehen, bei Datei 3 von 62, ohne Fehlermeldung, ohne FEHL, ohne
Absturz. Nach zwoelf Minuten stand er immer noch dort. Von aussen sieht
"noch nicht fertig" genauso aus wie "haengt fuer immer"; deshalb ist
mir das gestern nicht aufgefallen, sondern erst, als ich den Lauf
gezielt beobachtet habe.

DIE URSACHE. pruef-alle-wege.mjs geht stumpf ueber ALLE 134
Schnittstellen und liest jede Antwort mit `await a.text()` aus. Der
Chat haelt seine Verbindung aber absichtlich offen und schickt neue
Nachrichten hinein, solange jemand zusieht (SSE). `text()` wartet, bis
der Server fertig ist -- und der wird nie fertig. Angemeldet als
DogFather trat der Lauf dort ein und kam nicht wieder heraus.

DIE ABHILFE, zwei Teile, die zusammengehoeren:
  * Jeder Ruf hat jetzt eine Frist von 8 s. Laeuft sie ab, ist das ein
    ERGEBNIS ("hing") und kein Absturz. Ein neuer Abschnitt meldet am
    Ende, WELCHER Weg nicht geantwortet hat -- statt dass der Lauf
    wortlos stehenbleibt.
  * Bekannte Stroeme stehen in einer Liste MIT BEGRUENDUNG und werden
    nicht uebersprungen, sondern anders geprueft: verbinden, Status
    ablesen, abbrechen. Die Schranke wird damit genauso gemessen wie
    ueberall. Zusaetzlich wird nachgemessen, dass ein eingetragener
    Strom auch wirklich offen bleibt -- sonst verdeckte die Ausnahme
    nur seine Inhaltspruefung.
Der "hing"-Zustand musste eigens gesammelt werden: In Abschnitt 1 haette
er ausgesehen wie "ohne Anmeldung erreichbar", in Abschnitt 2 waere er
ganz durchgefallen (`"hing" >= 500` ist false, Zeichenkette gegen Zahl).
Genau so verschwinden Befunde.

Ergebnis: 134 Schnittstellen, 532 Aufrufe, alles gruen, kein Haenger.

AUSSERDEM, gefunden beim Nachsehen:

  * pruef-handy.mjs pruefte 15 Seiten -- aus einer Liste von Hand, die
    veraltet war. chat.html, leistung.html und steckbrief.html standen
    nicht darin: DREI von neunzehn Seiten waren nie auf einem Handy
    gemessen worden, ausgerechnet der Chat. Die Liste kommt jetzt aus
    dem Verzeichnis, die naechste neue Seite ist von selbst dabei.
  * chat.html und leistung.html fehlte <link rel="manifest">. Auf dem
    Handy heisst das: Wer die App installiert hat und ueber eine
    Benachrichtigung dort landet, verlaesst den App-Rahmen -- die Seite
    oeffnet im Browser, mit falscher Leistenfarbe. Ihre theme-color war
    ausserdem eine andere als auf allen uebrigen Seiten. Beides behoben
    UND als Pruefung in pruef-struktur nachgetragen, damit es beim
    naechsten Mal nicht am Gedaechtnis haengt.

NEU: tools/wiederherstellung-proben.mjs — die Probe aufs Exempel.
Die Sicherung ausserhalb des Servers laeuft taeglich und prueft
`integrity_check`. Das sagt: die Datei ist nicht zerschossen. Es sagt
NICHT, ob die Anwendung damit startet, ob man sich anmelden kann und ob
die Daten vollstaendig sind. Eine Sicherung, die man nie zurueckgespielt
hat, ist eine Hoffnung. Das Werkzeug kopiert die juengste Sicherung in
ein Wegwerf-Verzeichnis, startet die echte Anwendung dagegen (damit
laufen alle Schemawanderungen wirklich durch), zaehlt vorher und
nachher, meldet sich an und ruft jede Seite auf. Drei Ausgaenge, nicht
zwei -- "konnte nicht nachsehen" ist weder Erfolg noch Fehler.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-06 18:34:57 +02:00
DogFatherGitandClaude Opus 5 8759a46e5b iPhone-Symbole: quadratisch und deckend statt abgerundet
Gemeldet: "auf dem pc und auf dem handy soll alles funktionieren, auf
dem einen klappt es und auf dem anderen nicht."

Der Grund ist, dass PC und Handy ihr Symbol an drei verschiedenen
Stellen holen -- und jede stellt andere Anforderungen:

  Browser-Reiter   das normale Symbol, runde Ecken erlaubt
  Android          die maskable-Fassung, aussen wird beschnitten
  iPhone           <link rel=apple-touch-icon> -- und iOS rundet SELBST
                   ab und fuellt alles Durchsichtige mit SCHWARZ

Unser 180er brachte seine eigene Rundung mit, also durchsichtige Ecken.
Auf dem iPhone wurden daraus schwarze Zipfel, die dann ein zweites Mal
beschnitten wurden. Auf dem PC sieht dieselbe Datei tadellos aus --
genau daher der Unterschied zwischen den Geraeten.

Jetzt wird die 180er-Fassung randvoll und deckend gebaut. Nachgemessen
an allen zehn: 0,00 Prozent durchsichtig, Ecken voll deckend. Die
normale Fassung bleibt abgerundet (4,75 Prozent) -- auch das gemessen,
damit der Fix nicht die andere Seite kaputtmacht.

Dazu eine Pruefung in pruef-struktur.mjs: alle sechs Groessen je App
vorhanden, und jede Seite nennt beide Symbolarten. Fehlt das
iPhone-Symbol, nimmt iOS einen Bildschirmausschnitt der Seite.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-05 12:46:32 +02:00
DogFatherGitandClaude Opus 5 e9709a5aa8 Maskable-Symbole: das ganze Symbol verkleinern, nicht nur das Logo
Gemeldet von Filipe: "die symbole sehen aber auf meinem pc nicht aus
wie auf dem browser mit diesen geilen farben." Er hatte recht -- die
maskable-Fassungen sahen aus wie eine schlechte Kopie: blass, das
Medaillon riesig, der Doppelring ueber den Rand hinaus. Und genau die
nimmt das Betriebssystem fuer installierte Apps.

Der erste Entwurf verkleinerte nur das LOGO (52 statt 68 Prozent) und
liess den Hintergrund unveraendert. Das geht bei einer glatten Flaeche
gut und bei allem anderen schief: Medaillon, Doppelring, Raster und
Eckband rechnen ihre Kreise in Prozent der FLAECHE. Wird aussen ein
Fuenftel weggeschnitten, sitzt der Ring nicht mehr, wo er hingehoert.

Jetzt wird das fertige Symbol als Ganzes auf 78 Prozent verkleinert und
in eine Huelle aus dem dunkelsten Ton der App gesetzt. Damit bleibt
jedes Verhaeltnis erhalten -- Ring zu Flaeche, Logo zu Ring, Verlauf zu
Kante. Weggeschnitten wird nur ruhige Randfarbe.

Nachgeprueft mit einer Vorschau, die den Zuschnitt nachstellt: rund
(Android) und abgerundetes Quadrat (Windows/iOS). Beide sehen jetzt
praktisch aus wie die Fassung im Browser.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-05 12:12:54 +02:00
DogFatherGitandClaude Opus 5 7fe6a51233 ZockerAnstalt und Analyse: Symbole unter den richtigen Namen
Der erste Entwurf legte sie unter eigenen Namen daneben
(dogfather-zocker-192.png). Die Dateien lagen da, die Manifeste zeigten
weiter auf icon-192.png -- das neue Symbol waere nie angekommen. Der
Kopiervorgang meldete trotzdem 6 Symbole kopiert.

Jetzt werden die vorhandenen Namen ueberschrieben. Damit greifen
Manifest und HTML ohne weitere Aenderung, und es gibt keine zweite
Stelle, an der ein Verweis uebersehen werden kann. Fehlt ein erwarteter
Name, wird das gemeldet statt still uebergangen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-05 11:48:17 +02:00
DogFatherGitandClaude Opus 5 51c3d4402b Audit des Creator Workspace, App-Symbole fuer alle Apps der Domain
AUDIT (Auftrag: vollstaendiger Durchgang, Fehler direkt beheben)

Ausgangslage waren 40 Pruefungen mit 1616 Einzelpunkten, alle gruen.
Acht neue Pruefungen kamen dazu; sie haben gefunden, was die alten nicht
sehen konnten.

Der schwerste Fund: Die Zugangsschranke verglich req.path EXAKT gegen
eine Liste. Express raeumt Punkt-Segmente selbst weg, mehrfache
Schraegstriche aber nicht. Damit kam //workspace/start.html OHNE
Anmeldung mit HTTP 200, und ein Creator bekam ueber
/workspace//personen.html die Verwaltungsseite. Die DATEN waren nie
betroffen (nachgemessen: 404 bzw. 401). Behoben durch Normalisierung
UND eine Umkehr der Logik -- jetzt ist jede .html geschuetzt ausser der
Anmeldeseite, statt nur die in der Liste. Eine vergessene neue Seite
steht damit nicht mehr versehentlich offen.

Weiter behoben:
  * Kaputter/abgebrochener Rumpf ergab 500 in HTML statt 400 in JSON --
    die Oberflaeche ruft ueberall a.json() und lief in einen zweiten
    Fehler; der Knopf hing ohne Meldung.
  * POST /zustand/sichern war der einzige von 60 schreibenden Wegen
    ohne Herkunftspruefung.
  * workspace-sicherung.js gab interne Pfade in Fehlermeldungen nach
    aussen; alle 23 anderen Module antworten neutral.
  * admin_notiz war als einziges von 14 Feldern ohne <label>.
  * Der aktive Filter hatte keinen sichtbaren Fokus (CSS-Spezifitaet
    0,3,0 schlug 0,2,0) -- genau der Knopf, auf dem man steht.
  * h1 -> h3 ohne Zwischenstufe auf zwei Seiten.
  * HSTS ging auch ueber http mit (RFC 6797, 7.2 verbietet das).
  * upgrade-insecure-requests galt auch auf 127.0.0.1 -- dadurch war
    WebKit/Safari ueberhaupt nicht pruefbar, also der Browser, den
    jedes iPhone benutzt.
  * pruef-grosscheck las readdirSync(".") und pruefte aus server/
    gestartet NULL oeffentliche Seiten -- meldete aber "ok".

Neue Pruefungen: struktur, schranke, haerte, alle-wege,
barrierefrei-workspace, breiten, tempo-workspace, browser.
Jede mit Gegenprobe und mit der geprueften Anzahl in der Bedingung.
Vier davon sind beim Bauen durch die eigene Gegenprobe aufgeflogen und
haetten sonst dauerhaft gruen gemeldet, ohne etwas zu messen.

APP-SYMBOLE (Wunsch: alle Apps der Domain, jede anders, ausser
safeaddress)

Zehn Apps, zehn Stile, zehn in OKLCH gerechnete Farben. Zusammen haelt
sie dasselbe Logo, dieselbe Eckenrundung und eine gemeinsame gedeckte
Farbreihe. Beim Bauen wird gemessen, ob sich das Logo vom Grund abhebt
(19 bis 58 Helligkeitsstufen).

Dabei aufgefallen: Das Kundenportal hatte kein eigenes Manifest und
trug Namen und Symbol der Webdesign-Seite. Der Workspace hatte gar
keins und war als App nicht installierbar. Beide haben jetzt eins.

Geaendert wurde AUSSCHLIESSLICH das Symbol. Ein Zwischenstand hatte
auch die Themenfarben gesetzt; das war mehr als bestellt und wurde
zurueckgenommen.

Werkzeuge: tools/logo-freistellen.mjs, tools/app-symbole.mjs,
tools/app-symbole-einbinden.mjs -- alles im Browser gerechnet, kein
Bildprogramm, keine neue Abhaengigkeit.

Gitea und Nextcloud sind bereits live und nachgeprueft.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-05 11:42:17 +02:00
DogFatherGitandClaude Opus 5 fc26597083 Wer sich einen neuen Code gibt, sperrt sich nicht mehr selbst aus
Gemeldet: "ich hab einen neuen code fuer mich gemacht aber ich wurde raus
gekickt bevor ich den neuen code kopieren konnte jetzt komm ich nicht mehr
rein."

DER FEHLER
Ein neuer Code beendete ALLE Sitzungen der Person -- auch die, in der der
Code gerade auf dem Bildschirm stand. Der naechste Aufruf der Seite lief in
ein "nicht angemeldet", die Umleitung zur Anmeldung nahm den Kasten samt
Code mit, und der Code ist nirgends noch einmal abrufbar (in der Datenbank
steht nur seine Pruefsumme). Ergebnis: ausgesperrt, Rueckweg nur ueber
einen Eingriff auf dem Server.

Bitter daran: Die Rueckfrage sagte das sogar an ("Deine aktuelle Sitzung
wird sofort beendet") -- als Warnung formuliert, nicht als Fehler erkannt.
Ein Ablauf, den man nur mit gutem Timing ueberlebt, ist keiner.

DREI RIEGEL, NICHT EINER

1. DIE EIGENE SITZUNG BLEIBT. codeNeu() beendet weiterhin alle Sitzungen
   der Person -- ausser der einen, aus der heraus der Code gerade erneuert
   wird. Sicherheitlich kostet das nichts: Wer den Code tauscht, hat sich
   mit genau dieser Sitzung soeben ausgewiesen und haelt sie in Haenden.
   Alle ANDEREN Geraete fliegen weiterhin hinaus -- das ist der Sinn der
   Uebung und wird eigens geprueft.

2. DER KASTEN BLEIBT STEHEN. Solange ein frischer Code angezeigt wird,
   springt die Personenseite nicht mehr von selbst zur Anmeldung. Selbst
   wenn eine Sitzung aus einem anderen Grund endet (Zeitablauf, Neustart),
   bleibt der Code lesbar, bis er weggeklickt ist -- mit einem Hinweis,
   ihn jetzt abzuschreiben. Ein Code, den man nicht mehr lesen kann, ist
   schlimmer als gar keiner.

3. EINE TUER VON AUSSEN: tools/notfall-code.sh. Setzt auf dem Server einen
   neuen Code, zeigt ihn an und loescht die Sperre nach acht Fehlversuchen
   gleich mit. Weigert sich, als root zu laufen (sonst gehoerten die
   Hilfsdateien der Datenbank danach root und der Dienst koennte nicht
   mehr schreiben). Dokumentiert als "Fall 0" in WIEDERHERSTELLUNG.md --
   dem ersten Fall, den man aufschlaegt, wenn nichts kaputt ist ausser
   dem Zugang.

   KEIN fest hinterlegter Notfall-Code in der Anwendung: Der waere eine
   Hintertuer, die dauerhaft offensteht, fuer jeden der sie findet, ohne
   dass es auffiele. Dieser Weg verlangt Zugang zum Server, hinterlaesst
   einen Protokolleintrag, und es gibt nichts zu erraten.

Die Rueckfrage sagt jetzt, was wirklich passiert, statt vor etwas zu
warnen, das nicht mehr eintritt.

GEPRUEFT: server/pruef-code.mjs, 17 Pruefungen -- darunter die Gegenprobe,
dass das ZWEITE Geraet derselben Person sehr wohl abgemeldet wird (ohne sie
waere die Reparatur auf dem Weg, einen neuen Code zur Formalie zu machen),
dass der alte Code nicht mehr gilt, dass beim Erneuern eines FREMDEN Codes
weiterhin alles hinausfliegt, und dass die Seite nach dem Erzeugen nicht
zur Anmeldung springt. Das Notfall-Skript ist mit beiden Wegen getestet
(Treffer und unbekannter Name). Bestehende Laeufe gruen: Rollen 97,
Personen-Liste 33, Sicht 48.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-02 23:05:29 +02:00
DogFatherGitandClaude Opus 5 15cfee1078 Gesamtlauf aller Pruefungen -- und eine Pruefung, die nichts geprueft hat
Auf "CHECK MAL AB, DASS ALLES PERFEKT LAEUFT. ALLES."

Ergebnis: 29 von 29 Pruefdateien in Ordnung, 1178 von 1178 Einzelpunkten
bestanden. Der Server laeuft ohne Neustart, alle 33 oeffentlichen Seiten
antworten, keine Schnittstelle gibt ohne Anmeldung etwas heraus.

DER EIGENTLICHE FUND WAR EINE PRUEFUNG, DIE NICHTS GEPRUEFT HAT.

tools/alles-pruefen.mjs zaehlt nicht nur gruen/rot, sondern die ANZAHL
der Einzelpruefungen je Datei -- und pruef-kopf-messen.mjs kam auf NULL.
Sie war nie eine Pruefung, sondern ein reines Messwerkzeug: Sie druckte
Zahlen und endete IMMER mit Exitcode 0. Weil sie "pruef-..." heisst, lief
sie bei jedem Gesamtlauf mit und meldete brav "bestanden". Sie konnte
gar nicht fehlschlagen.

Mit blossem Auge war das nicht zu sehen: Der Lauf war gruen, die Datei
stand unauffaellig zwischen den anderen. Aufgefallen ist es nur, weil
die Zahl mitgezaehlt wurde -- ein gruener Lauf ist eben kein Beweis,
solange nicht auch die Anzahl stimmt.

ZWEI KONSEQUENZEN:

1. Die Datei prueft jetzt wirklich. Die beiden Zahlen, um die es geht,
   wurden laengst gemessen und werden nun auch beurteilt:
     UEBERSTAND          muss 0 sein
     ABMELDEN ERREICHBAR muss wahr sein -- es ist der einzige Weg wieder
                         heraus; liegt er ausserhalb des Bildes, sitzt
                         man fest.
   Die Messwerte bleiben in der Ausgabe: Sie sagen bei einem Fehlschlag
   sofort, WELCHES Teil zu breit ist.
   Gegenprobe gemacht: Mit einer unerfuellbaren Bedingung meldet sie
   "3 Breiten gemessen, 3 beanstandet" und endet mit 1. Sie kann also
   anschlagen -- vorher nicht.

2. Der Laeufer wertet "0 Pruefungen" ab jetzt als FEHLER, nicht als
   Erfolg. Sonst haette dieselbe Falle beim naechsten Mal wieder
   jemanden getaeuscht.

Der Laeufer selbst bleibt im Ordner tools/: Er faengt einen Fehlschlag
je Datei ab (statt beim ersten abzubrechen), zeigt die Dauer mit -- eine
Pruefung, die ploetzlich dreimal so lange braucht, wartet meist auf
etwas, das es nicht mehr gibt -- und druckt am Ende die Gesamtzahl.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-01 21:59:36 +02:00
DogFatherGitandClaude Opus 5 2bebab156b Profilbild gebaendigt, Steckbrief von der Creator-Akte getrennt
ZWEI FEHLER, DIE FILIPE GESEHEN HAT.

1. DAS PROFILBILD LAG UEBER DER HALBEN SEITE. Als Patrick sein Bild
   hochlud, zog sich ein roter Balken quer ueber die Startseite.

   Ursache: Die CSS-Regel .wer__bild hat GEFEHLT. Das Element wurde in
   kopf.js erzeugt, die Regel dazu nie geschrieben -- und ein <img> ohne
   Groessenangabe nimmt seine natuerliche Groesse an, bei einem Handyfoto
   also mehrere tausend Pixel. Dazu fehlte overflow: hidden am Traeger.

   WARUM KEINE PRUEFUNG DAS GEFUNDEN HAT: Sie lud ein 1x1-Pixel-PNG hoch.
   Klein, schnell, von Hand gebaut -- und voellig unfaehig, irgendetwas
   zu ueberdecken. Die Pruefung war gruen, der Fehler war da, und gesehen
   hat ihn der Nutzer. Sie arbeitet jetzt mit einem 1200x1200-Bild, also
   in der Groesse, die wirklich hochgeladen wird, und misst danach: Bleibt
   das Bild in seinem 28-px-Feld, ragt es irgendwo heraus, laeuft die
   Seite ueber. Gegenprobe gemacht -- ohne die Regel meldet sie
   1200x1200 in 28x28 und 918 px Ueberlauf.

2. ZWEI PERSONEN AUF EINEM BILDSCHIRM. Auf der Profilseite stand oben
   "Profil: SpongBobSchwammKopf" und mittendrin "MEIN PROFIL: Dogfather".
   Niemand konnte sagen, welche Angabe zu wem gehoert.

   Es sind auch wirklich zwei verschiedene Dinge:
     MEIN STECKBRIEF  gehoert MIR -- Bild, ein Satz ueber mich, meine
                      Kanaele. Fuehre ich selbst.
     CREATOR-PROFILE  die BETREUUNGSAKTE eines anderen Menschen --
                      Ziele, 90-Tage-Plan, interne Notizen. Fuehren die
                      Betreuer.

   Scouts, Manager und DogFather haben jetzt zwei getrennte Kacheln und
   eine eigene Seite (steckbrief.html, serverseitig geschuetzt). Ein
   Creator behaelt beides zusammen -- er hat nur eine Seite und sieht
   dort ausschliesslich sich selbst. Die Logik liegt in einer eigenen
   Datei statt hinten an profil.js: Sie gehoert der angemeldeten Person,
   nicht der Akte.

ACHTZEHN KACHELN, ACHTZEHN FARBEN. Die neue Kachel haette sich ihren
Farbton mit den Creator-Profilen geteilt -- zwei Nachbarn in derselben
Farbe. Statt eine Farbe dazuzuerfinden, wurde tools/kachel-farben.mjs
fuer 18 Winkel neu gerechnet, samt der neuen Nachbarschaft im Raster.
Der kleinste Abstand zweier Nachbarn liegt weiterhin bei 100 Grad.
Gefunden hat das die Startseitenpruefung ("17 Farben auf 18 Kacheln").

Die Trennung wird jetzt fuer JEDE Rolle geprueft: welche Kacheln sie
sieht, dass auf der Akte kein fremder Steckbrief steht, und dass die
eigene Seite die richtige Person zeigt. Eine alte Pruefung, die das
Gegenteil verlangte, wurde ersetzt statt stehen gelassen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-01 15:04:23 +02:00
DogFatherGitandClaude Opus 5 766c75b51d Die Buehnen richtig: nicht mehr beschnitten, hell, mit Lesespur
Drei handfeste Fehler, alle im Screenshot zu sehen gewesen.

1. ABGESCHNITTEN. background-size stand auf "138% auto". Auf einem
   2540 px breiten Schirm wurde das Bild damit 3500 px breit und knapp
   2000 px hoch -- in einem 1300 px hohen Fenster fehlten 700 px, und
   zwar oben. Genau deshalb waren die Figuren riesig und ihre Koepfe
   weg. Jetzt cover mit Verankerung auf 50% 42%: Die Flaeche wird immer
   gefuellt, so wenig wie noetig skaliert, und wenn etwas beschnitten
   werden muss, dann Fussboden und Decke -- nicht die Gesichter.

2. DIE VIGNETTE LAG FALSCH HERUM. Abgedunkelt wurde die MITTE, also
   genau der Teil, in dem die Szene steht. Man sah die Raender des
   Bildes und in der Mitte einen grauen Fleck. Jetzt laufen die RAENDER
   ins Dunkle und die Mitte bleibt klar -- so wie in der Fotografie.

3. ZWEI SCHICHTEN DUNKELHEIT. Zusaetzlich zur Vignette legte der
   Schleier .86/.58/.44 Schwarz ueber dasselbe Bild. Jetzt nur noch
   oben (Kopfleiste) und unten (Seitenende) ein Streifen.

Dazu die Bilder selbst: Helligkeit 0.66 -> 0.88, mehr Kontrast und
Farbe. Sie sind ein BILD, kein Nebel.

DIE LESESPUR ist der eigentliche Kniff. In allen neun Szenen stehen
HasiDog und DogFather AUSSEN, die Mitte ist frei -- danach wurden sie
ausgesucht. Diese Aufteilung wird jetzt benutzt statt bekaempft: aussen
bleibt das Bild hell und scharf, in der Mitte (wo der Text steht) wird
gedaempft. Der klare Rand ist in jedem Fenster mindestens 400 px breit.
Auf dem Handy gibt es daneben keinen Platz, dort deckt die Spur alles.

Was frei stand und keine Karte hatte, bekommt eine Lesezone mit
backdrop-filter: Der Hintergrund bleibt in Farbe und Form sichtbar,
wird an dieser Stelle aber weichgezeichnet. Die billige Loesung waere
gewesen, das Bild wieder abzudunkeln -- damit waere man dort, wo man
angefangen hat.

ZWEITER FUND AN DER EIGENEN KONTRASTMESSUNG. Sie tastete
ausschliesslich NEBEN dem Element ab. Traegt ein Text seine Flaeche
aber selbst (eine Beschriftung mit Hintergrund und Polsterung), liegt
jeder Punkt daneben schon auf dem Bild -- gemeldet wurden 1,89:1,
obwohl der Text auf deckender Flaeche steht und tadellos lesbar ist.
Jetzt wird zuerst in der eigenen Polsterung gemessen, also auf dem,
worauf der Text WIRKLICH liegt. (Der erste Fund an derselben Stelle war
gestern: Sie mass Text gegen Nachbartext.)

Nach dem Aufhellen einmal komplett durchgemessen: von sieben roten
Stellen auf null. Schlechtester Wert jetzt 4,70:1 bei 4,5:1 Norm.

Die Bilder sind groesser geworden (580 KB -> 1,8 MB fuer alle achtzehn),
weil weniger Dunkelheit weniger komprimierbar ist. Geladen wird pro
Seite genau eine: 42 bis 132 KB.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-01 11:43:08 +02:00
DogFatherGitandClaude Opus 5 fc4fde0f02 Buehnen hell, Flaechen dicht - und die Kopfleiste wieder kurz
DIE BUEHNEN WAREN ZU DUNKEL. Bei 0.42 Helligkeit sah man Schemen, nicht
die Szene -- "zu dunkel und sieht ganz komisch aus" traf es genau. Jetzt
0.66 mit etwas mehr Farbe (1.08), die Vignette schwaecher (0.52 statt
0.72). Die Bilder kommen durch.

MOEGLICH IST DAS NUR MIT DEM GEGENZUG: Alle Kacheln, Karten und Spalten
lagen bei 2 bis 3 Prozent WEISS -- also praktisch durchsichtig. Solange
der Hintergrund fast schwarz war, fiel das nicht auf; sobald er hell
wurde, lief das Bild mitten durch den Text. Jetzt gibt es --flaeche
(rgba(9,13,22,.78)), eine deckende dunkle Flaeche, und 44 Stellen in 16
Dateien holen sich ihre Farbe von dort.

Der Unterschied ist genau der, den Filipe beschrieben hat: Der
Hintergrund bleibt sichtbar, aber ZWISCHEN den Kacheln -- nicht hinter
der Schrift. Wer die Flaechen kuenftig dichter oder durchlaessiger will,
aendert eine einzige Zeile statt 44.

Die Kacheln selbst tragen ihren Farbton jetzt AUF der Flaeche
(color-mix mit --flaeche statt mit transparent) -- dadurch bleibt die
Farbe erkennbar, ohne dass die Kachel durchsichtig wird.

DIE KOPFLEISTE war so breit wie das ganze Fenster, obwohl der Text kurz
ist: .marke__text stand auf flex: 1 1 auto. Das war unsichtbar, solange
der Schriftzug nur Text war -- seit er einen Rahmen traegt, lief die
Pille quer durchs Bild. Jetzt flex: 0 1 auto (schrumpfen ja, wachsen
nein). Gemessen: 375 px statt 1280.

Kontrast an echten Bildpunkten auf allen sechs Seiten nachgemessen --
haelt trotz des viel helleren Bildes (schlechtester Wert 4,69:1).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-01 11:20:02 +02:00
DogFatherGitandClaude Opus 5 0391a91d14 Neun Buehnen statt einer - jede Seite hat ihre eigene Szene
Filipe hat neun Bilder geschickt, damit es VERSCHIEDENE Hintergruende
gibt. Benutzt wurde davon genau eines (das Studio), die uebrigen acht
lagen unbenutzt im Ordner -- lounge.png und skyline.png sogar schon
fertig kopiert. Zu Recht beanstandet.

Jetzt wird aus jeder Szene eine Buehne, breit und schmal, und jede Seite
bekommt die, die zu ihr passt:

  studio      Startseite            der neutrale Ort, alles beginnt hier
  showbuehne  Dashboard, Review     die grosse Buehne, alles im Blick
  garage      Aufgaben, Technik     Werkstatt, hier wird gearbeitet
  skyline     Kalender              Nacht ueber der Stadt, Zeit
  lounge      Calls, Community      Sitzecke, hier wird geredet
  arena       Dateien, Wissen       Archiv hinter dem Portal
  halle       Profil, Personen      die Halle, in der jemand steht
  wald        Start-Check, Scouting der Weg, den man erst sucht
  portal      Content, LIVE         Durchgang, hier entsteht etwas

Die Zuordnung steht in bereiche.js -- derselben Liste, aus der schon
Zeichen und Farbton kommen. Eine Seite traegt damit dreierlei aus einer
einzigen Quelle: Farbe, Zeichen und Buehne. Sie koennen nicht
auseinanderlaufen.

Alle neun bekommen dieselbe Behandlung (abgedunkelt auf 0.42, Vignette
in der Mitte, wo der Text steht, oben ausgeblendet, wo die Kopfleiste
sitzt). Sie sehen verschieden aus und verhalten sich gleich -- eine
Buehne, die je Seite anders hell waere, waere Unruhe statt Vielfalt.
Der schmale Ausschnitt ist je Szene ein anderer, weil ein auf 9:16
gequetschtes Breitbild nur noch Wand zeigt; genommen wird der Bereich,
in dem die Figuren stehen.

18 Dateien, zusammen 580 KB -- pro Seite werden davon zwei geladen
(breit ODER schmal), also 16 bis 48 KB. Die Rohbilder waren 2,4 MB je
Stueck.

Kontrast auf allen sechs geprueften Seiten an echten Bildpunkten
nachgemessen: haelt (schlechtester Wert 4,59:1).

FUND: Die Buehnenpruefung suchte nach "buehne-breit" und fand die neuen
Namen nicht mehr -- sie meldete "die Buehne liegt im Hintergrund: FEHL",
obwohl sie da war.

Die Seitenpruefung sieht jetzt nach, dass jede Seite ihre Szene hat UND
dass das Bild wirklich ankommt: Ein data-buehne ohne passende CSS-Regel
waere still wirkungslos.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-01 10:36:16 +02:00
DogFatherGitandClaude Opus 5 e74254263f Buehne aus den echten Marken-Bildern, Kopfleiste und Begruessung neu
Filipe hatte recht, und zwar zweifach: Der Husky war der FALSCHE (ein
fremder Neon-Husky aus dem alten Bilderordner statt DogFather), und zwei
in die Ecken geklebte Bilder ergeben noch kein Bild.

DIE BUEHNE, zweiter Anlauf. Aus den zehn geschickten Bildern das Studio
gewaehlt, in dem HasiDog und DogFather stehen -- nicht aus Geschmack,
sondern wegen der ANORDNUNG: Die beiden stehen weit aussen, die Mitte ist
dunkel. Genau dort steht der Inhalt. Bei den Bildern mit den Figuren in
der Mitte waeren sie hinter dem Text gelandet.

Ueber die ganze Flaeche, fest an der Scheibe, 138 % breit: Bei 100 %
staenden die beiden bei 20 % und 78 % der Breite -- mitten unter der
Textspalte. Vergroessert man das Bild ueber die Scheibe hinaus, wandern
sie nach aussen (rund 9 % und 88 %) und der leere Hallenboden liegt dort,
wo gelesen wird. Ein Bild groesser zu machen, damit WENIGER davon im Weg
ist, klingt verkehrt und ist genau richtig.

Fuer schmale Schirme ein eigener Hochkant-Ausschnitt derselben Szene --
ein auf 9:16 gequetschtes Breitbild zeigt nur noch Wand.
1,9 MB PNG -> 28 KB WebP.

DIE VIER STELLEN aus den Bildschirmfotos:

* Kopfleiste: der DogFather-Kopf davor. Als MASKE aus dem Logo gerechnet
  (Dunkelheit wird Deckkraft), nicht als Bild -- so laesst er sich im
  Stil einfaerben; ein fertig eingefaerbtes Bild muesste man fuer jede
  Farbe neu bauen. 114 KB -> 3 KB.

* "Dogfather · DogFather" war der peinlichste Punkt: Name und Rolle lasen
  sich gleich, es sah nach einem Fehler aus. Jetzt drei unterscheidbare
  Dinge -- Zeichen mit dem Anfangsbuchstaben, Name, Rolle als Marke in
  ihrer Farbe. Gebaut in kopf.js, EINMAL statt vierzehnmal: Jede
  Seitendatei setzte diese Zeile bisher selbst zusammen.

* Begruessung: leuchtender Strich, groesserer Gruss, auslaufende
  Trennlinie. Dieselben Striche vor "WAS IST DRAN" und "DEINE AUFGABEN" --
  so gehoert sichtbar zusammen, was zusammengehoert.

ZWEI EIGENE FEHLER, die die Pruefungen gefunden haben:

1. Ich hatte Verlaeufe IM TEXT gebaut (background-clip mit durchsichtiger
   Schrift). Sah gut aus, und der Kontrasttest meldete 1,05:1 -- zu Recht.
   Durchsichtige Schrift haengt an einer einzigen Technik; faellt sie aus
   (Kontrastmodus, Druck, aeltere Browser), ist der Text UNSICHTBAR statt
   nur anders gefaerbt. Das ist kein Schoenheitsfehler, das ist ein
   Ausfall. Jetzt feste Farbe mit einem Hauch Leuchten.

2. Auf dem Handy stand der Abmelden-Knopf 9 px aus dem Bild. Die Suche
   nach der Ursache ging zuerst in die Irre -- der Test nannte das
   Wasserzeichen, das aber von seiner Kachel sauber abgeschnitten wird
   und nur seine Masse meldet. Gemessen war es die Marke: 209 px + 139 px
   rechte Gruppe passten nicht in 390 px. Auf dem Handy bleibt jetzt nur
   der Kopf stehen; der Markenzug steht zwei Zeilen tiefer ohnehin als
   Ueberschrift. Fuer Vorleseprogramme bleibt er im Dokument.

Und einmal habe ich mir beim Ersetzen eines CSS-Blocks das halbe
Stylesheet geloescht (die Kachel-Regeln lagen zwischen den beiden
Suchmarken). Aufgefallen sofort am Bildschirmfoto, zurueckgeholt aus Git,
danach zeilengenau ersetzt.

118 Pruefungen, alle gruen. Der Kontrast wird weiterhin an echten
Bildpunkten gemessen, jetzt an bis zu 35 Stellen je Seite.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-01 05:45:59 +02:00
DogFatherGitandClaude Opus 5 fcebbd18bb Workspace: Casper und HasiDog als Buehne im Hintergrund
Filipe: "der hintergrund soll genau so krass und speziell sein, benutz
den hasen und husky."

Gefunden in assets/img: hero-husky.png (Casper, neonblau auf dunkel --
farblich genau die Oberflaeche) und char-hasidog.jpg (HasiDog). Der
Sticker "HasiDog & Casper" hat bestaetigt, dass die beiden zusammen
gehoeren.

Beide sitzen FEST an der Scheibe in den unteren Ecken -- sie scrollen
nicht mit, sondern stehen da wie ein Buehnenbild, vor dem gearbeitet
wird. Die Mitte bleibt frei, dort steht der Inhalt. HasiDog ist weiter
nach aussen geschoben und schwaecher als Casper: Er ist heller, sein
Gesicht zieht den Blick staerker, und direkt neben einer Kachel wuerde
man ihn ansehen statt der Kachel.

AUFBEREITET STATT EINGEBUNDEN (tools/buehne-bauen.mjs):
  * stark abgedunkelt und leicht entsaettigt -- Stimmung, kein Motiv
  * weiche Raender ins Bild EINGERECHNET. Ein hartes Rechteck saehe nach
    aufgeklebtem Foto aus; und eine Maske ueber ein 900-Pixel-Bild kostet
    bei jedem Bildaufbau Rechenzeit.
  * 290 KB PNG -> 41 KB WebP, 110 KB -> 32 KB
Gerechnet mit dem Browser, der ohnehin fuer die Pruefungen da ist -- kein
Bildprogramm, keine neue Abhaengigkeit, 0 EUR.

GEPRUEFT WIRD NICHT, OB ES HUEBSCH IST, sondern ob der Text noch lesbar
ist -- an echten BILDPUNKTEN aus dem fertigen Bildschirmfoto, nicht an
der Farbangabe im Stil. Die weiss naemlich nichts davon, was
dahinterliegt. Gemessen wird der Untergrund direkt NEBEN jedem sichtbaren
Text, auf fuenf Seiten, auf Computer und Handy: bis zu 34 Stellen je
Seite gegen den WCAG-Massstab (4,5:1, bei grosser Schrift 3:1).

UND DAS HAT SOFORT EINEN ALTEN FEHLER GEFUNDEN: Der leiseste Grauton
(--text-still) lag bei 4,43:1 -- knapp UNTER der Norm. Das war schon
lange so, nur hatte es nie jemand nachgerechnet, weil bisher niemand an
echten Bildpunkten gemessen hat. Von #6d7d92 auf #75859a angehoben; jetzt
4,95:1 auf dem hellsten Untergrund. Das gilt fuer JEDE Seite, nicht nur
fuer die mit dem Hintergrundbild.

Schlechtester Wert jetzt: 4,97:1. Alle 30 Messungen bestanden.

Nebenbei eine Falle in den Pruefungen selbst: Ein haengengebliebener
Testserver auf demselben Port fing die Anfragen ab -- der Test sprach mit
einem ALTEN Prozess und dessen anderer Datenbank, und meldete "no such
table". Der Port ist jetzt ein anderer; die Lehre steht hier, weil das
Bild "Server laeuft" trotzdem erscheint und alles richtig aussieht.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-01 00:10:09 +02:00
DogFatherGitandClaude Opus 5 7673c12136 Startseite: 17 eigene Farben -- gerechnet, nicht gewaehlt
Filipe: "jede kiste soll seine eigene farbe haben. und die kacheln sollen
viel spezieller, viel spezieller sein."

BEIM ERSTEN MAL HATTE ICH ABGELEHNT, und das war zu bequem. Mein Einwand
stimmte zwar -- ein Versuch mit frei gewaehlten Farben ergab Paare mit
1,4 Grad Abstand, also praktisch dieselbe Farbe -- aber daraus "geht
nicht" zu machen, war falsch. Es geht, man muss nur rechnen.

Der Denkfehler war die Annahme, alle 17 muessten sich voneinander
unterscheiden. Das Auge vergleicht aber nur, was NEBENEINANDER liegt.
Also:

1. 17 Toene, gleichmaessig um den Farbkreis (je 21 Grad), gerechnet in
   OKLCH -- dort sind gleiche Abstaende auch fuer das Auge gleich.
   Helligkeit und Farbstaerke konstant, damit keine sich vordraengt. Wo
   die Farbstaerke den darstellbaren Bereich verliesse (Gelb und Gruen
   frueher als der Rest), wird sie gesenkt, bis sie hineinpasst.

2. Die ZUORDNUNG ist eine Suche ueber die tatsaechlichen Nachbarschaften
   im Raster (nebeneinander UND untereinander). Gesucht: die Anordnung
   mit dem groesstmoeglichen kleinsten Nachbarabstand. Ergebnis:
   mindestens 105,9 Grad zwischen allen Nachbarn.

3. Unter allen Anordnungen, die eine harte Untergrenze schaffen, gewinnt
   die passendste: LIVE rot, Technik gelb, Reports gruen, Personen
   rot-gold, Schutz stahlblau.

Steht als tools/kachel-farben.mjs im Repo, mit festem Zufallsstartwert --
derselbe Lauf ergibt dieselben Farben. Wer Kacheln umsortiert, aendert
die Nachbarschaften und muss es neu laufen lassen; das steht auch in
start.js.

Geprueft: Helligkeitsband, Farbstaerke und Kontrast bestehen fuer alle
siebzehn gegen genau diesen Hintergrund.

VIEL SPEZIELLER -- das WASSERZEICHEN:

Jede Kachel traegt ihr eigenes Zeichen noch einmal, riesig, angeschnitten
und fast unsichtbar (7 % Deckung) in der Ecke. Das ist der Grund, warum
siebzehn Kacheln nicht mehr wie siebzehn Kaesten aussehen: Jede bekommt
eine eigene grosse Form, ohne dass ein einziges zusaetzliches Bild
geladen wird -- es ist derselbe Pfad, nur groesser. Bewusst so schwach,
dass man es nicht liest, sondern nur spuert. Beim Ueberfahren wird es
etwas deutlicher und wandert zwei Pixel.

Dazu: Zeichenfeld 46 auf 52 px mit farbigem Schein darunter, Name auf
1,06 rem, mehr Polsterung. Alles mit prefers-reduced-motion abgesichert.

44 Pruefungen. Neu: dass jede Kachel eine EIGENE Farbe hat (17 Farben auf
17 Kacheln, gemessen an der berechneten Strichfarbe) und dass das
Wasserzeichen da und schwach genug ist.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-31 23:32:22 +02:00
DogFatherGitandClaude Opus 5 17c605b93d Sicherung: laeuft von allein, und ein stiller Ausfall faellt auf
Filipe zu Recht: "wieso soll ich diesen Befehl einmal die Woche eingeben,
ich will einmal und dass es dann alleine laeuft". Ein Befehl, den man
selbst eintippen muss, wird irgendwann vergessen -- und zwar genau dann,
wenn er zaehlt.

tools/sicherung-einrichten.ps1 legt eine Windows-Aufgabe an: taeglich
statt woechentlich (der Lauf dauert Sekunden, bei woechentlich waere die
Kopie im schlimmsten Fall sechs Tage alt), 13:30 statt nachts (der
Rechner laeuft nicht durch), und mit StartWhenAvailable -- war der
Rechner aus, holt Windows den Lauf beim naechsten Hochfahren nach. Ohne
diesen Schalter fiele jeder verpasste Termin ersatzlos aus. Braucht keine
Administratorrechte und macht am Ende gleich einen Probelauf: eine
Einrichtung, die man nicht ausprobiert, ist eine Vermutung.

Damit entsteht aber ein neues, schlimmeres Problem: Wenn die Aufgabe
still klemmt oder der Rechner wochenlang aus ist, merkt es NIEMAND. Man
glaubt, man haette eine Kopie ausser Haus, und hat sie nicht. Deshalb
meldet sich das Abholskript nach jedem Lauf beim Server zurueck, und die
Automationen-Seite zeigt, wie alt die Kopie ist -- nach zehn Tagen wird
sie auffaellig.

Die Rueckmeldung laeuft ueber einen eigenen langen Schluessel, nicht ueber
einen Zugangscode: Das Skript laeuft unbeaufsichtigt und muesste einen
Code sonst dauerhaft auf der Platte halten. Der Schluessel kann NUR einen
Zeitstempel setzen -- nichts lesen, nichts aendern. Verglichen wird
zeitunabhaengig.

Dabei eine unauffaellige Falle gefunden: In workspace-aufgaben.js steht
`aufgabenRouter.use("/workspace/api", angemeldet)` -- eine Schranke ueber
JEDEN Pfad unter /workspace/api, nicht nur die eigenen. Alle spaeter
eingehaengten Module leben stillschweigend davon. Die Rueckmeldung wurde
dort mit 401 abgewiesen, bevor ihr Schluessel ueberhaupt geprueft wurde;
der richtige Schluessel sah dadurch aus wie ein Fehler in der Pruefung.
Das Sicherungsmodul haengt jetzt VOR dem Aufgabenmodul und bringt seine
eigene Schranke mit -- damit haengt es an keinem anderen Modul mehr.

Ausserdem: Die Ueberschrift im Kasten nennt jetzt den GRUND, aus dem er
gelb ist. Vorher stand dort "Zuletzt gesichert vor 2 Minuten", waehrend
die Farbe wegen der fehlenden Kopie warnte -- die Anzeige widersprach
sich selbst und man sucht den Fehler an der falschen Stelle.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-31 18:34:46 +02:00
DogFatherGitandClaude Opus 5 3f18e1bd69 Sicherung: Kopie auf den PC, Dateien mit dabei, Wiederherstellungs-Anleitung
Eine Sicherung, die auf derselben Platte liegt wie das Original, ist keine
-- sie hilft gegen versehentliches Loeschen, nicht gegen einen
Plattenausfall. tools/sicherung-holen.sh holt sie deshalb auf den
Arbeitsrechner.

Dabei ist gleich eine zweite Luecke aufgefallen und mitgeschlossen: Die
Datenbank kennt hochgeladene Dateien und die PDFs der Bibliothek nur ueber
ihren Namen -- die Dateien selbst liegen daneben im Dateisystem und
stecken NICHT in der Datenbanksicherung. Nach einem Plattenausfall haette
man eine Bibliothek voller Verweise auf PDFs, die es nicht mehr gibt.
Werden jetzt mitgeholt.

Bewusst nur auf dem PC und nicht zusaetzlich auf dem Server: Eine zweite
Kopie auf derselben Platte haette gegen nichts geholfen, was die erste
nicht schon ueberlebt haette. Und weil scp nie loescht, bleibt ein einmal
geholtes PDF hier erhalten, auch wenn es auf dem Server verschwindet.

Geprueft wird mit Node statt mit dem sqlite3-Programm: Node bringt SQLite
selbst mit, auf diesem Windows-Rechner ist sqlite3 gar nicht da -- die
erste Fassung gab nur Fragezeichen aus und meldete trotzdem "fertig".

WIEDERHERSTELLUNG.md beschreibt drei Faelle (aus Versehen geloescht /
Datenbank zurueckspielen / Server ganz weg), jeweils als EIN Block zum
Kopieren. Der Ruecklauf legt den kaputten Stand mit mv zur Seite statt
ihn zu loeschen -- falls die Sicherung aelter war als gedacht.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-31 18:24:32 +02:00
DogFatherGitandClaude Opus 5 c0ac041122 Workspace: Versionsstempel gegen Cloudflares 4-Stunden-Cache
Filipe sah die neue Kachel nicht, obwohl sie live war. Ursache gemessen,
nicht vermutet:

  Node liefert   : Cache-Control: no-cache        (richtig)
  Cloudflare macht: Cache-Control: max-age=14400  (ueberschreibt es)
  cf-cache-status: REVALIDATED, Server: cloudflare

Cloudflares voreingestellte Browser-Cache-Zeit von vier Stunden setzt
sich ueber das no-cache des Servers hinweg -- aber NUR bei JS und CSS.
HTML kommt mit DYNAMIC und no-cache immer frisch durch (geprueft an
/creator.html und /workspace/).

Genau deshalb genuegt ein Stempel in der HTML: neue Seite -> neue
Adresse -> Cloudflare kennt sie nicht -> frische Datei. Keine
Cloudflare-Einstellung noetig, nichts, worauf ich warten muss.

tools/workspace-stempel.mjs setzt den Stempel auf alle 71 Verweise in
13 Dateien. Der Lauf ist wiederholbar: ein vorhandener Stempel wird
ersetzt, nicht angehaengt (geprueft).

Gehoert ab jetzt vor jeden Deploy, der JS oder CSS im Workspace anfasst.
Ich verlasse mich damit nicht mehr aufs Erinnern -- das war der
eigentliche Fehler.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-28 13:03:33 +02:00