Der Zweig vom Vormittag war zu eng: user liegt in drei Auspraegungen vor (objectId 7.130 / array 826 / fehlend 418), und 102 der Listen sind leer. {user:null} trifft eine leere Liste nicht (418 statt 520) — die 102 waren nach dem ersten Rollout fuer NIEMANDEN mehr sichtbar. Kategorien wie bei den unadressierten, also Broadcasts.
$in statt $size:0 — dieselben 520 Treffer, aber indizierbar.
An der Sammlung gemessen liegt `user` in drei Auspraegungen vor: objectId 7.130, array 826, fehlend 418. Von den Listen sind 102 LEER — und {user:null} trifft eine leere Liste NICHT ({user:null}=418, {$in:[null,[]]}=520). Diese 102 tragen dieselben Kategorien wie die unadressierten und waren vor dem Schnitt fuer jeden sichtbar; mit dem engeren Zweig waeren sie fuer NIEMANDEN mehr sichtbar gewesen.
$in statt $size:0 — dieselben 520 Treffer, aber indizierbar.
unreadNotifications + page.notifications lasen {_customerID, markread:false} — der Verteiler legt aber EIN Dokument JE EMPFAENGER an, die Glocke zeigte also die ungelesene Post der Kollegen. Neu: eigene ODER unadressierte, nie fremde.
Zweite Haelfte und ohne sie waere die erste wirkungslos: der Zwischenspeicher- Schluessel traegt jetzt userId statt customerId — sonst fuellt der erste Nutzer den Eintrag und jeder weitere bekommt 30 s lang dessen Post, ohne Fehler.
Empfaenger-Schnitt auch auf den zwei Mengen-Schreibwegen (PUT /many, updateMode many)
changeMany/updateMany bauen ihren Filter intern aus {_id} und nehmen keine zusaetzliche Bedingung entgegen — der Schnitt liegt deshalb auf einer Vorab-Lesung (filterIdsToRecipient). Fremde Kennungen fallen still heraus; trifft die Verengung nichts, wird kein leerer bulkWrite gefahren (waere ein 500).
Rest-Schnitt zum P1 notifications-nutzer-scope (2026-08-23).
Drei CEO-Befunde der Runde vom 2026-08-22, zwei davon aus EINER Ursache.
1) Stumm-Knoepfe antworteten „until fehlt" und haben nie eine Stummschaltung angelegt. GEMESSEN sass der Fehler auf der CLIENT-Seite: der bibliothekseigene Anbieter schickte eine DAUER (`minutes`), der Vermittler verlangt einen ZEITPUNKT (`until`, buildSnoozeDoc in @tolinax/ayoune-core). Die einzige andere Bindung (clients/desktop-client) rechnet seit jeher korrekt um -- ein „Fix" am Vermittler haette sie mitgerissen und eine zweite Drift erzeugt.
2) Weisser Grund im Dunkeln UND Fremd-Rahmen im Hellen sind EIN Fehler: dem Akustik-Fenster (seit 2026-08-21) fehlte sein [popover]-Ruecksetz-Block, also schlug das Browser-Blatt durch (`background-color: Canvas`, `border: solid`). Der Block existierte fuer die fuenf aelteren Top-Layer-Flaechen.
3) Quittieren war rot und teilte sich die Zeile mit den drei Stumm-Knoepfen. Jetzt eigene Zeile, volle Breite, 60px hoch, Farbe aus --brand-primary. Der rote Rahmen der Karte BLEIBT -- er zeichnet den Alarm, nicht die Handlung.
Karte, Innentexte und Stumm-Knoepfe ziehen gegen --brand-background/--brand-text (bisherige Werte als Rueckfall), damit ein heller Mandanten-Anstrich traegt.
Proben: 8 zum Rumpf-Vertrag + 10 zum Top-Layer (als REGEL ueber alle Flaechen aus dem Bauplan, nicht als Einzelfall), je mit Positiv-Kontrolle und Umkehrprobe, beide flip-geprueft. Volle Reihe gruen.
Nicht enthalten: der vorgelesene Satz (CEO „Alerts created by System"). Er entsteht in domains/config/worker-notifications/src/lib/alertTts.ts:101 aus subject+body -- ausserhalb der beanspruchten Pfade dieses Auftrags.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>