Optional · Benachrichtigung · Schritt für Schritt
Am Ende des täglichen Laufs prüft das Skript, ob seit der letzten Nachricht etwas passiert ist: eine neue Rezension mit ein oder zwei Sternen, eine App, deren Ampel umspringt, ein Sprung der Absturzrate. Nur dann geht eine knappe Nachricht raus, per E-Mail, Slack, Teams oder Webhook, mit dem Kernsatz der KI und dem Link zum Bericht. Nichts Neues, keine Nachricht.
Bewertungen: 2 neue 1–2 ★ · Ampel rot: Scanbox AMPEL - Scanbox (Apple): gelb → rot – 3 × 1–2 ★ in 7 Tagen NEUE 1–2-★-REZENSIONEN - Scanbox (Apple), 1 ★, 2026-10-24, DEU, Version 2.4.1 „Login geht nicht mehr“ Seit dem Update komme ich nicht mehr rein. KI: Anmeldung schlägt seit Update fehl (Dringlichkeit hoch) - Scanbox (Apple), 2 ★, 2026-10-23, AUT Dauernd Abstürze beim Öffnen des Postfachs. Bericht: https://bewertungen.firma.intern/ Sätze mit „KI:“ stammen aus der gespeicherten KI-Analyse (anthropic (claude-sonnet-5-5)); Zahlen stammen nie von der KI.
Wann sie läuft
./ratings.sh daily macht drei Dinge nacheinander: Abruf (mit KI-Analyse, falls eingeschaltet), Bericht, Benachrichtigung. Sie steht bewusst am Ende, damit Ampel, KI-Sätze und der verlinkte Bericht auf dem Stand des Tages sind.
Das Skript merkt sich in data/notify-state.json, wann es zuletzt gemeldet hat, welche Ampelstufe jede App hatte und ob ein Absturzgrund vorlag, und führt dort einen Meldungsverlauf (die letzten 500 Vorfälle). Läuft daily am selben Tag noch einmal, findet es nichts Neues und schweigt. Den Verlauf zeigen ./ratings.sh notify --history und der Bericht unter „Datenstand“; neben einer roten oder gelben Ampel steht „seit 3 Tagen“.
Nach dem Einschalten merkt sich der erste Lauf nur den Stand. Sonst käme eine Nachricht mit jeder jemals abgerufenen 1–2-★-Rezension. Wer das ausdrücklich will, setzt quietOnFirstRun auf false.
Antwortet kein Kanal (Mailserver weg, Webhook mit Fehler), bleibt der gemerkte Stand stehen und der nächste Lauf meldet dieselben Vorfälle erneut. Hat ein Kanal zugestellt, gilt der Vorfall als gemeldet; der Lauf endet trotzdem mit Exit-Code 1, damit der Fehler im Log auffällt.
Die Benachrichtigung braucht keinen Zugang zu Apple, Google oder der KI. Sie liest nur die Dateien unter data/, dieselben wie der Bericht. Im GitHub-Workflow ist es derselbe Schritt, unter Windows der dritte Aufruf in daily.cmd. Mit notify.enabled: false (Standard) passiert gar nichts, daily läuft wie bisher.
Was eine Nachricht auslöst
Die Benachrichtigung erfindet keine eigenen Schwellen. Was im Bericht gelb oder rot wird, wird auch gemeldet; die Regeln stehen an einer Stelle (src/metrics.py) und sind im Bericht unter „Ampel“ erklärt.
Jede Rezension mit ein oder zwei Sternen, die seit dem letzten Lauf neu abgerufen wurde: App, Sterne, Datum, Land, Version, Titel und Text (gekürzt). Läuft die KI-Analyse, steht ihr Kernsatz dazu, etwa „KI: Anmeldung schlägt seit Update fehl“. Mehr als zehn werden gezählt statt aufgelistet.
Eine App wird gelb oder rot, oder sie ist wieder grün. Mit den Gründen, wie sie der Bericht formuliert: „3 × 1–2 ★ in 7 Tagen“, „Abstürze 0,8 → 1,9“, „Store unter 4 ★“; „2 ohne Antwort“ nur, wenn diese Regel in der Einrichtung zugeschaltet ist (Vorgabe aus). Eine Besserung von rot auf gelb wird nicht gemeldet, erst die Rückkehr auf grün.
Die Absturzrate je 1000 Sitzungen hat sich mindestens um die Hälfte erhöht oder liegt über 2, und das ist neu seit dem letzten Lauf. Auch ohne Ampelwechsel. Nur Apple, erst ab 500 Sitzungen im Fenster, wie im Bericht.
Rezensionen mit drei bis fünf Sternen, neue Downloads, Antworten des Supports, ein neues Update. Das steht alles im Bericht; die Nachricht soll selten sein und dann zählen.
Wie die Nachricht aussieht
Klartext, keine Bilder, kein HTML. Dieselbe Nachricht geht an E-Mail, Slack und Teams (dort als Karte, eine Zeile je Textblock); der Webhook bekommt sie zusätzlich als strukturiertes JSON.
Zählt, was drin ist, damit die Posteingangsliste reicht: Bewertungen: 2 neue 1–2 ★ · Ampel rot: Scanbox. In Slack ist das die fette erste Zeile.
AMPEL mit Stufe vorher → nachher und Gründen. ABSTÜRZE mit der Rate vorher → nachher. NEUE 1–2-★-REZENSIONEN je eine Zeile Kopf, Titel, Text, KI-Satz. Leere Blöcke fehlen.
Link zum Bericht aus settings.reportUrl (ohne Angabe der Dateipfad). Enthält die Nachricht KI-Sätze, nennt sie Anbieter und Modell. Zahlen kommen nie von der KI. Sprache de oder en.
Einrichten · Schritt 1 bis 3
config.json.Der Block notify steht fertig in config/config.example.json. Du brauchst nur den Zugang zu dem Kanal, über den die Nachricht kommen soll. Alle drei gleichzeitig gehen auch.
E-Mail: SMTP-Server, Port, Benutzername und Passwort eines Postfachs, das senden darf; bei vielen Anbietern ein „App-Passwort“. Versand verschlüsselt, STARTTLS auf 587 oder SSL auf 465.
Slack: In Slack eine App mit „Incoming Webhooks“ anlegen und einen Webhook für den Kanal erzeugen. Die Adresse https://hooks.slack.com/services/… ist das Geheimnis.
Teams: Im Kanal die drei Punkte, „Workflows“, Vorlage „Post to a channel when a webhook request is received“ anlegen, nichts ändern. Die Adresse https://…logic.azure.com/workflows/… ist das Geheimnis. Noch nicht gegen ein echtes Teams geprüft.
Webhook: Eine HTTPS-Adresse, die JSON per POST annimmt (n8n, Zapier, Power Automate mit eigenem Ablauf, eigener Dienst). Optional ein gemeinsamer Schlüssel für die Signatur.
Passwort, Webhook-Adresse und Signaturschlüssel stehen nie in config.json, nur ihr Variablenname. Für den täglichen Lauf gehört die Variable in die Umgebung des Zeitplaners: systemd-Unit, launchd-Plist, Aufgabenplanung oder die Secrets des CI-Systems (siehe BETRIEB.md).
# ~/.zshrc oder ratings.env des Dienstes export RATINGS_SMTP_PASSWORD="…" export RATINGS_SLACK_WEBHOOK="https://hooks.slack.com/services/…" export RATINGS_TEAMS_WEBHOOK="https://…logic.azure.com/workflows/…" # prüfen, ohne den Wert zu zeigen test -n "$RATINGS_SMTP_PASSWORD" && echo gesetzt
Steht ein Passwort oder eine Webhook-Adresse versehentlich in der Datei, lehnt das Skript die Konfiguration ab. In Logs und Fehlermeldungen wird der geheime Teil entfernt.
Am einfachsten in der Einrichtung im Browser, Schritt Benachrichtigung. Von Hand: enabled auf true, beim gewünschten Kanal ebenfalls. Dazu settings.reportUrl mit der Adresse, unter der die Firma den Bericht erreicht.
"settings": { "reportUrl":
"https://bewertungen.firma.intern/" },
"notify": {
"enabled": true,
"language": "de",
"channels": [
{ "type": "email", "enabled": true,
"host": "smtp.firma.de", "port": 587,
"security": "starttls",
"username": "bericht@firma.de",
"passwordEnvironmentVariable":
"RATINGS_SMTP_PASSWORD",
"from": "bericht@firma.de",
"to": ["chef@firma.de"] },
{ "type": "slack", "enabled": true,
"webhookUrlEnvironmentVariable":
"RATINGS_SLACK_WEBHOOK" },
{ "type": "teams", "enabled": false,
"urlEnvironmentVariable":
"RATINGS_TEAMS_WEBHOOK" },
{ "type": "webhook", "enabled": false,
"urlEnvironmentVariable": "RATINGS_WEBHOOK_URL",
"secretEnvironmentVariable":
"RATINGS_WEBHOOK_SECRET" }
]
}Schritt 4 · Testen
Beide Befehle gibt es auch im Menü unter „Status und Übersicht“. Keiner ändert den gemerkten Stand.
Zeigt die Nachricht, die der Tageslauf jetzt senden würde, mit allen Vorfällen. Es wird nichts gesendet und nichts gemerkt. Vor dem Einschalten ist das meist leer oder „erster Lauf, Stand gemerkt“.
./ratings.sh notify --dry-run
Schickt eine kurze Testnachricht an alle freigeschalteten Kanäle und sagt, welcher zugestellt hat. So prüfst du Passwort, Port und Webhook-Adresse, ohne auf eine echte 1-★-Rezension zu warten.
./ratings.sh notify --test
Testnachricht: 2 von 2 Kanälen zugestellt.Danach ist nichts mehr zu tun. Der erste echte Lauf merkt sich den Stand, jeder weitere meldet, was seitdem dazukam. Läuft der Zeitplaner schon, reicht es, die Umgebungsvariablen dort einzutragen.
./ratings.sh daily
… Bericht erzeugt …
Benachrichtigung: 3 Vorfälle, 2 von 2 Kanälen zugestellt.Einstellungen
notify, alle optional.Die Vorgaben passen für den Alltag. Die Tabelle steht auch in BENACHRICHTIGUNG.md und README.md.
| Feld | Bedeutung | Standard |
|---|---|---|
enabled | Schalter für den ganzen Schritt | false |
language | Sprache der Nachricht, de oder en | de |
triggers | negativeReviews, ampelChange, crashJump einzeln an oder aus | alle true |
quietOnFirstRun | erster Lauf merkt sich nur den Stand | true |
maxReviewsPerMessage | so viele neue 1–2-★-Rezensionen stehen einzeln in der Nachricht, der Rest wird gezählt | 10 |
channels[].type | email, slack, teams oder webhook; jeder Kanal hat ein eigenes enabled | leer |
email | host, port, security (starttls, ssl, none nur zu 127.0.0.1), username, passwordEnvironmentVariable, from, to (Liste) | Port 587, STARTTLS |
slack | webhookUrlEnvironmentVariable | |
teams | urlEnvironmentVariable (Adresse des Teams-Workflows) | |
webhook | urlEnvironmentVariable, optional secretEnvironmentVariable (HMAC-SHA256 über den Body, Header X-Ratings-Signature) | |
settings.reportUrl | Adresse des bereitgestellten Berichts für den Link in der Nachricht | null = Dateipfad |
Welche Daten gehen raus
Empfänger sind nur die Adressen, die du einträgst: dein Mailserver, dein Slack-Arbeitsbereich, dein Teams-Mandant, dein Webhook-Dienst. Rezensionen sind öffentliche Texte, können aber Angaben enthalten, die der Verfasser selbst hineingeschrieben hat. Die Empfänger gehören deshalb in die Firma, nicht in offene Verteiler.
Verschlüsselt. E-Mail nur mit STARTTLS oder SSL und Zertifikatsprüfung, Webhooks nur über HTTPS; unverschlüsselt geht allein ein Relay auf demselben Rechner. Passwort, Webhook-Adresse und Signaturschlüssel kommen nur aus Umgebungsvariablen; in Logs wird auch der geheime Teil einer Slack-Adresse entfernt. Der bereitgestellte Bericht nennt die Benachrichtigung in seiner Datenschutzerklärung (Abschnitt 4b).
Wenn etwas nicht klappt
Das Log liegt in data/logs/notify.log. Ein Kanalfehler hält die anderen Kanäle nicht auf.
notify.enabled steht auf false.
Beim Kanal fehlt "enabled": true.
Die Variable steht in deiner Shell, aber nicht in der Umgebung des Dienstes. In systemd-Unit, Plist, Aufgabenplanung oder CI-Secrets eintragen.
Host, Port, Firewall. Port 587 braucht starttls, Port 465 ssl.
Benutzername oder Passwort falsch; viele Anbieter verlangen ein App-Passwort statt des Kontopassworts.
Workflow gelöscht, ausgeschaltet oder Adresse falsch kopiert (sie ist lang und enthält sig=…). In Teams unter „Workflows“ den Ausführungsverlauf ansehen, dort steht der Grund.
Webhook in Slack gelöscht oder Adresse falsch kopiert. In Slack einen neuen erzeugen und die Variable ersetzen.
data/notify-state.json fehlt oder wurde gelöscht; dann ist es wieder ein erster Lauf, der nur mit quietOnFirstRun: false sendet.
./ratings.sh notify --dry-run zeigt, was anliegt. Kam die Rezension vor dem Einschalten, gilt sie als bekannt.