bd42a0462e1fd0df8a05c804d61536e8595a42a9
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d7cf598b00 |
"Heute" war zwei Stunden lang gestern -- und vier Fehler auf Handy und PC
Auftrag: "einen grossen Check machen, ob alles klappt, auf dem Handy und
PC." Dafuer ein neuer Rundgang (pruef-grosscheck.mjs), der stumpf ueber
alles geht: 19 Workspace-Seiten mal 4 Rollen mal 2 Bildschirmgroessen
plus 33 oeffentliche Seiten, zweimal. 208 Seiten, 50 774 Elemente.
Solche Rundgaenge finden andere Fehler als gezielte Pruefungen: nicht
den falsch gerechneten Wert, sondern die Seite, die bei genau einer
Rolle ueberlaeuft.
=== DER WICHTIGSTE FUND: "heute" war in UTC gerechnet ===
Der Check lief um 01:10 Uhr. Ortszeit war der 2. September, in UTC noch
der 1. -- und in diesem Fenster rechnete die Anwendung an ZWOELF Stellen
"heute" als toISOString(), also in UTC. Server und Benutzer stehen beide
auf Europe/Berlin.
Was das im Alltag bedeutete, jede Nacht zwischen 0 und 2 Uhr:
* eine heute faellige Aufgabe galt noch nicht als faellig
* eine um Mitternacht ueberfaellig gewordene erschien erst um 2 Uhr
* der Filter "Heute faellig" zeigte den Vortag
* Datumsfelder schlugen gestern vor
* der Kalender begann seine Vorgabe einen Tag zu frueh
Also genau dann, wenn nach einem Stream gearbeitet wird.
kalender.js machte es die ganze Zeit RICHTIG -- samt Begruendung, warum
die ARITHMETIK trotzdem in UTC laufen muss (UTC-Mittag ueberlebt die
Zeitumstellung; wer lokal rechnet, verliert am 27. Oktober einen Tag).
Diese Trennung gilt jetzt ueberall, aus je einer Quelle:
RECHNEN mit Datumsangaben -> UTC-Mittag, unveraendert
WELCHER TAG IST HEUTE -> Ortszeit (heuteLokal/tagLokal im Server,
window.heuteLokal in kopf.js)
WIE ES AUFFIEL, und das ist die eigentliche Lehre: Zuerst schlugen zwei
Pruefungen fehl -- und die Ursache lag in IHNEN, sie rechneten selbst in
UTC (36 Stellen in 17 Dateien). Nach deren Reparatur schlugen sie WIEDER
fehl, und erst da zeigten sie auf die Anwendung. Wer beim ersten Mal
aufgehoert haette ("ist ja nur die Pruefung"), haette den echten Fehler
nie gesehen.
Nachtrag desselben Musters: pruef-uebersicht legte den Termin weiterhin
in UTC an, waehrend die Erwartung schon auf Ortszeit stand. Wer eine
Datumsrechnung umstellt, muss BEIDE Seiten umstellen -- die, die
schreibt, und die, die prueft.
=== VIER FEHLER AUF HANDY UND PC ===
1. Ein langer Creator-Name ("SpongBobSchwammKopf") schob die Startseite
auf dem Handy um 48 Pixel aus dem Bild -- ein Wort ohne Trennstelle,
und die Seite liess sich seitlich wegschieben. Trifft echte Namen:
Creator heissen selten "Tim".
2. Die klebende Speicherleiste verdeckte auf dem Handy ein Textfeld.
Beim Tippen sieht man die eigene Zeile nicht. Behoben mit
scroll-margin-bottom (WCAG 2.2, 2.4.11 "Focus Not Obscured").
3./4. Zwei Beschriftungen waren mit 9,6 px (Uebersicht: "ueberfaellig",
"dringend", "offen") und 9,9 px (Kalender: "heute") zu klein. Fuers
Handy gab es laengst eine Ausnahme -- nur der Rechner war vergessen
worden. Ausgerechnet die Woerter, die den Zahlen ihre Bedeutung geben.
=== WAS KEINE FEHLER WAREN ===
Der erste Durchgang meldete 19 Maengel, die keine waren. Alle einzeln im
Quelltext nachgeprueft und dem Rundgang beigebracht:
* Kacheln und Kopfzeilen "abgeschnitten" -- das Wasserzeichen ragt
ABSICHTLICH ueber den Rand (steht so im Quelltext)
* "verdeckt: wahl2__echt" -- das echte <select> liegt absichtlich
unsichtbar unter seinem Knopf
* "zurueck-knopf__text abgeschnitten" -- das uebliche Muster fuer
"nur fuer Vorleseprogramme"
* drei "zu kleine" Verweise -- WCAG 2.5.8 nimmt Verweise im Fliesstext
AUSDRUECKLICH aus. Eine Pruefung, die ihre eigene Messlatte nicht
kennt, misst nichts.
Beim vierten Punkt haette ich fast an der falschen Stelle repariert.
Und statt die Sticky-Meldung abzuschalten (dann faende sie auch echte
Ueberdeckungen nie mehr), wurde sie GENAUER: Ueberdeckt etwas Klebendes
ein Eingabefeld, ist das nur in Ordnung, wenn das Feld genug
scroll-margin-bottom hat, um darunter hervorzukommen. Aus einer vagen
Meldung wird eine pruefbare Zusage.
Vier Gegenproben belegen, dass der Rundgang ueberhaupt etwas finden
kann: ein zu breites Element, ein winziger Knopf, ein winziger Verweis
AUSSERHALB eines Satzes und ein wirklich abgeschnittenes Wort werden
alle gemeldet. Ohne diesen Nachweis waere "alles in Ordnung" wertlos.
Co-Authored-By: Claude Opus 5 <[email protected]>
|
||
|
|
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]>
|
||
|
|
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]> |
||
|
|
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. |
||
|
|
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. |
||
|
|
ef79659f8f |
Workspace: Kalender mit Terminen, Calls und Aufgaben-Fristen
/workspace/kalender.html -- letzter grosser Baustein aus Phase 1.
Zeigt zwei Quellen in EINER Ansicht, wie im Konzept gefordert
("Kalender & Calls" neben "Deadlines" und "Wiedervorlagen"):
* eigene Termine (Arten: Call, Termin, Review)
* Fristen offener Aufgaben, nur lesend eingeblendet
Nach Tagen gruppiert statt als Monatsraster: Es geht um wenige, dafuer
konkrete Termine. Eine Liste liest sich dabei besser und funktioniert auf
dem Handy ohne Umbau. Zeitraum umschaltbar: 14 / 30 / 90 Tage, wobei 90
den 90-Tage-Plan aus dem Konzept abdeckt.
Sichtbarkeit wie bei den Aufgaben, wieder an einer Stelle definiert.
Geprueft mit drei Konten:
Chef 2 Termine + 2 Fristen | Luna 2 + 1 | Sam 0 + 1
Die Fristen folgen dabei exakt der Aufgaben-Regel -- Sam sieht nur seine.
Loeschen darf das Management und wer den Termin selbst angelegt hat.
Sonst koennte ein Creator einen Call absagen, den das Management
angesetzt hat. Geprueft: Luna auf Chefs Call 403, auf ihren eigenen 200,
Sam sieht ihn gar nicht (404).
Weiteres:
- Ort/Link wird nur dann als Verweis dargestellt, wenn er wirklich mit
http(s) beginnt -- sonst liesse sich javascript: einschleusen
- Zeitpunkt und Dauer werden geprueft (kaputtes Datum 400,
5000 Minuten 400)
- Beginn steht als lokale Zeit ohne Zeitzone: Alle Beteiligten sitzen in
derselben, eine falsch umgerechnete Uhrzeit waere schlimmer als gar
keine Umrechnung
|