FAQ & Glossar

Changelog

Alle nennenswerten Änderungen an diesem Projekt werden hier dokumentiert.

Format orientiert sich an Keep a Changelog; das Projekt folgt Semantic Versioning.


[4.8.0] — 2026-08-10

Fokus: Wetter-Modul (#210) — amtliche DWD-Warnungen, Regenradar und Wetterlage am Einsatz

Ein neues zubuchbares Zusatzmodul „Wetter": die amtlichen Warnungen des Deutschen Wetterdienstes für Deine Beobachtungsgebiete, aktuelle Messwerte, eine 24-Stunden-Vorschau, Warnflächen, Regenradar, Blitze und Wetter-Rose auf den Karten, eine automatische Momentaufnahme der Wetterlage bei jeder Einsatz-Anlage und ein Lagebild zum Ausdrucken. Warnung und aktuelles Wetter lassen sich per Knopf als Kommentar ins Tagebuch übernehmen. Die Warnflächen folgen dabei der Systematik des DWD — jede Warnart mit eigenem Symbol, Hitze und UV nach eigener Farbskala —, und neben der Wetter-Rose steht eine Warntafel, sodass ein Klick beide Fragen beantwortet: was ist hier gewarnt, und wie steht das Wetter. Als zweiter Wetterdienst ist MET Norway wählbar (nur Kennzahlen und Vorhersage; amtliche Warnungen kommen immer vom DWD). Das Modul ist standardmäßig aus: Ohne Freischaltung unter Wetter verwalten gibt es weder den Menüpunkt noch die Wetterseiten (sie antworten mit „Nicht gefunden") noch die Wetter-Ebenen der Karten — unabhängig von den vergebenen Rechten.

Das Zwischenrelease 4.7.5 ist hier mit gebündelt. Es wurde nie veröffentlicht; sein Inhalt steckt vollständig in dieser Version — vier gemeldete Bugs, Einsätze anheften, der Leitungs-Einsatz am Schwerpunkt, die Sperre durch offene Bevölkerungswarnungen, das Recht mowas.export und die selbst gesetzte Zeitzone.

Schema-Check nötig (/admin/schema-check.php → „Reparieren") — vier neue Tabellen (wetter_gebiet, wetter_cache, wetter_moment, wetter_warngebiet) und die Vorgabewerte des Moduls, dazu aus 4.7.5 die neue Spalte einsaetze.ist_fixiert und das Recht mowas.export. Ohne den Lauf bleibt das Wetter stumm, stehen fixierte Einsätze nicht oben, und außer dem Administrator kann niemand Formulare herunterladen. Derselbe Lauf verteilt auch das Recht „Wetter sehen" (wetter.view) — an jede Rolle, die schon lagekarte.view hat.

Neu

  • Zusatzmodul „Wetter" (zubuchbar, Lizenz-Schalter) — Unter Administration → Feuerwehr → Wetter (admin.config) schaltest Du das Modul frei, optional mit Laufzeit bis; danach schaltet es sich selbst ab. Der Schalter ist ein Vertriebs-Schalter, kein Sicherheits-Schalter — wer was sieht, regelt weiterhin das Recht wetter.view. Ist das Modul aus, verschwindet der Menüpunkt vollständig (kein toter Knopf, kein Schloss-Symbol), die Wetterseiten und alle Wetter-Schnittstellen antworten mit 404 — bewusst nicht mit 403, ein nicht gebuchtes Modul soll sich nicht durch eine Fehlermeldung verraten. Sichtbar bleibt allein die Kachel in der Administration. Fail-closed in jede Richtung: fehlender Schalter, leerer Wert und ein unlesbares Ablaufdatum sperren.
  • Wetterseite (Sidebar → Lage → Wetter, Recht wetter.view) — Für das gewählte Beobachtungsgebiet: die amtliche Warnlage des DWD (Stufe, Ereignis, Laufzeit, Beschreibung und Handlungsempfehlung; ab Stufe 3 von vornherein aufgeklappt), vier Kennzahlen (Temperatur, Wind, Böen, Niederschlag) samt Herkunftszeile, weitere Messwerte mit Messstation und Entfernung, die Karte des Gebiets und das Live-Intervall (Aus / 10 / 30 / 60 s, vorbelegt 60 s). Der Stand („gerade eben" / „Letzter bekannter Stand …" / „unbekannt") ist Teil der Aussage: „Warnlage unbekannt" heißt nicht „keine Warnung" und sieht deshalb anders aus als die Ruhe-Anzeige. Anleitung: Wetter.
  • 24-Stunden-Vorschauleiste — Eine Warnung kommt, wenn die Lage da ist; eine Freiwillige Feuerwehr braucht die Zeit davor. Die Leiste zeigt je Stunde Temperatur, Niederschlag und Böen und markiert auffällige Stunden mit Grund im Klartext („kräftige Böen", „viel Regen", „Frost") — ausdrücklich keine dritte Warnstufe: Im ETB zählen DWD (1–4 aufsteigend) und Bevölkerungswarnung (1–3 absteigend) bereits gegenläufig. Über der Leiste steht die erste auffällige Stunde als Vorwarnzeit („Vorhersage: kräftige Böen in 5 Stunden"), jede Stunde ist antippbar. Fällt der Abruf aus, entfällt die Leiste ersatzlos — eine Vorhersage von gestern ist keine Vorhersage.
  • Wetter-Ebenen auf drei KartenLagekarte, Wetterseite und die maximierte Karte eines Einsatzes bekommen dieselben drei Schalter (alle anfangs aus): Wetterwarnungen legt die amtlichen Warnflächen des DWD schraffiert über die Karte (die Schraffur kodiert die Stufe zusätzlich zur Farbe, ab Zoom 9 trägt jede Fläche zusätzlich das Symbol ihrer Warnart, ab Zoom 14 bleibt nur die Kante); Aktuelles Wetter blendet das Regenradar mit Zeitleiste ein (zwei Stunden zurück bis zwei Stunden Vorhersage in Fünf-Minuten-Schritten, abspielbar, Vorhersage gestrichelt) und setzt per Klick eine Wetter-Rose auf einen beliebigen Kartenpunkt — Temperatur als Ring und als Zahl, Windkeil in Wehrichtung, Böen als Zacken; Blitze & Vorhersage zeichnet die erkannten Blitze des DWD und die Vorhersage für die nächste Stunde auf dieselbe Zeitachse (schaltet das Radar bei Bedarf mit ein, denn ohne Zeitleiste gäbe es keinen Zeitpunkt dazu; der Name nennt die Vorhersage ausdrücklich — nicht jedes Zeichen heißt „hier hat es eingeschlagen"). Auf der Einsatzkarte sitzt die Rose sofort auf der Einsatzstelle. Zu jeder Ebene erscheint die passende Legende.
  • Warnarten des DWD statt bloßer Stufen — Eine Warnfläche zeigt jetzt, ob es um Gewitter, Sturm, Regen, Schnee, Glätte, Frost, Tauwetter, Nebel, Hitze oder UV geht: 46 amtliche Warnkennziffern werden auf neun Gruppen abgebildet, jede mit eigenem Symbol; unbekannte Kennziffern werden als „Sonstige Warnung" gezeichnet statt verschwiegen. Auch die Farbe folgt jetzt der DWD-Systematik: Hitze und UV haben eine eigene Skala und tragen deshalb keine „DWD-Stufe N" mehr — eine Hitzewarnung ist nicht harmloser als eine Sturmwarnung, sondern etwas anderes. Sie stehen in der Karten-Legende neben der Stufenleiter, dort sichtbar mit „eigene Skala" beschriftet; der Hinweis „Symbol = Warnart" erklärt die Piktogramme und bleibt auch auf schmalen Bildschirmen stehen. Eine Warnung, die erst später einsetzt (Vorabinformation), bekommt eine eigene Farbe und wird mit „ab …" statt „bis …" beschriftet.
  • Warntafel neben der Wetter-Rose — Ein Klick auf die Karte beantwortet jetzt beide Fragen auf einmal: Die Rose zeigt die Messwerte, rechts daneben steht die Warnlage an genau diesem Punkt — mit Warnsymbol, Gebietsname („Hitze — Gemeinde Wachtberg"), Einordnung, Ereignis und Laufzeit, hinterlegt in der pastelligen DWD-Warnfarbe. Vorher schlossen sich beide Auskünfte aus, und der zweite Klick nahm die erste wieder weg. Höchstens drei Warnungen, darüber „+ N weitere"; die vollständigen Texte samt Handlungsempfehlung stehen weiterhin auf der Wetterseite — auf Lage- und Einsatzkarte führt dorthin der Link „Vollständige Warnung", sobald wirklich eine Warnung anliegt. Die Tafel gehört zur Ebene Wetterwarnungen und verschwindet mit deren Schalter. Für Screenreader und schmale Bildschirme gibt es dieselbe Aussage zusätzlich als gesprochenen Satz in der Textzeile über der Karte.
  • Warnflächen in der Auflösung, die zum Ausschnitt passt — Kleine Ausschnitte holen die Gemeinde-Ebene (feiner, und nur sie bringt den Gebietsnamen mit), großflächige die Landkreis-Ebene — genau wie die Karte des DWD, der einen ganzen Landkreis warnt, sobald ein Teil davon die Schwelle reißt. Auf der groben Ebene sagt die Legende es dazu („Übersicht auf Landkreis-Ebene — hineinzoomen für einzelne Gemeinden"). Die Entscheidung fällt auf dem Server, nicht im Browser.
  • Momentaufnahme der Wetterlage bei der Einsatz-Anlage — Jeder neu angelegte Einsatz mit Koordinaten hält automatisch fest, wie das Wetter an der Einsatzstelle war (Temperatur, Wind in beiden Lesarten, Böen, Station bzw. Modell, Messzeitpunkt, laufende Warnungen). Sie steht im Einsatz-Detail in der Zeile Wetter und im PDF-Export. Genau diese Angabe sucht man Wochen später beim Einsatzbericht — ein Live-Abruf liefert dann das Wetter von heute. Gilt für beide Anlage-Wege (Formular und Mail-Parser). Scheitert der Abruf, wird der Einsatz trotzdem angelegt: im Alarmfall zählt der Einsatz, nicht die Temperatur.
  • „In die Lage übernehmen" und „Jetziges Wetter ins Tagebuch" — Ein Knopf an jeder Warnkarte der Wetterseite schreibt die Warnung als Kommentar in das Tagebuch eines laufenden Einsatzes; ein Knopf an der Wetter-Zeile des Einsatz-Details schreibt das aktuelle Wetter an der Einsatzstelle hinein (der Fall im Einsatz: zwei Stunden später hat der Wind gedreht, die Absperrung muss neu gelegt werden). Beides ist manuell — kein Automatismus schreibt ungefragt ins Tagebuch, der Eintrag trägt Deinen Namen. Der Text entsteht serverseitig aus frisch geholten Werten, nichts kommt aus dem Formular; die Warnung wird beim Abschicken über ihre Kennung neu gesucht. Es gelten dieselben Riegel wie am normalen Kommentarweg: Recht einsatz.comment, Sichtbarkeits-Scope (ein Disponent mit Eigentums-Filter schreibt nur in seine eigenen Einsätze) und der Abschluss-Freeze. Gibt es keinen laufenden Einsatz oder keine Koordinaten, gibt es keinen Knopf.
  • Wetter-Lagebild zum Ausdrucken — „Lagebild drucken" auf der Wetterseite bringt alle Beobachtungsgebiete auf ein Blatt: Warnlage, Messwerte und 24-Stunden-Vorschau, schwarz auf weiß, mit Erstellungszeit und Name im Kopf. Großlagen halten sich nicht an Gemeindegrenzen, und ein zweites Blatt für den Nachbarort holt in der Lagebesprechung niemand.
  • Vollbild für die Wetterkarte — Der Knopf „Vollbild" über der Karte der Wetterseite bringt sie auf die volle Fensterbreite. Es entsteht dabei keine zweite Karte: Ausschnitt, Zoom, Schalterstellung, geladene Radarbilder und eine gesetzte Wetter-Rose bleiben unverändert erhalten. Zurück geht es über „Verkleinern", das oder Esc.
  • Beobachtungsgebiete und amtlicher DWD-Gebiets-Katalog — Unter Wetter verwaltenBeobachtungsgebiete legst Du fest, wofür Warnungen und Messwerte geholt werden (eigene Gemeinde, Nachbarn, Kreis). Die amtliche Warngebiets-Liste des DWD (rund 11.600 Einträge) holt ein Knopf einmalig in die Datenbank; danach wählst Du das Gebiet über Bundesland → Kreis → Gemeinde aus, inklusive der echten DWD-Warngebiete „Gesamter Kreis" und „Gesamtes Bundesland". Warncell- ID und Mittelpunkt füllt das ETB selbst; für Sonderfälle bleibt die Eingabe von Hand. Die Messstation ist wählbar (angeboten werden nur Stationen, die tatsächlich aktuelle Messwerte liefern); fällt die festgelegte Station aus, weicht das ETB auf die nächstgelegene aus und schreibt das als Hinweis dazu.
  • Herkunft der Messwerte einstellbarModellwerte (MOSMIX) gelten für Deine Koordinate (keine Messung, dafür am richtigen Punkt), Stationsmessungen sind echte Messwerte, im dünnen DWD-Netz aber oft aus zehn Kilometern Entfernung. Voreinstellung sind die Modellwerte. Die Oberfläche schreibt an jeder Anzeige dazu, was von beidem sie gerade zeigt — auch im Tagebuch-Eintrag und im PDF-Export („gemessen" nur bei einer echten Stationsmessung, sonst „berechnet für"). Dazu einstellbar: die Laufzeiten des Zwischenspeichers für Warnungen (30–900 s) und Messwerte (60–1800 s).
  • MET Norway als zweiter Wetterdienst — Unter Wetter verwaltenAktuelles Wetter ist neben dem Deutschen Wetterdienst (über Bright Sky) jetzt MET Norway wählbar — ein europäisches Modell als Vergleich, wenn Dir die DWD-Werte für Deinen Ort zu grob erscheinen. Gewählt wird damit nur, woher Kennzahlen und Vorhersage kommen: Die amtlichen Warnungen bleiben immer beim DWD, denn MET Norway führt sie ausschließlich für Norwegen, und eine leere Warnliste wäre von „keine Warnungen" nicht zu unterscheiden. Pflicht ist eine Kontakt-Kennung (E-Mail-Adresse oder Internetadresse) — die Nutzungsbedingungen verlangen, dass sich jede Anwendung erkennbar zu erkennen gibt; ohne gültige Kennung lässt sich der Dienst gar nicht erst auswählen (die Meldung steht am Feld, Eingabe und Auswahl bleiben stehen), und fehlt sie später, bleibt das ETB bei der Standardquelle statt eine Sperre zu riskieren. Wichtig außerhalb Norddeutschlands: MET Norway liefert dort in aller Regel keine Böen (und weder Sichtweite noch Regenwahrscheinlichkeit) — dann fehlen die Zacken der Wetter-Rose, die Schwellen „kräftige/schwere Böen" der Vorschauleiste und die Windstärke-Einordnung. Die Wahl zwischen Modellwert und Stationsmessung greift bei MET Norway nicht (es rechnet immer ein Modell); die Einstellung bleibt gespeichert und wirkt beim Zurückwechseln wieder. Die Daten stehen unter CC BY 4.0, die Namensnennung ist Pflicht und steht in der Herkunftsangabe.
  • Herkunftsangabe an einer Stelle — Die Zeile „Datenbasis: …" nennt jetzt überall den Dienst, der die Zahlen wirklich geliefert hat — auf der Wetterseite, im gedruckten Lagebild, in der Kartenauskunft, im Tagebuch-Eintrag und bis in Kopfzeile, Fußzeile und Kacheltext der Wetter-Verwaltung; unterscheiden sich Warn- und Messquelle, werden beide genannt. Auch ein letzter bekannter Stand aus dem Zwischenspeicher trägt die Quelle, aus der er stammt, statt sie aus der aktuellen Einstellung zu raten.
  • Administration → Wetter ist eine Übersicht mit Unter-Kacheln — Wie bei der Bevölkerungswarnung führt die Wetter-Kachel jetzt auf eine Übersicht mit vier eigenen Seiten: Freischaltung, Beobachtungsgebiete, Wetterwarnungen (Laufzeit des Zwischenspeichers und eine Erklärung, was die Karte zeigt — Auflösungen, Warnarten, Schraffur) und Aktuelles Wetter (Wetterdienst, Herkunft der Kennzahlen, Zwischenspeicher). Noch offene Einrichtungsschritte sind an der Kachel farbig markiert.
  • Neues Recht „Wetter sehen" (wetter.view) — Reines Leserecht für Wetterseite, Wetter-Ebenen der Karten und die Wetterlage am Einsatz; das Modul ist passiv und schreibt von sich aus nichts. Bei einer Neu- Installation haben es alle Rollen bis hinunter zum Gast — Wetter ist eine Lage-Information wie die Karte selbst und enthält keine personenbezogenen Daten. Bei einer bestehenden Installation zieht der Schema-Check es einmalig für jede Rolle nach, die schon lagekarte.view hat — genau die Kopplung, die auch die Vorgabewerte verwenden; danach entscheidet der Rollen-Editor. Wichtig: Das Recht allein öffnet nichts — ohne freigeschaltetes Modul bleibt das Wetter für alle unsichtbar.
  • Kontext-Hilfe für die neuen Seiten — Das „?" der Wetterseite und der Verwaltungsseiten öffnet die passenden Handbuch-Themen Wetter und Wetter verwalten.
  • Einsätze fixieren (anheften) — Ein neues Reißzwecken-Symbol in der Einsatz-Übersicht (Karte und Zeile) heftet einen Einsatz oben in der Liste an — unabhängig von Sortierschlüssel und -richtung. Kein neues Recht: einsatz.edit genügt. Die Fixierung selbst landet im Audit-Log. In der Detailsicht gibt es den Knopf bewusst nicht: Dort siehst Du die Liste nicht, die er ordnet — sie zeigt stattdessen den Hinweis-Chip „oben fixiert".
  • Leitungs-Einsatz am Schwerpunkt — Beim Anlegen eines Schwerpunkts gibt es in Schritt 1 jetzt die Checkbox „Einen Einsatz ‚Leitung Schwerpunkt' anlegen" (vorbelegt an) samt Adressfeldern für den Standort der Schwerpunkt-Leitung. Aktiviert legt sie einen ganz normalen Einsatz „Leitung Schwerpunkt # " an, bindet ihn an den Schwerpunkt und fixiert ihn (s. o.) — hier dokumentierst Du alle Maßnahmen rund um den Schwerpunkt selbst. Er verhält sich wie jeder andere Einsatz, auch beim Abschluss: Er muss zuerst erledigt werden, bevor sich der Schwerpunkt erledigen lässt. War die Checkbox abgewählt, lässt er sich in den Schwerpunkt-Einstellungen über einen eigenen Knopf jederzeit nachrüsten. Sichtbar nur mit den Rechten „Einsatz anlegen" und „Einsatz-Stammdaten bearbeiten" (am Nachrüst-Knopf zusätzlich „Einsätze zuweisen / verschieben").
  • Bevölkerungswarnung sperrt das Erledigen — Ein Einsatz oder Schwerpunkt lässt sich nicht auf „Erledigt" bzw. „Abgeschlossen" setzen, solange an ihm eine Bevölkerungswarnung noch offen ist — offen heißt jede Phase außer „Abgeschlossen", auch ein liegengebliebener Entwurf. Der Knopf „Einsatz erledigen" im Einsatz-Detail führt Dich dafür in festen Stufen durch die Hürden — erst die Warnungen, dann die Abschnitte, dann der Abschluss-Kommentar; jede Stufe zeigt sich erst, wenn die vorherige leer ist. Am Status-Auswahlfeld in Einsatz-Übersicht und -Detail sowie beim Erledigen/Abschließen eines Schwerpunkts öffnet sich stattdessen sofort ein Sperr-Dialog — statt wie bisher erst nach dem Bestätigen eine Fehlermeldung. Er listet die blockierenden Warnungen mit Nummer und Phase auf, genau wie der seit Längerem bekannte Dialog für offene Abschnitte. Steht eine der Warnungen auf einer aktiven Entwarnung, schließt sie ein Knopf direkt im Dialog ab (Recht „Bevölkerungswarnung freigeben", mowas.release, Vier-Augen-Prinzip) — wer sie selbst eingereicht hat, sieht den Knopf ausgegraut mit der Begründung statt ihn wortlos wegzulassen; nur der Administrator darf sich über das Vier-Augen-Prinzip hinwegsetzen. Sind danach alle blockierenden Warnungen zu, läuft die ursprüngliche Aktion automatisch weiter. Wer das Leserecht mowas.view nicht hat (der Schwerpunkt-Disponent kann es nie bekommen), sieht den Dialog ebenfalls, aber nur mit einem allgemeinen Hinweis ohne Nummer, Phase oder Liste — gesperrt wird trotzdem. Unverändert bleiben die Sammelaktion „Status" im Bulk, das Bearbeiten-Formular und der Abschluss-Arbeitsplatz „Einsätze abschließen" (der zeigt die Sperre weiterhin bereits vorab in der Zeile, mit Link zur Warnung).
  • Neues Recht „MoWaS-Formulare herunterladen" (mowas.export) — Bis v4.7.0 hing der Download des Dokuments (PDF) bzw. des Leitstellen-Formulars (Excel) am Leserecht mowas.view, das der Disponent per Default hat. Jetzt ist Sehen und Herunterladen getrennt: Default für Administrator, Einsatzleiter und Lage; dem Disponenten zuschaltbar, aber bewusst nicht voreingestellt. Bestehende Installationen: Wer bisher mowas.create oder mowas.release hatte, behält den Download automatisch (Schema-Check-Migration). Jeder Download landet mit Benutzer, Warnung und Stand im Anwendungsprotokoll. Unverändert bleibt: Der Disponent sieht Warnungen weiterhin überall (Symbol samt Mouseover in Liste/Detail/Schwerpunkt-Leiste, Warn-Radien auf der Lagekarte, Warnung lesbar) — anlegen, bearbeiten und freigeben bleiben wie bisher Lage und Einsatzleiter vorbehalten. Für Admins: Die Migration legt mowas.export nur an, wenn der Schlüssel in role_permissions noch gar nicht vorkommt — entziehst Du ihn zum Testen mal allen Rollen, legt der nächste Schema-Check ihn aus mowas.create/mowas.release wieder an (dasselbe Verhalten wie bei den Migrationen für user.assign_temp_role und alarm.trigger_manual).
  • Filter „Mit Warnung" in der Einsatz-Übersicht — Zeigt nur Einsätze mit einer offenen Bevölkerungswarnung; sichtbar nur mit mowas.view.

Geändert

  • Reihenfolge im Hauptmenü, Gruppe „Lage" — erst der Vorgang (Einsätze, Schwerpunkte), dann die Lagedarstellung (Lagekarte), dann was auf ihr liegt (Warnungen, Wetter), zuletzt die Mittel (Einsatzmittel). Die Lagekarte steht jetzt vor den Warnungen.
  • Feste Reihenfolge der Karten-Ebenen — Von hinten nach vorn: DWD-Warnungen → Regenradar → Blitze → Bevölkerungswarnungen → Einsatz-Elemente. Die DWD-Warnung beschreibt ein Verwaltungsgebiet und ist Hintergrund; das Radar zeigt, wo die Zelle gerade steht, und muss darüber liegen; die eigene Bevölkerungswarnung wiegt schwerer als beides, und der Einsatz geht immer vor. Bis dahin lag das Radar hinter der Warnfläche und war ausgerechnet innerhalb der gewarnten Zelle kaum zu sehen; Radar und Blitze konnten außerdem beim Umschalten die Reihenfolge tauschen.
  • Regenradar neu gebaut — flüssige Animation — Statt für jeden Zeitschritt rund zwanzig Einzelkacheln zu laden, holt das ETB jetzt ein Bild je Zeitschritt. Für die volle Schleife sind das 25 statt rund 500 Abrufe; nach dem Vorladen berührt das Abspielen kein Netz mehr — aus Einzelbildern wird ein weicher Lauf. Beim Verschieben der Karte wird nur der gerade sichtbare Schritt nachgeholt, der Vorrat erst, wenn die Karte kurz ruht oder abgespielt wird.
  • Zeitachse des Radars sagt die Wahrheit — Die Beschriftung stand fest auf „−2 h / jetzt / +2 h" und setzte „jetzt" damit immer in die Mitte. Sie wird jetzt aus den echten Zeitschritten gefüllt: die Enden nennen den tatsächlichen Abstand, und der Jetzt-Strich steht dort, wo die Vorhersage wirklich beginnt — wie weit der DWD vorausrechnet, schwankt mit seinem letzten Lauf.
  • DWD-Stufe 4 in der Farbe des DWD — Das bisherige Lila lag zu nah an der Hitzeskala, die beim DWD ebenfalls violett ist. Stufe 4 („extremes Unwetter") trägt jetzt das Bordeaux-Magenta des amtlichen Kartenstils.
  • Vorabinformationen werden zuverlässiger erkannt — Bisher nur am Wort „VORABINFORMATION" im Ereignisnamen, jetzt zusätzlich an der amtlichen Dringlichkeit (URGENCY = Future) — so, wie der DWD selbst unterscheidet. Beide Merkmale zusammen fallen erst aus, wenn der DWD beide ändert.
  • Fixier-Knopf nur noch in der Übersicht — Das Anheften ordnet die Liste; in der Detailsicht hätte der Knopf keine sichtbare Wirkung. Dort steht stattdessen der Hinweis-Chip „oben fixiert", damit erklärbar bleibt, warum dieser Einsatz oben steht. Das Symbol ist jetzt eine Reißzwecke im Outline-Stil — die frühere Nadel von oben war vom Karten-Pin nicht zu unterscheiden.
  • Beaufort wird aus dem Mittelwind gerechnet, nicht aus der Böe — Die Skala ist auf das 10-Minuten-Mittel definiert; aus Böen gerechnet lag die Stufe zwei bis drei zu hoch. „Bft 9" ist eine Ansage, nach der Absperrungen gesetzt werden. Die Angabe steht deshalb an der Wind-Kachel, nicht an der Böen-Kachel — betrifft Wetterseite und Tagebuch-Übernahme.
  • Einsätze löschen und der ETB-Reset räumen die Wetter-Momentaufnahmen mit ab — Begleitdokumentation zu genau einem Einsatz, ohne ihn wertlos (anders als eine Bevölkerungswarnung, die bewusst revisionsfest stehen bleibt). Fehlt die Tabelle, weil der Schema-Check noch nicht gelaufen ist, wird sie übersprungen statt die Löschung scheitern zu lassen.
  • Einsatz-Rollen: Vergabe auch aus einer geliehenen Rolle heraus — Bis v4.7.0 durfte, wer eine Einsatz-Rolle nur geliehen hatte, sie nicht weiterverleihen (geprüft wurde die feste Basis-Rolle). Das ist jetzt umgedreht: Auch mit geliehener Rolle darf man vergeben, wenn die effektive Rolle das Recht trägt. Die Kette wird stattdessen über die Laufzeit gedeckelt — eine vergebene Rolle endet spätestens dann, wenn die eigene geliehene Rolle endet, kann sich also nur verkürzen, nie verlängern; die 48-Stunden-Obergrenze gilt weiterhin immer. Nicht gelockert ist der Entzug: „Entfernen" und „Alle Einsatz-Rollen zurücksetzen" verlangen weiterhin die feste Basis-Rolle (siehe „Behoben" — dort war die Trennung zunächst nicht gezogen). Das Einsatz-Rollen-Modal zeigt jetzt bei jeder aktiven Rolle die Restlaufzeit, und wer über eine geliehene Rolle vergibt, sieht einen Hinweis auf seinen eigenen Ablauf. Die per Alarm-Knopf übernommene Lage darf weiterhin unabhängig vom Vergabe-Häkchen vergeben — das ist jetzt die einzige verbliebene Alarm-Sonderregel.
  • Sperrmeldungen nennen jetzt Namen statt nur Anzahl — Lässt sich ein Einsatz wegen Abschnitten in Arbeit bzw. ein Schwerpunkt wegen offener Einsätze nicht erledigen/abschließen, nennt die Meldung jetzt die blockierenden Abschnitte bzw. Einsätze beim Namen (ab dem sechsten gekürzt: „… und 3 weitere") statt nur ihre Anzahl.

Behoben

  • Die Warnliste der Wetterseite sprach eine andere Sprache als die Karte daneben — Sie färbte sich allein nach der Stufe, während die Karte schon nach Warnart färbte. Eine Hitzewarnung stand links gelb als „DWD-Stufe 1" und lag rechts violett als „Hitze" auf der Fläche. Jetzt trägt jede Warnkarte dasselbe Warnart-Piktogramm und dieselbe Farbe wie die Fläche, und bei Hitze und UV steht „eigene Skala des DWD" statt einer Stufennummer.
  • Die Karte vergaß, ob Du sie hell oder dunkel wolltest — Der Karten-Umschalter merkte sich bisher nur „anders als die Seite". Wer die Karte bewusst hell stellte und danach das Seiten-Thema wechselte, bekam ungefragt eine dunkle Karte. Jetzt merkt sich der Schalter, was Du wolltest; ohne eigene Wahl folgt die Karte weiterhin dem Seiten-Thema. Eine vorhandene Einstellung wird beim ersten Aufruf übernommen — Du musst nichts neu setzen.
  • Das Vollbild wurde vom Minutentakt weggeräumt — Die Wetterseite lädt sich jede Minute neu und fragt vorher, ob gerade jemand mit der Karte arbeitet. Das geöffnete Vollbild zählte nicht dazu: Wer die Karte groß gemacht hatte und nur schaute, flog nach 60 Sekunden heraus.
  • Kein Weg von der Warntafel zur vollständigen Warnung — Auf Lagekarte und Einsatzkarte zeigt die Tafel bewusst nur den Kern. Dass es mehr gibt, stand nirgends. Jetzt führt ein Verweis Vollständige Warnung zur Wetterseite.
  • Fehler beim Speichern der Datenquelle standen nur oben im Streifen — Wies das ETB eine MET-Norway-Kennung ab, sprang die Auswahl auf den DWD zurück und die getippte Kennung war weg. Jetzt bleibt die Eingabe stehen, das Feld ist markiert, und der Grund steht direkt darunter.
  • Erklärungen, die es auf dem Tablet nicht gab — „Symbol = Warnart" (der Schlüssel zu den neun Piktogrammen) und „eigene Skala" steckten nur in Tooltips bzw. verschwanden unter 720 Pixeln. Beide stehen jetzt sichtbar in der Legende. Der Blitz-Schalter heißt „Blitze & Vorhersage" — „Blitze" allein las sich, als hätte es dort eingeschlagen.
  • Leere Zeilen im Wetter-Lagebild sahen aus wie fehlende Daten — Eine Zeile „mm" mit 24 leeren Feldern heißt „es regnet nicht", las sich auf Papier aber wie ein Datenfehler. Zeilen ohne jeden Wert entfallen jetzt, sonst steht dort eine „0".
  • Tippziel des Karten-Umschalters auf 40 Pixel — Er war mit 32 Pixeln der einzige Ausreißer in einer Leiste voller 40-Pixel-Schalter.
  • Hitze- und UV-Warnungen wurden falsch eingefärbt — Der DWD färbt beide nach einer eigenen Skala; eine Hitzewarnung trägt den amtlichen Schweregrad „gering" und wurde bei uns deshalb als Stufe 1 gelb gezeichnet, während der DWD sie violett zeigt. Im August 2026 betraf das 66 von 67 bundesweit aktiven Warnungen — die Karte sah für eine Hitzelage harmlos aus.
  • Herausgezoomt blieb die Warn-Ebene leer — Über einer bestimmten Kartenspanne wurden gar keine Warnflächen mehr geholt. Eine leere Warnkarte liest sich als „keine Warnungen", und das ist der gefährlichste Zustand, den ein Warnsystem haben kann. Die Warnungen werden jetzt auf jeder Zoomstufe gezeigt; der Ausschnitt wird stattdessen auf den Datenbereich des DWD zugeschnitten.
  • Ein abgebrochener Abruf galt als Erfolg — Riss beim Holen der Warnflächen die Größenbremse, kam eine leere Liste zurück, die sich als „keine Warnungen · gerade eben" ausgab. Unbrauchbare Antworten führen jetzt in den Ausfallweg (letzter bekannter Stand bzw. „unbekannt") statt in eine vorgetäuschte Entwarnung.
  • Die Quellenangabe stand fest auf „Deutscher Wetterdienst" — auch dann, wenn die Kennzahlen von MET Norway kamen. Da Modellwerte die Voreinstellung sind, traf das jeden Abruf — bis in den revisionssicher festgeschriebenen Tagebuch-Eintrag hinein, wo sich eine falsche Urheberangabe hinterher nicht mehr korrigieren lässt. Zugleich ein Verstoß gegen die CC-BY-Lizenz von MET Norway.
  • Ein Klick auf eine Warnfläche blieb ohne Antwort, wenn nur die Ebene „Wetterwarnungen" eingeschaltet war — genau die Geste, die unter Stress zuerst kommt. Jetzt erscheint die Warntafel auch ohne die Ebene „Aktuelles Wetter", dann eben ohne Wetter-Rose.
  • Hover-Schatten der Verwaltungs-Kacheln im Dunkelmodus — Die Kacheln der Übersichtsseiten hoben sich unter dem Zeiger mit einem fest verdrahteten Schatten, der auf dunklem Grund unsichtbar blieb. Er kommt jetzt aus einem Design-Token und ist in beiden Erscheinungsbildern zu sehen.
  • Eine geliehene Einsatz-Rolle konnte Rollen entziehen — Die Lockerung (oben unter „Geändert": vergeben aus der effektiven statt der Basis-Rolle) war für das Vergeben gedacht und ist dort über die Laufzeit gedeckelt. Für den Entzug gibt es keine solche Deckelung: Wer die Einsatzleiter-Rolle geliehen bekam, konnte sie seinem eigenen Verleiher nehmen und mit „Alle Einsatz-Rollen zurücksetzen" auch die per Alarm-Knopf übernommene Lage löschen. „Entfernen" und „Alle zurücksetzen" verlangen jetzt die feste Basis-Rolle — serverseitig geprüft, und ohne das Recht erscheinen die beiden Knöpfe im Einsatz-Rollen-Modal erst gar nicht. Das Vergeben bleibt aus der geliehenen Rolle möglich.
  • Warn-Symbol mit fester Größe statt Zeilenhöhe — Das Zivilschutz-Symbol in Liste, Detail und Schwerpunkt-Leiste übernahm bisher die Höhe seiner Zeile (align-self: stretch) — Zeilen mit EM-Chips oder Personal-Pill machten es dadurch sichtbar größer als schmalere Zeilen. Es hat jetzt eine feste Größe je Kontext, auf schmalen Bildschirmen gestuft kleiner.
  • Zeitzone verlässt sich nicht mehr auf den Hoster — Das ETB hat die Zeitzone bisher nirgends gesetzt. Dass die Uhrzeiten stimmten, lag allein an der php.ini des Hosters; ohne deren Vorgabe fällt PHP auf UTC zurück (bei einer Docker-Installation der Normalfall), und sämtliche Zeitstempel im Tagebuch wären um ein bis zwei Stunden verschoben — bei einem Dokument, dessen Zeiten revisionsrelevant sind, gravierend. Die Anwendung legt die Zeitzone jetzt selbst fest (APP_TIMEZONE in config/.env, ohne Eintrag Europe/Berlin, siehe Installation) und zieht die Datenbank beim Verbindungsaufbau auf dieselbe Zone nach. Das behebt zugleich einen bis dahin unbemerkten Fehler: Eine befristete Rolle (Einsatz-Rollen) wurde in der Anwendung gerechnet, aber in der Datenbank gegen deren Uhr geprüft — bei zwei Stunden Versatz lief eine auf zwei Stunden befristete Rolle vier. Neue Karte Zeitzone unter System-Status zeigt, ob Anwendung und Datenbank synchron laufen. Kein Schema-Check nötig; bestehende Installationen auf Strato ändern ihr Verhalten nicht.

Intern

  • Abruf-Bremse für die Wetter-Schnittstellen — 40 Abrufe je Benutzer, Bereich und Minute, danach HTTP 429. Die Endpunkte nehmen frei wählbare Koordinaten, jede neue Koordinate ist ein Abruf beim DWD und bindet für dessen Zeitlimit einen PHP-Arbeiter — auf Shared Hosting genügen wenige parallele Anfragen, um die Instanz auszubremsen.
  • Härtung der Wetter-Abrufe — Die Größenbremse greift jetzt während des Ladens statt danach, alle drei Quellen laufen mit erzwungenem HTTPS und geprüftem Zertifikat, die Laufzeit des Zwischenspeichers wird serverseitig geklemmt, und die Entscheidung Gemeinde- oder Landkreis-Ebene hängt nicht mehr am frei wählbaren Zoom-Parameter aus dem Browser, sondern an der tatsächlich zugeschnittenen Spanne. Die Kontakt-Kennung für MET Norway weist Steuerzeichen ab — sie geht als User-Agent hinaus.
  • Warnart-Tabellen doppelt gepflegt — Die Zuordnung Kennziffer → Warnart → Farbe und Symbol liegt einmal in PHP (Server) und einmal in JavaScript (Karte), nach demselben Muster wie der Kontrast-Helfer. Ein Test vergleicht beide Dateien zeichenweise und fällt, sobald sie auseinanderlaufen.
  • Ausweichweg für die Warnungen — Fällt der Dienst Bright Sky aus, holt das ETB die Warnungen über den DWD-Geodienst, der ohnehin die Warnflächen der Karten liefert (derselbe Datenherr, dieselbe Lizenz, keine neue Abhängigkeit). Der Wechsel wird über der Warnliste benannt. Reihenfolge: frischer Zwischenspeicher → Bright Sky → DWD-Geodienst → letzter bekannter Stand → „unbekannt". Dabei behoben: Ein Ausfall lieferte bisher eine leere Liste und war damit von „keine Warnungen" nicht zu unterscheiden — der dritte Zustand („unbekannt") konnte gar nicht erreicht werden.
  • Zwischenspeicher trennt nach Quelle — Der Schlüssel für Messwerte und Vorhersage trägt jetzt den Dienst mit; nach einem Wechsel bekäme man sonst minutenlang die Werte des alten Dienstes, beschriftet mit dem Namen des neuen.
  • Rückruf nach der Einsatz-AnlageEinsatzService kennt das Wetter-Modul nicht; das Bootstrap hängt den Rückruf nur bei freigeschaltetem Modul ein. Er läuft nie innerhalb einer offenen Transaktion (der Leitungs-Einsatz eines Schwerpunkts hält dort ein FOR UPDATE) und nie zu Lasten der Anlage.
  • Gewitterlage (NowCastMIX) liegt fertig, aber ohne Schalter — Quelle, Schnittstelle, Tests und die geklärte Zugrichtungs-Konvention sind vorhanden; die Darstellung hat in der Abnahme nicht überzeugt und ist deshalb aus allen drei Karten genommen. Ohne Schalter läuft von dort nichts — kein Abruf, kein Zeichnen.
  • Kachel-Stile zentral — Das Raster der Übersichtsseiten (.tile-grid / .tile) lag in jeder Seite als fast wortgleicher Stil-Block; wer eine neue Übersicht anlegte, vergaß ihn zuverlässig und bekam nackte Links. Es steht jetzt einmal in components.css.
  • Sperrtext-Kürzung als gemeinsamer HelferSperrlistenText fasst das „erste 5 Einträge, dann ‚und N weitere'"-Muster zusammen, das zuvor dreifach fast identisch inline stand (Warnung, Abschnitte, Einsätze).

[4.7.0] — 2026-08-02

Fokus: Bevölkerungswarnung — Export im Original-Formular der Leitstelle Rhein-Sieg-Kreis (#208)

Die Kreisleitstelle des Rhein-Sieg-Kreises nimmt unser Standard-Dokument nicht an, sondern besteht auf ihrem eigenen Excel-Formular. Das ETB befüllt dieses Original-Formular jetzt maschinell aus der Warnung und bietet es als Download an — in Excel weiterhin bedienbar. Damit es sauber passt, wird die Gemeinde einmalig aus dem Formular selbst ausgewählt, eine neue Formular-Version der Leitstelle spielt der Administrator geprüft selbst ein, und der zu warnende Bereich ist wahlweise ein Umkreis oder die gesamte Gemeinde. Gilt die Warnung der ganzen Gemeinde — weil das in Feld 7 so gewählt ist oder weil unter den Warnbereichen (Feld 11) einer als „Gesamt" markiert ist —, zeichnen Lagekarte und die Karte des einzelnen Einsatzes den Umriss der Gemeinde statt eines Kreises; ohne gespeicherten Umriss bleibt die Fläche bewusst leer, ein Kreis wäre dort irreführend. Wer keine solche Vorgabe hat, merkt nichts: Das bisherige Dokument bleibt vollständig erhalten und ist weiter die Voreinstellung. Schema-Check nötig (/admin/schema-check.php → „Reparieren") — neue Spalte für die gespeicherte Auswahlreihenfolge der Warnbereiche (siehe „Behoben" unten).

Neu

  • Leitstellen-Formular als Excel-Download — Steht die Export-Vorlage auf Rhein-Sieg-Kreis, erscheint in der Warnungs-Ansicht ab der Freigabe der Knopf „Formular Leitstelle (Excel)" als Hauptknopf; „Dokument (PDF)" bleibt daneben erhalten. Das ETB füllt das Original-Formular der Leitstelle (F.1 Anlage A, Version 8.3) mit den Angaben der Warnung: anfordernde Stelle samt angekreuzter Organisationen, Koordinate im gewählten Format, Umkreis bzw. Verwaltungsbereich, Warnbereiche (positionsgetreu: der erste gewählte Bereich ins erste Feld, der zweite ins zweite, der dritte ins dritte), Warnstufe und Warnmittel-Empfänger als Kreuze, Warninhalt inkl. Zyklus-Kennzeichen in der Überschrift, Handlungsempfehlungen und Bürgerinformation. Layout, Logos und Druckbereiche des Originals bleiben unangetastet; die Datei trägt die Warnungsnummer im Namen (z. B. MoWaS-Anlage-A_E027-01.xlsx). Auch jeder archivierte Stand lässt sich so ausgeben („Formular Leitstelle (Excel) dieses Standes"). Das Formular hat fünf Zeilen für Handlungsempfehlungen — sind mehr erfasst, weist ein Hinweis neben dem Knopf darauf hin, dass die ersten fünf übernommen werden.
  • Einstellung „Export-Vorlage" — Unter Admin → Bevölkerungswarnung → Stammdaten wählst Du zwischen Standard-MoWaS-Formular (Voreinstellung, unser bisheriges Dokument) und MoWaS-Vorlage Rhein-Sieg-Kreis. Steht der Excel-Export auf dem Server nicht zur Verfügung (fehlende PHP-Erweiterung zip oder fehlende Vorlagendatei), erscheint dort ein Hinweis, der Excel-Knopf bleibt aus und es bleibt beim bisherigen Dokument.
  • Zugeordnete Gemeinde — einmalig im Admin festgelegt — Steht die Export-Vorlage auf Rhein-Sieg-Kreis, wählst Du unter Admin → Bevölkerungswarnung → Stammdaten Eure Gemeinde aus (Pflichtangabe). Die Auswahlliste stammt aus dem Leitstellen-Formular selbst; damit stehen der Gemeindename für Feld 2 und der Verwaltungsbereich-Code für Feld 7 B fest. Das Formular erwartet exakte Schreibweisen — passt der Name nicht, bleiben im erzeugten Excel die Auswahllisten der Warnbereiche leer. Der Wert wird je Warnung beim Speichern eingefroren, eine spätere Änderung wirkt also nicht rückwirkend auf archivierte Stände.
  • Feld 7: Umkreis oder gesamte Gemeinde — Der zu warnende Bereich ist jetzt eine Entscheidung zwischen Umkreis (Radius in Metern, wie bisher) und Gesamte Gemeinde; genau eine der beiden Angaben ist Pflicht, gespeichert wird nie beides. Bei Gesamte Gemeinde ist nichts einzutippen — es gilt die im Admin hinterlegte Gemeinde. Ist dort keine hinterlegt, ist die Möglichkeit gesperrt („nicht eingerichtet") und die Oberfläche erklärt, woran es liegt. Der Platzhalter {umkreis} in Meldungsvorlagen wird dann zum Gemeindenamen.
  • Neue Formular-Version selbst einspielen — Liefert der Kreis eine neue Version des Formulars, lädst Du sie bei aktiver Kreis-Vorlage direkt in den Stammdaten hoch. Sie wird zuerst geprüft und nur bei Kompatibilität übernommen: Ändern sich nur Inhalte (Gemeindeliste, Warnbezirke), bleibt die Vorlage gültig und die neuen Inhalte gelten; ändert sich die Struktur (verschobene Zellen, fehlende Ankreuzfelder), wird sie abgelehnt — dann ist eine Anpassung der Anwendung nötig. Geprüft wird immer serverseitig und beim Übernehmen erneut; jede Übernahme landet mit Dateiname und Prüfsumme im Protokoll. „Zur mitgelieferten Vorlage zurück" stellt jederzeit den Auslieferungsstand her. Bleibt der Gemeinde-Code gleich und ändert sich nur die Schreibweise des Namens, zieht das ETB die hinterlegte Gemeinde automatisch nach.
  • Gemeindegrenze auf den Karten — Betrifft eine Warnung die gesamte Gemeinde — weil das in Feld 7 so gewählt ist oder weil unter den Warnbereichen (Feld 11) einer als „Gesamt" markiert ist (z. B. „WAC-GESAMT") —, zeichnen die große Lagekarte und die Karte des einzelnen Einsatzes statt eines Kreises den Umriss der Gemeinde (gleiche Status-Farbe, gleiche Randlinie). Den Umriss holt der Administrator in den Stammdaten einmalig per Knopfdruck von OpenStreetMap und speichert ihn — nie automatisch im Hintergrund oder beim Kartenaufruf, mit Sperrfrist zwischen zwei Versuchen. Blockiert OpenStreetMap gerade (Rate-Limit), lässt sich der Umriss stattdessen als GeoJSON-Datei hochladen (z. B. Export von OpenStreetMap, einem kommunalen Geoportal oder QGIS) — die Fehlermeldung eines gescheiterten Abrufs weist auf diesen Rückfall hin, der Bereich dafür klappt dann von selbst auf. Erkannt werden eine FeatureCollection, ein einzelnes Feature oder eine nackte Geometrie; enthält die Datei mehrere Flächen, zählt die mit den meisten Stützpunkten (mit Hinweis in der Rückmeldung), eine Datei ganz ohne Fläche wird mit verständlicher Begründung abgelehnt. Die Statuszeile zeigt danach erkennbar „hochgeladen am …" statt „geholt am …", die Karten selbst zeichnen den Umriss unabhängig vom Zustandekommen identisch. Ohne gespeicherten Umriss zeigen die Karten für solche Warnungen nichts, statt ersatzweise einen Kreis zu zeichnen — der würde einen viel kleineren Bereich suggerieren, als tatsächlich gewarnt wird; das ist ein zulässiger Zustand.
  • Standardwerte für die Bürgerinformation (Feld 17) — Ansprechstelle, Bürgertelefon und Info-URL lassen sich in denselben Stammdaten hinterlegen und belegen jede neu angelegte Warnung vor; im Formular bleiben sie änderbar, leer gelassene Werte lassen die Felder leer. Bestehende Warnungen ändern sich dadurch nicht.

Geändert

  • Übermittlungs-Dialog nennt das richtige Dokument — Der Hinweis beim Klick auf „An Leitstelle übermitteln" spricht jetzt von dem Artefakt, das bei der eingestellten Export-Vorlage tatsächlich an die Leitstelle geht (Excel-Formular bzw. PDF-Dokument) — damit niemand versehentlich das falsche Dokument verschickt.
  • Ankreuzfelder über den internen Katalog-Schlüssel — Ob im Leitstellen-Formular das Kreuz bei einer Warnstufe oder einem Warnmittel-Empfänger landet, entscheidet der unveränderliche Key (intern) des Katalog-Eintrags (hoch/mittel/niedrig bzw. kritis/medien/warnmittel), nicht mehr das frei editierbare Label. Wer eigene Einträge anlegt, sollte diese Schlüssel verwenden — ein unbekannter Schlüssel lässt das Kreuz bewusst leer, statt das falsche zu setzen. Umbenannte Labels wirken sich dagegen nicht mehr aus.
  • Warnbereiche müssen zu den Codes des Leitstellen-Formulars passen — Das Formular kennt für die eigene Gemeinde eine feste Liste von Bereichs-Codes (z. B. WAC-01). Steht im Katalog ein anderer Wert, weist ihn das erzeugte Excel als ungültige Auswahl aus und die Klartext-Zeile darunter bleibt ohne Ortsnamen. Die Prüfung beim Einspielen einer neuen Formular-Version meldet solche Abweichungen als Hinweis.
  • Erzeugtes Excel bleibt bedienbar — Die heruntergeladene Datei rechnet beim Öffnen komplett neu durch. Dadurch funktionieren die Auswahllisten des Formulars (Warnbereiche) wie im leeren Original, und die Klartext-Zeilen unter den Bereichs-Feldern berechnen sich selbst aus den eingetragenen Codes — vorher blieb beides auf dem Stand der leeren Vorlage stehen.
  • Feld 7 heißt überall „Zu warnender Bereich" — In der Warnungs-Ansicht, in archivierten Ständen und im PDF-Dokument trägt die Zeile jetzt eine konstante Beschriftung; die Variante steckt im Wert („Umkreis 500 m" bzw. „Gesamte Gemeinde Wachtberg (18-WAC)"). Ein Wechsel der Variante zwischen zwei Zyklen bleibt eine erkannte Änderung und wird im Dokument rot markiert. Auch die Pflichtfeld-Meldung beim Einreichen nennt jetzt diesen Namen.
  • Kontext-Hilfe für die MoWaS-Stammdaten — Die Seite Admin → Bevölkerungswarnung → Stammdaten trägt jetzt wie die übrigen Seiten das „?" in der Aktionsleiste. Es öffnet das neue Handbuch-Thema MoWaS-Stammdaten, das jede Karte der Seite erklärt — Absender, Leitstelle, Bestätigung nach dem Versand, Export-Vorlage samt Gemeinde, Gemeindegrenze und Formular-Datei sowie die Standardwerte der Bürgerinformation. Das Kapitel Bevölkerungswarnung bleibt die fachliche Gesamtdarstellung und verweist auf die neue Seite.
  • Lagekarte: „Warn-Radien" heißen „Warnflächen" — Der Knopf „Warnungen" und der Unterfilter „Abgeschlossene zeigen" sprechen von Warnflächen, weil jetzt auch Gemeinde-Umrisse gezeichnet werden. Bedienung und Filter bleiben unverändert.

Behoben

  • Telefonnummern verloren beim Speichern ihre führende Null — Ein rein numerisch aussehender Einstellungswert (z. B. 0228123456 oder mit +-Vorwahl) wurde beim Lesen versehentlich in eine Zahl gewandelt und verlor dabei die führende Null bzw. das Pluszeichen. Betroffen waren u. a. die Rückrufnummer der Wehrleitung (Feld 5 „Ständige Erreichbarkeit" im MoWaS-Formular), die Leitstellen- und die Bürgertelefonnummer. Nummern mit Leerzeichen oder Bindestrich blieben unberührt — deshalb fiel der Fehler lange nicht auf.
  • Warnbereiche landeten nicht positionsgetreu im Leitstellen-Formular — Die drei Warnbereiche wurden nach Typ (eigen/Nachbar) statt nach ihrer Position im Melde-Formular verteilt: Warnbereich 1 = WAC-01 und Warnbereich 2 = WAC-02 (beides eigene Bereiche) landeten dadurch kommasepariert zusammengefasst im ersten Feld statt einzeln im ersten und zweiten. Jetzt zählt ausschließlich die Formular-Position — Warnbereich 1/2/3 landet 1:1 im ersten/zweiten/dritten Feld, unabhängig davon, ob es ein eigener oder ein Nachbarbereich ist.
  • Auswahlreihenfolge der Warnbereiche jetzt dauerhaft gespeichert — Der vorherige Fix (siehe oben) verteilte zwar positionsgetreu, verließ sich beim Auslesen aber noch auf die Katalog-Id als Behelfs-Sortierung, weil die Zuordnungstabelle keine eigene Reihenfolge-Spalte hatte. Das passte nur zufällig, wenn die drei Warnbereiche in aufsteigender Katalog-Reihenfolge gewählt wurden — bei Warnbereich 1 = eine höhere Id und Warnbereich 2 = eine niedrigere vertauschte die Anzeige die beiden im amtlichen Formular. Eine neue Spalte hält jetzt die tatsächliche Formular-Position fest, auch über „Zurückziehen" (verworfene Aktualisierung/Entwarnung) hinweg.
  • Karte des einzelnen Einsatzes zeichnet jetzt auch Warnflächen — Die Mini- und die Vollbild-Karte auf der Einsatz-Detailseite kannten bisher ausschließlich den Umkreis-Kreis einer Warnung; Flächen zeichnete allein die große Lagekarte. Beide Karten folgen jetzt derselben Entscheidungsregel, sodass dieselbe Warnung überall gleich dargestellt wird.
  • Gesamt-Warnbereich (Feld 11) wirkt jetzt wie „Gesamte Gemeinde" (Feld 7) — Ein unter Admin → Bevölkerungswarnung → Warnbereiche als „Gesamt" markierter Warnbereich (z. B. „WAC-GESAMT") erzwingt auf beiden Karten den Gemeinde-Umriss, selbst wenn in Feld 7 zusätzlich ein Umkreis eingetragen ist. Bisher zeigte die Karte in diesem Fall nur den Umkreis-Kreis — bei einer Warnung für die ganze Gemeinde nicht bloß unvollständig, sondern irreführend. Ein „Gesamt"-Warnbereich entspricht inhaltlich dem Verwaltungsbereich aus Feld 7 B: Es wird die ganze Gemeinde gewarnt.

Intern

  • Vorlagen-Prüfwerkzeugphp scripts/warnformular-vorlage.php pruefen [datei] prüft eine (neue) Formular-Datei der Leitstelle gegen unser Feld-Mapping (alle Zellanker, 13 Ankreuzfelder, keine vorgesetzten Haken) und zusätzlich Gemeinde-Helferformel, Gültigkeitsprüfungen der Warnbereichs-Felder und die Neuberechnungs-Einstellung. Struktur-Befunde (ohne Code-Anpassung nicht behebbar) meldet es getrennt von Inhalts-Hinweisen (Datei bleibt gültig). Ohne Pfad prüft es die gerade aktive Vorlage — also eine im Admin übernommene, sonst die mitgelieferte. Die Alternative zum Einspielen über die Oberfläche.
  • Übernommene Vorlage & Gemeindegrenze unter storage/warnformular/ — beides liegt außerhalb des Web-Verzeichnisses, ist gitignored und wird von beiden Deploy-Wegen ausgespart; es übersteht damit ein Update und ist jederzeit neu erzeugbar.
  • Kreis oder Fläche — eine gemeinsame Entscheidungsregel — Ob eine Warnung als Umkreis-Kreis oder als Gemeinde-Umriss erscheint, entscheidet für beide Karten dieselbe Stelle (WarnungService::warnDarstellung(), ohne Datenbankzugriff und damit direkt testbar). Die Lagekarte ermittelt dabei in derselben Abfrage mit, ob eine Warnung einen „Gesamt"-Warnbereich trägt (kein N+1); die Einzel-Einsatz-Karte fragt es für ihre eine Warnung gezielt ab.
  • CI — der Test-Job installiert zusätzlich die PHP-Erweiterung zip, damit die Formular-Tests echte XLSX-Pakete erzeugen statt zu überspringen.

[4.6.0] — 2026-07-24

Fokus: Bevölkerungswarnung (MoWaS) — Meldeformular mit Freigabe-Workflow, Zyklen & Historisierung (#208)

Neu

  • Bevölkerungswarnung (MoWaS) — Das ETB kann jetzt das Anforderungsformular für eine Bevölkerungswarnung über das Modulare Warnsystem (MoWaS) erfassen, freigeben und als Dokument erzeugen. Eine Warnung wird an einem Einsatz oder Schwerpunkt gestartet (Button „Bevölkerungswarnung"), die Felder werden aus dem Einsatz und den Stammdaten vorbelegt und bleiben editierbar. Das Melde-Formular führt in fünf Abschnitten (Absender, Gefahrenbereich, Warnstufe & Empfänger, Warninhalt, Bürgerinformation) durch die Erfassung; die Abschnitte schalten sich der Reihe nach frei, und die Pflichtfelder werden beim Einreichen streng geprüft (nach dem Original-Meldeformular). Die Warnung wird nicht automatisch versendet — das ETB erzeugt nur das Dokument, Übermittlung und telefonische Bestätigung bleiben beim Menschen.
  • Ablauf als Phase × Zyklus mit Vier-Augen-Freigabe — Jede Warnung durchläuft je Zyklus (Erstwarnung → Aktualisierung 1…n → Entwarnung) dieselben Phasen Entwurf → Zur Freigabe → Freigegeben → Bei Leitstelle → Aktiv. Die Rolle Lage erstellt, reicht ein, übermittelt und löst aus; die Rolle Einsatzleiter gibt frei und schließt ab. Die Freigabe und der Abschluss erfordern in jedem Zyklus das Vier-Augen-Prinzip (freigebende ≠ einreichende Person; Administrator kann übersteuern, wird protokolliert). Eine Freigabe lässt sich vor der Übermittlung widerrufen, eine begonnene Aktualisierung/Entwarnung vor der Übermittlung verwerfen. Ab „Zur Freigabe" ist die Warnung revisionsfest; das versandfertige PDF-Dokument entsteht ab „Freigegeben" per Druckdialog.
  • Drei neue Rechtemowas.view (Standard: Lage, Einsatzleiter und Disponent — reines Leserecht) / mowas.create (Standard: Lage) / mowas.release (Standard: Einsatzleiter). Für Schwerpunkt-Dispo und Gast sind die MoWaS-Rechte bewusst nicht zuweisbar (Warnungen tragen keinen Scope-Filter — sonst sähe ein scope-beschränkter Nutzer alle Warnungen inkl. Kontaktdaten).
  • Schwerpunkt-Anbindung — In der Schwerpunkt-Titelleiste (zwischen Bearbeiten und Erledigen) startest Du eine Warnung für die Großlage. Ein Dialog „Basis-Einsatz wählen" übernimmt Adresse/Koordinaten eines zugewiesenen Einsatzes als Vorlage; gebunden wird die Warnung an den Schwerpunkt. Einsätze, die einem Schwerpunkt zugeordnet sind, lösen keine eigene Warnung mehr aus — die Lage läuft über den Schwerpunkt.
  • Gefahrenbereich & Warnbereiche — Vier Koordinatenformate (Dezimalgrad als Standard, Grad/Minuten/Sekunden, UTM 32U, what3words aus den Einsatz-Geodaten), ein Umkreis als Pflichtangabe und bis zu drei Warnbereiche: das erste Feld listet nur die eigenen Bereiche, die Folge-Felder zusätzlich die Nachbarn; ein als „Gesamt" markierter eigener Bereich (ganze Gemeinde) schränkt die Folge-Felder auf Nachbarn ein.
  • Handlungsempfehlungen als editierbarer Text — Statt fester Verweise sind Handlungsempfehlungen jetzt freier Text: über ein Auswahl-Fenster (nach Ereignis filterbar) übernimmst Du mehrere Katalog-Sätze auf einmal oder fügst eigene hinzu. Ihre Zahl ist auf ein im Admin einstellbares Maximum (Standard 5) begrenzt.
  • Meldungsvorlagen mit Platzhaltern — Ziehst Du eine Vorlage, werden Überschrift, Warntext und die hinterlegten Handlungsempfehlungen als editierbarer Vorschlag übernommen; Platzhalter ({ortslage}, {adresse}, {umkreis}, {url}, {telefon}) werden durch Deine Angaben ersetzt.
  • Administrierbare Kataloge, Stammdaten & Musterdaten-Loader — Unter Admin → Bevölkerungswarnung pflegst Du Kategorien, Warnstufen (mit Farben), Empfänger, Umkreis-Stufen, Warnbereiche (eigen/Nachbar/„Gesamt"), Ereignisse, Meldungsvorlagen und Handlungsempfehlungen sowie die Absender- Stammdaten (Gemeinde, Wehrleiter, Leitstellen-Kontakt, Max. HE). Die Grundlisten sind mit dem bundesweiten MoWaS-Standard vorbelegt; die Textbausteine (Handlungsempfehlungen, Ereignisse, Meldungsvorlagen) starten leer und werden per Knopfdruck als Musterdaten geladen — additiv oder mit der Option „Vorhandene zuerst löschen" als sauberer Neuaufbau (die Grundlisten-Kategorien bleiben dabei erhalten).
  • Historisierung — Jede Übermittlung an die Leitstelle wird als revisionsfester Stand archiviert; der Block „Übermittelte Stände" listet alle Zyklen mit Link zum jeweiligen Stand. Bei Übermittlung, Auslösung und Abschluss schreibt das ETB zusätzlich einen revisionsfesten System-Kommentar mit Stand-Link in den Verlauf des gebundenen Einsatzes.
  • Warn-Indikator & Warn-Radien — Ein Zivilschutz-Zeichen signalisiert in Einsatz-Liste/-Detail und in der Schwerpunkt-Liste/-Titelleiste, dass eine Warnung existiert; der farbige Ring zeigt den Status (blau/gelb/orange/rot/ grün/grau), ein Klick führt zur Warnung. Auf der Lagekarte und der Mini-Karte im Einsatz-Detail wird der Warn-Radius in der Status-Farbe gezeichnet (auf der Lagekarte über den Knopf „Warnungen" ein-/ausblendbar).
  • Mehrere warnende Organisationen — Im Absender lassen sich mehrere Stellen ankreuzen (Feuerwehr vorausgewählt) statt nur einer.
  • Automatisch gekennzeichnete Folgemeldungen — Startest Du eine Aktualisierung oder die Entwarnung, trägt das ETB die Überschrift als AKTUALISIERUNG X – <bisherige Überschrift> bzw. ENTWARNUNG – <bisherige Überschrift> ein. Die Leitstelle erkennt so sofort den Bezug; die Überschrift bleibt editierbar und Kennzeichen stapeln sich über mehrere Zyklen nicht.
  • Warnstufen-Farbe im Melde-Dokument — Wie im Original-Formular sind die Zeilen der Sektion „Warnstufe & Empfänger" (Empfänger, Cell Broadcast, Warnsirenen) in der Farbe der gewählten Warnstufe hinterlegt; die Farbe wird beim Einreichen mit eingefroren, damit archivierte Stände farbtreu bleiben.
  • Bestätigung nach dem Versand — Verlangt die Leitstelle eine telefonische Rückbestätigung, hinterlegst Du das in den MoWaS-Stammdaten (Schalter, Telefonnummer, optionale Rufgruppe). Beim Klick auf „An Leitstelle übermitteln" führt das ETB dann die nötigen Schritte samt Kontaktdaten auf.
  • Koordinate aus der Adresse ermitteln — Im Melde-Formular sitzt neben dem Karten-Mittelpunkt ein Knopf, der die Koordinate aus der Adresse (Feld 3) geocodiert — über denselben Dienst wie der Einsatz (inkl. Zwischenspeicher) — und Dezimalgrad, Grad/Minuten/Sekunden und UTM aktualisiert. what3words bleibt unangetastet (kostenpflichtiger Abruf).
  • Änderungen für die Leitstelle sichtbar — Bei einer Aktualisierung oder Entwarnung sind im Melde-Dokument die Zeilennummern rot markiert, deren Inhalt sich gegenüber der vorherigen übermittelten Meldung geändert hat; ein Hinweis im Kopf erklärt die Markierung. Die Erstwarnung bleibt unmarkiert.
  • MoWaS-Logo und Zyklus im Melde-Dokument — Der Kopf trägt jetzt das MoWaS-Logo sowie die Angabe, ob es sich um die Erstwarnung, eine Aktualisierung X oder die Entwarnung handelt.
  • Interne Warnungsnummer — Jede Warnung bekommt beim Anlegen eine feste Nummer nach dem Schema E#027-01 (erste Warnung zum Einsatz 027) bzw. SP#001-02 (zweite Warnung zum Schwerpunkt 001). Die laufende Nummer zählt Warnungen, nicht Zyklen — eine Aktualisierung behält ihre Nummer. Sie erscheint in der Übersicht, auf der Detailseite, im Brotkrumen-Pfad und in der Fußzeile des Melde-Dokuments. Die Übersicht zeigt sie als eigene Spalte, ist nach Bindung getrennt (Einsätze oben, Schwerpunkte darunter) und je Liste aufsteigend nach Nummer sortiert — ein Klick auf den Spaltenkopf „Nummer" kehrt die Reihenfolge um. Die frühere Spalte „Bindung" entfällt dadurch.
  • Archivierte Stände als Melde-Dokument drucken — In der Stand-Ansicht öffnet „Dokument (PDF) dieses Standes" das Melde-Formular im Druck-Layout mit den damals übermittelten Daten (statt wie bisher nur den Browser-Druck der Detailansicht auszulösen).
  • Lagekarte merkt sich Deine Einstellungen — Ansicht, „Nur offene", Wichtigkeits-Filter, Einsatzmittel-Gruppe, Schwerpunkt-Schalter, der Warnungen-Layer samt Unterfilter und das Live-Intervall werden im Browser gespeichert und beim nächsten Öffnen wiederhergestellt.

Marke & Erscheinungsbild

  • Neuer Produktname: „ETB – Das Einsatztagebuch" — Das Produkt der Firma BrunSoft heißt ab sofort durchgängig ETB – Das Einsatztagebuch, kurz ETB. Handbuch, README, Changelog und Wiki sprechen einheitlich diesen Namen; für Dich als Anwender ändert sich nichts an der Bedienung.
  • Neue Standard-Bilder (ETB-Logo) — Logo, Menü-Logo und Favicon werden jetzt im neuen ETB-Erscheinungsbild ausgeliefert (etb-logo.png, etb-menu.png, etb-favicon.png); die bisherigen BrunSoft-Bilder sind entfallen. Hat Deine Wehr unter Admin → Branding eigene Bilder hochgeladen, bleiben diese unverändert bestehen — nur wer den ausgelieferten Standard nutzt, sieht das neue Logo. Alte Standard-Pfade in der Konfiguration werden beim Schema-Check automatisch auf den neuen Standard zurückgesetzt (und greifen auch ohne Schema-Check sofort).

Behoben

  • Warnkreis eines gelöschten Einsatzes blieb auf der Lagekarte stehen — Seit die Radien unabhängig von den Markern geladen werden, überlebte der Kreis das Löschen seines Einsatzes. Es werden jetzt nur noch Warnungen gezeichnet, deren Einsatz bzw. Schwerpunkt es wirklich (noch) gibt.
  • Warnkreis blieb bei geänderter Koordinate an der alten Stelle — Der Mittelpunkt des Warnkreises stammte aus den Geodaten des Einsatzes und wurde beim Anlegen der Warnung einmalig kopiert; das sichtbare Koordinaten-Feld änderte nur den Text im Meldeformular. Jetzt ist die Dezimalgrad-Eingabe führend: änderst Du die Koordinate, wandert der Kreis mit. Für Grad/Minuten/Sekunden, UTM und what3words (nicht zurückrechenbar) gibt es im Formular die neuen Felder Karten-Mittelpunkt (Breite/Länge) zum Ändern von Hand.
  • Lagekarte zeigte nicht alle Warn-Radien — Die Radien wurden aus den sichtbaren Markern abgeleitet. Dadurch fehlten sie, sobald der zugehörige Einsatz keine eigenen Koordinaten hatte oder über „Nur offene" ausgeblendet war — und bei Schwerpunkten, sobald der Schwerpunkt gar keinen Marker bekam (kein geokodierter Einsatz bzw. Status außerhalb aktiv/pausiert). Die Radien werden jetzt unabhängig von den Markern aus den Warnungen selbst geladen; je Einsatz bzw. Schwerpunkt erscheint der jeweils relevanteste Stand. Zur Unterscheidung ist die Randlinie durchgezogen (Einsatz) bzw. gestrichelt (Schwerpunkt); ein Unterfilter blendet abgeschlossene Warnungen aus.

Geändert

  • Update-Hinweis: einmaliger Schema-Check nötig (/admin/schema-check.php → „Reparieren") — legt die neuen MoWaS-Tabellen (Warnungen, Kataloge, Zuordnungen, Versionen, Audit) und die Konfigurations-Werte an.
  • MoWaS-Leitstelle als eigene Stammdaten — die Leitstelle, die die Bevölkerungswarnung empfängt, wird jetzt vollständig (Bezeichnung, Anschrift, E-Mail, Fax) unter Admin → Bevölkerungswarnung → Stammdaten gepflegt — bewusst getrennt von der Funkzentrale des Einsatzbetriebs.
  • Melde-Dokument (PDF) übersichtlicher — Cell Broadcast und Warnsirenen (10/11), Kategorie und Ereignis (12/13) sowie die Bürgerinformation (17: Ansprechstelle, Telefon, URL) stehen je in eigenen Zeilen; die Handlungsempfehlungen (16) sind wie die übrigen Felder als nummerierte Zeile mit Liste formatiert.
  • Behoben: Beim Ansehen einer Warnung erzeugte das Hauptmenü eine horizontale Laufleiste (der Seitenrahmen erbte auf dieser Seite keinen box-sizing-Reset) — jetzt zentral in der Sidebar abgesichert. Gleiches Härten im Snapshot-Ansicht („Stand ansehen").
  • Telegram-Webhook-URL konfigurierbar — die Webhook-Status-Seite nutzt jetzt TELEGRAM_WEBHOOK_URL aus der Konfiguration (Setup-Assistent bzw. config/.env) statt einer fest verdrahteten Adresse; ohne konfigurierte URL ist „Webhook setzen" gesperrt.
  • Ortsneutrale Beispiele — Platzhalter, Hilfe-Beispiele und Vorschau-Daten sind jetzt generisch („Musterstadt"/„Musterdorf"); der Geocoding-Bias nutzt die konfigurierte Gemeinde. Instanz-Daten (Orte, Löschgruppen …) bleiben unberührt.
  • Schwerpunkt-Warnungen im SP-Verlauf — eine an einen Schwerpunkt gebundene Warnung dokumentiert Übermittlung, Auslösung und Abschluss jetzt in der Schwerpunkt-Historie (mit klickbarem Link zum jeweiligen Stand), analog zum System-Kommentar am gebundenen Einsatz.

[4.5.1] — 2026-07-21

Fokus: Layout- & Modal-Aufräumen (#200 komplett) — überwiegend interner Refactor, dazu eine kleine Barrierefreiheits-Verbesserung

Barrierefreiheit & Bedienung

  • Modal-Tastaturbedienung vereinheitlicht (#200-A) — In den beiden Fenstern der Schwerpunkt-Einstellungen („+ Einsätze zuweisen" und „+ SP-Dispo anlegen") bleibt der Tastatur-Fokus jetzt im offenen Dialog: Tab und Shift-Tab wandern nicht mehr hinter das Fenster in den verdeckten Seiteninhalt — genau wie es die übrigen Dialoge des ETB schon hielten (WCAG 2.4.3 / 2.1.2). ESC schließt den Dialog, und das Schließen-X sitzt jetzt app-weit einheitlich oben rechts im Fenster.
  • Sauberere Adresszeile bei Statusmeldungen (#200-B2) — Erfolgsmeldungen wie „Stammdaten aktualisiert." laufen nicht mehr über einen sichtbaren ?msg=…-Parameter in der URL, sondern über einen einmaligen Sitzungs-Hinweis. Die Meldung selbst ist unverändert — nur die Adresszeile bleibt nach dem Speichern sauber.

Intern (Refactoring)

  • Seitenrahmen der Sidebar-Seiten zentralisiert (#200-B1) — der bislang auf rund 40 Seiten (Dashboard, Einsatz-, Abschnitts- und Schwerpunkt-Seiten sowie alle Admin-Seiten) von Hand kopierte Seitenrahmen — vom <!DOCTYPE> über den <head> mit den zentralen Kopf-Assets bis zum öffnenden <div class="layout-main"> samt der schließenden Tags am Seitenende — sitzt jetzt in drei neuen Helfern MainNavSidebar::pageHead(), pageBody() und pageEnd(). Die Seiten rufen diese Helfer auf, statt den Rahmen-Boilerplate zu wiederholen (unterm Strich rund 490 Zeilen weniger Quelltext). Rein internes Refactoring: kein funktionaler, bedienungs- oder optischer Unterschied — die App sieht und verhält sich exakt wie zuvor. Kein Schema-Check nötig.
  • flash()-Helfer statt ?msg=-URL-Parameter (#200-B2) — Erfolgsmeldungen legt der neue MainNavSidebar::flash()/flashPop()-Helfer nach dem Post/Redirect/Get-Muster in die Session; über 50 Redirects auf 16 Seiten sind vom bisherigen ?msg=<key>-Muster (samt des seiteneigenen Text-match()) darauf umgestellt. Gleiche Meldungen, nur ohne Query-Parameter in der Adresszeile.
  • sp_url()-Helfer auf die Einsatzübersicht ausgeweitet (#200-C) — die Kontext-Links der Einsatz-Übersicht („+ Neuer Einsatz", „Zurücksetzen", „Alle anzeigen", „neuen Einsatz anlegen") tragen den Schwerpunkt-Kontext ?schwerpunkt=… jetzt über den zentralen sp_url()-Helfer weiter, statt ihn von Hand anzuhängen — identische Ziel-Links.
  • Modal-Schließen-X vereinheitlicht (#200-A1) — die zuvor drei eigenen Close-X-Stile (.dlg-close, .abm-close, .em-dlg-close) weichen dem einen geteilten .modal-x (absolut positioniert oben rechts, token-basiert inkl. Dark-Mode). Weniger CSS, überall dasselbe X.
  • Modal-Öffnen/-Schließen auf einen Helfer vereinheitlicht (#200-A2) — der neue EtbModal-Helfer führt die bislang drei divergenten Anzeige-Mechaniken (hidden-Attribut / .is-open-Klasse / inline style.display) auf eine zusammen (das hidden-Attribut) und zentralisiert ESC-zu-Schließen sowie die Fokus-Rückgabe an das auslösende Element. Verhaltensneutral.
  • Fokusfalle der Modals zentralisiert (#200-A3) — die zuvor kopierte Tab-Fokusfalle liegt jetzt einmal zentral (opt-in per [data-autotrap]). Nebeneffekt ist die oben genannte Barrierefreiheits-Verbesserung: die beiden Schwerpunkt-Einstellungen-Fenster bekommen die Falle, die ihnen bisher fehlte.

Damit ist #200 vollständig in 4.5.1 — es folgt bewusst kein Rest mehr in 4.6.


4.5.0 — 2026-07-21

Fokus: Rechte-Drifts schließen & härten, Aufräumen im Hintergrund, mobil ohne Netz, Hydrantenplan aus eigenen Daten, Kurz-Standort je Einsatz

Neu

  • Kurz-Standort je Einsatz: Plus Codes & what3words (#186) — jeder Einsatz bekommt jetzt optional ein kompaktes Standort-Kürzel, automatisch aus den GPS-Koordinaten abgeleitet — zusätzlich zur Adresse. Zwei Anbieter, unter Einstellungen einzeln zuschaltbar und beide standardmäßig aus:

    • Plus Codes (Open Location Code, Google) werden komplett offline berechnet — kein Schlüssel, keine Kosten, kein externer Abruf.
    • what3words ist schon ohne Schlüssel nutzbar: Die drei Wörter (z. B. der vom Anrufer genannte Wert) lassen sich von Hand eintragen, werden angezeigt und verlinkt — kostenlos, kein Abruf. Ein kostenpflichtiger API-Schlüssel (der Gratis-Plan kann die Umwandlung seit 25.11.2024 nicht) schaltet zusätzlich die automatische Umwandlung aus den Koordinaten, den Live-Check, das Kontingent und den Pro-Einsatz-Deckel frei; jeder automatische Abruf zählt dann gegen Dein Kontingent. Ein von Hand eingetragener Wert bleibt bei einer Koordinaten-Änderung stehen.

    Beide Kürzel sind in Übersicht, Detail und Geocode-Liste anklickbar und öffnen den Ort auf plus.codes bzw. what3words.com im neuen Tab. Sichtbar in der Einsatz-Übersicht (ein im Admin wählbares Primär-Format hinter Ort/Straße), im Einsatz-Detail (beide aktiven Formate in einer eigenen „Kurz-Standort"-Zeile) und in der Geocode-Liste (als Zweitzeile, dort auch von Hand überschreibbar). Beim Bearbeiten kannst Du statt GPS auch einen Plus Code (offline) oder — mit Schlüssel — eine what3words-Adresse als Koordinaten-Quelle eingeben (Priorität GPS > Plus Code > what3words); das ETB rechnet danach alle Werte frisch nach (bidirektionale Angleichung), sodass GPS, UTM und die Kürzel nie auseinanderlaufen. Ein neues Panel unter Einstellungen zeigt den Schlüssel- Status, prüft ihn auf Knopfdruck (Verbindungstest = 1 realer what3words- Aufruf, der aber nicht gegen den lokalen Zähler zählt) und führt einen Monatszähler; die Karte „what3words-Kontingent" im System-Status und der Tages-Heartbeat warnen ab 80 % eines optional hinterlegten Limits. Kosten-Disziplin: what3words wird nur bei tatsächlicher Koordinaten-Änderung neu abgerufen (ein Edit ohne Standort-Änderung kostet nichts); zusätzlich schützt ein Pro-Einsatz-Deckel (Standard 5, konfigurierbar) davor, dass an einem Einsatz durch wiederholtes Neusetzen der Koordinaten beliebig viele Abrufe anfallen — nach dem Deckel wird der what3words-Wert eingefroren (Plus Code und GPS laufen weiter). In der Geocode-Liste lassen sich Plus Code und what3words außerdem von Hand überschreiben — das schreibt direkt ohne API-Aufruf und gibt einen eingefrorenen Einsatz wieder frei. Der Schlüssel gehört als W3W_API_KEY in config/.env, nie in die Datenbank. Update-Hinweis: einmaliger Schema-Check legt die neuen Spalten plus_code/w3w/w3w_derive_count an und trägt für Bestandseinsätze den Plus Code offline nach; what3words wird zum Kostenschutz bewusst nicht rückwirkend befüllt.

  • Hydrantenplan aus einer eigenen Datei statt Google MyMaps (#181) — die Wasserentnahmestellen kamen bisher aus einer Google-MyMaps-Karte — ein Überbleibsel aus dem ursprünglichen Einsatztagebuch. Jetzt lädst Du unter Administration → Feuerwehr → Hydrantenplan eine eigene GeoJSON-Datei hoch; es wird nichts mehr aus dem Internet nachgeladen, die Daten gehören der Wehr. Der Upload ist zweistufig und sicher: Datei prüfenVorschau (wie viele Hydranten gelesen, wie viele ohne Dimension bzw. ohne Ort, wie viele verworfen und warum) → erst Übernehmen ersetzt den bisherigen Plan; bis dahin bleibt alles unverändert. Das Format ist tolerant: Pflicht ist nur name, dazu werden dimension (Nennweite in mm), ort und beschreibung gelesen — samt gängiger Alternativbezeichnungen (nennweite/dn/durchmesser, ortsteil/gemeinde/stadtteil, bemerkung/info); fehlt die Dimension als eigenes Feld, wird sie notfalls aus dem Namen gelesen („H150", „DN 200"). Hydranten ohne Ort landen unter „(ohne Ort)". Eine Beispieldatei steht zum Download bereit. Für den Umstieg gibt es den Knopf „Bestand als eigene Daten übernehmen": Solange noch keine eigene Datei hochgeladen wurde, übernimmst Du damit den bisher angezeigten Plan eins zu eins, ohne etwas neu beschaffen zu müssen. Siehe Hydrantenplan verwalten und Hydrantenplan. Kein Schema-Check nötig.

  • Dimensionsklassen des Hydrantenplans frei konfigurierbar (#181) — auf derselben Seite stellst Du jetzt ein, ab welcher Nennweite ein Hydrant als klein / mittel / groß / XL gilt (drei Schwellen in mm) und wie jede Klasse heißt und aussieht (Bezeichnung + Farbe). Änderungen wirken sofort auf allen Karten — dem Standalone-Hydrantenplan und dem Hydranten-Overlay der Lagekarte in der Einsatz-Detailansicht —, ohne dass die hochgeladenen Daten neu eingelesen werden müssen: In der Datei steht nur die Nennweite, die Klasse berechnet das ETB bei jeder Anzeige aus den aktuellen Schwellen. Lässt Du die Bezeichnung leer, folgt sie automatisch den Schwellen (z. B. „Mittel (150–199)"). Die Schwellen müssen positiv und aufsteigend sein (klein < mittel < groß). Siehe Hydrantenplan verwalten. Kein Schema-Check nötig.

  • Freundliche Offline-Seite statt Browser-Fehlermeldung (#195) — verlierst Du unterwegs die Verbindung, zeigt das ETB jetzt eine eigene Seite „Keine Verbindung" im gewohnten Erscheinungsbild (hell/dunkel je nach Gerät) statt der nackten Browser-Fehlerseite. Sie bietet einen „Erneut versuchen"-Knopf und eine kurze Rückmeldung darunter („Immer noch keine Verbindung (Stand 14:12)." bzw. „Verbindung ist zurück — Du kannst neu laden."). Besonders in der installierten App (PWA) hilft das: Dort gibt es keine Adressleiste als Ausweg. An der bewussten Nicht-Offline-Fähigkeit ändert sich nichts — es gibt weiterhin keine Offline-Speicherung: Was im Moment des Verbindungsverlusts abgeschickt wurde, ist nicht gespeichert und wird auch später nicht nachgereicht; es muss nachgetragen werden. Die Seite sagt das ausdrücklich. Voraussetzung sind HTTPS und ein vorheriger Aufruf mit Netz. Siehe ETB auf Smartphone & Tablet. Kein Schema-Check nötig.

  • Sprungknopf „Zu den Einsatzmitteln" auf schmalen Bildschirmen (#195) — am Handy und am Tablet im Hochformat steht die Einsatzmittel-Seitenleiste unter dem Inhalt; bei einer langen Einsatzliste musste man erst an der ganzen Liste vorbeiscrollen, um an einen EM-Chip zu kommen. Jetzt steht dort oben ein Knopf „🚒 Zu den Einsatzmitteln", der direkt dorthin springt (und den Tastatur-/Vorlese-Fokus mitnimmt). Er erscheint automatisch nur im einspaltigen Layout — am breiten Bildschirm, wo die Seitenleiste ohnehin daneben steht, bleibt er unsichtbar. Verfügbar in Einsatz-Übersicht, Einsatz-Detail und Abschnitt. Kein Schema-Check nötig.

  • Karte „Export-Bild-Cache" im System-Status (#203) — die Seite System-Status zeigt jetzt, wie viel Platz die verkleinerten Bild-Fassungen des PDF-Exports belegen (Größe, Anzahl, Obergrenze 250 MB, Alter des ältesten Eintrags) — mit Ampel „unkritisch" / „fast voll". Es gibt nichts zu tun: Der Ordner ist ein reiner Zwischenspeicher, der sich selbst aufräumt (siehe unten). Die Anzeige ist das Frühwarnsystem für den Fall, dass der Tages-Heartbeat auf einer Instanz gar nicht eingerichtet ist. Kein Schema-Check nötig.

Geändert

  • Sanfter Hinweis statt Fehlerseite, wenn nach einem Update ein Datenbank-Feld fehlt — direkt nach einem Update liegt für einen kurzen Moment schon der neue Programmstand auf dem Server, während der Schema-Check die neuen Felder noch nicht angelegt hat. Bisher brach eine betroffene Seite (z. B. die Einsatzliste) dann mit einer harten Fehlerseite ab. Jetzt erscheint stattdessen eine freundliche Zwischenseite mit einem direkten Link zur Schema-Prüfung („Reparieren") — die Daten bleiben unberührt, ein Klick genügt. Betrifft nur dieses Update-Zeitfenster; im Normalbetrieb ändert sich nichts.

  • Status setzen verlangt jetzt überall das Recht „Status setzen" (#201) — an mehreren Stellen genügte bisher das breitere Recht „Einsatz bearbeiten" (einsatz.edit), um den Status eines Einsatzes zu ändern, während andere Stellen bereits korrekt einsatz.status verlangten. Jetzt gilt einheitlich einsatz.status: für das Status-Dropdown in der Einsatz-Übersicht und deren Sammelaktion „Status", für das Dropdown auf der Einsatz-Detailseite, für das Status-Feld im Bearbeiten-Formular sowie serverseitig in den Schnittstellen dahinter. Der Knopf „Einsätze abschließen" (Abschluss-Arbeitsplatz) verlangt jetzt folgerichtig einsatz.abschluss und einsatz.status — Abschließen ist ein Status-Wechsel, einsatz.abschluss ist das zusätzliche Vier-Augen-Recht obendrauf, kein Ersatz. Unverändert bleiben die automatischen Übergänge: Wer einen Disponenten bzw. ein Einsatzmittel zuweisen darf, schiebt den Einsatz damit weiterhin auf „Disponent" bzw. „In Bearbeitung" — der Status folgt dort der Arbeit. Mehr unter Status & Lebenszyklus und Permission-Matrix. Kein Schema-Check nötig.

  • Verhaltensänderung für selbst gebaute Rollen (#201) — eine Rolle mit einsatz.edit, aber ohne einsatz.status, kann den Status jetzt nicht mehr setzen. Sie sieht die Status-Umschalter in Liste, Detail und Bulk-Leiste gar nicht erst, und im Bearbeiten-Formular steht der Status nur noch als Klartext statt als Auswahl — alle übrigen Felder bleiben normal bearbeitbar. Alle Standard-Rollen tragen beide Rechte, für sie ändert sich nichts. Betroffen sind ausschließlich individuell zugeschnittene Rollen: Prüfe sie nach dem Update im Rollen-Editor und setze das Häkchen „Status setzen" dazu, wenn die Rolle den Status weiterhin ändern können soll.

  • EM-Zuweisung an Abschnitte hängt auf allen Wegen am Recht „EMs zu Abschnitt zuweisen" (#202)abschnitt.em_assign galt bisher nur für den Hauptweg (Drop-Zone auf der Abschnitts-Seite). Zwei Nebenwege liefen daran vorbei: die Einsatzmittel-Vorbelegung im Modal „Abschnitte bilden" und ein optionaler Abschnitts-Anteil beim Zuweisen eines EM zum Einsatz. Beide verlangen das Recht jetzt ebenfalls. Fehlt es, läuft die Hauptaktion weiter — die Abschnitte entstehen, das EM hängt am Einsatz —, nur der Abschnitts-Anteil entfällt, und die Rückmeldung sagt das ausdrücklich („… dafür fehlt Dir die Berechtigung.") statt es still zu verschlucken. Die Standard-Rollen, die Abschnitte bilden dürfen, haben das Recht ohnehin; für sie ändert sich nichts. Kein Schema-Check nötig.

  • Status beim Anlegen eines Einsatzes verlangt jetzt dieselben Rechte (#204) — bisher konnte jeder mit „Einsatz anlegen" (einsatz.create) einen beliebigen Status vergeben, auch Abgeschlossen: Das Formular bot die Auswahl zwar nur mit den passenden Rechten an, angenommen wurde sie aber trotzdem — damit ließ sich das Vier-Augen-Prinzip beim Anlegen umgehen. Jetzt gilt: Ein von Neu abweichender Status verlangt „Status setzen" (einsatz.status), der Wert Abgeschlossen zusätzlich „Einsatz abschließen" (einsatz.abschluss). Wer einen Einsatz direkt als Erledigt oder Abgeschlossen anlegt, wird jetzt außerdem als „Erledigt von" bzw. „Abgeschlossen von" vermerkt — bisher blieben diese Angaben bei solchen Nachträgen leer. Unverändert: Der automatische Sprung auf „Disponent" beim Anlegen mit Disponent verlangt weiterhin kein zusätzliches Recht, und Einsätze aus Alarm-Mails entstehen wie bisher immer als „Neu". Mehr unter Status & Lebenszyklus und Einsatz anlegen & bearbeiten. Kein Schema-Check nötig.

  • Das Recht „Abschnitt anlegen" wirkt jetzt tatsächlich (#205)abschnitt.create stand seit jeher im Rollen-Editor und ließ sich an- und abwählen, geprüft hat es aber niemand: Zum Bilden von Abschnitten genügte faktisch „Einsatz bearbeiten", das Häkchen war wirkungslos. Die Oberfläche versprach damit eine Steuerbarkeit, die es nicht gab. Jetzt verlangt das Anlegen beides: einsatz.edit (darf an diesem Einsatz überhaupt arbeiten) und abschnitt.create (darf Abschnitte anlegen). Fehlt eines von beiden, erscheinen der Knopf „Abschnitte bilden" bzw. „Abschnitt hinzufügen" und das zugehörige Fenster auf der Einsatz-Detailseite gar nicht erst, und die Schnittstelle dahinter weist den Versuch ebenfalls ab. Siehe Abschnitt-Detail und Permission-Matrix. Kein Schema-Check nötig.

  • Verhaltensänderung für selbst gebaute Rollen (#205) — alle Standard-Rollen, die Abschnitte bilden dürfen (Lage, Einsatzleiter, Dispo, SP-Dispo; Administrator über den Failsafe), tragen einsatz.edit und abschnitt.create gemeinsam — für sie ändert sich nichts. Betroffen sind ausschließlich individuell zugeschnittene Rollen, und zwar in beide Richtungen: Wer bei einer eigenen Rolle „Abschnitt anlegen" abgewählt hatte (in der Annahme, das tue etwas), verliert die Funktion jetzt wirklich — setze das Häkchen im Rollen-Editor wieder, wenn die Rolle Abschnitte bilden können soll. Wer umgekehrt „Einsatz bearbeiten" abgewählt, „Abschnitt anlegen" aber stehen gelassen hatte, gewinnt dadurch keine Rechte dazu: Ohne Bearbeiten-Recht bleibt das Anlegen gesperrt (ausdrücklich abgesichert, damit die Umstellung keiner Bestandsrolle Schreibzugriff verschafft).

  • Export-Bild-Cache räumt sich selbst auf (#203) — der Zwischenspeicher der seit v4.1.0 (#191) für den PDF-Export verkleinerten Bilder wuchs unbegrenzt weiter; auf Shared Hosting mit knappem Platz konnte er über Monate zum Problem werden. Der tägliche Heartbeat-Lauf räumt jetzt auf: Fassungen, die seit 30 Tagen nicht mehr gebraucht wurden, fliegen raus — und liegt der Ordner danach immer noch über 250 MB, zusätzlich die ältesten, bis er wieder passt. Das ist gefahrlos: Der Ordner enthält nur aus den Anhängen berechnete Kopien, die Originale bleiben unangetastet, und gelöschte Fassungen entstehen beim nächsten Export automatisch neu. Wurde etwas entfernt, meldet das die Heartbeat-Nachricht („🖼 Export-Bilder aufgeräumt: … frei"); gab es nichts zu tun, bleibt die Zeile weg. Das Aufräumen läuft unabhängig von Telegram — auch Instanzen ohne Alarmpush profitieren, sofern der Heartbeat-Cron-Job eingerichtet ist (siehe Cron & Mail-Verarbeitung). Kein Schema-Check nötig.

  • „H"-Link der Telegram-Alarm-Nachricht zeigt auf den eigenen Hydrantenplan (#181) — der H-Link in der Alarm-Nachricht öffnete bisher die Google-MyMaps-Karte; jetzt führt er wie der HYD-Knopf in der Einsatz-Detailansicht auf den eigenen Hydrantenplan, zentriert auf die Einsatzstelle (setzt eine konfigurierte App-Basis-URL voraus, sonst entfällt der Link — wie bei OSM). Die frühere Einstellung „Hydrant: Google-MyMaps-ID" unter Einstellungen entfällt ersatzlos. Kein Schema-Check nötig.

Sicherheit

  • Rechte-Härtung als Nachlauf der Konsolidierung (#206) — drei Verschärfungen aus der Abnahme: Der zentrale Status-Riegel lässt sich nicht mehr per Parameter aus Versehen abschalten — systemseitige Automatik-Übergänge (z. B. „erste Einsatzmittel zugewiesen → in Bearbeitung") laufen jetzt über eine ausdrückliche, getrennte Methode. Die Obergrenze Max. Abschnitte pro Einsatz wird jetzt serverseitig erzwungen (vorher nur im Dialog begrenzt), sodass niemand mehr durch massenhaftes Anlegen von Abschnitten den Abschluss eines Einsatzes blockieren kann. Und das manuelle Auslösen von Alarm-Regeln legt Folge-Abschnitte nur noch an, wenn der Auslösende auch das Recht „Abschnitt anlegen" hat (beide Auslöse-Wege). Kein Schema-Check nötig.

  • Rollen-Editor: Beschreibung von „Hydrantenplan sehen" korrigiert (#207) — die Beschreibung nannte ein „Foto-Inventar", das es im Code nicht gibt; jetzt beschreibt sie nur die tatsächliche Standalone-Karte. Kein Schema-Check nötig.

  • Der Riegel für Status-Wechsel sitzt jetzt zentral (#201, #204) — bisher musste jede Stelle, die einen Einsatz-Status setzt, das Recht selbst prüfen; genau das war mehrfach unbemerkt auseinandergelaufen, weil die Standard-Rollen die betroffenen Rechte gemeinsam tragen und der Fehler im Alltag nie auffällt. Die Prüfung liegt jetzt zusätzlich an einer zentralen Stelle, durch die alle Wege laufen — Übersicht, Detailseite, Bearbeiten-Formular, Sammelaktion, Anlegen und die Schnittstellen dahinter. Damit sind auch Aufrufe abgedeckt, die an der Oberfläche vorbei abgeschickt werden. Die Prüfungen an den Schnittstellen und in der Oberfläche bleiben zusätzlich bestehen: Sie liefern die verständlicheren Meldungen und verhindern, dass die Oberfläche etwas anbietet, das der Server ablehnt. Ausgenommen bleiben die automatischen Übergänge (Disponent zugewiesen → „Disponent", erstes Einsatzmittel zugewiesen → „In Bearbeitung") — sie sind Folge einer bereits berechtigten Handlung. Für Standard-Rollen ändert sich nichts. Kein Schema-Check nötig.

  • storage/ gegen direkten Web-Zugriff abgesichert (#203) — der Ordner storage/uploads/ war bereits geschützt, der seit v4.1.0 hinzugekommene storage/cache/ nicht — dort liegen verkleinerte Kopien von Kommentar-Anhängen, also unter Umständen personenbezogene Einsatzfotos. Eine Schutzregel auf Ebene von storage/ deckt jetzt alle Unterordner ab. Bei korrekt auf public/ gesetztem Document-Root war der Ordner ohnehin nicht erreichbar; die Regel ist die Absicherung für den Fall einer fehlkonfigurierten Instanz. Anhänge werden weiterhin ausschließlich über den geprüften Download-Endpoint ausgeliefert. Kein Schema-Check nötig.

4.1.0 — 2026-07-18

Neu

  • Sondersignal steuert automatisch die Wichtigkeit (#41) — die Alarm-Mail der Leitstelle enthält eine Zeile „Sondersignal" (Ja/Nein). Das ETB wertet sie beim Anlegen eines Einsatzes jetzt automatisch aus: In der Wichtigkeit-Verwaltung legst Du per Klick fest, welche Wichtigkeit als Eil (Sondersignal = Ja) und welche als Zeit (Sondersignal = Nein) gilt — zwei neue Spalten neben dem Standard-Wert. So bleibt die Benennung der Stufen frei konfigurierbar. Fehlt die Zeile oder ist keine Eil-/Zeit-Stufe markiert, greift der konfigurierte Standard-Wert. Die Auswertung wirkt nur beim Anlegen; eine von Hand geänderte Wichtigkeit wird durch Folgemails nicht überschrieben, und automatische Folge-Einsätze aus dem Multi-Alarm-Regelwerk behalten ihre in der Regel hinterlegte Wichtigkeit. Kein Schema-Check nötig (die neuen Einstellungen legt der Schema-Check/CLI-Migrationslauf idempotent an).

  • Echte App-Icons für die installierte App (#194) — beim Installieren des ETB auf dem Startbildschirm (ETB auf Smartphone & Tablet) diente bisher das rohe Branding-Logo als App-Icon; je nach Gerät wurde es unsauber skaliert oder beschnitten. Jetzt rendert das ETB aus dem hochgeladenen Logo (Menü-Logo bevorzugt, sonst Login-Logo) automatisch einen vollständigen Icon-Satz: 192 px und 512 px für Android/Chrome — jeweils auch als „maskable"-Variante für adaptive (rund/abgerundet beschnittene) Android-Icons — und ein opakes 180-px-Icon für den iOS-Home-Bildschirm. Neue Installationen bekommen nach einem Logo-Wechsel automatisch das frische Icon. Die Branding-Empfehlung „möglichst quadratisches PNG als Menü-Logo" gilt weiterhin — sie ergibt die schönsten Icons; kann ein Logo nicht gerendert werden, dient wie bisher das Logo selbst als Icon. Kein Schema-Check nötig.

Sicherheit

  • CSV-Import mit Zeilen-Obergrenze (#196) — die Vorschau des Stichwort-Katalog-Imports akzeptiert jetzt maximal 5000 Datenzeilen pro Datei. Größere (versehentliche oder missbräuchliche) Dateien werden mit einer verständlichen Meldung abgelehnt, statt die Server-Session aufzublähen. Reale Kataloge liegen weit darunter.

  • Abgelaufene temporäre Rollen werden aufgeräumt (#196) — bisher wurden abgelaufene Temp-Rollen (Einsatzleiter/Lage auf Zeit) nur ignoriert, die Zuweisung blieb aber dauerhaft in der Datenbank stehen. Der reguläre Cron-Lauf setzt sie jetzt automatisch zurück (mit Sammel-Eintrag im Rollen-Audit); an der Rechte-Wirkung ändert sich nichts, abgelaufen war abgelaufen. Intern sichern neue Service-Tests gegen echte MariaDB die Temp-Rollen-Pfade ab (Vergabe-Sperren, 48-h-Deckel, Cleanup).

  • Obergrenze für Massen-Aktionen auf Einsätzen (#189) — die Mehrfach-Bearbeitung und das Mehrfach-Löschen in der Einsatz-Übersicht („Mehrere auf einmal") nehmen jetzt höchstens 500 Einsätze pro Aktion entgegen. Eine größere Auswahl — versehentlich oder missbräuchlich — lehnt das ETB mit einer verständlichen Meldung ab, noch bevor die (beim Löschen destruktive) Verarbeitung startet. Reale Auswahlen liegen weit darunter; für den normalen Betrieb ändert sich nichts.

  • Ausgehende Verbindungen und das Telegram-Protokoll gehärtet (#189) — mehrere Schutzmaßnahmen ohne sichtbare Bedienungsänderung: Geocoding (Nominatim/Photon) und der Telegram-Versand folgen Weiterleitungen jetzt nur noch zu HTTPS-Zielen, damit eine manipulierte Umleitung nicht auf file://, ftp:// o. Ä. ausweichen kann. Das Telegram-Protokoll speichert nicht mehr die vollständige API-Antwort — die den gesendeten Nachrichtentext und Chat-Metadaten zurückspiegelt —, sondern nur noch Erfolg und Nachrichten-ID (Datensparsamkeit). Und der interne Baustein des Einsatz-Exports prüft zusätzlich den Zugriffsbereich des angeforderten Einsatzes — ein vorsorglicher Riegel für den Fall, dass das Export-Recht künftig einer bereichsbeschränkten Rolle zugewiesen wird.

Geändert

  • Einheitliche Stapel-Reihenfolge (z-index-Leiter) (#189, intern) — die bisher über viele Dateien verstreuten z-index-Werte laufen jetzt über eine zentrale, benannte Leiter in tokens.css. Spürbarer Nebeneffekt: schwebende Hinweise (Toasts) liegen jetzt zuverlässig über geöffneten Dialogen, dem mobilen Menü und dem Schwerpunkt-Rahmen — vorher konnten sie je nach Seite dahinter verschwinden. Sonst ändert sich an der Darstellung nichts.

  • Schwerpunkt-Kontext in Links zentralisiert (#189, intern) — der neue Helfer sp_url() trägt den aktiven Schwerpunkt (?schwerpunkt=<id>) automatisch in Links und Weiterleitungen des Schwerpunkt-Tagebuchs mit (Leitplanke), statt in jeder Seite eigene $spSuffix/$spQuery-Varianten zu pflegen. Umgestellt sind die Einsatz-/Abschnitts-Detailseiten; die Ausgabe ist unverändert (getestet). Für die Bedienung ändert sich nichts.

  • Design-Tokens projektweit vereinheitlicht (#189, intern) — Schrift- größen, Eckenradien und der Karten-Schatten der Oberfläche greifen jetzt durchgängig auf die zentralen Design-Tokens (tokens.css) zu, statt die Werte in jeder Seite einzeln hart zu hinterlegen. So bleiben Hell-/Dunkel- Modus und das Erscheinungsbild an einer Stelle pflegbar. Die eigenständig-hellen Anmelde-Seiten (Login, Passwort-Reset) und die Druck-/Export-Bausteine bleiben bewusst tokenfrei. Rein optische Angleichung (kleine Radien vereinheitlicht) — für die Bedienung ändert sich nichts.

  • Komponenten-Bausteine projektweit zusammengeführt (#189, intern) — rund 25 Seiten bauten Buttons, Karten, Hinweis-Banner (Toasts) und Tabellen bisher in ihrem eigenen <style>-Block nach (vielfach kopiert). Diese Duplikate nutzen jetzt die zentralen Komponenten aus components.css (über die Marker-Klasse .cmp-scope), ergänzt um die Größen-Varianten .btn.sm und .btn.lg. Rund 260 Zeilen doppelter CSS entfallen — das Aussehen bleibt gleich, bis auf kleine bewusste Angleichungen (einheitlicher Erfolgs-Toast- Grünton, vereinheitlichte Button-Größen). Feature-spezifische Stile (Status-/Rollen-Pills, Badges, System-Status-Kacheln, der bewusst kräftig rote „Zurücksetzen"-Button) bleiben unberührt. Die eigenständigen Seiten (Login/Passwort, Druck-/Export-Bausteine und der Erst-Installations-Assistent, der sein CSS bewusst inline mitbringt) bleiben außen vor. Für die Bedienung ändert sich nichts.

  • Einheitliche Antwortform der AJAX-Endpoints (#189, intern) — alle JSON-Schnittstellen antworten jetzt projektweit im selben {ok: …}-Format (statt vereinzelt {error: …}). Ein neues internes Endpoint-Kit bündelt den bisher vielfach kopierten Zugriffs-/Prüf-Vorspann an einer Stelle. Für die Bedienung ändert sich nichts; die vier bisher abweichenden Endpoints (Lagekarten-Daten, Einsatzmittel-Liste, Geocode-Verwaltung, manueller Alarmpush) liefern die alte error-Form übergangsweise zusätzlich mit, damit nichts bricht.

  • PDF-Export: Bilder werden automatisch verkleinert (#191) — der Einsatz-Export („Als PDF speichern" über den Druck-Dialog) bettete Bild-Anhänge bisher in Originalauflösung ein — schon wenige Handy-Fotos machten die PDF-Datei viele MB groß. Der Export nutzt jetzt automatisch eine verkleinerte JPEG-Fassung (längste Kante 1600 px) — für den A4-Druck ohne sichtbaren Unterschied, die Datei wird um ein Vielfaches kleiner. Das gilt für Einsatz- und Abschnitts-Anhänge und ebenso für den Schwerpunkt-Export. Die Originale bleiben unverändert (Ansehen und Herunterladen im Tagebuch liefern weiterhin die volle Auflösung), GIFs werden nicht angetastet, und schlägt die Verkleinerung fehl, landet still das Original im PDF. Kein Schema-Check nötig.

  • Einheitliche Zugriffs-Meldungen der Einsatz-/Abschnitts-Endpoints (#160) — die Scope-Prüfung („gehört dieser Einsatz/Abschnitt zu Deinem Zuständigkeitsbereich?") steckt jetzt in einer zentralen, getesteten Logik statt vierfach kopiert in den Endpoints. Für die Bedienung ändert sich fast nichts: Fehlermeldungen und Statuscodes sind jetzt überall einheitlich (die knappen Meldungen der Mehrfach-Bearbeitung lauten nun wortgleich wie bei Einzel-Aktionen), und eine unbekannte Einsatz-Nummer meldet konsequent „nicht gefunden". Die Sonderregel, dass ein direkt einem Abschnitt zugeordneter Disponent dessen Status auch ohne Einsatz-Zuordnung ändern darf, bleibt erhalten und ist jetzt per Test abgesichert.

  • EM-Zuweisung hängt einheitlich am Recht „EMs zuweisen / entfernen" (#160/#189) — das Zuweisen von Einsatzmitteln per Drag&Drop auf der Einsatz-Detailseite prüfte bisher das allgemeine Bearbeiten-Recht, während die Einsatzmittel-Seite dieselbe Aktion am dedizierten EM-Recht festmachte. Jetzt gilt überall em.assign: in der API, an der Drop-Zone der Detailseite, an den Zeilen-Drop-Zielen der Einsatz-Liste und im Anlege-/Bearbeiten-Formular (Anzeige und Server-Übernahme). Die Standard-Rollen tragen beide Rechte gemeinsam — für sie ändert sich nichts; nur individuell zugeschnittene Rollen werden jetzt konsistent behandelt.

  • Projekt-Umzug zu GitLab — Repository, Releases und Issue-Tracker liegen jetzt unter gitlab.com/brun-soft/das-etb. Alle Verweise in App, Handbuch und README wurden umgestellt; der „Wiki"-Link in der In-App-Hilfe öffnet nun das GitLab-Wiki.

Behoben

  • Gesamt-Reset räumt jetzt auch das Alarm-Dedup-Log ab (#193) — beim kompletten Zurücksetzen des ETB (ETB zurücksetzen) blieb bisher das interne Dedup-Log stehen, das sich merkt, welche Alarm-Regel für welchen Einsatz schon ausgelöst hat (eine Regel feuert pro Einsatz nur einmal). Weil der Reset die laufenden Nummern auf 1 zurücksetzt, konnten diese Waisen-Einträge nach dem Reset Alarm-Auslösungen für neue Einsätze unterdrücken. Das Dedup-Log wird jetzt mit geleert und erscheint als eigene Zeile („Alarm-Regel-Ausloesungen") in der Detail-Status-Liste nach dem Reset. Intern wird die Vollständigkeit der Reset- und der Lösch-Kaskade jetzt automatisch per Schema-Abgleich getestet — eine künftige einsatzgebundene Tabelle kann nicht mehr unbemerkt in einer der Kaskaden fehlen. Kein Schema-Check nötig.

  • CLI-Migration macht jetzt den Voll-Repair wie der Schema-Check (#190)php scripts/migrate.php legte bisher nur fehlende Tabellen an; Indizes, Spalten-Migrationen und Default-Daten fehlten. Eine frisch per CLI aufgesetzte Installation startete dadurch mit veraltetem Schema — das Anlegen eines Einsatzes scheiterte mit „Interner Fehler", bis ein Admin im Schema-Check auf „Reparieren" klickte. Jetzt erledigt das Skript dieselben Schritte wie der Schema-Check (fehlende Indizes nachziehen, Spalten migrieren, Default-Daten seeden) — ein CLI-Install/-Update ist sofort voll funktionsfähig, der „Jetzt reparieren"-Klick entfällt. --dry-run zeigt zusätzlich anstehende Spalten-Migrationen an; schlagen einzelne Reparatur-Schritte fehl, endet das Skript mit Exit-Code 4, damit CI/Aufrufer Teil-Fehler nicht als Erfolg werten.

  • Einsatz-Status-Farben: Live-Vorschau mit korrekter Textfarbe (#192) — auf der Admin-Seite Einsatz-Status-Farben zeigte die Vorschau-Pille beim Wählen einer Farbe immer schwarze Schrift — auch auf dunklen Farben, auf denen weiße Schrift lesbar wäre. Die Live-Vorschau nutzt jetzt dieselbe automatische Schwarz/Weiß-Kontrastwahl (WCAG AA) wie die gespeicherte Ansicht; das Speichern selbst war korrekt. Rein optisch, kein Schema-Check nötig.

  • Karten-Chips TIM/DZ/HYD leichter zu treffen (#187) — die kleinen Karten-Links auf der Einsatz- und der Abschnitts-Detailseite unterschritten die von WCAG 2.5.8 geforderte Mindest-Trefferfläche (24 px). Sie sind jetzt mindestens 28 px hoch, auf Touch-Geräten (Tablet in der Halle, Handschuh) volle 44 px, mit etwas mehr Abstand zwischen den Chips als Fehlgriff-Puffer. Nur Geometrie — Farben und Verhalten unverändert; kein Schema-Check nötig.


4.0.0 — 2026-07-06

Neu

  • Einsätze endgültig löschen — berechtigte Rollen können Einsätze jetzt aus der Einsatz-Übersicht endgültig löschen: einzeln über das Papierkorb-Symbol in der Aktions-Zelle (neben „Zuweisen") oder mehrere auf einmal über den roten „Löschen"-Button in der Bulk-Auswahl. Jede Löschung verlangt eine Begründung, die ins Anwendungsprotokoll geschrieben wird — der Einsatz selbst wird samt Abschnitten, Einsatzmitteln, Kommentaren, Anhängen und Audit-Spuren hart entfernt und lässt sich nicht wiederherstellen. Das Recht heißt einsatz.delete („Einsatz löschen") und ist per Default an für Administrator, Einsatzleiter und Lage; es lässt sich pro Rolle abwählen und an weitere Rollen delegieren. Für eine gescopte Rolle (Dispo ohne „alle sehen") sind nur die eigenen Einsätze löschbar — der Endpoint erzwingt den Scope zusätzlich autoritativ.

  • Digitaler Zwilling NRW als Karten-Link (#175) — neben TIM und HYD gibt es einen neuen grünen Karten-Link „DZ" zum Digitalen Zwilling NRW (dz.nrw.de), dem landesweiten 3D-Geo-Kartensystem. Er erscheint in der Einsatz-Detailseite (zwischen TIM und HYD, nur wenn der Einsatz Koordinaten hat) und in der Telegram-Alarm-Nachricht (Link-Reihe TIM | DZ | OSM | H, DZ nur bei echten Einsatz-Koordinaten — kein Fallback aufs Ortszentrum). Der DZ arbeitet mit UTM-Koordinaten (EPSG:25832, Rechts-/Hochwert); die App berechnet diese automatisch aus den vorhandenen GPS-Koordinaten (WGS84) — kein manuelles Feld. Gesteuert über das neue Feature „Digitaler Zwilling NRW" (feature_dz_nrw_enabled) unter Administration → Konfiguration → Features (Default an): Feuerwehren außerhalb von NRW schalten es aus, dann verschwindet der DZ-Link überall. → einmaliger Schema-Check nach dem Update (neue Spalten utm_ost/utm_nord + einmaliger Backfill der UTM-Werte für Bestandseinsätze).

  • UTM-Koordinaten in der Geocode-Übersicht (#175) — die Geocode-Übersicht (/admin/geocode-admin.php) zeigt jetzt zwei zusätzliche Spalten „Rechtswert" und „Hochwert" (UTM / EPSG:25832). Sie sind nur Anzeige (abgeleitet, nicht editierbar) und aktualisieren sich automatisch, sobald Du die GPS-Koordinaten einer Zeile bearbeitest oder neu geocodierst. In der Einsatz-Detailseite und im Einsatz-Formular werden die UTM-Werte bewusst nicht angezeigt — sie dienen allein dem DZ-Link.

  • Lagekarte: Einsatzmittel-Panel im Tablet-Hochformat als Vollbild (#179) — im Tablet-Hochformat (ca. 768–1024 px, Portrait) öffnet das Einsatzmittel-Panel auf der Lagekarte jetzt als Vollbild-Overlay über der Karte — genau wie am Smartphone. Bisher quetschte das feste Panel die Karte auf dem Tablet unbrauchbar schmal. Im Querformat (genug Platz für beides) bleibt das Panel wie gewohnt seitlich. Rein additiv, kein Schema-Check nötig.

  • Einsatz-Status-Farben admin-konfigurierbar (#164) — unter Administration → Einsatz-Status-Farben (/admin/einsatz-status-farben.php, Recht admin.stammdaten) legst Du je Einsatz-Status (Neu, Disponent, In Bearbeitung, Erledigt, Abgeschlossen) eine Farbe fest — mit Farbwähler, Live-Vorschau und „Auf Standard zurücksetzen". Die Farbe wirkt überall: Status-Pillen, farbiger Zeilenbalken in der Einsatzliste, Status-Kacheln, Lagekarten-Marker und Status-Filter-Punkte. Die Textfarbe (schwarz/weiß) wählt das ETB automatisch kontraststark (WCAG AA). Die Status selbst (Namen/Keys) bleiben fest — nur die Farbe ist konfigurierbar. Kein Schema-Check nötig (Ablage in der bestehenden Konfig-Tabelle). Solange Du keine eigene Farbe setzt, bleiben die getrennt abgestimmten Hell-/Dunkel- Standardfarben unverändert; im Dark-Mode ist der Zeilenbalken für „Abgeschlossen" bewusst dezent (dunkle Statusfarbe) — die Status-Pille bleibt der gut sichtbare Haupt-Anzeiger.

  • Stärke-Eingabe über drei Felder ZVF / GF / Ma (#168) — beim Zuweisen eines Einsatzmittels (Drag & Drop auf einen Einsatz) gibst Du die Stärke jetzt über drei kleine Zahlenfelder ein — ZVF (Zug- und Verbandführer), GF (Gruppenführer), Ma (Mannschaft). Die Gesamtstärke wird daneben automatisch berechnet und angezeigt. Gespeichert und angezeigt wird weiterhin das gewohnte Schema A/B/C/S — die drei Felder sind nur die bequemere Eingabe (statt einen Schrägstrich-String von Hand zu tippen). Kein Schema-Check nötig.

  • Zuletzt zugewiesene Stärke an der EM-Sidebar (#169) — in der Einsatzmittel-Seitenleiste steht hinter jedem Einsatzmittel klein in Klammern die zuletzt zugewiesene Stärke (Schema A/B/C/S, Gesamtzahl doppelt unterstrichen), sofern bei einer früheren Zuweisung eine erfasst wurde. Rein informativ fürs Disponieren; kein Schema-Check nötig.

  • Überörtliches Einsatzmittel direkt im Schwerpunkt-Wizard anlegen (#172) — im Schwerpunkt-Anlage-Wizard (Schritt 4, Einsatzmittel-Pool) gibt es den Button „Überörtliches Einsatzmittel anlegen" (nur mit dem Recht „üÖrt-EM beim Zuweisen neu anlegen", em.uoert_create — das bisher nur den Zuweisen-Dialog freischaltete). Der Dialog fragt Name, Stärke (drei Felder ZVF/GF/Ma) und Kontakt ab; das Einsatzmittel wird als normales überörtliches EM angelegt und direkt in den Pool aufgenommen — ohne Umweg über die Stammdaten-Pflege. Legt zwei Spalten em_stammdaten.default_anzahl / default_kontakt an → einmaliger Schema-Check nach dem Update.

    • Vorbelegung für die spätere Zuweisung: Stärke und Kontakt werden als Standard am Einsatzmittel gespeichert und beim ersten Drag & Drop auf einen Einsatz als Vorschlag angeboten (die Einsatz-Historie hat Vorrang, sobald es eine gibt).
    • Sicherheit: Der Wizard-Zugang (schwerpunkt.create) allein reicht nicht — das Anlegen verlangt zusätzlich em.uoert_create (Button und Server-Endpoint prüfen das). Die Kontakt-Vorbelegung bleibt für gescopte Disponenten verborgen (wie die Historien-Kontakte); die Stärke-Vorbelegung ist unkritisch und für alle sichtbar.
  • Wizard-EM-Pool per Tastatur bedienbar (#180) — die Einsatzmittel-Chips im Schwerpunkt-Anlage-Wizard (Schritt 4) sind jetzt vollständig per Tastatur bedienbar: Chip mit Tab anspringen, Enter / Leertaste nimmt ihn in den Pool auf bzw. entfernt ihn wieder; der Fokus folgt dem Einsatzmittel. Damit ist auch der letzte verbliebene Nur-Maus-Bereich der EM-Zuweisung barrierefrei (WCAG 2.1.1); der frühere Workaround-Hinweis im Handbuch entfällt. Kein Schema-Check nötig.

  • Mitscrollende EM-Übersicht + fixe Filterleiste (#166) — in der Einsatz-Übersicht bleibt auf breiten Bildschirmen die Einsatzmittel-Seitenleiste beim Scrollen der Liste rechts sichtbar (sie wandert mit), und die Filterleiste klebt oben am Rand — so lassen sich auch weit unten in einer langen Liste Einsatzmittel zuweisen und Filter setzen, ohne nach oben zu scrollen. Klappst Du die Filterleiste dabei auf, scrollt sie sanft in den Blick, statt Einsatzzeilen zu verdecken. Auf dem Smartphone (einspaltig) bleibt alles wie gehabt. Kein Schema-Check nötig.

  • Alarm-Knopf — Einsatz-Rolle übernehmen (#163) — je Alarm-Regel konfigurierbar (neuer Block „Alarm-Knopf — Einsatz-Rolle übernehmen": angebotene Rolle Lage oder Einsatzleiter plus Laufzeit 6–48 h in 6-h-Stufen). Löst die Regel aus (Alarm-Mail, „Alarm auslösen"-Knopf oder Bestätigungs-Banner), entsteht ein einmaliges Rollen-Angebot: Im Seitenmenü erscheint ein Blitz-Knopf neben dem Benutzernamen. → einmaliger Schema-Check nach dem Update legt die neue Tabelle und die Spalten an (alarm_role_offer, users.temp_role_source, alarm_rule.temp_role_offer/…_hours).

    • Übernehmen (Disponent): ein Disponent ohne aktive Einsatz-Rolle übernimmt die Rolle per Bestätigungs-Dialog — sie wirkt sofort ohne Neuanmeldung, die Laufzeit zählt ab der Übernahme. Genau ein Gewinner (race-sicher); danach verschwindet der Knopf für alle.
    • Entschärfen (höhere Rechte): Lage, Einsatzleiter und Administrator — auch wer per Einsatz-Rolle bereits höher ist — können das Angebot stattdessen entschärfen (verschwindet für alle, revisionssicher im Rollen-Audit).
    • Weiterverleih-Ausnahme: die per Alarm-Knopf übernommene Lage darf ihrerseits Einsatz-Rollen vergeben (einzige Ausnahme von der Weiterverleih-Sperre, damit der erste Disponent die Führungsstruktur aufspannen kann — setzt voraus, dass die Rolle Lage das Recht „Einsatz-Rollen vergeben" hat, per Default aus); die Kette endet dort — von ihr ernannte Rollen und ein per Alarm-Knopf übernommener Einsatzleiter verleihen nicht weiter.
    • Sicherheit: Gast und SP-Dispo sehen den Knopf nie (server-seitig gesperrt); nur ein Angebot gleichzeitig und kein neues, solange eine per Alarm übernommene Rolle läuft; ungenutzte Angebote verfallen nach 48 h, der ETB-Reset räumt sie ab; Übernahme und Entschärfen stehen im Rollen-Audit (temp_role_claim_alarm, alarm_offer_dismiss).
  • Schwerpunkt-Abschluss — Erledigen & endgültiges Abschließen (#170) — der Schwerpunkt-Lebenszyklus zieht mit dem Einsatz gleich. Die beiden Endzustände heißen jetzt „Erledigt" (früher „Geschlossen") und „Abgeschlossen" (früher „Archiviert"); die internen Keys bleiben. → einmaliger Schema-Check nach dem Update benennt unveränderte Werks-Labels um (selbst angepasste bleiben unberührt).

    • „Erledigen"-Button im Schwerpunkt-Banner (Recht „Schwerpunkt schließen / archivieren", schwerpunkt.close, Default Lage/EL/Admin): setzt den Schwerpunkt auf Erledigt, sobald alle seine Einsätze mindestens erledigt sind — bereits erledigte Einsätze blockieren das SP-Erledigen nicht mehr (vorher mussten alle abgeschlossen sein). Bei offenen Einsätzen erklärt der Dialog den Weg über „Einsätze abschließen".
    • Sammel-Abschluss in der Schwerpunkt-Übersicht: der Button „Schwerpunkte abschließen (N)" öffnet ein Fenster mit allen erledigten Schwerpunkten — einzeln oder alle auf einmal endgültig abschließen; Zeilen mit zwischenzeitlich wieder geöffneten Einsätzen sind gesperrt. Der Erledigt-Zeitstempel bleibt beim Abschließen erhalten (Historie und Export zeigen weiter „Erledigt").
    • Reaktivierung nur durch den Administrator: einen abgeschlossenen Schwerpunkt kann nur ein Admin (Basis-Rolle) wieder auf Aktiv/Pausiert stellen.
    • Ort-Eindeutigkeit: ein Ort kann nur einem offenen Schwerpunkt zugeordnet sein — geprüft beim Zuordnen der Orte und bei der Reaktivierung; Orte erledigter/abgeschlossener Schwerpunkte sind wieder frei.
  • Blockierende Abschnitte direkt erledigen (#162) — überall dort, wo die Abschnitts-Sperre einen Einsatz am Erledigen/Abschließen hindert, lassen sich die betroffenen Abschnitte jetzt an Ort und Stelle erledigen (gleiches Recht wie das Abschnitts-Status-Dropdown, abschnitt.status); kein Schema-Check nötig.

    • Das Fenster „Einsatz erledigen" arbeitet zweistufig: Bei Abschnitten in Arbeit zeigt es zuerst einen Warnhinweis samt Liste mit „Erledigen"-Button je Abschnitt (der Erledigen-Knopf des Einsatzes bleibt solange deaktiviert); sind alle erledigt, erscheint automatisch das Kommentarfeld. Ohne blockierende Abschnitte startet es direkt beim Kommentar.
    • Die Status-Dropdowns (Übersicht und Detailseite) öffnen bei blockierenden Abschnitten den Dialog „Abschnitte noch in Arbeit" mit denselben Erledigen-Buttons — danach läuft der Statuswechsel automatisch weiter.
    • Das Fenster „Einsätze abschließen" listet die blockierenden Abschnitte gesperrter Einsätze als Unterzeilen mit „Erledigen"-Button.
    • Statuswechsel von oder zu „Erledigt"/„Abgeschlossen" laden die Detailseite neu — der „Einsatz erledigen"-Button erscheint bzw. verschwindet damit automatisch.
  • Adress-Suffix je Ort (#174) — in der Orts-Verwaltung gibt es je Ort den Haken „Eigenes Adress-Suffix" plus Textfeld: Es ersetzt beim Geocodieren (und im TIM-Kartenlink) das Standard-Suffix aus „System & Konfiguration" — gedacht für Orte außerhalb der eigenen Gemeinde (überörtliche Einsätze). Ein leeres Feld bei gesetztem Haken bedeutet bewusst „kein Suffix anhängen". → einmaliger Schema-Check nach dem Update legt die beiden Spalten an.

  • Direkt-Zugriff auf den Geocode-Cache (#171) — die Geocodes-Übersicht trägt für Admins den neuen Toolbar-Button „Geocode-Cache"; bisher war die Cache-Seite nur über den System-Status auffindbar. Kein Schema-Check nötig.

  • Stichwort-Katalog (Phase 1) — eine neue Admin-Seite „Stichwort-Katalog" (Bereich Feuerwehr, Recht admin.stammdaten) zum Pflegen der Einsatzstichworte. Legt die neue Tabelle stichwort_katalog an → einmaliger Schema-Check nach dem Update nötig.

    • Einzelpflege: pro Stichwort Kategorie (Combobox: vorhandene wählen oder neue eintippen), volles Stichwort (eindeutig, z. B. SU-B1-Sonstiges), Anzeige-Variante (was später in den Listen erscheint, z. B. B1-Sonstiges), Aliase (komma-getrennt) sowie Sortierung und Aktiv.
    • CSV-Import: Datei mit Kopfzeile Kategorie;Stichwort hochladen → Vorschau (inkl. abgeleiteter Anzeige-Spalte und Hinweis neu / aktualisiert) → übernehmen; bestehende Einträge werden über das volle Stichwort aktualisiert. Eine Beispiel-Datei steht zum Download bereit.
    • Ausblend-Präfixe: ein komma-getrenntes Feld über der Liste (z. B. SU-). Daraus leitet das ETB die Anzeige-Variante aus dem vollen Stichwort ab (führendes Präfix abschneiden). Eine Änderung zeigt erst eine Vorschau der betroffenen Einträge, bevor alle Anzeige-Stichworte neu berechnet werden.
    • Erste Stufe eines größeren Vorhabens: Diese Stufe liefert nur die Katalog-Verwaltung im Admin. Die Auswahl im Einsatz-Formular, die automatische Erkennung und das Alarm-Auslösen folgen in späteren Ausbaustufen.
  • Stichwort-Auswahl im Einsatz-Formular (Stage 2) — beim Anlegen/Bearbeiten eines Einsatzes ist das Stichwort nun an den Stichwort-Katalog gekoppelt. Ergänzt die neue Spalte einsaetze.stichwort_katalog_id (NULL = Freitext) → einmaliger Schema-Check nach dem Update nötig.

    • Zwei verkettete Auswahlfelder: zuerst Kategorie, dann das Stichwort dieser Kategorie (gezeigt wird die Anzeige-Variante aus dem Katalog). Nur aktive Katalog-Einträge erscheinen zur Auswahl.
    • Freitext weiterhin möglich: über die Kategorie „— Freitext —" erscheint statt des Stichwort-Dropdowns ein freies Eingabefeld — für Stichworte, die (noch) nicht im Katalog stehen.
    • Pflichtfeld bleibt: entweder eine Katalog-Auswahl oder ein Freitext. Beim Bearbeiten ist die bisherige Eingabe vorbelegt (Katalog-Stichwort mit Kategorie bzw. Freitext).
    • Whitelist serverseitig: Eine übergebene Katalog-ID wird gegen den Katalog geprüft; das gespeicherte Stichwort kommt aus dem Katalog (Anzeige-Variante). Unbekannte/gelöschte IDs fallen sicher auf Freitext zurück und werden nie ungeprüft übernommen.
    • Die automatische Erkennung aus Alarm-Mails und das Alarm-Auslösen bei manuellen Einsätzen folgen in späteren Ausbaustufen.
  • Alarm-Regeln auch bei manuellen Einsätzen (Stage 4) — Alarm-Regeln feuern bisher nur aus einer Leitstellen-Mail oder über den Knopf „Alarm auslösen" in der Übersicht. Jetzt prüft das ETB auch manuell angelegte oder bearbeitete Einsätze. Legt die neue Tabelle alarm_einsatz_trigger an → einmaliger Schema-Check nach dem Update nötig.

    • Bestätigungs-Banner: Trifft das Stichwort eines manuell angelegten Einsatzes (oder ein geändertes Stichwort) eine aktive Alarm-Regel, erscheint auf der Einsatz-Ansicht ein Banner mit jeder treffenden Regel und einer Vorschau, wie viele Folge-Einsätze/-Abschnitte sie anlegen würde — plus Buttons Auslösen / Überspringen.
    • Telegram standardmäßig aus: Eine Checkbox „Zusätzlich per Telegram alarmieren" steuert den Versand; sie ist hier nicht vorbelegt (anders als beim Knopf „Alarm auslösen"), damit eine Nachdokumentation nicht versehentlich den Alarm-Chat benachrichtigt.
    • Berechtigung: Das Auslösen am Banner ist an „Einsatz-Stammdaten bearbeiten" (einsatz.edit, Default Lage/Einsatzleiter/Dispo + Admin) gebunden; Dispo und SP-Dispo nur im Rahmen ihres Einsatz-Scopes — derselbe Zugriffs-Schutz wie beim Bearbeiten.
    • Dedup: Eine Regel feuert pro Einsatz nur einmal; eine schon ausgelöste Regel erscheint nicht erneut, und der Server fängt gleichzeitige Doppel-Klicks ab (er löst nur noch wirklich offene Regeln aus).
    • Vorschläge im Alarm-Regel-Editor: Das Feld Trigger-Stichworte bietet jetzt Vorschläge aus dem Stichwort-Katalog (Anzeige-Varianten) — ein Stichwort lässt sich picken oder weiterhin als Wildcard-Muster (B3*) tippen.
  • Arbeitsplatz „Einsätze abschließen" — ein dedizierter Prüf- und Abschluss-Weg in der Einsatz-Übersicht. Rein additiv, kein Schema-Check nötig; am Vier-Augen-Prinzip und der Abschluss-Sperre ändert sich nichts.

    • Toolbar-Button: Wer das Recht „Einsatz abschließen" (einsatz.abschluss) hat (Default: Lage, Einsatzleiter, Admin), sieht in der Übersicht den Knopf „Einsätze abschließen" — mit einem Zähler der erledigten Einsätze, die auf den Abschluss warten.
    • Sammel-Modal: Der Knopf öffnet ein Fenster mit allen erledigten Einsätzen des aktuellen Bereichs (Nummer, Stichwort, Ort sowie wann und von wem erledigt). Einsätze lassen sich dort einzeln („Abschließen") oder gesammelt („Alle abschließen") abschließen.
    • Abschluss-Sperre sichtbar: Einsätze mit noch offenen Abschnitten sind im Modal gesperrt (mit Hinweis, wie viele Abschnitte offen sind) und werden bei „Alle abschließen" übersprungen.
    • Schwerpunkt-Einsätze im Schwerpunkt: Im normalen ETB zeigt und zählt der Arbeitsplatz nur Einsätze ohne Schwerpunkt — erledigte Einsätze eines Schwerpunkts erscheinen hier bewusst nicht (passend zur Übersicht). Im Schwerpunkt-Tagebuch (?schwerpunkt=<id>) erscheint derselbe Knopf, beschränkt auf die erledigten Einsätze dieses Schwerpunkts.
    • Der bisherige Weg über Status-Dropdown der Zeile und die Bulk-Aktion bleibt unverändert erhalten; die Mutationen laufen über dieselben abgesicherten Endpoints, die Sperre und der Vier-Augen-Check greifen serverseitig.
  • Kontext-Hilfe-Schublade + seiten-genaues Handbuch (Etappe 7) — auf den meisten Seiten findest Du jetzt rechts in der Aktions-Leiste einen „?"-Knopf. Ein Klick öffnet rechts eine Hilfe-Schublade mit der genau zu dieser Seite passenden Handbuch-Erklärung; ein weiterer Klick, der ×-Knopf oder Esc (wenn der Fokus in der Schublade liegt) schließt sie wieder. Rein additiv, kein Schema-Check nötig, kein neues Recht.

    • Dieselbe Quelle wie das Handbuch: Es ist derselbe Inhalt, den Du auch unter Hilfe liest — nur eben direkt im Kontext der Seite. Oben in der Schublade führt „Im Handbuch öffnen ↗" zur Vollansicht; auch Querverweise in der Schublade öffnen das Handbuch in einem neuen Tab, damit die Schublade beim Seiten-Thema bleibt.
    • Seiten-genau statt grobem Kapitel: Jeder Bildschirm hat sein eigenes Thema (im Admin je Kachel eine eigene Seite). Das „?" erscheint nur, wo ein passendes Thema hinterlegt ist; reine Hintergrund-/Konzept-Themen (Rollen, Status-Lebenszyklus, FAQ, Glossar) tragen bewusst kein „?", werden aber aus den Seiten-Themen verlinkt. Anmelde-Seite und Setup-Wizard sind ausgenommen.
    • Inhalt weicht aus, die Bedienung bleibt sichtbar: Die Schublade beginnt unter der Titelleiste und schiebt nur den Seiten-Inhalt nach links — Titelleiste und Aktions-Leiste (samt „?") bleiben stehen, nichts springt.
    • Bleibt offen über Reload & Seitenwechsel: Hast Du die Schublade geöffnet, bleibt sie es auch nach einem Seitenwechsel oder Neuladen geöffnet und zeigt dann das Thema der neuen Seite (ohne den Fokus zu stehlen). Der Zustand wird pro Browser gemerkt (localStorage).
    • Breite anpassbar: Am linken Rand der Schublade kannst Du sie breiter oder schmaler ziehen; die gewählte Breite wird ebenfalls pro Browser gemerkt. Auf schmalen Bildschirmen (Smartphone, Tablet im Hochformat) und in der installierten App (PWA) ist die Schublade bewusst ausgeblendet — dort nutzt Du das vollständige Handbuch (Menü „Hilfe" oder das öffentliche Handbuch).
  • Öffentliches Handbuch ohne Login (/handbuch.php, Etappe 7) — das komplette Handbuch ist jetzt auch ohne Anmeldung lesbar, unter /handbuch.php. Auf der Anmelde-Seite führt neben „Passwort vergessen?" ein neuer Link „Handbuch" dorthin (öffnet in neuem Tab).

    • Eigenes, schlankes Layout im App-Look mit aufklappbarem Themen-Menü und einem „← Zum Login"-Link; bewusst nur hell (kein Dark-Mode vor der Anmeldung).
    • Read-only und dieselbe Quelle: Es liest dieselben Handbuch-Texte wie die In-App-Hilfe — der Inhalt wird also nur einmal gepflegt. Du kannst die Bedienungsanleitung so z. B. auf dem Tablet aufschlagen, ohne Dich erst anzumelden.
  • Hilfe-Menü als aufklappbare Gruppen (Etappe 7) — die Themenliste der In-App-Hilfe (/hilfe.php) und des öffentlichen Handbuchs ist jetzt nach Gruppen gegliedert, die sich auf- und zuklappen lassen (Akkordeon). Beim Öffnen eines Themas klappt seine Gruppe automatisch auf und der aktive Eintrag rückt in Sicht.

  • Design-Konsolidierung: Status-Kachel & Komfort/Kompakt-Umschalter (Etappe 6) — der „Mischung"-Rollout der Einsatz-Listen und -Detailansicht. Rein visuell bzw. additiv, keine geänderte Bedienung, kein Schema-Check nötig.

    • Farbige Status-Kachel: Jede Einsatz-Zeile (Übersicht), der Detail-Kopf und jeder Abschnitt tragen links eine Kachel mit der laufenden Nummer (#007 bzw. A#001) und einem Kurz-StatusNEU, DISPO, AKTIV, FERTIG, ABG. Die Kachel ist in der Status-Farbe eingefärbt und zieht bei einem Inline-Statuswechsel (Dropdown der Zeile bzw. im Detail-Kopf) sofort in Farbe und Label nach. Die Abschnitts-Kachel nutzt die frei konfigurierbare Abschnitts-Status-Farbe; die Textfarbe wird luminanzbasiert gewählt, sodass sie auch auf hellen Status-Farben den WCAG-AA-Kontrast (1.4.3) einhält.
    • Ansicht „Komfort | Kompakt": Über der Einsatz-Liste schaltest du zwischen Komfort (luftige Karten-Zeilen mit allen Spalten) und Kompakt (dichte, einzeilige Darstellung; Neben-Spalten ausgeblendet — für viele Einsätze auf einen Blick) um. Die Wahl wird pro Browser gemerkt (localStorage).
    • Abschnitte direkt in der Liste aufklappen: Einsätze mit Abschnitten tragen vor dem Stichwort einen Chevron (›), der die Abschnitte ohne Seitenwechsel ein-/ausklappt.
    • Bulk-Auswahl als Overlay-Checkbox: Die Mehrfach-Auswahl-Checkbox sitzt jetzt filigran oben auf der Status-Kachel des Einsatzes (statt in einer eigenen Spalte) — sie erscheint nur bei Einsätzen, die du bearbeiten darfst. „Alle" in der Sortierleiste markiert die ganze Seite. Rein optisch, gleiche Bulk-Aktionen wie bisher.
    • Lagekarte-Marker an Statusfarben: Die Einsatz-Marker der Lagekarte übernehmen die Status-Kachel (laufende Nummer + Status-Farbe), passend zur Liste.
  • Mobil, Tablet & App (PWA) — die Anwendung ist jetzt durchgängig auf Smartphone und Tablet bedienbar. Rein additiv, kein Schema-Check nötig.

    • Einsatzmittel per Tippen zuweisen: Auf Touch-Geräten genügt ein kurzer Tipp auf ein Einsatzmittel in der Seitenleiste — gibt es nur ein mögliches Ziel, wird sofort zugewiesen; bei mehreren öffnet ein Auswahl-Dialog mit den Einsätzen. Das bisherige Ziehen (lange drücken, dann ziehen) bleibt zusätzlich erhalten.
    • Schmale Bildschirme: Formulare brechen sauber einspaltig um, breite Admin-Tabellen werden horizontal scrollbar statt abgeschnitten, der Einsatz-Detail-Kopf bricht um, und das Off-Canvas-Menü lässt sich per Tastatur bedienen (Esc schließt, der Fokus bleibt im Menü).
    • Als App installierbar (PWA): Die Anmeldeseite ist jetzt PWA-tauglich (Manifest, an das Thema angepasste Status-Leiste, Service-Worker), sodass die als App installierte Anwendung auch bei abgelaufener Sitzung sauber startet. (Eigene App-Symbole folgen mit dem Produktiv-Deploy.)
  • Kommentare erweitert: Ziel-Auswahl Einsatz/Abschnitt (Etappe 4) — schließt #31. Erweiterungen rund ums Kommentieren in der Einsatz-Detailansicht:

    • Ziel wählen (Einsatz oder Abschnitt): Hat ein Einsatz aktive Abschnitte, erscheint in der Einsatz-Detailansicht über dem Eingabe-Feld eine Auswahl „Ziel"Einsatz (Standard) oder ein konkreter Abschnitt („A#001 …"). Anhänge landen an derselben Stelle wie der Kommentar. Ohne Abschnitte bleibt alles wie bisher (die Auswahl wird gar nicht erst angezeigt).
    • Kombinierte Kommentar-Liste: Der Verlauf des Einsatzes zeigt Einsatz- und Abschnitts-Kommentare gemeinsam, chronologisch gemischt. Abschnitts-Kommentare tragen ein Herkunfts-Badge („A#001 …"); Bearbeiten/Löschen wirkt jeweils auf den richtigen Kommentar. Die Abschnitts-Detailseite zeigt weiterhin nur ihre eigenen Kommentare.
    • Kommentieren hängt jetzt am Kommentar-Recht: Ein Einsatz-Kommentar verlangt einsatz.comment, ein Abschnitts-Kommentar abschnitt.comment — vorher war das Anlegen an das Bearbeiten-Recht (einsatz.edit) gekoppelt. Erledigte Abschnitte kann ein Dispo/SP-Dispo nicht kommentieren.
  • Alarmregeln manuell auslösen + Leitstellen-Adresse (Etappe 3) — schließt #115 (UW-ERSTALARM per Knopfdruck). Ein neuer Knopf „⚡ Alarm auslösen" in der Einsatz-Übersicht löst eine Alarmregel von Hand aus, wenn die Leitstelle keine Mail schickt.

    • Er legt — exakt wie der echte Mail-Alarm — den Basis-Einsatz (Trigger-Stichwort der Regel) plus — je nach Regel-Typ — die hinterlegten Folge-Einsätze oder Folge-Abschnitte an der gewählten Adresse an; die Telegram-Alarmierung ist optional (Checkbox im Dialog, standardmäßig an — so lassen sich auch nur die Einsätze anlegen, ohne zu alarmieren). Eine Erfolgsmeldung bestätigt anschließend, wie viele Einsätze angelegt wurden und ob mit oder ohne Telegram; per „Zum Einsatz" geht es weiter zum neuen Basis-Einsatz.
    • Auslöse-Dialog: Regel wählen (alle aktiven Regeln — Folge- Einsätze und Folge-Abschnitte, der Typ steht hinter dem Namen) → Adresse prüfen (vorbelegt, immer überschreibbar, Straße Pflicht) → Telegram-Haken optional setzen → „Alarm auslösen". Ein roter Warnhinweis macht die echte Auslösung deutlich.
    • Adress-Quelle pro Regel (im Alarm-Regel-Editor): Lokale Leitstelle (Adresse aus „Organisation & Branding"), Feste Adresse (an der Regel) oder Bei Auslösung eingeben (leer). Dafür gibt es unter Admin → Organisation & Branding die neue Karte „Leitstelle" (Straße + Ort).
    • Schutz gegen Doppelauslösung: dieselbe Regel ist nach dem Auslösen 60 Sekunden gesperrt, höchstens 10 manuelle Auslösungen pro Stunde je Regel. Die Sperre hängt an der Regel (nicht am Benutzer); der Mail-Alarm bleibt unberührt.
    • Neues Recht „Alarm manuell auslösen" (alarm.trigger_manual, Gruppe „Einsätze") — per Default bei Lage und Einsatzleiter, Administrator über den Failsafe; nicht an Dispo/SP-Dispo/Gast. Eine geliehene Einsatz-Rolle (temp EL/Lage, Etappe 2) zählt mit, da das Alarmieren eine operative Führungsaufgabe ist. Die Permission-Matrix umfasst damit jetzt 40 atomare Rechte.

    ⚠️ Nach dem Update einmalig /admin/schema-check.php → „Reparieren" ausführen. Etappe 3 legt drei neue Spalten an der Alarmregel-Tabelle an (manual_address_mode, manual_strasse, manual_ort) sowie die Tabelle alarm_trigger_throttle für den Cooldown; das Recht alarm.trigger_manual wird bei Lage und Einsatzleiter nachgerüstet. Bis dahin bleibt die Funktion still inaktiv (keine Fehler), es erscheint der Schema-Banner.

  • Einsatz-Rollen — temporäre Rollen leihen (Etappe 2) — schließt #30 (Rollenwechsel bei Anmeldung). Eine neue Seite „🤝 Einsatz-Rollen" (Sidebar-Gruppe „Werkzeuge") erlaubt es Einsatzleiter und Admin, einem Benutzer befristet (max. 48 Stunden) die höhere Rolle Einsatzleiter oder Lage zu leihen — z. B. für eine mehrtägige Lage.

    • Wirkt sofort ohne Neuanmeldung („Highlander"-Prinzip): Die geliehene Rolle kommt zur festen Rolle hinzu (Vereinigung der Rechte), das höhere Recht gewinnt. Nach Ablauf des gedeckelten Zeitpunkts läuft die Einsatz-Rolle automatisch aus.
    • „Entfernen" je Benutzer und „Alle Einsatz-Rollen zurücksetzen" beenden sie sofort. Die betroffene Person sieht in der Seitenleiste bei ihrer Rolle den Zusatz „(temp)" (z. B. „Einsatzleiter (temp)").
    • Sicherheits-Leitplanken: Administrator und Schwerpunkt- Dispo nehmen am Einsatz-Rollen-System nicht teil (weder als Geber noch als Empfänger). Man kann sich nicht selbst eine Einsatz-Rolle geben. Eine geliehene Rolle kann nicht weiterverliehen werden (das Recht wird gegen die Basis-Rolle geprüft — ein temporärer Einsatzleiter sieht die Einsatz-Rollen- Funktion nicht). Bekommt ein Dispo eine Einsatz-Rolle, entfällt für deren Dauer sein Eigentums-Filter (er sieht dann alle Einsätze/Schwerpunkte).
    • Neues Recht im Rollen-Editor: „Einsatz-Rollen vergeben" (user.assign_temp_role, neue Gruppe „Einsatz-Rollen") — per Default beim Einsatzleiter, optional für die Lage; nicht vergebbar an Dispo/SP-Dispo/Gast. Die Permission-Matrix umfasst damit jetzt 39 atomare Rechte. Vergabe, Änderung und Rücknahme landen im Rollen-Audit-Log.

    ⚠️ Nach dem Update einmalig /admin/schema-check.php → „Reparieren" ausführen. Die Einsatz-Rollen legen vier neue Spalten an der Benutzer-Tabelle an (temp_role, temp_role_until, temp_role_by, temp_role_at). Bis dahin bleibt die Funktion still inaktiv (keine Fehler), es erscheint der Schema-Banner.

  • Neuer Einsatz-Status-Lebenszyklus & Vier-Augen-Abschluss (Etappe 1) — schließt #3 (Status-Workflow) und #114 (Dispo sah keine Einsätze). Der Einsatz durchläuft jetzt fünf klar benannte Stufen: Neu → Disponent → In Bearbeitung → Erledigt → Abgeschlossen. Die alten Stufen „Status 3 (Anfahrt)", „Status 4 (vor Ort)" und „Abschluss beantragt" entfallen.

    • Automatische Übergänge nehmen dir Klickarbeit ab (nur vorwärts): Wer einen Disponenten zuweist, hebt den Einsatz von „Neu" auf „Disponent"; das erste zugewiesene Einsatzmittel schaltet ihn auf „In Bearbeitung". Jeder Automatik-Sprung steht mit Begründung in der Historie.
    • Neuer Button „✅ Einsatz erledigen" (ersetzt „Abschluss-Freigabe beantragen"): setzt den Status auf „Erledigt" und bietet ein optionales Abschluss-Kommentarfeld — mit Text wird ein normaler Kommentar gespeichert, ohne Text ein revisionsfester System-Kommentar.
    • Vier-Augen-Prinzip beim Abschluss: Der finale Schritt auf „Abgeschlossen" verlangt das Recht „Einsatz abschließen" (einsatz.abschluss, Default Lage/Einsatzleiter/Admin). Ein Dispo kann erledigen, aber nicht abschließen — die Sperre greift im Status-Dropdown und in der Bulk-Aktion. Lage/EL/Admin behalten das freie Status-Dropdown (auch rückwärts).
    • Übersicht für Disponenten: Die ETB-Übersicht zeigt einem Dispo (ohne das Recht „alle Einsätze sehen") beim ersten Aufruf nur die eigenen zugewiesenen Einsätze — mit sichtbarem Hinweis und „Alle anzeigen"-Link. Neuer Filter „👥 Anderen zugeordnet" ergänzt „Mir zugeordnet" und „Nicht zugeordnet".
    • Einsatzmittel werden automatisch frei, sobald alle ihre Einsätze erledigt oder abgeschlossen sind (vorher endeten sie u. a. an den entfallenen Status 3/4).

    ⚠️ Nach dem Update einmalig /admin/schema-check.php → „Reparieren" ausführen. Die Umstellung migriert die Einsatz-Status in der Datenbank (Status 3/4 → „In Bearbeitung", „Abschluss beantragt" → „Erledigt") und legt neue Spalten an. Ohne diesen Schritt zeigt das ETB den Schema-Banner; bestehende Einsätze bleiben dabei erhalten.

  • Wiederverwendbare UI-Bausteine (Grundlage, noch nicht flächig im Einsatz): eine Formularfeld-Komponente (.form-field) mit zugehöriger Inline-Validierung (form-validate.js, opt-in über data-validate am <form> — bestehende Formulare bleiben unberührt) sowie die Design- Bausteine Mono-Einsatznummer (.einsatznr-mono), Status-Akzentleiste (.status-accent), Filter-Chip (.toggle-chip), Identitäts-Akzent (.identity-accent) und eine Icon-Basisklasse (.icon).

  • Icon-Bibliothek (IconLibrary, src/IconLibrary.php): zentrales Inline-SVG-Set im Tabler-Stil (MIT, Single-File-Vendoring, kein Build). Löst künftig die verstreuten Emoji ab; rendert mit currentColor und passenden a11y-Attributen (dekorativ aria-hidden, mit Label role="img").

Barrierefreiheit & UI-Politur

  • Dialoge fangen den Tastatur-Fokus ein (#124): Solange ein Dialog (z. B. eine Sicherheitsabfrage) offen ist, bleibst Du beim Durchtabben innerhalb des Dialogs — der Fokus springt nicht mehr hinter das Fenster. Nach dem Schließen kehrt der Fokus auf das Element zurück, mit dem Du den Dialog geöffnet hast. Der Rest der Seite wird währenddessen für Screenreader stillgelegt, sodass nur noch der Dialog vorgelesen wird (WCAG 2.1.2 / 2.4.3 / 4.1.2).
  • Größere Touch-Ziele (#124, #118): Die Buttons in Dialogen und die Status-Filter-Chips in der Einsatzliste haben jetzt eine ausreichende Mindesthöhe — leichter zu treffen, vor allem auf Tablet und Smartphone.
  • Sichtbarer Wartezustand der Status-Auswahl (#118): Wenn Du in der Einsatzliste oder der Einsatz-Detailansicht einen Status über das Dropdown umstellst, zeigt das Auswahlfeld während des Speicherns einen abgeblendeten, gesperrten Zustand an — Du siehst, dass die Änderung läuft, und kannst nicht versehentlich doppelt klicken. Bisher gab es diese Optik nur in der Abschnitts-Ansicht.
  • Schwerpunkt-Übersicht auf schmalen Bildschirmen (#116): Die Tabelle der aktiven Schwerpunkte wird auf schmalen Geräten jetzt horizontal scrollbar dargestellt, statt am rechten Rand abgeschnitten zu werden — die rechten Spalten sind damit wieder vollständig erreichbar.
  • Einheitliche Begriffe und Aktions-Verben in der Oberfläche (#119): Über die gesamte Oberfläche heißen gleiche Aktionen jetzt überall gleich — Zuweisen (Einsatzmittel oder Einsatz an ein Ziel hängen), Zuordnen (eine Person setzen, z. B. den Disponenten), Entfernen (eine Zuordnung lösen) und Löschen (einen Datensatz endgültig vernichten). Das frühere „Herausnehmen" entfällt zugunsten von „Entfernen"; ein an einen Einsatz oder Schwerpunkt gehängtes Einsatzmittel ist nun durchgängig „zugewiesen" (nicht mehr „zugeordnet"). Die durchgängige Du-Anrede wurde vereinheitlicht (die letzte Sie-Stelle entfernt, „Dein/Deine/Deinem" durchgehend groß), und alle sichtbaren Meldungen nutzen jetzt echte Umlaute (z. B. „gelöscht" statt „geloescht"). Aus den Buttons sind die ⏳-Lade-Emoji verschwunden — der Lade-/Gesperrt-Zustand wird ohne Emoji angezeigt. Die Einsatzmittel-Status-Bezeichnungen sind angeglichen: „Nicht eingesetzt" (vorher „Nicht zugewiesen") und „Anfahrt" (vorher „Auf Anfahrt"). Es ändert sich nur die Beschriftung, keine Funktion. Als verbindliche interne Referenz für künftige UI-Texte ist dazu das Glossar docs/microcopy-glossar.md neu hinzugekommen.
  • Einheitlichere Chip-Darstellung beim Schwerpunkt-Bearbeiten: Im Dialog Schwerpunkt bearbeiten sehen die Einsatzmittel im Pool jetzt genauso aus wie die zugewiesenen Einsatzmittel im Einsatz — eine grüne, entfernbare Pille statt der bisherigen grauen Darstellung. Auch die Trigger-Orte erscheinen als saubere Auswahl-Pille (blau hervorgehoben, wenn ausgewählt) statt mit roher Checkbox; die Bedienung per Tastatur und der sichtbare Fokusring bleiben erhalten. Das fügt sich stimmig zu den Einsatzmittel-Chips. Es ändert sich nur die Optik, keine Funktion.
  • Aktiver Lagekarten-Filter im Dark-Mode jetzt rot statt blau: Die aktiven Umschalter „Filter" und „Einsatzmittel" auf der Lagekarte werden im dunklen Design jetzt rot hinterlegt — passend zur hellen Variante und zu den aktiven Status-Pillen, und mit ausreichendem Kontrast (Weiß auf Rot, WCAG AA).
  • Besserer Dark-Mode-Kontrast (Voll-Review vor v4.0.0): Die Überschrift der Schwerpunkte-Übersicht und der Lagekarten-Umschalter (Pill-Hover) stellen sich im dunklen Design jetzt mit ausreichendem Kontrast dar — vorher war die grüne Überschrift bzw. der Hover auf der dunklen Pille schwer lesbar (WCAG 1.4.3).
  • Mehr per Tastatur bedienbar (Voll-Review vor v4.0.0): Die Bild-Lightbox in der Einsatz-Detailansicht lässt sich jetzt komplett ohne Maus bedienen — ein Bild öffnest Du mit Enter / Leertaste, der ×-Knopf reagiert ebenfalls auf die Tastatur. Auch der Zuweisen-/Verschieben-Dialog der Einsatz-Übersicht fängt den Tastatur-Fokus jetzt ein (Tab bleibt im Dialog, Esc schließt, der Fokus kehrt danach zurück) — wie die übrigen Dialoge (WCAG 2.1.1 / 2.1.2 / 2.4.3). Zusätzlich hat das Koordinaten-Eingabefeld im Geocode-Werkzeug wieder einen sichtbaren Fokus-Indikator (WCAG 2.4.7).
  • Einsatzmittel komplett per Tastatur zuweisen (Voll-Review vor v4.0.0, WCAG 2.1.1): Die Chips der EM-Seitenleiste erreichst Du jetzt mit Tab; Enter oder Leertaste weist das Einsatzmittel zu — bei genau einem sichtbaren Ziel direkt, bei mehreren öffnet sich der bekannte Auswahl-Dialog „… zuweisen", der den Fokus einfängt, sich mit Esc schließen lässt und den Fokus danach zum Chip zurückgibt. Das gilt überall, wo die EM-Seitenleiste erscheint: Einsatz-Übersicht, Einsatz-Detail, Abschnitt-Detail, Einsatz anlegen/bearbeiten und Schwerpunkt-Einstellungen. Auch der Schwerpunkt-Anlage-Wizard (Schritt 4, Einsatzmittel-Pool) ist inzwischen tastaturbedienbar (siehe #180 unter „Neu").
  • Einheitliche Stärke-Lesart an den EM-Chips (Voll-Review vor v4.0.0): Die Stärke eines einzelnen Einsatzmittels (an Einsatz und Abschnitt) zeigt die Gesamtzahl jetzt wie die Summen-Pillen doppelt unterstrichen und erklärt die Positionen per Tooltip („Zug- und Verbandführer / Gruppenführer / Mannschaft / Gesamt"). Rein optisch, keine geänderte Bedienung.
  • EM-Status in der Seitenleiste nicht mehr nur über Farbe (WCAG 1.4.1): Jeder Einsatzmittel-Chip in der EM-Seitenleiste trägt seinen Status jetzt zusätzlich als kurzen Text („frei", „im Einsatz", „entlassen", „n. zugew.") — bisher war er nur am farbigen Punkt und im Hover-Tooltip ablesbar. Damit ist die Frei-/Belegt-Unterscheidung auch bei Farbfehlsichtigkeit, auf Touch (kein Hover) und für Screenreader wahrnehmbar; der farbige Punkt bleibt als schnelle Zusatz-Codierung erhalten (dekorativ, aria-hidden). Rein additiv, kein Schema-Check nötig.
  • Bestätigungs-Dialoge im Marken-Rot statt Blau (Abschluss-Politur): Der zentrale Bestätigungs-/Abfrage-Dialog (Sicherheitsabfragen, Eingabe-Prompts) färbt seinen Bestätigen-Knopf jetzt im Marken-Rot der Anwendung statt im bisherigen Bootstrap-Blau — es war der letzte blaue Primär-Knopf der Oberfläche. Weißer Text auf dem Identity-Rot bleibt kontraststark (WCAG AA). Zugleich zieht der Dialog seine gesamte Optik (Box, Kopf, Rumpf, Fußzeile, Buttons, Eingabefeld) jetzt durchgängig aus den zentralen Design-Tokens — damit sitzt auch der Dark-Mode ohne Sonder-Overrides richtig. Rein optisch, keine geänderte Bedienung.
  • Weitere Dialoge fangen den Tastatur-Fokus ein (Abschluss-Politur, WCAG 2.1.2 / 2.4.3): Auch der Abschnitte-bilden-Dialog und der Einsatzmittel-zuweisen-Dialog halten den Fokus beim Durchtabben jetzt im Fenster, statt ihn hinter das Overlay in den verdeckten Seiteninhalt wandern zu lassen — wie schon die übrigen Dialoge. Die zuvor mehrfach kopierte Fokus-Logik ist dafür zentralisiert (opt-in je Dialog); Dialoge mit eigener Fokus-Verwaltung bleiben unberührt.
  • Vereinheitlichte Fokus-Ringe und einzelne Dark-Kontraste (Abschluss-Politur): Sichtbare Fokus-Ringe reagieren jetzt konsistent auf Tastatur-Fokus (:focus-visible) und nutzen die Marken-Farbe, sodass ein Klick mit der Maus keinen dauerhaften Rahmen mehr stehen lässt. Einzelne Pillen (u. a. Status erledigt/entlassen, Rollen-Pillen Gast/off) im dunklen Design haben einen minimal helleren Text für AA-Kontrast (≥ 4.5:1). Rein optisch, kein Schema-Check nötig.

Geändert

  • Rechte: einsatz.delete ist jetzt das echte Einsatz-Löschrecht, Kommentar-Moderation wandert nach comment.delete — der Schlüssel einsatz.delete trug bislang das Label „Einsatz löschen", steuerte faktisch aber nur die Moderation fremder Einsatz-Kommentare. Mit dem neuen Löschen-Feature bedeutet einsatz.delete jetzt tatsächlich „Einsatz löschen" (Entity). Die frühere Kommentar-Moderation läuft über den neuen Schlüssel comment.delete („Einsatz-Kommentare moderieren") weiter — das Verhalten der Moderation selbst bleibt unverändert. Der Rollen-Editor zeigt entsprechend beide Rechte getrennt. → einmaliger Schema-Check nach dem Update nötig: Er benennt die bestehenden einsatz.delete-Zuordnungen aller Rollen einmalig auf comment.delete um (bewahrt so die bisherige Moderation) und setzt einsatz.delete als neues Löschrecht für Administrator, Einsatzleiter und Lage. Die Umstellung ist über einen Marker gegen doppelte Ausführung abgesichert.

  • Einheitliche Symbole auf dem Rückmelde-Dashboard (#178) — die Rückmelde-Status auf dem Dashboard (Komme, ESt, Später, Nicht, ELW raus, Abbruch, LG) und das Schema-Update-Warnsymbol nutzen jetzt einheitliche SVG-Symbole statt Emojis — je Status in seiner Statusfarbe, sowohl in den Kacheln als auch in den Listen-Badges. Rein optisch, keine Bedienungsänderung. Der orangefarbene Status („Später") wurde zugleich leicht abgedunkelt, damit der weiße Badge-Text den AA-Kontrast erreicht.

  • A11y-/Dark-Feinschliff (#177) — kleinere Politur an mehreren Stellen: größere Touch-Flächen an den Einsatzmittel-Entfernen-Buttons (×), vereinheitlichte Platzhalter in Auswahl-Feldern, ergänzte Screenreader-Beschriftungen und abgestimmte Dark-Mode-Farben.

  • Schwerpunkt-Stärke: dritte Gruppe „entlassen" (#165) — die Kräfte-Aufschlüsselung eines Schwerpunkts (Kräfte-Pill in der Übersicht und der Titelleiste, PDF-Export) weist aus dem Einsatz entlassene Einheiten jetzt getrennt aus: „N im Einsatz · M Reserve · K entlassen". Bisher zählten entlassene Einheiten unsichtbar in die Reserve. Die Gesamtzahl bleibt Pool-basiert und enthält alle drei Gruppen — Entlassene werden nur getrennt ausgewiesen, nicht abgezogen. Kein Schema-Check nötig.

  • Einheitliche Eingabefelder in den EM-Dialogen (Maintainer-Feedback) — die Textfelder im EM-Zuweisungs-Dialog und im neuen üÖrt-Anlage-Dialog folgen jetzt demselben Standard-Look wie die Einsatz-Formularfelder (gemeinsame Design-Tokens, Dark-Mode-korrekt) — vorher trugen sie teils noch hartkodierte helle Farben. Rein optisch, keine geänderte Bedienung.

  • Neue Abschluss-Semantik: „in Arbeit" blockiert, „geplant" nicht mehr (#162) — ein Einsatz lässt sich weder erledigen noch abschließen, solange Abschnitte in Arbeit sind (begonnen, aber nicht erledigt — z. B. „Im Aufbau", „Im Einsatz"). Neu dabei: Geplante (nie begonnene) Abschnitte blockieren nicht mehr, und die Sperre greift jetzt auch schon beim Erledigen (bisher nur beim Abschließen). Sie wirkt serverseitig überall — Status-Dropdown, Bulk-Aktion, Bearbeiten-Formular und Abschluss-Arbeitsplatz.

  • Ort ist Pflicht-Auswahl aus der Orts-Verwaltung (#173) — der feste Ort einer Alarm-Regel (Adress-Quelle „Feste Adresse"), der Ort im Dialog „Alarm auslösen" und der Leitstellen-Ort (Organisation & Branding) sind jetzt Dropdowns mit den aktiven Katalog-Orten statt Freitext — gespeichert wird immer die kanonische Katalog-Schreibweise (Freitext erzeugte bisher Orte außerhalb der Orts-Übersicht). Ohne gepflegte Orte ist die manuelle Alarm-Auslösung gesperrt (mit Hinweis zur Orts-Verwaltung), und der Regel-Modus „Feste Adresse" lässt sich nicht speichern. Alt-Werte außerhalb des Katalogs werden markiert angezeigt („— nicht mehr im Orts-Katalog") und lassen sich nicht erneut speichern; ein unveränderter Leitstellen-Alt-Wert blockiert das Speichern der übrigen Branding-Felder bewusst nicht.

  • Neue Standard-Bilder (BrunSoft) — Logo, Menü-Logo und Favicon haben jetzt neutrale Standard-Bilder (brunsoft-logo.png, brunsoft-menu.png, brunsoft-favicon.png). Sie gelten, solange Deine Organisation unter Admin → Organisation & Branding keine eigenen hochlädt — eigene Uploads bleiben unverändert. Alte instanzspezifische Bilder wurden entfernt; bestehende Instanzen fallen automatisch auf die neuen Standardbilder zurück (kein Handgriff nötig).

  • Mail-Parser behält das Stichwort-Präfix + Katalog-Abgleich (Stage 3): Der Parser für eingehende Alarm-Mails schnitt bei Alarm- und Unwetter-Stichworten bisher die ersten Zeichen (das Präfix, z. B. SU-) ab — das volle Stichwort bleibt jetzt erhalten. Anschließend gleicht das ETB das mail-erzeugte Stichwort gegen den Stichwort-Katalog ab: Bei einem Treffer wird die Anzeige-Variante gespeichert und angezeigt (samt Katalog-Verknüpfung stichwort_katalog_id), ohne Treffer das volle Stichwort als Freitext. Dadurch kann sich das angezeigte Stichwort automatisch erzeugter Einsätze gegenüber früher ändern. Die Alarm-Regel-Prüfung läuft jetzt auf der Anzeige-Variante — die bestehende Wildcard-Logik (B3*) greift unverändert.

  • Handbuch-Seite optisch überarbeitet (Hilfe//hilfe.php): Die in-App- Hilfe trägt jetzt über jedem Artikel eine „Kapitel-Plakette" — die Kapitelnummer (aus dem Datei-Präfix, z. B. 16) in Mono-Schrift auf dem Feuerwehr-Rot-Identitätsakzent, darüber als Eyebrow die Gruppe (z. B. „Tagesbetrieb"). Das greift dasselbe Zahl-auf-Farbe-Motiv wie die Status-Kachel der App auf. Die Stylesheet-Farben sind vollständig auf die zentralen Design-Tokens umgestellt (0 hartkodierte Farben) — Hell und Dunkel stellen sich damit automatisch korrekt dar; das frühere Fremd-Blau (Hover/Aktiv-Markierung der Themenliste, Prev/Next) ist dem Identitätsakzent gewichen. Die Vor-/Zurück-Navigation am Seitenende nutzt jetzt SVG-Pfeile (statt Unicode-Pfeile), Übergänge respektieren prefers-reduced-motion, und der Aktiv-/Akzent-Ton wurde so aufgehellt, dass er auch im Dunklen Modus den 3:1-Kontrast (WCAG 1.4.11) erreicht. Rein optisch — Inhalte, Navigation und Bedienung bleiben gleich.

  • Handbuch seiten-genau neu geschnitten (Etappe 7, docs/handbuch/): Passend zur Kontext-Hilfe ist das Handbuch von rund 20 großen Kapiteln auf gut 50 seiten-genaue Themen umgestellt — ein Thema je Bildschirm (im Admin je Kachel). Die Themen sind in einer logischen Reihenfolge gruppiert (Einstieg → Betrieb & Installation → Konzepte → Einsätze → Schwerpunkte → Karten → Werkzeuge → Admin · Feuerwehr/Konfiguration/ Aktionen/Logs & Diagnose → FAQ & Glossar); FAQ und Glossar sind jetzt getrennte Themen. Jede Datei trägt ein Frontmatter (title/slug/ groups/order/context), das Reihenfolge und Gruppe steuert — der Dateiname ist nicht mehr für die Sortierung zuständig. Inhaltlich derselbe Stoff, nur kleinteiliger auffindbar; betrifft nur die Dokumentation, an der Anwendung selbst ändert sich dadurch nichts.

  • Rollen-Beschreibung präzisiert (Etappe 7, Handbuch): Die Rollen-Themen benennen die Rollen jetzt mit ihren sprechenden Namen und stellen klar, dass die Lage über dem Einsatzleiter steht. Reine Doku-Präzisierung.

  • Handbuch-Inhalt durchgesehen und aktualisiert (docs/handbuch/): Ein Inhalts-Audit hat die Bedienungsanleitung auf den aktuellen Stand der Oberfläche gebracht. Neu ist ein eigenes Kapitel „Mobil, Tablet & App" (Gruppe „Einstieg") zum Tippen-statt-Ziehen der Einsatzmittel, zum einspaltigen Reflow schmaler Bildschirme und zur PWA-Installation. Außerdem entfernt: rund 67 veraltete Button-Symbole über 17 Seiten, weil die Oberfläche seit Etappe 6 durchgängig SVG-Icons statt Emoji nutzt (Callout-Marker ℹ️/⚠️/💡 sowie echte Telegram-/Status-Symbole bleiben erhalten) — sowie mehrere Verweise auf frühere, nie veröffentlichte Zwischenstände. Betrifft nur die Dokumentation; an der Anwendung ändert sich nichts.

  • Deploy-Werkzeug räumt verwaiste Server-Dateien auf (--prune): Das SFTP-Deploy (scripts/deploy-sftp.php) lud bisher nur hoch und ließ umbenannte oder gelöschte Dateien als Karteileichen auf dem Webspace zurück (z. B. eine alte Handbuch-Seite nach einer Umbenennung). Mit dem neuen Opt-in-Flag --prune entfernt es nach dem Upload genau diese verwaisten Dateien. Secrets (config/.env*, .htpasswd), Build-Stempel und hochgeladene Runtime-Daten (public/branding/, public/uploads/) bleiben dabei immer unangetastet; gelöscht wird nur mit --yes bzw. Bestätigung, auf Prod nur vom main-Branch und nur bei sauberem Working-Tree. Reines Maintainer-Werkzeug — am ETB selbst ändert sich nichts. Details in docs/DEPLOYMENT.md.

  • Einsatz-Rollen jetzt als Modal auf der Einsatz-Übersicht (Etappe 6): Die Vergabe temporärer Einsatz-Rollen ist keine eigene Sidebar-Seite mehr, sondern ein Modal, das über den Button „🤝 Einsatz-Rollen" auf der Einsatz-Übersicht (zwischen „Schwerpunkt erstellen" und „⚡ Alarm auslösen") aufgeht. Wer das Recht user.assign_temp_role nicht über seine Basis-Rolle hat, sieht den Button nicht (geliehene Rollen können nach wie vor nicht weiterverliehen werden); Berechtigungs-Prüfung und Mutation laufen unverändert über den abgesicherten Endpoint. Der alte Deep-Link /einsatz-rollen.php leitet weiter auf die Übersicht und öffnet das Modal — Lesezeichen bleiben gültig.

  • Sechs editierbare Telegram-Templates (Etappe 6): Der Template-Editor (/admin/telegram-templates.php) deckt jetzt alle sechs Nachrichten- Arten ab — neben main, alarmierung und error auch heartbeat (Status-Ping), reset (ETB-Reset-Meldung) und selftest (Selbsttest-Ping). Jedes Template lässt sich einzeln bearbeiten, per Haken aktivieren/deaktivieren (sonst gilt der hartkodierte Standard-Text), auf Default zurücksetzen und mit Beispiel-Daten an den Debug-Chat testen. Die reset-Vorlage kennt die Blöcke {#ok} (✅) und {#fail} (❌), die das ETB je nach Ausgang des Resets rendert.

  • Status- und Wichtigkeit-Symbole entfernt (Etappe 6): Abschnitts-Status, Schwerpunkt-Status und Wichtigkeit unterscheiden sich jetzt nur noch über Farbe + Label — es gibt kein Icon und keine Marker-Form mehr. In den Admin-Katalogen (/admin/wichtigkeit.php, /admin/abschnitt-status.php) sind Icon und Karten-Marker-Form nicht mehr einstellbar (die DB-Spalten bleiben unangetastet, nur ohne UI). Die Lagekarte stellt Einsätze über eine einheitliche Status-Kachel dar, deren Farbe dem Einsatz-Status folgt — nicht mehr der Wichtigkeit-Form.

  • Standard-Wert per Stern (★) in den Admin-Katalogen (Etappe 6): Den Standard-Wert (vorausgewählte Wichtigkeit bzw. Abschnitts-Status bei neuen Einträgen) legst du jetzt über einen klickbaren Stern (★) in der Spalte „Standard" fest; der aktive Standard ist mit einem gefüllten ★ markiert. Nur aktive Stufen sind als Standard wählbar.

  • Branding vereinfacht: „Eigenes Theme" entfernt (Etappe 6): Die frei konfigurierbare Marken-Farb- und -Schrift-Auswahl unter Admin → Organisation & Branding (vormals „Eigenes Theme" / Custom-Theme- und Font-Engine) ist entfallen. Geblieben sind Org-Name, Logo, Favicon, Menü-Logo und Leitstellen-Adresse sowie der normale Hell-/Dunkel-Umschalter. Farben und Schrift kommen jetzt einheitlich aus dem ausgelieferten Design (zentrale Design-Tokens), damit Hell- und Dunkel-Variante überall sauber lesbar bleiben. Bereits hinterlegte Theme-Werte werden ignoriert (keine Migration nötig); für die übrige Bedienung ändert sich nichts.

  • Durchgängige Icons statt Emoji (Etappe 6): Sidebar, Einsatz-Listen und -Detail, Lagekarte sowie rund 33 Admin- und Schwerpunkte-Seiten zeigen jetzt einheitliche Inline-SVG-Icons (Tabler-Stil, gerendert in currentColor mit passenden a11y-Attributen) statt der bisherigen Unicode-Emoji. Rein optisch — Beschriftungen, Tooltips und Abläufe bleiben gleich.

  • PWA: Browser-Chrome folgt dem Theme (Etappe 6): Die theme-color (Statusleisten-/Adressleisten-Farbe auf Mobilgeräten und im installierten PWA-Fenster) folgt jetzt dem aktiven Hell-/Dunkel-Theme und schaltet beim Umstellen mit um.

  • Lagekarte: Dark-Mode-Feinschliff der Filterleiste (Etappe 6): Die Filter-/Ansichts-Leiste der Lagekarte ist jetzt token-basiert und stellt sich im Dunklen Modus korrekt dar (kein heller Streifen mehr); der Karte-hell/dunkel-Umschalter sitzt als Icon-Knopf an gewohnter Stelle.

  • CSS-/Token-Konsolidierung (Etappe 6, intern): Auflösung der zuvor in Etappe 0.5 angekündigten theme.css-Duplikate, neue Tokens für die Status-Kachel (Hell + Dunkel) und für die Alarm-Regel-Chips (/admin/alarm-regeln.php), die damit von hartkodierten Farben auf Tokens umgestellt sind. Ohne sichtbare Wirkung auf die Bedienung.

  • Entmandantisierung — neutrale Standard-Texte & interne Umbenennungen (Etappe 5): Alle fest auf die Referenz-Wehr zugeschnittenen Kennungen wurden entfernt, damit das ETB ohne Nacharbeit bei jeder Feuerwehr startet. Für die tägliche Bedienung ändert sich nichts — die betroffenen Werte waren intern oder werden ohnehin über „Organisation & Branding" und die Stammdaten je Instanz gepflegt.

    • Neutrale Vorgaben: Branding-Standardtexte (z. B. „Freiwillige Feuerwehr" statt eines konkreten Wehr-Namens), leere Logo-/URL- Vorgaben sowie neutrale Platzhalter im Admin-Bereich. Deine bereits eingetragenen eigenen Werte bleiben unverändert.
    • Interne Umbenennungen ohne sichtbare Wirkung: Der interne Speicherwert der Einsatzmittel-Kategorie „eigene" heißt in der Datenbank jetzt eigene (vorher ein wehr-spezifisches Kürzel); im Einsatzmittel-Editor stand und steht weiterhin das Label „eigene". Auch der Name des Sitzungs-Cookies wurde neutralisiert (FFETB_SID).
    • Doku-Quellen vereinheitlicht: Die Doku-Links in Handbuch, README, CONTRIBUTING und SECURITY zeigen jetzt einheitlich auf den aktuellen Projekt-Owner, und die Handbuch-Beispiele nennen neutrale Dummy-Orte statt eines realen Wehrgebiets.

    ⚠️ Nach dem Update einmalig /admin/schema-check.php → „Reparieren" ausführen. Die Entmandantisierung benennt den internen Speicherwert der Einsatzmittel-Kategorie um (DB-ENUM von einem wehr-spezifischen Kürzel auf eigene); der Schema-Check zieht bestehende Einsatzmittel verlustfrei und idempotent mit. Bis dahin zeigt das ETB den Schema-Banner.

    ℹ️ Einmaliger Logout beim Update: Weil der Sitzungs-Cookie umbenannt wurde (FFETB_SID), werden mit dem Deploy alle aktiven Sitzungen einmalig beendet — alle Nutzer müssen sich einmal neu anmelden. Das ist bewusst so eingeplant; danach läuft alles normal weiter.

  • Rollen-, Einsatz-Rollen- und Aktiv-Status-Änderungen wirken jetzt sofort (Etappe 2, #30): Der Anmelde-Status wird bei jedem Seitenaufruf frisch aus der Datenbank geprüft (statt nur aus der Sitzung). Ändert ein Admin die Rolle eines Benutzers oder vergibt/entzieht eine Einsatz-Rolle, greift das ohne Neuanmeldung beim nächsten Klick — vorher konnte das bis zu 12 Stunden dauern. Deaktivierte Konten werden jetzt sofort ausgeloggt (beim nächsten Seitenaufruf), statt erst nach Ablauf der Sitzung. Für die Bedienung ändert sich sonst nichts.

  • Bessere Tastatur- und Touch-Bedienbarkeit (Barrierefreiheit, WCAG 2.2 AA): Wer mit der Tastatur navigiert (Tab-Taste), sieht jetzt app-weit einen deutlich sichtbaren Fokus-Rahmen — vorher war er besonders im Dunklen Modus kaum zu erkennen. Das gilt auch für die Disponenten-Auswahl in den Einsatz-/Abschnitts-Zeilen, die zuvor gar keinen sichtbaren Fokus hatte. Auf Smartphone und Tablet sind Buttons, Filter- und Auswahl-Chips sowie Eingabefelder jetzt durchgängig mindestens 44 px hoch und damit fingerfreundlicher. Eingabefehler in Formularen werden zusätzlich für Screenreader angekündigt (aria-invalid / role="alert"). Mit der Maus ändert sich nichts (der Fokus-Rahmen erscheint nur bei Tastatur-/Programm-Fokus).

  • Erweiterte Design-Tokens (tokens.css): zentrale Skalen für Abstände, Radien, Schatten und Schriftgrößen, eine zentrale Breakpoint-Referenz, ein Mono-Font-Token sowie ein dezenter, von der Status-/Alarm-Farbe getrennter Identitäts-Akzent (Feuerwehr-Rot, in Hell und Dunkel sichtbar). Die Light-Defaults der Admin-Rollen-Pills liegen jetzt ebenfalls zentral als Tokens vor (Auflösung der theme.css-Duplikate folgt in Etappe 6).

Behoben

  • Lagekarte: einheitliche Höhe der Topbar-Buttons bei schmaler Ansicht (#179) — die Umschalter Einsätze, Filter und Einsatzmittel in der Kopfleiste der Lagekarte hatten bei schmaler Breite unterschiedliche Höhen, weil ihr Text intern umbrach. Sie halten jetzt Symbol und Text einzeilig und brechen als ganzer Button in die nächste Zeile um — dadurch bleiben sie gleich hoch. Rein optisch, kein Schema-Check nötig.

  • Lagekarte-Filter „Nur offene" blendet jetzt auch erledigte Einsätze aus — bisher zeigte Nur offene noch Einsätze im Status Erledigt; nur Abgeschlossen wurde ausgeblendet. Jetzt zeigt Nur offene konsistent nur aktive Einsätze (Neu, Disponiert, In Bearbeitung) — Erledigt und Abgeschlossen sind beide ausgeblendet, passend zu Einsatzliste und Zählern. Kein Schema-Check nötig.

  • Kleine Nachbesserungen aus dem Abschluss-Reviewkein Schema-Check nötig.

    • Schwerpunkt anlegen: Orte, die bereits einem offenen Schwerpunkt zugeordnet sind, werden im Ort-Schritt jetzt ausgegraut mit „belegt"-Kennzeichnung gezeigt (statt kommentarlos zu fehlen) — so ist klar, warum ein Ort nicht wählbar ist.
    • Abschnitts-Status: Zum Ändern eines Abschnitts-Status verlangt der Server jetzt konsistent das Recht „Abschnitts-Status setzen" (genau wie schon in der Oberfläche) statt des allgemeineren Einsatz-Bearbeiten-Rechts. Für die Standard-Rollen ändert sich nichts.
    • Einsatzmittel am Abschnitt zuweisen: Das Zuweisen/Entfernen von Einsatzmitteln an einem Abschnitt verlangt server­seitig jetzt konsistent das Recht „EMs zu Abschnitt zuweisen" (abschnitt.em_assign) — genau das Recht, an dem auch schon der EM-Editor in der Abschnittsansicht hängt. Vorher prüfte der Endpoint das allgemeinere Einsatz-Bearbeiten-Recht, wodurch Oberfläche und Server bei eigenen (Custom-)Rollen auseinander­ laufen konnten. Für die Standard-Rollen (die beide Rechte gemeinsam tragen) ändert sich nichts.
    • Schwerpunkt erledigen: Die Warnung „noch X Einsätze offen" am Erledigen-Knopf im Schwerpunkt-Banner nutzt jetzt den aktuellen Stand statt eines evtl. veralteten Werts vom Seitenaufbau.
  • Korrektheit & Politur (Nachzieher aus dem Voll-Review) — kleine Korrekturen ohne geänderte Bedienung; kein Schema-Check nötig.

    • Abschluss-/Erledigt-Vermerk auch beim Formular-Speichern korrekt: Änderst du den Status eines Einsatzes über das Bearbeiten-Formular, werden die Vermerke „erledigt von/am" und „abgeschlossen von/am" jetzt genauso konsistent gesetzt bzw. wieder geleert wie über das Status-Dropdown — vorher konnte das Formular veraltete Stempel stehenlassen. Ein über das Formular ausgelöster Disponenten-Wechsel landet außerdem korrekt in der Historie.
    • Alarm-Regeln: kein Doppel-Anlegen bei gleichzeitigem Auslösen. Beim manuellen Auslösen einer Alarm-Regel am Einsatz konnte ein Doppelklick oder ein zweiter Tab in seltenen Fällen die Folge-Einsätze/-Abschnitte doppelt anlegen. Der Server merkt sich die Auslösung jetzt vor dem Anlegen und überspringt parallele Zweitversuche; eine manuell ausgelöste Regel wird zudem zuverlässig protokolliert, sodass das Bestätigungs-Banner sie danach nicht erneut als offen anbietet.
    • „Einsätze abschließen": schnellere Liste. Die Liste der erledigten Einsätze (Zähler und Sammel-Modal) lädt die Anzahl noch offener Abschnitte jetzt in einer Abfrage statt einzeln pro Zeile — spürbar flotter bei vielen Einsätzen und bei Live-Aktualisierungen.
    • Deaktivierte Katalog-Stichworte zählen nicht als Auswahl: Beim Speichern eines Einsatzes wird eine übergebene Stichwort-Katalog-ID nur noch akzeptiert, wenn der Eintrag aktiv ist; ein deaktivierter Eintrag fällt sauber auf Freitext zurück.
    • Erledigen-Dialog: Tastatur-Bedienung & Fokus (Barrierefreiheit, WCAG 2.1.2 / 2.4.3). Im Fenster „Einsatz erledigen" bleibt der Fokus jetzt im Dialog (Tab springt nicht mehr dahinter), und nach dem Schließen kehrt er auf den auslösenden Knopf zurück.
    • Größere Tipp-Flächen auf Touch-Geräten: Das Status-Auswahlfeld und die Einsatzmittel-Chips sind jetzt mindestens 44 px hoch und damit auf dem Smartphone besser zu treffen.
    • Auto-Aktualisierung pausiert bei offenem Dialog: Die automatische Listen-Aktualisierung hält jetzt an, solange ein Dialog (z. B. „Erledigen") offen ist, und reißt ihn nicht mehr unter den Händen weg.
    • Dark-Mode-Lesbarkeit nachgezogen: Mehrere Flächen, die im dunklen Erscheinungsbild noch hellgrau hinterlegt waren (gesperrtes Disponenten-Feld, CSV-Status-Markierungen im Stichwort-Katalog, Hinweis-Einblendungen, aufgeklappte Schwerpunkt-Unterzeilen sowie die graue „vorhanden/—"-Pille), nutzen jetzt die Theme-Farben und sind im Dunkelmodus sauber lesbar.
  • SMTP („Passwort vergessen") jetzt im Setup-Wizard und unter Admin → Einstellungen sichtbar — der ausgehende Mailversand ließ sich bisher nur per Hand in config/.env eintragen und tauchte nirgends in der Oberfläche auf; nach einer Frischinstallation fehlte er im Wizard komplett, sodass „Passwort vergessen" tot war und sich der Fehler nicht diagnostizieren ließ. Jetzt:

    • Der Setup-Wizard fragt in Schritt 3 (unter dem Alarmpush-Postfach) optional die SMTP-Felder ab — Host, Port, Verschlüsselung (tls/ssl/none), Benutzer, Passwort, Absender und Absender-Name — und schreibt sie nach config/.env; die Zusammenfassung (Schritt 7) zeigt sie an (Passwort nie im Klartext). Leerer Host = Versand bewusst aus.
    • Admin → Einstellungen (/admin/config.php) zeigt den SMTP-Block jetzt als eigene Sektion (read-only, Passwort maskiert), sodass Du auf einen Blick siehst, was hinterlegt ist. Geändert wird weiter über den Wizard bzw. config/.env.
    • Als Merkhilfe: Port 587 = STARTTLS (tls), Port 465 = implizites SSL (ssl); der Wizard warnt, wenn Port und Verschlüsselung nicht zusammenpassen.
    • Damit ist „Passwort vergessen" ohne .env-Handarbeit konfigurierbar. Kein Schema-Check nötig.
  • .env-Vorlage entrümpelt: Der nicht mehr gelesene Eintrag ALARMPUSH_BASE_URL ist aus config/.env.example entfernt — die App-Basis-URL (z. B. für Einsatz-Links in Telegram) kommt aus dem DB-Setting org_url (Setup-Wizard Schritt 1 bzw. Admin → Organisation & Branding).

  • „Einsätze abschließen" lässt den Komfort/Kompakt-Schalter in Ruhe: Der eigenständige Knopf teilt sich für die Optik die .lvt-btn-Klasse mit dem Komfort/Kompakt-Umschalter und wurde dadurch von dessen JavaScript miterfasst — ein Klick entfernte die aktive (rote) Markierung des Umschalters. Die Umschalt-Logik greift jetzt nur noch die echten Toggle-Buttons (mit data-view).

  • Geocodierung beim Bearbeiten folgt der Adressänderung: Wurde bei einem bestehenden Einsatz die Straße/Adresse geändert und gespeichert, blieb die alte Geocodierung (Lagekarte-Marker) stehen — die automatische Geocodierung brach ab, weil das Formular die alten Koordinaten mittrug. Jetzt werden bei geänderter Adresse die alten Koordinaten verworfen und neu geocodiert; selbst eingetragene Koordinaten behalten Vorrang. Liefert die Neu-Geocodierung keinen Treffer (Dienst nicht erreichbar oder Adresse unbekannt), bleiben die bisherigen Koordinaten erhalten, statt den Marker stumm zu verlieren.

  • Schwerpunkt-Personalstärke aktualisiert sich live: Die Einsatzkräfte-Summe in der Schwerpunkt-Titelleiste aktualisiert sich jetzt automatisch beim Hinzufügen/Entfernen von Einsatzmitteln, Ändern der Einsatzstärke und bei Status-/Abschluss-Wechseln — vorher war ein Browser-Reload nötig.

  • Standard-Stern in den Status-Stammdaten korrekt ausgerichtet: In den Katalog-Seiten (Wichtigkeit, Abschnitts-/Schwerpunkt-Status) saß der gold markierte Standard-Stern etwas weiter links als die klickbaren Sterne der übrigen Zeilen — der markierte Stern ist ein <span> ohne Innenabstand, die klickbaren ein <button> mit Padding. Der Span bekommt jetzt dieselbe Box (display: inline-block + gleiches Padding), sodass der gelbe Stern exakt mittig über den anderen sitzt.

  • ETB-Reset meldet jetzt echte Datenbank-Fehler (Etappe 6): Der ETB-Reset wertete bisher jeden Durchlauf als „erfolgreich" und schickte den grünen Haken per Telegram — selbst wenn einzelne DELETE-Operationen an einem echten Datenbank-Fehler (Lock-Timeout, Fremdschlüssel o. ä.) scheiterten und Daten gar nicht gelöscht wurden. Jetzt zählt nur eine fehlende Tabelle als unkritisch (übersprungen); jeder andere Fehler setzt die Reset-Meldung auf die ❌-Variante und wird je Tabelle im Detail ausgewiesen. Betrifft Anzeige im Admin und die Telegram-reset-Nachricht.

  • Detail-Mini-Karte: Theme-Leak behoben (Etappe 6): Die Mini-Karte der Einsatzstelle (Einsatz-Detail) und der Abschnitts-Detailseite folgt jetzt zuverlässig dem aktiven App-Erscheinungsbild (hell/dunkel). Der frühere eigene Hell/Dunkel-Umschalter dieser kleinen Karten ist entfernt — er konnte dazu führen, dass eine Karte im falschen Modus „hängen blieb". Der manuelle Karten-Umschalter wirkt bewusst nur noch auf Lagekarte und Hydrantenplan (die Vollkarten).

  • „Auch SP-Einsätze anzeigen" bleibt beim Filtern erhalten (Etappe 6): Hattest du in der Einsatz-Übersicht die freien Einsätze um die Schwerpunkt-Einsätze erweitert („Auch SP-Einsätze in Liste anzeigen") und danach einen Filter gesetzt (Status, Wichtigkeit, Suche, Disponent), sprang die Liste fälschlich zurück auf „nur freie Einsätze". Der Schalter (sowie eine aktive Sortierung und der Schwerpunkt-Kontext) wird jetzt über das Filter-Formular mitgeführt und bleibt erhalten.

  • Lesbare Textfarbe auf frei gewählten Status-/Wichtigkeit-Farben (Barrierefreiheit, WCAG 1.4.3, Etappe 6): Die Status- und Wichtigkeit-Pillen sowie die Abschnitts-Status-Kachel zeigten ihren Text bisher immer weiß. Auf mittelhellen Farben — etwa Grün (#229954), Orange (#e98011) oder Gelb (#f1c40f) — unterschritt das die geforderten 4,5:1 Kontrast und war schlecht lesbar. Die Textfarbe (Schwarz oder Weiß) wird jetzt automatisch anhand der Helligkeit der hinterlegten Farbe gewählt und hält den AA-Kontrast auf jeder gültigen Farbe ein. Betroffen sind die Einsatz-Liste (Wichtigkeit-, Schwerpunkt-Status-, Abschnitts-Status-Pille und die Wichtigkeit-Filter-Chips), die Einsatz-Detailseite (Wichtigkeit-Pille im Kopf + Abschnitts-Status- Kachel), die Abschnitts-Detailseite, die Schwerpunkt-Liste, -Bearbeitung und -Historie, die Admin-Kataloge Wichtigkeit / Abschnitts-Status / Schwerpunkt-Status (Vorschau-Pillen samt „★ Standard"-Badge), PDF-Export und Druckansicht sowie die Kartenbeschriftungen: die Schwerpunkt-Marker der Lagekarte (grün = aktiv, gelb = pausiert; Weiß auf Gelb war zuvor nur ~1,6:1) und die farbigen Hydranten-Größen-Chips in den Karten-Popups (Hydrantenplan, Admin-Hydranten-Karte und Einsatz-Detailansicht) sowie die interaktiven Status-Dropdowns (das Status-<select> der Abschnitts- Detailseite und der Schwerpunkt-Übersicht) — dort wird die lesbare Textfarbe sowohl beim Laden als auch sofort beim Statuswechsel (ohne Neuladen) gewählt. Karten- und Server-Beschriftung nutzen dieselbe Kontrast-Logik, sodass eine Farbe überall dieselbe Textfarbe erhält. Für Admins heißt das: Beim Festlegen einer Status- oder Wichtigkeit-Farbe musst du nicht mehr selbst auf den Textkontrast achten — die Lesbarkeit stellt sich automatisch ein. Rein optisch, keine geänderte Bedienung, kein Schema-Check nötig.

  • Abschnitt eines abgeschlossenen Einsatzes lässt sich nicht mehr ändern (Voll-Review vor v4.0.0): Solange ein Einsatz abgeschlossen ist, weist das ETB einen Status-Wechsel seiner Abschnitte jetzt ab — sonst hätte ein „abgeschlossener" Einsatz wieder einen offenen Abschnitt haben können (genau der Zustand, den die Abschluss-Sperre verhindert). Wer einen Abschnitt ändern will, muss den Einsatz erst wieder öffnen (Recht „Wiedereröffnen", einsatz.reopen); die Meldung sagt das auch so. Kein Schema-Check nötig.

  • Einsatzmittel in den Schwerpunkt-Pool hinzufügen ist jetzt atomar (Voll-Review vor v4.0.0): Beim Hinzufügen eines Einsatzmittels zum Schwerpunkt-Pool laufen das Herauslösen aus freien Einsätzen und der Pool-Eintrag jetzt in einem Schritt. Bricht etwas mitten dabei ab, wird alles zurückgerollt — vorher konnte ein verwaister Zustand entstehen (Einsatzmittel aus den Einsätzen entfernt, aber nicht im Pool gelandet). Kein Schema-Check nötig.

  • Abschnitts-Disponent: „– nicht zugewiesen –" wählbar, kein stilles Umspringen mehr (#167, Voll-Review vor v4.0.0): Das Disponenten-Dropdown der Abschnitts-Detailseite zeigte ohne zugewiesenen Disponenten fälschlich den ersten Eintrag der Liste an — und schon eine Berührung des Feldes speicherte diesen still. Jetzt steht „– nicht zugewiesen –" als erster Eintrag im Dropdown und ist korrekt vorausgewählt, wenn kein Disponent zugewiesen ist; über diesen Eintrag lässt sich eine bestehende Zuweisung auch wieder entfernen. Hängt der Mutter-Einsatz an einem Schwerpunkt, zeigt die Detailseite den Disponenten jetzt nur lesend mit Schloss-Symbol (er folgt zwangsweise dem Schwerpunkt-Disponenten) — vorher stand dort ein scheinbar editierbares Dropdown, dessen Änderungen kommentarlos verworfen wurden. Kein Schema-Check nötig.

  • Einsatzkräfte-Summen: Gesamtzahl immer aus den drei Positionen (#165, Voll-Review vor v4.0.0): Alle Stärke-Summen — die Zeile „Einsatzkräfte" im Einsatz-Detail, die Gesamt-Einsatzstärke in der Titelzeile der Einsatz-Übersicht und die Kräfte-Anzeige der Schwerpunkte (Titelleiste und Übersicht) — leiten die Gesamtzahl (letzte Position) jetzt immer aus A+B+C ab, genau wie die Eingabe beim Zuweisen normalisiert wird. Vorher konnten inkonsistent gespeicherte Alt-Werte (Gesamt ≠ Summe der drei Positionen) die angezeigten Summen verfälschen. Der Schema-Check bereinigt solche Alt-Werte zusätzlich einmalig in der Datenbank (Normalisierung auf das Schema A/B/C/S) → einmaliger Schema-Check nach dem Update empfohlen.

  • Internes Aufräumen vor v4.0.0: toter Code entfernt (u. a. eine ungenutzte Diagnose-Seite und nicht mehr verdrahtete Service-Bausteine), doppelte CSS-Farbwerte zu zentralen Design-Tokens zusammengeführt. Ohne sichtbare Wirkung auf die Bedienung.

Sicherheit

  • Lagekarte respektiert den Disponenten-Scope — ein auf seine eigenen Einsätze beschränkter Disponent (Rolle Dispo ohne das Recht „Alle Einsätze sehen", einsatz.view_all) sah auf der Lagekarte bisher die Marker und Adressen aller Einsätze — also genau die Daten, die ihm die Einsatz-Übersicht vorenthält. Die Karte wendet jetzt denselben Eigentums-Filter an wie die Liste (eigene + zugewiesene Einsätze) und zeigt beide Ansichten damit im selben Scope. Der Schwerpunkt-Dispo-Scope wird zusätzlich wie bisher am Endpoint erzwungen; bewusst fail-safe gehalten (die Karte kann höchstens strenger filtern als die Liste, nie durchlässiger). Einsatzleiter, Lage und Admin sehen unverändert alle Einsätze. Kein Schema-Check nötig.

  • Link-Icon-URLs auf http(s):// beschränkt (#177) — in der Link-Verwaltung akzeptiert das ETB als Icon-URL jetzt ausschließlich http://- oder https://-Adressen (wie schon bei der Link-URL). Andere Schemata (z. B. javascript: oder data:) werden beim Speichern verworfen und beim Anzeigen defensiv herausgefiltert — auch für Alt-Daten, die vor dieser Prüfung gespeichert wurden. Das schließt einen möglichen XSS-Vektor im <img src> der Linksammlung. Kein Schema-Check nötig.

  • Abgeschlossener Einsatz auch serverseitig komplett eingefroren (#162) — der Freeze eines abgeschlossenen Einsatzes war bei Kommentaren und der Einsatzmittel-Zuordnung bisher teils nur eine UI-Sperre (verstecktes Formular). Jetzt weisen die Endpoints Kommentare und EM-Zuordnungen am Einsatz und an seinen Abschnitten serverseitig ab, und die Abschnittsseite zeigt die Sperre auch in der Oberfläche — relevant, seit geplante Abschnitte den Abschluss nicht mehr blockieren (ein nie begonnener Abschnitt kann jetzt an einem abgeschlossenen Einsatz hängen). Ausnahme wie gehabt: das Recht „Einsatz wiedereröffnen" (einsatz.reopen, Default Admin + Einsatzleiter). Kein Schema-Check nötig.

  • Review-Härtung (Nachzieher aus dem Voll-Review) — gezielte Absicherungen ohne neue Bedienung; kein Schema-Check nötig.

    • Abschließen über das Bearbeiten-Formular respektiert das Vier-Augen-Prinzip: Setzt jemand einen Einsatz im Bearbeiten- Formular auf „Abgeschlossen", greifen jetzt dieselben Sperren wie beim Status-Dropdown — das Recht „Einsatz abschließen" (einsatz.abschluss) und die Sperre „erst, wenn alle Abschnitte erledigt sind". Wer das Recht nicht hat (z. B. Disponent), bekommt die Stufe „Abgeschlossen" im Formular gar nicht mehr angeboten — wie schon zuvor im Status- und Bulk-Dropdown. (Ein bereits abgeschlossener Einsatz zeigt seinen Status weiterhin an.)
    • Schwerpunkt-Dispo bleibt strikt auf die eigenen Schwerpunkte begrenzt: Die mutierenden Schwerpunkt- und Abschnitts-Endpoints (Schwerpunkt bearbeiten, EM zum Pool hinzufügen/entfernen, Einsatz zuweisen/herauslösen/verschieben sowie Abschnitt löschen) prüfen den SP-Dispo-Scope jetzt durchgängig serverseitig — beim Verschieben sowohl für den Quell- als auch den Ziel-Schwerpunkt. Aktionen außerhalb der eigenen Schwerpunkte werden mit einer klaren Meldung abgewiesen. (Der SP-Dispo-Scope ist Code-Logik und greift immer — unabhängig davon, welche Häkchen ein Admin gesetzt hat.)
    • Schwerpunkt-/Abschnitts-Vollrechte nur noch in Führungshand: Die Rechte Schwerpunkt bearbeiten / zuweisen / löschen / schließen (schwerpunkt.edit, …assign_einsatz, …delete, …close) und Abschnitt löschen (abschnitt.delete) erscheinen im Rollen-Editor jetzt nur noch bei Einsatzleiter und Lage (Admin über den Failsafe). Für Dispo, Schwerpunkt-Dispo und Gast tauchen sie gar nicht erst auf, sie lassen sich diesen Rollen also auch nicht versehentlich zuteilen.
    • Telegram-Vorschau: HTML-Attribute härter gefiltert: Die Server-Vorschau der Telegram-Nachricht ließ bei den erlaubten Formatierungs-Tags bisher beliebige Attribute durch. Sie entfernt jetzt alle Attribute der Formatierungs-Tags und lässt bei Links nur ein href mit sicherem Schema (http/https/tg/mailto) stehen — wie es der Telegram-HTML-Modus ohnehin verlangt.
  • Schwerpunkt schließen / archivieren nur noch für Lage, EL und Admin — der Status-Wechsel eines Schwerpunkts auf „geschlossen" oder „archiviert" verlangt jetzt fest das Recht „Schwerpunkt schließen / archivieren" (schwerpunkt.close, Default: Lage, Einsatzleiter, Admin). Vorher konnte der Wechsel über das breitere schwerpunkt.edit-Recht des Endpoints laufen; SchwerpunktService erzwingt das schwerpunkt.close-Recht nun serverseitig (defense-in-depth), unabhängig vom Endpoint. Damit ist der Abschluss eines Schwerpunkts ein Vier-Augen-Schritt wie der Einsatz-Abschluss (einsatz.abschluss). Die bestehende Sperre — „geschlossen" erst, wenn alle Einsätze des Schwerpunkts abgeschlossen sind — bleibt unverändert. In den Schwerpunkt-Oberflächen sind die Aktionen „Schließen"/„Archivieren" für Nutzer ohne dieses Recht jetzt ausgegraut bzw. nicht wählbar (statt erst beim Klick serverseitig abgewiesen zu werden). Kein Schema-Check nötig.

  • CSRF-Schutz für die JSON-API (Header-Token, Etappe 0.7): Alle mutierenden AJAX-/JSON-Aktionen (public/api/* — z. B. Kommentar anlegen, Status ändern, Einsatzmittel zuweisen, Schwerpunkt/Abschnitt bearbeiten) verlangen jetzt zusätzlich ein X-CSRF-Token im Request-Header. Ein zentraler fetch-Wrapper (etb-common.js) hängt dieses Token automatisch an jeden mutierenden, gleich-stammenden (same-origin) Request an; serverseitig erzwingt es Csrf::checkHeader() (Vergleich mit hash_equals). Das ergänzt die bereits bestehende SameSite=Lax-Absicherung des Session-Cookies als zweite Verteidigungslinie gegen Cross-Site-Request-Forgery. Für Dich ändert sich an der Bedienung nichts — alle Aktionen laufen wie bisher.

    ℹ️ Nach dem Update einmal neu laden: Hat der Browser noch die alte JavaScript-Version zwischengespeichert, kann eine AJAX-Aktion kurz mit dem Hinweis „Sicherheits-Token … bitte die Seite neu laden" abbrechen. Ein einmaliges Neuladen der Seite (Strg+F5) behebt das.

  • Stichwort-Katalog: Änderungen mit auslösendem Benutzer protokolliert — jede Mutation am Stichwort-Katalog (Stichwort anlegen / ändern / löschen, CSV-Import, Änderung der Ausblend-Präfixe) wird jetzt nachvollziehbar mit dem auslösenden Benutzer im Anwendungs-Protokoll festgehalten. Für Dich ändert sich an der Bedienung nichts; kein Schema-Check nötig.

  • Härtung vor v4.0.0 (Voll-Review) — gezielte Absicherungen ohne neue Bedienung; kein Schema-Check nötig.

    • Gehärtete Ausgabe-Codierung gegen XSS: Die Bestätigungs- und Fehler-Meldungen beim Anlegen eines Schwerpunkts geben Name und eventuelle Konflikt-Texte jetzt maskiert aus, statt sie roh in die Seite zu schreiben. Ebenso betten die Karten-Seiten (Lagekarte-/ Hydrantenplan-Daten) ihre Daten jetzt mit härteren Maskierungs-Schaltern ein, sodass Inhalte aus der Datenbank nicht als aktives Markup wirken können. Sichtbar ändert sich nichts.
    • Zusätzlicher Zugriffs-Scope beim Anhängen an Kommentare: Wer eine auf eigene Einsätze beschränkte Rolle (Disponent / Schwerpunkt-Dispo) hat, kann an einen Kommentar (Einsatz oder Abschnitt) nur dann noch eine Datei anhängen, wenn der zugehörige Einsatz im eigenen Scope liegt — derselbe Schutz, der schon beim Bearbeiten/Löschen von Kommentaren greift.

3.0.1 — 2026-06-15

Neu

  • Neues Recht „Als Disponent arbeiten" (dispo.act_as): Im Rollen-Editor (/admin/rollen.php, Gruppe „Einsätze") gibt es ein neues, administrierbares Recht. Es steuert, wer in den Disponenten- Auswahllisten (Einsatz, Abschnitt, Schwerpunkt) erscheint und als Disponent zugewiesen werden kann. Der Default ist unverändert: nur die Rolle „Dispo" hat das Recht — und zwar fest (das Häkchen ist gesperrt/🔒, kann ihr also nicht entzogen werden); im Schwerpunkt-Kontext kommt wie bisher der Schwerpunkt-Dispo dazu. Neu zuschaltbar: Der Admin kann das Recht jetzt zusätzlich an „Lage" und „Einsatzleiter" vergeben — diese Rollen tauchen dann ebenfalls in den Disponenten-Listen auf. Administratoren erscheinen über den Admin-Failsafe ebenfalls in den Listen (sie haben ohnehin jedes Recht). Bewusst ausgeschlossen bleiben „Schwerpunkt-Dispo" (bleibt auf seine Schwerpunkte beschränkt — das Häkchen wird für diese Rolle gar nicht angezeigt) und Gast. Alle Disponenten-Dropdowns zeigen die Auswahl jetzt einheitlich im Format „Name (Rolle)". Bestands-Installationen ziehen das Recht beim nächsten /admin/schema-check.php → „Reparieren" für „Dispo" nach; dank der Festschreibung wirkt es aber sofort, auch ohne Schema-Lauf.

Geändert

  • Administratoren erscheinen jetzt ebenfalls in den Disponenten- Auswahllisten (Einsatz, Abschnitt, Schwerpunkt): Da ein Admin per Admin-Failsafe jedes Recht hat, gilt das auch für „Als Disponent arbeiten" (dispo.act_as). Damit lässt sich ein Admin wie ein Dispo zuweisen. (Korrigiert das zuvor dokumentierte Verhalten, wonach Admins bewusst nicht in den Listen standen.) Schwerpunkt-Dispo und Gast bleiben weiterhin ausgeschlossen.
  • EM-Seitenleiste der ETB-Übersicht: Live-Update bei Status-Änderung: Änderst du in der Einsatz-Übersicht den Status eines Einsatzes über das Status-Dropdown der Zeile, ziehen die zugeordneten Einsatzmittel in der Seitenleiste jetzt sofort nach (ohne Reload): Sie wechseln passend zwischen „frei" und „im Einsatz", die zugeordnete laufende Nummer (#007) kommt hinzu bzw. fällt weg. Das ergänzt den bereits bestehenden Live-Update beim Zuweisen per Drag&Drop.
  • SP-Pool-Einsatzmittel bleiben in der ETB-Übersicht ausgeblendet: In der normalen Einsatz-Übersicht werden Einsatzmittel, die einem aktiven Schwerpunkt-Pool angehören, weiterhin ausgeblendet — sie sind dem Schwerpunkt vorbehalten und stehen anderen Einsätzen nicht zur Verfügung, sollen also nicht zur Doppel-Zuweisung verleiten. Sichtbar bleiben diese EM innerhalb des jeweiligen Schwerpunkttagebuchs, wo die Seitenleiste auf den Pool gefiltert ist und als Pool-Picker dient. (Nimmt die kurzzeitige Änderung zurück, die SP-Pool-EM auch im ETB-Modus einblendete.)
  • Einsatz-Übersicht: zugeordnete Einsatzmittel jetzt auch auf dem Smartphone sichtbar: Auf schmalen Bildschirmen ist die eigene Einsatzmittel-Spalte weiterhin ausgeblendet. Damit die zugeordneten Einsatzmittel eines Einsatzes mobil nicht ganz fehlen, erscheinen sie dort jetzt als kompakte Chip-Zeile direkt unter dem Stichwort der Einsatz-Zeile. Am Desktop bleibt es unverändert bei der eigenen Spalte.
  • Lagekarte: Einsatznummer im Format #007: Marker-Tooltip und Marker- Popup zeigten die Einsatznummer bisher roh bzw. siebenstellig. Sie steht jetzt als unsere laufende Nummer im Format #007 — konsistent mit der Anzeige im restlichen ETB. Ebenso angeglichen ist die Einsatz-Geocoding- Admin (/geocode-admin.php), wo Liste und Status-Meldungen die laufende Nummer nun im #007-Format ausgeben.
  • Disponent-Anzeige einheitlich „Name (Rolle)": Wo der Disponent eines Einsatzes nur lesend angezeigt wird (gesperrtes Feld, z. B. bei einem schwerpunkt-gekoppelten oder abgeschlossenen Einsatz), erscheint jetzt ebenfalls das Format „Name (Rolle)" wie in den Auswahllisten — statt nur des Namens.

Behoben

  • Neutrale Links, Buttons und Kacheln bleiben nach Klick neutral (app-weit): Viele Elemente, die technisch Links sind — Menü- und Admin-Kacheln, Buttons (.btn/.btn-link), die Linksammlung (/links.php), die Hilfe-Navigation (Inhaltsverzeichnis + Vor/Zurück), Sortier-Spaltenköpfe in den Tabellen, die Telegram-Vorlagen-Reiter und die Karten-Buttons (TIM/Hydrant) — färbten sich nach einem Klick oder beim Hovern über die globale Link-Farbe blau (inkl. :visited). Sie bleiben jetzt in allen Zuständen neutral; nur der jeweils gewollte Hover (Hintergrund, Rahmen, Schatten) wirkt noch. Aktive/primäre Varianten (z. B. ein aktiver Reiter oder ein „primary"-Button) behalten unverändert ihre eigene Farbe.
  • Einsatzmittel-Sidebar: laufende Nummer statt Leitstellen-Nummer: Unter einem zugeordneten Einsatzmittel zeigte die EM-Sidebar (Einsatz- Übersicht, Einsatz-Detail und Schwerpunkt) fälschlich die Leitstellen-Einsatznummer an. Jetzt steht dort immer unsere laufende Nummer im Format #007 — konsistent mit dem Rest der Anwendung. Das gilt auch für den Live-Update nach Drag&Drop, die Einsatzauswahl beim Anlegen eines Schwerpunkts und die Kaskaden-Bestätigungsdialoge beim Umhängen belegter Einsatzmittel. Die Leitstellen-Nummer dient weiterhin nur intern der Duplikaterkennung eingehender Alarm-Mails.
  • Frisch alarmierte Einsatzmittel werden als „im Einsatz" angezeigt: Ein Einsatz startet im Status „neu" (egal ob aus Alarm-Mail oder manuell angelegt) und hat seine Einsatzmittel damit bereits draußen. Bisher galten EM an einem „neu"-Einsatz in der Sidebar trotzdem als frei (ohne Nummer) — besonders störend auf Smartphone/Tablet, wo die Einsatzmittel-Tabellenspalte ausgeblendet ist und nur die Sidebar bleibt. Jetzt zählt „neu" als „im Einsatz": solche EM erscheinen als belegt mit Nummer, und zwar identisch beim ersten Laden wie nach dem Live-Update per Drag&Drop. Auf der Lagekarte bzw. im Einsatzmittel-Panel zählen „neu"-EM zur Disp.-Stufe. Die Status erledigt, Abschluss beantragt und abgeschlossen gelten unverändert als frei (Nachlauf).
  • Dark-Mode: zwei hell leuchtende Pillen abgedunkelt: Die Zähler-/Quellen-Pillen in der EM-Gruppen-Verwaltung (/admin/em-gruppen.php) und im Geocode-Cache (/admin/geocode-cache.php) hatten fest hinterlegte Hellblau-Töne und leuchteten dadurch im Dunklen Modus grell. Sie nutzen jetzt die zentralen Design-Tokens und schalten im Dark-Mode korrekt mit um.
  • Zugewiesener, aber nicht mehr berechtigter Disponent verschwindet nicht still: Verliert ein bereits einem Einsatz oder Abschnitt zugewiesener Disponent nachträglich seine Berechtigung (inaktiv gesetzt oder das Recht „Als Disponent arbeiten" (dispo.act_as) entzogen), fiel er bisher kommentarlos aus dem Auswahl-Dropdown — beim nächsten Speichern wäre die Zuordnung damit unbemerkt verloren gegangen. Jetzt bleibt er als selektierte Option „Name (Rolle) — nicht mehr verfügbar" sichtbar (im Bearbeiten-Formular und in der Inline-Auswahl von Einsatz und Abschnitt), sodass die bestehende Zuordnung erhalten bleibt, bis sie bewusst geändert wird.
  • Dark-Mode: Setup-Wizard (installiert) und Geocode-Filter lesbar: Ruft man den Setup-Wizard aus dem installierten Admin-Menü auf, wurden mehrere Flächen (die Tabellen-Anlage-Liste in Schritt 2, die Zusammenfassungs- Blöcke, die Schalter-Box und die Buttons) noch mit festen hellen Farben gezeichnet — im Dunklen Modus schwer lesbar. Sie nutzen jetzt die zentralen Design-Tokens und dunkeln korrekt mit (die Erstinstallation bleibt bewusst hell, da dort noch kein Theme existiert). Außerdem waren im Geocode-Admin die Filter-Schaltflächen („Alle / Nicht geocodiert / Geocodiert") im Dark-Mode schwarz und kaum lesbar — sie sind jetzt hell.

3.0.0 — 2026-06-14

Neu

  • Versionsanzeige in der Seitenleiste: Ganz unten im Menü (unter den Buttons Abmelden / Theme / Einklappen) steht jetzt dezent die laufende Programmversion, z. B. „Version 2.4.0-58-a1b2c3d" — die Release-Version plus Build-Nummer (Anzahl der Commits seit dem letzten Release) und Commit-Kürzel. Direkt auf einem Release-Tag steht sie sauber als „Version 3.0.0". Per Maus-Tooltip gibt es Build-Zeitpunkt und Instanz (TEST/PROD). Die Angabe wird bei jedem Deploy automatisch aus dem Git-Stand erzeugt — so sieht man auf TEST und PROD sofort, welcher Stand läuft, und kann beide vergleichen. Sobald ein neuer Release-Tag (z. B. v3.0.0) gesetzt ist, zeigt sie automatisch „Version 3.0.0". Im eingeklappten Menü wird die Zeile ausgeblendet; zusätzlich steht die Version dezent auf der Login-Seite (TEST/PROD-Vergleich schon vor der Anmeldung).
  • PDF-Export: Einsatzmittel-Übersicht mit Stärke & Kontakt (#32): Am Ende des Einsatz-Berichts steht jetzt eine Übersichts-Tabelle der eingesetzten Einsatzmittel mit ihrer Stärke (Zug- und Verbandführer / Gruppenführer / Mannschaft / Gesamt) und ihrem Kontakt (hinterlegte Erreichbarkeit bzw. Funkrufname), abgeschlossen durch eine Gesamtstärke-Summenzeile. Die Tabelle erscheint nur, wenn mindestens ein Einsatzmittel eine Stärke oder einen Kontakt hinterlegt hat. Im Kopf des Berichts bleiben die Einsatzmittel bewusst eine reine Namensliste.
  • Passwort vergessen — Selbsthilfe per E-Mail-Link (#39): Die Login-Seite hat jetzt einen Link „Passwort vergessen?". Du gibst Deinen Benutzernamen oder Deine hinterlegte E-Mail-Adresse ein und bekommst einen einmalig verwendbaren Link an diese Adresse, über den Du (mit Wiederholung) ein neues Passwort vergibst. Der Link ist 30 Minuten gültig; mit dem ersten erfolgreichen Setzen werden alle weiteren offenen Links des Kontos entwertet. Aus Sicherheitsgründen funktioniert das nur für Konten mit hinterlegter E-Mail-Adresse — Konten ohne E-Mail bekommen den Hinweis, sich an einen Admin zu wenden (der die Adresse in der Benutzerverwaltung nachträgt oder das Passwort direkt zurücksetzt). Es gibt keine Selbstregistrierung. Die Rückmeldung der Seite ist bewusst neutral (Anti-Enumeration), und ein Rate-Limit bremst Missbrauch.
    • Betreiber-Hinweis — neuer SMTP-Mailversand: Für die Reset-Mail bringt das ETB jetzt ausgehenden Mailversand per SMTP mit, getrennt vom IMAP-Postfach (das nur Alarm-Mails liest). In config/.env kommen dafür die Keys SMTP_HOST, SMTP_PORT, SMTP_SECURITY (tls/ssl/none), SMTP_USER, SMTP_PASS, SMTP_FROM und SMTP_FROM_NAME hinzu (Vorlage in config/.env.example). Ist kein SMTP konfiguriert, bleibt die „Passwort vergessen"-Funktion inaktiv und zeigt statt eines Versands einen Admin-Hinweis. Nach dem Update einmal /admin/schema-check.php ausführen — es gibt eine neue Tabelle pw_reset (sonst erscheint der Schema-Hinweis-Banner).
  • Menü-Logo für die Seitenleiste: Unter Organisation & Branding (/admin/branding.php) lässt sich jetzt ein separates Logo für die dunkle/eingefärbte Seitenleiste hochladen — getrennt vom bestehenden (Login-)Logo. Empfohlen wird ein möglichst quadratisches PNG mit Transparenz, mindestens 256 px; es wird auf eine feste Fläche zentriert eingepasst. Ist kein Menü-Logo gesetzt, fällt die Seitenleiste wie bisher auf das Login-Logo zurück.
  • Logo, Menü-Logo und Favicon wieder entfernbar (#88): Unter Organisation & Branding (/admin/branding.php) gibt es jetzt pro Bild eine Checkbox „… entfernen (auf Standard zurücksetzen)". Damit lässt sich ein hochgeladenes Bild wieder löschen und auf den Standard zurücksetzen (Menü-Logo zurück auf das Login-Logo) — vorher war nur Ersetzen möglich. Kommt im selben Vorgang ein neuer Upload fürs gleiche Bild, gewinnt der Upload.
  • Eigenes Erscheinungsbild (Theme) pro Organisation: Neuer Bereich Erscheinungsbild in Organisation & Branding mit der Wahl zwischen dem ausgelieferten Standard-Theme (Hell/Dunkel) und einem eigenen Theme. Beim eigenen Theme sind Primärfarbe (Akzent: Buttons/Links/aktive Elemente), Sekundärfarbe (aktiver Marker in der Seitenleiste), Seitenleisten-Hintergrund, Seitenleisten-Text und die Schriftart (aus einer kuratierten, lokal ausgelieferten Auswahl — kein externes Laden) einstellbar. Der Hell-/Dunkel-Umschalter bleibt in beiden Modi aktiv: Das eigene Theme legt nur eine Marken-Ebene über die Hell-/Dunkel-Basis, Grundflächen und Status-Farben bleiben hell-/dunkel-gesteuert. Ungesetzte Werte bleiben auf dem Standard.
  • Mobile Bedienung (Off-Canvas-Menü): Auf schmalen Bildschirmen (Smartphone, kleines Tablet) wird die Hauptnavigation zu einem ausklappbaren Menü. Oben links öffnet das Menü-Symbol (☰) die Seitenleiste als Schublade über einem abgedunkelten Hintergrund; ein Tippen auf den abgedunkelten Bereich schließt sie wieder. Zusätzlich werden Formulare einspaltig, Touch-Ziele (Schaltflächen, Chips) größer und breite Admin-Tabellen seitlich scrollbar statt abgeschnitten.
  • Als App installierbar (PWA): Das ETB bringt jetzt ein Web-App- Manifest und einen Service-Worker mit und lässt sich über den Browser („Zum Startbildschirm hinzufügen") als App-ähnliche Verknüpfung mit eigenem Icon im Vollbild installieren. Am iPhone/iPad (Safari) funktioniert „Zum Home-Bildschirm" jetzt auch ohne HTTPS (über Apple-eigene Meta-Tags, ohne Service-Worker); die Android-Chrome- Vollinstallation und der Service-Worker brauchen weiterhin HTTPS (auf der unverschlüsselten Test-Instanz bleibt der SW inaktiv). Als App-Icon und -Titel dienen am iPhone das (Login-)Logo und der konfigurierte App-Titel. Es werden bewusst keine Einsatzdaten offline zwischengespeichert (das ETB braucht stets aktuelle Daten, Strategie „Network-first") — nur statische Programm-Assets (Design, Symbole) werden gecacht und laden dadurch schneller; HTML-Seiten und /api/ nie. Die Browser-/App-Leistenfarbe (theme-color) folgt der (ggf. eigenen) Seitenleisten-Farbe.

Geändert

  • Passwort-Reset beendet bestehende Sessions des Kontos (#96, Sicherheit): Wird das Passwort eines Kontos zurückgesetzt — über den „Passwort vergessen"-E-Mail-Link (#39) oder durch einen Admin-Reset in der Benutzerverwaltung — werden ab jetzt alle laufenden Sessions dieses Kontos beim nächsten Request serverseitig beendet; danach ist ein erneutes Anmelden nötig. So lässt sich ein Eindringling, der bereits eine offene Sitzung hat, durch das Setzen eines neuen Passworts wirklich aussperren. Setzt ein Admin sein eigenes Passwort zurück, loggt ihn das selbst aus (gewollt) — beim normalen „Passwort vergessen"-Flow ist das folgenlos, da man dabei ohnehin nicht angemeldet ist. Bestehende Sitzungen werden durch das Update nicht schlagartig beendet; die Sperre greift erst, wenn nach dem Update ein Passwort geändert wird. Nach dem Update einmal /admin/schema-check.php ausführen — es gibt eine neue Spalte users.password_changed_at (sonst erscheint der Schema-Hinweis-Banner und die Invalidierung bleibt still inaktiv).
  • Schwerpunkt-Stärke getrennt nach „im Einsatz" und „Reserve" (#34): Die Einsatzkräfte-Pill eines Schwerpunkts weist die Personalstärke jetzt aufgeschlüsselt aus — „im Einsatz" sind die Einsatzmittel an einem aktiven Einsatz des Schwerpunkts (Status neu, in Dispo, Status 3, Status 4), „Reserve" die Pool-Einsatzmittel ohne aktiven Einsatz; „Gesamt" zählt beide zusammen, jedes Fahrzeug nur einmal. Ein beendeter Einsatz zählt nicht mehr als „im Einsatz": Sobald ein Einsatz erledigt, Abschluss beantragt oder abgeschlossen ist, fallen seine Einsatzmittel in die Reserve (vorher zählten alle nicht-abgeschlossenen Einsätze als „im Einsatz", auch bereits erledigte). Die Reserve-Stärke ist die zuletzt bekannte Anzahl aus der Einsatz-Historie des Fahrzeugs (ein EM ohne jede Einsatz-Historie zählt 0). Reine Pool-EMs fließen ebenfalls in die Reserve ein. Die Aufschlüsselung erscheint im Schwerpunkt-Banner, in der ETB-Übersicht, der Schwerpunkt-Übersicht, der SP-Historie und im PDF-Export.
  • Theme-Engine eingeführt; Erscheinungsbild jetzt org-konfigurierbar (Refactoring-Scheibe T3): Marken-Farben und -Schrift laufen über zentrale Design-Tokens, sodass ein eigenes Theme als Override-Ebene greift. Im Zuge dessen wurden in Seitenkopf, Toolbar und Schema-Bannern verbliebene hartkodierte Farben auf Tokens umgestellt und der Basis-Font-Stack als Token (--font-base) zentralisiert — ohne sichtbare Änderung am Standard-Aussehen.
  • Klareres Symbol für „Einsatz übernehmen/verschieben" (#33): In der Schwerpunkt-Einsatzliste trägt die Aktion zum Übernehmen, Verschieben oder Herausnehmen eines Einsatzes jetzt einen grünen Haken (✅) statt des bisherigen Wiederhol-Symbols (🔄); der Tooltip nennt zusätzlich „Übernehmen".
  • Einsatzmittel-Stärke im Schema A/B/C/S, Gesamt rechnet das ETB: Beim Speichern der Personalstärke eines Einsatzmittels wird die Eingabe jetzt auf das Format A/B/C/S (Zug- und Verbandführer / Gruppenführer / Mannschaft / Gesamt) normalisiert und die Gesamtzahl S automatisch als A + B + C gesetzt. Eine falsch oder gar nicht eingetippte Gesamtzahl wird damit korrigiert bzw. ergänzt (1/0/5/7 und 1/0/5 ergeben beide 1/0/5/6); eine leere Eingabe bleibt leer (die Stärke ist optional). So sind alle Stärke-Werte einheitlich vierstellig und in sich stimmig — Grundlage für die korrekte Aufsummierung in den Personal-Pills und im PDF-Export.
  • Lagekarte: Modus „Taktisch" entfernt: Die Lagekarte bietet jetzt nur noch die Ansichten 📍 Status und 🔥 Dichte (Heatmap). Der bisherige Modus Taktisch mit großen taktischen Zeichen pro Einsatzmittel (und der zugehörige Filter) ist entfallen — die taktischen Symbole überdeckten benachbarte Marker und brachten in der Praxis keinen Mehrwert gegenüber der Status-Ansicht.
  • Setup-Wizard: Schritt-Navigation links statt oben: Die sieben Setup-Schritte stehen jetzt als senkrechte Liste links neben dem Eingabe-Bereich (vorher eine waagerechte Pill-Leiste oben). Auf schmalen Bildschirmen klappt die Schrittliste über den Inhalt. Die Inhalte der Schritte sind unverändert.
  • Hauptmenü in Gruppen gegliedert: Die Einträge der Seitenleiste sind jetzt in die Gruppen Lage (Einsätze, Schwerpunkte, Lagekarte, Einsatzmittel), Werkzeuge (Rückmeldungen, Linksammlung, Hydrantenplan, Geocodes) und System (Hilfe, Administration) unterteilt — jede mit leiser Überschrift. Leere Gruppen (alle Einträge per Rolle ausgeblendet) erzeugen keine Überschrift; im eingeklappten Menü schrumpfen die Überschriften zu Trennlinien. Die Einträge selbst und ihre Berechtigungen bleiben unverändert.

Behoben

  • PDF-Export immer im Hellmodus: Der Druck-/PDF-Export erzwingt jetzt ausdrücklich helle Darstellung (color-scheme: light, Sonderfall wie die Login-Seite). Auf Geräten mit aktivem (Browser-)Dunkelmodus wurde die Export-Seite sonst automatisch abgedunkelt — beim Druck ist der Hintergrund aber immer weiß, sodass hell eingefärbte Inhalte unlesbar waren.

  • Hauptmenü-Links behalten nach dem Klick ihre Farbe: Mit der globalen Link-Farbe (für die Dark-Mode-Lesbarkeit) hatten besuchte Menüpunkte die Verweis-Farbe angenommen. Die Seitenleisten-Einträge bleiben jetzt unabhängig vom Besucht-Status in ihrer normalen Farbe (Sonderfall), Hover und aktiver Eintrag wie gehabt.

  • Einsatzmittel per Touch zuweisen (Handy/Tablet): Auf Touch-Geräten ließ sich ein EM bisher nicht zuverlässig per Drag&Drop zuordnen (je nach Browser startete stattdessen das Kontextmenü). Ein langer Druck auf einen EM-Chip startet jetzt das Ziehen; ein Vorschau-Bild folgt dem Finger, die Seite scrollt an den Rändern automatisch (damit auch ein weiter oben liegendes Einsatz-/EM-Feld erreichbar ist), und beim Loslassen wird das Feld darunter getroffen. Kurzes Wischen scrollt wie gewohnt, kurzes Tippen bleibt ein Klick.

  • Bild-Anhänge: Galerie-Navigation in der Großansicht: Klickt man ein an einen Kommentar angehängtes Bild an, lässt sich jetzt per Pfeil-Buttons, Pfeiltasten (←/→) oder Bildzähler durch alle Bilder desselben Kommentars blättern — vorher zeigte die Großansicht nur das eine angeklickte Bild, und man musste sie schließen und das nächste Vorschaubild einzeln öffnen. Gilt für Einsatz- und Abschnitts-Kommentare.

  • PDF-Export: große/viele Kommentarbilder werden sauber dargestellt: Bei mehreren oder hochauflösenden Fotos in einem Kommentar wurden Bilder am Seitenumbruch zerschnitten oder es entstanden große Leerräume. Ursache war ein „nicht umbrechen"-Zwang auf dem gesamten Kommentar-/Anhang-Block, der höher als eine Seite werden kann. Jetzt darf der Block über Seiten umbrechen, nur das einzelne Bild bleibt unzertrennlich, und Bilder werden kompakter eingebettet (mehrere pro Seite) — so bleibt jedes Foto vollständig und der Bericht lesbar.

  • Hinweis beim Anlegen, wenn noch keine Orte angelegt sind (#59): Der Ort ist beim Einsatz-Anlegen ein Pflichtfeld aus den Stammdaten. Gab es noch gar keine Orte (frische Installation), schlug das Speichern wortlos an der Pflichtfeld-Prüfung fehl. Jetzt erscheint am Ort-Feld ein Hinweis mit Link zur Orte-Stammdatenseite (Admin → Stammdaten → Orte).

  • Doppelte Einsätze durch Doppelklick verhindert (#81): Beim Anlegen eines Einsatzes wird der „Anlegen"-Button nach dem ersten Absenden gesperrt („⏳ … wird gespeichert"), sodass ein zweiter Klick oder ein Doppelklick keinen zweiten Einsatz mehr erzeugt.

  • Einsatzmittel aus der ETB-Liste entfernen fragt jetzt nach (#71): Ist ein Einsatzmittel noch in Abschnitten des Einsatzes zugewiesen, zeigte das Entfernen über den EM-Chip in der Einsatzliste nur eine wirkungslose Meldung. Jetzt kommt — wie auf der Detailseite — ein echter Bestätigungs-Dialog („Trotzdem entfernen"); erst nach Bestätigung wird das Einsatzmittel auch aus den Abschnitten gelöst.

  • Kommentar-Bearbeitungs-Marker zeigte Platzhalter wörtlich an (#73): Bei einem bearbeiteten Kommentar ohne angegebene Begründung erschien der interne Platzhalter „(ohne Begründung)" im Verlauf. Dieser Text wird — wie beim Löschen — nicht mehr angezeigt.

  • Echte Umlaute in Katalog- und Hinweistexten (#69): An mehreren Stellen (z. B. „gelöscht", „Einsätzen") standen noch ASCII-Ersatzschreibweisen; sie zeigen jetzt korrekte Umlaute.

  • Einsatzmittel aus abgeschlossenen Einsätzen lassen sich wieder einem Schwerpunkt zuordnen (#35): Ein Fahrzeug, das noch (historisch) in einem abgeschlossenen Einsatz hängt, ließ sich im Schwerpunktmenü nicht in den Pool aufnehmen — und die Pool-Aufnahme hätte den Eintrag sogar lautlos aus dem abgeschlossenen Einsatz gelöscht (Revisionsbruch). Die Pool-Aufnahme klammert abgeschlossene Einsätze jetzt aus: Sie gelingt, der historische Eintrag im abgeschlossenen Einsatz bleibt unverändert erhalten. Im selben Zuge ist auch das „Schwerpunkt-mit-EM-Auswahl zuweisen" gegen abgeschlossene Einsätze abgesichert (es hätte sonst beim Abwählen von Einsatzmitteln deren Historie im abgeschlossenen Einsatz verändert).

  • Kleinere UI-Korrekturen (Refactoring-Scheibe S5, Befunde der Test-Durchläufe): Das Haus-Symbol in den Einsatzmittel-Kacheln „Entlassen"/„Nicht eingesetzt" war unsichtbar (#66) und ist wieder da; im Schwerpunkt-Wizard sind die Auswahlkarten „Bestimmte Ortsteile"/„Einzelne Einsätze" und die ausgewählten Orts-Chips im Dark-Mode jetzt lesbar (#65); der Erstinstallations-Hinweis unterscheidet jetzt „Datenbank leer" von „noch kein Benutzer" (#60); die System-Status-Texte sprechen statt vom installations­spezifischen „Homey-Flow" neutral von der „Alarmverarbeitung" (#61); der Adress-Platzhalter im Wizard ist als Beispiel gekennzeichnet (#58).

  • Erstinstallation steckte nach dem Tabellen-Schritt fest (Tester-Blocker): Sobald Wizard-Schritt 2 die Tabellen angelegt hatte, galt die Installation nicht mehr als „frisch" und der Wizard verlangte einen Login — den ersten Admin legt aber erst der Abschluss-Schritt an. Wizard und Auto-Weiterleitung bleiben jetzt im Erstinstallations-Modus, solange noch kein einziger Benutzer existiert (bewusst nicht „kein aktiver Admin" — eine laufende Installation mit deaktivierten Admins darf den Wizard nicht öffnen).

  • Orte-Verwaltung auf Neuinstallationen defekt (Tester-Blocker): Der Tabellen-Bauplan der orte-Tabelle kannte die Spalten geolat/geolng nicht, die die Orte-Verwaltung fest erwartet — „Interner Fehler" beim Anlegen, und ohne Ort ließ sich kein Einsatz erfassen. Bauplan ergänzt; der Schema-Check erkennt jetzt auch komplett fehlende Spalten und ergänzt sie per Reparieren-Knopf (neuer Migrations-Mechanismus, hilft auch künftigen Fällen).

  • Erstinstallations-Wizard immer hell: Im Frisch-Modus lädt der Wizard kein zentrales Stylesheet (Datenbank existiert noch nicht) — die Farbvariablen waren undefiniert und die Seite sah kaputt aus. Der Wizard definiert die hellen Farben jetzt lokal (wie die Login-Seite: kein Dark-Mode vor dem ersten Login).

  • Doku/Pfad-Korrektur Branding-Verzeichnis (#85): Handbuch, README und Deploy-/Backup-Hinweise nannten für hochgeladenes Logo/Favicon noch den alten Pfad storage/branding/. Tatsächlich liegen die Dateien in public/branding/ — überall korrigiert (kein Verhalten geändert, reine Doku-/Pfad-Richtigstellung).

  • Dark-Mode-Anzeige an mehreren Stellen korrigiert: In verschiedenen Admin- und Wizard-Seiten waren noch helle Farben fest verdrahtet, sodass Flächen, Eingabefelder und Hinweis-Boxen im Dark-Mode falsch (zu hell) dargestellt wurden. Betroffen waren u. a. der Logo-/Favicon-Upload unter Organisation & Branding (Vorschau-Box, Datei- und Farbfelder, Schrift-Auswahl), die Schwerpunkt-Anlage (Wizard-Schritt-Marken, Auswahl-Tabellen, Buttons), der Setup-Wizard sowie diverse Toast-Meldungen, Eingabefelder und Tabellen quer durch den Admin-Bereich. Alle betroffenen Stellen nutzen jetzt die zentralen Design-Tokens und folgen damit korrekt dem hellen wie dem dunklen Theme.

  • Dark-Mode-Feinschliff nach dem Abnahme-Klick-Test: Vier weitere Stellen, die im dunklen Theme schlecht lesbar waren, sind korrigiert: gelöschte Kommentare behielten ihre helle Schraffur; Verweise/ Links nutzten das Browser-Standardblau bzw. -lila (jetzt ein theme-eigener, gut lesbarer Link-Ton); die Filter in der Geocode-Übersicht zeigten schwarzen statt hellen Text; und die Buttons im Webhook-Status hatten schwarze statt helle Beschriftung. Auch das Gelöscht-Banner und die Fehler-Toasts auf der Einsatz-Seite folgen jetzt dem Theme. Zusätzlich nutzten einige Admin- und Bearbeiten-Seiten (Abschnitt bearbeiten, Hydrantenplan, Admin-Übersicht, PDF-Export) ein fest verdrahtetes Fehler-Rot, das im Dark-Mode zu dunkel wirkte — auch diese folgen jetzt dem adaptiven Token.

  • Einsatzmittel-Stärke: Anzeige direkt nach dem Zuweisen korrekt: Beim Zuweisen eines Einsatzmittels zeigt der Chip jetzt sofort die vom ETB geprüfte Stärke im Schema A/B/C/S (mit automatisch berechnetem Gesamtwert S) — vorher stand kurzzeitig der unkorrigierte Eingabewert da, bis die Seite neu geladen wurde.

Behoben (Sicherheit)

  • Einsatzmittel-Vorbelegung: Kontaktdaten scope-begrenzt: Beim Zuweisen eines Einsatzmittels lädt der Dialog die zuletzt erfasste Stärke und den Kontakt als Vorbelegung. Diese Vorbelegung wird jetzt auf den eigenen Sichtbarkeitsbereich begrenzt: Disponenten (ohne „alle Einsätze sehen") und Schwerpunkt-Disponenten erhalten nur noch Werte aus Einsätzen ihres eigenen Scopes. Vorher konnte über die Vorbelegung der zuletzt gespeicherte Kontakt (z. B. eine Telefonnummer) eines Einsatzmittels aus einem fremden Einsatz bzw. Schwerpunkt sichtbar werden.

  • CSRF-Schutz für alle Admin- und Bearbeiten-Formulare: Sämtliche formularbasierten Schreibaktionen (Benutzer-, Branding-, Konfigurations- und Stammdaten-Verwaltung, Schwerpunkt- sowie Einsatz-/Abschnitt- Bearbeitung u. a.) verlangen jetzt zusätzlich zum bestehenden SameSite=Lax-Cookie ein sitzungsgebundenes CSRF-Token. Fehlt es oder ist es ungültig, wird die Aktion mit einem Hinweis abgewiesen (Defense-in-depth). Die AJAX-Endpoints und der Setup-Wizard nutzen weiterhin ihre eigenen Token-Mechanismen.

  • Hydranten-Daten respektieren die Berechtigung auch im Endpoint: Der GeoJSON-Abruf prüft jetzt hydranten.view (vorher nur „eingeloggt") — einer Rolle ohne Hydranten-Recht werden die Daten auch über die API nicht mehr geliefert.

  • Schwerpunkt-Disponent: Eignung wird serverseitig geprüft: Beim Setzen des SP-Disponenten akzeptiert der Server nur noch aktive Disponenten bzw. SP-Disponenten (identisch zum Auswahlmenü), nicht mehr beliebige Benutzer-IDs.

  • Kommentar-Moderation an den eigenen Bereich gebunden: Bearbeiten und Löschen von Kommentaren und Anhängen prüfen jetzt zusätzlich den Einsatz-Scope, sodass disponierende Rollen nur im eigenen Zuständigkeitsbereich moderieren können.

  • Setup-Wizard gegen CSRF gehärtet (#62): Die beiden schreibenden Schritte des Wizards — Tabellen anlegen (Schritt 2) und Speichern (Schritt 7) — liefen bisher per GET und ohne Token, ließen sich also durch einen vorbereiteten Link oder ein eingebettetes Bild von außen auslösen (heikel, weil der Wizard bei der Erstinstallation ohne Login erreichbar ist). Beide Aktionen verlangen jetzt POST und ein sitzungsgebundenes Token (X-CSRF-Token); ein einfacher GET-Aufruf wird mit 405, ein fehlendes/falsches Token mit 403 abgewiesen. Für Dich ändert sich an der Bedienung nichts — Du klickst dieselben Schaltflächen. Außerdem überschreibt „Speichern" eine bereits funktionierende .env nicht mehr mit leeren Datenbank-Zugangsdaten (Existenz-Prüfung mit Rückfall auf die bestehende Konfiguration; fehlen die Werte ganz, bricht der Schritt mit einem Hinweis ab, statt die Verbindung zu zerschießen).

  • Scope-Lücken geschlossen (Befunde des Security-Voll-Sweeps): api/abschnitt-update.php und api/geocode-admin.php prüften den Dispo-/SP-Dispo-Scope nicht — gescope-te Rollen konnten Stammdaten bzw. Geokoordinaten fremder Einsätze ändern. Beide Endpoints erzwingen jetzt das Scope-Muster ihrer Geschwister-Endpoints; Geocode-Bulk-Aktionen sind Lage/EL/Admin vorbehalten.

  • Lagekarten-API (api/mapdata.php) verlangt jetzt lagekarte.view und filtert die Einsatz-Marker für SP-Dispos auf deren eigene Schwerpunkte (vorher sahen sie alle Einsätze).

  • Geocode-Verwaltung hinter admin.access (Folge-Befund der Nach-Abnahme): Seite und API lieferten per GET jedem eingeloggten Benutzer die Adressliste samt Koordinaten ALLER Einsätze — der Sidebar-Eintrag war zwar Admin-gegated, das Backend aber nicht. Beide verlangen jetzt dieselbe Permission wie der Menüpunkt.

  • Login-Brute-Force-Bremse (#50): Nach 5 Fehlversuchen pro Konto+IP steigt die Pflicht-Wartezeit zwischen Login-Versuchen exponentiell (2 s → max. 60 s). Bewusst keine harte Sperre — im Einsatz darf sich niemand aussperren, und im Gerätehaus teilen sich alle eine IP. Der Zähler-Schlüssel faltet Groß-/Kleinschreibung und Akzente identisch zur DB-Collation, damit die Bremse nicht über Schreibvarianten (ädmin, ADMÍN) umgangen werden kann. Einträge leben max. 24 h (Datenschutz); neue Tabelle login_throttle (Schema-Check nach Update ausführen).

  • Keine internen Fehlertexte mehr im Browser (#51): Alle Endpoints und Admin-Seiten maskieren unerwartete Exceptions jetzt mit einer generischen Meldung (Details nur im Log-Dashboard); bewusste Validierungsmeldungen („Name fehlt", „bereits im Einsatz") bleiben über die neue UserFacingException erhalten. Zusätzlich erzwingt der Bootstrap display_errors=0 für alle Web-Requests (plus public/.user.ini als Absicherung auf Hoster-Ebene), unabhängig von der php.ini des Hosters.

  • EM-Entlassen-Toggle abgesichert (#52): Entlassen/Reaktivieren verlangt jetzt die EM-Dispositions-Permission em.assign (vorher reichte das breitere einsatz.edit), und SP-Disponenten können nur noch Einsatzmittel aus den Pools ihrer eigenen Schwerpunkte umschalten. Karten ohne Berechtigung sind nicht mehr klickbar.

Neu

  • Test-Instanz-Override — der Config-Loader akzeptiert die Umgebungsvariable ETB_ENV_FILE und lädt damit eine alternative .env (z. B. config/.env.test mit eigenem Tabellen-Präfix). Grundlage für eigenständige QA-Klick-Tests gegen isolierte test_*-Tabellen, ohne Produktivdaten anzufassen (siehe docs/DEPLOYMENT.md).

Geändert

  • Intern: Kommentar-/Anhang-/Audit-Services konsolidiert (Refactoring-Scheibe S7): Die je drei fast identischen Services für Einsatz, Abschnitt und Schwerpunkt teilen sich ihre Logik jetzt in gemeinsamen Basisklassen (KommentarServiceBase, AnhangServiceBase, AuditServiceBase); die bisherigen Klassen bleiben als dünne Erben bestehen (kein Aufrufer geändert). −494 Zeilen (−33 %), 21 neue Unit-Tests sichern die revisionsfesten System-Kommentare und die Upload-MIME-Whitelist ab. Verhalten unverändert.
  • Intern: Schwerpunkt-SQL in die Services verlagert (Refactoring- Scheibe S6): Direkte Datenbank-Abfragen aus den Schwerpunkt-Seiten und -Endpoints (Wizard, Bearbeiten, Historie, EM-Pool, Einsatz- Zuweisung-mit-EM) liegen jetzt als benannte Methoden in den zuständigen Services; die mehrschrittige „Einsatz mit EM-Auswahl zuweisen"-Operation ist als eine transaktionssichere Service-Methode gekapselt (inkl. Audit + revisionsfester System-Kommentare). Kein Verhaltensunterschied.
  • UI-Vereinheitlichung (Quick-Wins aus dem Code-Audit): Die Abschnitts-Bearbeiten-Seite, der Admin-Index, das Log-Dashboard und der System-Status nutzen jetzt die zentrale Seiten-Toolbar (Breadcrumbs + Aktionen) statt handgebautem Markup; der Lagekarten-Kopf verwendet Design-Tokens statt hartkodierter Farben — damit zeigt die Fehlermeldung im Dark-Mode wieder rot statt grau. Intern: app-config.js.php liefert die JS-Konfiguration nur noch an eingeloggte Benutzer, SchemaProvider bindet den letzten interpolierten Query-Parameter sauber.
  • Intern: Abschnitts-Detailseite entschlackt (Refactoring-Scheibe S4c): einsaetze/abschnitt-view.php gibt ihr Inline-CSS und -JS an die geteilte assets/css/einsaetze.css (neue Sektion „abschnitt-view.php"; mit view.php zeichengleiche Blöcke werden nicht dupliziert) und das neue assets/js/abschnitt-view.js ab (−893 Zeilen in der Seite); die 3 PHP-Interpolationen wandern in window.ABSCHNITT_VIEW_CONFIG. In theme.css entfallen fünf Dark-Overrides, die der Token-Switch jetzt 1:1 reproduziert (.em-pill-ro, .comments-empty, .comment-text, .comment-deleted-info, .att-meta). Beifang: lagekarte.js überschreibt nicht mehr das globale escapeHtml aus etb-common.js. Optik im Light-Mode unverändert; im Dark-Mode folgen die Eingabefelder der Abschnitts-Seite (Disponenten-Auswahl, Kommentar-Felder) jetzt dem dunklen Schema statt wie bisher weiß zu bleiben — die letzte Inkonsistenz, mit der die Seite damit zu den Einsatz-Seiten aufschließt.
  • Intern: Einsatz-Detailseite entschlackt (Refactoring-Scheibe S4b): einsaetze/view.php gibt ihr Inline-CSS und -JS an die geteilte assets/css/einsaetze.css (neue Sektion „view.php") und das neue assets/js/einsaetze-view.js ab (−1.825 Zeilen in der Seite); die 10 PHP-Interpolationen wandern in window.EINSAETZE_VIEW_CONFIG. Seiten-exklusive Regeln sind per :where(body.einsatz-…)-Marker gescopt (Spezifität 0 — Kaskade unverändert). Optik und Verhalten in beiden Themes unverändert.
  • Intern: ETB-Übersicht entschlackt (Refactoring-Scheibe S4a): Die größte Seite (einsaetze/index.php) gibt ihr Inline-CSS und -JS an assets/css/einsaetze.css und assets/js/einsaetze-index.js ab (−1.221 Zeilen in der Seite); 31 neue Design-Tokens ersetzen Hex-Farben, obsolet gewordene Dark-Overrides wurden entfernt. Optik und Verhalten unverändert.
  • Intern: gemeinsame Basisklasse für die Katalog-Services (Refactoring-Scheibe S3): Abschnitts-Status, Schwerpunkt-Status und Wichtigkeit teilen sich ihre CRUD-/Fallback-/Default-Logik jetzt in KeyedCatalogService (−209 Zeilen, −26 %); 19 neue Unit-Tests sichern Normalisierung, Fallback- und Default-Key-Logik ab. Verhalten und Fehlertexte unverändert.
  • Schema-Check zählt ehrlich (#57): Nach einer Reparatur meldet /admin/schema-check.php nur noch tatsächlich neu angelegte Tabellen („Nichts zu tun — Schema war bereits aktuell." statt „39 Tabellen angelegt").
  • Intern: CSS-Komponenten ausgebaut (Refactoring-Scheibe S2): Wiederkehrende Muster (schwebende Toasts, Spinner, Status-Banner, Sekundär-Buttons, Orts-Chips, Tabellen) leben jetzt zentral in components.css; die EM-Statusfarben sind benannte Design-Tokens. Sechs Seiten (Einsatzmittel, Geocodes, Schwerpunkte-Übersicht/ Wizard/Bearbeiten, Hydrantenplan) verloren ihre Inline-Duplikate. Optik unverändert (Dark-Mode: drei Detailfarben folgen jetzt den Tokens und passen damit erstmals zum restlichen Dark-Schema).
  • Intern: gemeinsame JS-Bausteine (Refactoring-Scheibe S1): escapeHtml/cssEsc/postJson und das EM-Drag&Drop-Verhalten leben jetzt zentral in assets/js/etb-common.js bzw. em-dnd.js statt fünf- bis sechsfach kopiert in den Seiten (rund 650 Zeilen Inline-JS entfernt, netto −226). Keine Verhaltensänderung; Nebeneffekt: Sonderzeichen wie Anführungszeichen werden überall einheitlich (und im Schwerpunkt-Wizard erstmals korrekt) escaped.

2.4.0 — 2026-05-29

Fokus: Schwerpunkt-Dispo-Kopplung, Folge-Abschnitte, Übersichtlichkeit

Großes Funktions-Release: Einsatz- und Abschnitts-Disponenten folgen im Schwerpunkt automatisch dem SP-Dispo, Alarm-Regeln können nun auch Folge-Abschnitte anlegen und den Auto-Reset gezielt stoppen, Einsatzmittel werden nach Gruppen strukturiert dargestellt, und es gibt administrierbare Standard-Werte. Dazu Beamer-Tauglichkeit der Lagekarte und diverse Politur.

Neu

  • SP-Dispo-Kopplung — solange ein Einsatz einem Schwerpunkt angehört, folgt sein Disponent (und der seiner Abschnitte) automatisch dem Schwerpunkt-Disponenten; das Dispo-Feld ist dann gesperrt (readonly + Hinweis). Herauslösen per Modal-Dialog mit Wahl eines übernehmenden Disponenten; Neuanlage im SP-Kontext wird dem SP zugewiesen; ein Wechsel des SP-Dispos propagiert auf alle zugeordneten Einsätze/Abschnitte.
  • Alarm-Regeln: Folge-Abschnitte — eine Regel ist nun entweder vom Typ Folge-Einsätze oder Folge-Abschnitte (exklusiv). Abschnitt- Regeln legen beim Greifen Abschnitte am ausgelösten Einsatz an.
  • Alarm-Regeln: Auto-Reset-Stopp pro Regel — eigene Checkbox je Regel (statt fest verdrahtet). Mehrere Regeln mit gleichem/ähnlichem Trigger feuern jetzt alle ihre Aktion.
  • Standard-Werte in der Administration — pro Liste ein Default für Wichtigkeit und Abschnitts-Status (★), der in den Dropdowns/bei der Anlage vorausgewählt wird. Neuer Abschnitts-Status „geplant" (dunkelgrau, ⏳) als Voreinstellung.
  • Personalstärke-Anzeige — je Einsatz unter dem Stichwort sowie die Gesamt-Einsatzstärke in der Titelzeile der Übersicht (dedupliziert pro EM, ohne abgeschlossene Einsätze), inkl. Schwerpunkt-/Einsatz- Zähler im Lagekarten-Stil.
  • Einsatzmittel nach Gruppen — Übersichtsseite und Lagekarten-Panel gruppieren EMs nach EM-Gruppe (üÖrt-Block am Ende), alphabetisch innerhalb der Gruppe.
  • Lagekarte: Filter-Leiste ein-/ausblendbar („🎛️ Filter") — zusammen mit eingeklapptem Menü eine große Beamer-Ansicht.
  • Geocode-Cache-Verwaltung — neue Admin-Unterseite (/admin/geocode-cache.php): alle gecacheten Geocodes mit Löschen je Zeile + „Alle löschen". Der Cache bleibt beim Reset erhalten.
  • Rufgruppe-Spalte in der Abschnitts-Tabelle der Einsatz-Detailseite.

Geändert

  • Personalstärke-Format überall korrigiert auf „Zug- und Verbandführer / Gruppenführer / Mannschaft / Gesamt".
  • Abschnitts-Disponent ist optional („– nicht zugewiesen –"); einsatz_abschnitt.assigned_dispo_user_id wurde nullable.
  • EM-Auswahl im Schwerpunkt-Kontext einheitlich — Übersicht, Einsatz-Detail und Bearbeiten zeigen denselben flachen Pool-Picker.
  • üÖrt-Anlage durchgängig per App-Dialog (kein Browser-prompt() mehr), inkl. Format-Hinweis „Ort FzArt" (z. B. „FFW DLK"). Auch das Löschen von Kommentaren nutzt jetzt den App-Dialog.
  • Aktive Toggle-Buttons der Lagekarte sind farbig hinterlegt (Light + Dark).

Behoben

  • Horizontaler Verschiebebalken auf Lagekarte, Einsatzmittel und Hilfe (fehlendes box-sizing: border-box).
  • Bulk-Dispo-Wechsel überspringt SP-gebundene Einsätze sauber, statt einen Fehler zu werfen.
  • Aufräumen: doppelte Schema-Migration entfernt, toter Code (findActiveByStichwort) entfernt.

Datenbank / Migration

  • Neue Tabelle alarm_rule_followup_abschnitt; neue Spalten alarm_rule.action_type + alarm_rule.stop_auto_reset; einsatz_abschnitt.assigned_dispo_user_id nullable; Abschnitts-Status „geplant" + Default-Settings. Nachziehbar über Admin → Schema-Check bzw. php scripts/migrate.php. Optional einmalig php scripts/migrate-sp-dispo-kopplung.php (koppelt Bestands-Einsätze an den SP-Dispo).

2.3.0 — 2026-05-28

Fokus: Dark-Mode, UI-Politur & CSS-Zentralisierung

Schwerpunkt dieses Releases ist ein app-weiter Dark-Mode, eine einklappbare Sidebar und die Zusammenführung des bis dahin in ~38 Seiten duplizierten CSS in zentrale Token- und Komponenten-Dateien (Trennung von Design und Funktionalität). Dazu kommen diverse Politur-Arbeiten im Admin-Bereich und ein paar funktionale Fixes.

Neu

  • Dunkler Modus — app-weiter Dark-Mode über den 🌙/☀️-Knopf neben „Abmelden". Initial via prefers-color-scheme, danach in localStorage gemerkt; FOUC-frei (Sync-Script im <head>).
  • Einklappbare Sidebar (« / ») — reduziert die Navigation auf reine Icons; im eingeklappten Zustand erscheint das Favicon statt Logo. Zustand persistent.
  • Karten-Hell/Dunkel-Toggle — Lagekarte, Hydrantenplan und die Einsatz-Detail-Karte lassen sich per 🌙/🌞 unabhängig vom App-Theme hell/dunkel schalten (Leaflet-Tiles via Invert-Filter).
  • Einklappbare Filterleiste in der Einsatz-Übersicht; Suchfeld rückt neben den Disponent-Filter, mit „Suchen" + „Zurücksetzen".
  • Zentrale Design-Tokens — neue tokens.css (alle Farben Light + Dark, eine Quelle) + components.css (wiederverwendbare Bausteine).

Geändert

  • Admin — einheitliche Breadcrumb-Leisten auf allen Seiten; Admin-Kacheln in vier Kategorien neu sortiert (Feuerwehr, Konfiguration, Aktionen, Logs & Diagnose). Einstellungen mit zentriertem Content-Container.
  • EM-Kategorie „FFWAC" wird benutzersichtbar als „eigene" angezeigt (DB-Wert intern unverändert).
  • Einsatz-Bearbeitung respektiert jetzt den Schwerpunkt-Pool bei der EM-Auswahl; EM-Gruppen-Summen zählen nur tatsächlich verfügbare EMs.
  • Schwerpunkt-Kontext bleibt bei Reset-/Neuanlage-/Toolbar-Links erhalten.
  • Hilfe/Handbuch + alle Modals (Confirm/Alert, „Abschnitte bilden", EM-Dialog u.a.) sind im Dark-Mode sauber dargestellt; Handbuch um die neuen Funktionen ergänzt.

Behoben

  • Farb-Leak in der Einstellungen-Settings-Nav (DB-Einträge erschienen hellgrau).
  • Null-Guard für den Alarmpush-Button auf der Admin-Startseite.

2.2.0 — 2026-05-27

Fokus: Bug-Fixing + Alarm-Regeln

Schwerpunkt dieses Releases waren ein langes Audit-Bündel von SP-Dispo- Bugs, ein generischer Schema-Reparatur-Mechanismus für veraltete DB-Definitionen und eine neue Feature-Funktion für Multi-Alarm- Regelwerke (UW-ERSTALARM → automatische Grundschutz- und Bereitstellungs- Einsätze).

Neu

  • Alarm-Regeln (/admin/alarm-regeln.php) — neues Multi-Alarm- Regelwerk. Pro Regel ein Trigger-Stichwort (z. B. UW-ERSTALARM) und beliebig viele Folge-Einsatz-Templates (Stichwort, Wichtigkeit, LGs, Sachverhalt mit Platzhaltern). Eine Trigger-Mail erzeugt automatisch den Haupteinsatz plus alle konfigurierten Folge-Einsätze (Adresse/Geo geerbt). Default-Regel UW-ERSTALARM (Grundschutz + Bereitstellung) wird mit-geseedet. Bei aktiver Multi-Alarm-Regel wird der morgendliche ETB-Reset deaktiviert, damit die Großlage nicht weggespült wird.
  • Wichtigkeit „Bereitstellung" (gelb, niedriger als „Normal") als neue Stammdaten-Stufe für Vorhalte-Einsätze.
  • Unwettermail Multi-Einsatz-Parsing — eine Unwettermail mit n Einsatz-Blöcken (Tabellen-Format) erzeugt jetzt n eigenständige Einsätze statt nur einen mit den Werten des letzten Tabellen- Eintrags. Block-Trigger ist der Marker ALARMDEPESCHE >>.
  • Pro-Page Feature-Tabellen-Banner (MainNavSidebar::featureBanner()). Bestimmte Admin-Pages (/admin/alarm-regeln.php, /admin/rollen.php, /admin/abschnitt-status.php, /admin/schwerpunkt-status.php) prüfen pro Request frisch (kein Cache), ob ihre Feature-Tabellen vorhanden sind, und zeigen sonst einen prominenten Hinweis-Banner mit Direkt-Link zum Schema-Check.
  • Schema-Check erweitertapplyColumnMigrations() und seedMissingDefaults() ergänzen den vorhandenen Tabellen-Anlage- Pfad. Erkennt veraltete ENUM-Spalten (z. B. users.role ohne sp_dispo, einsaetze.wichtigkeit ohne bereitstellung) und fehlende Default-Daten, alles per Knopfdruck reparierbar.
  • Spalten-Migrations-Pipeline in SchemaProvider::columnMigrations() — generisches Muster für künftige Drift-Fälle (Liste von {table, column, detect, targetType, issue}).
  • Handbuch: neues Topic Alarm-Regeln und FAQ-Einträge zu Multi-Alarm-Verarbeitung + Schema-Migrationen.

Geändert

  • System-Status „Verarbeitete Alarme" zeigt jetzt die echte Anzahl aus der einsaetze-Tabelle (gesamt seit ETB-Reset + 24-h- Counter) statt nur den letzten Cron-Lauf (war typisch 0).
  • Heartbeat-Mail „Verarbeitete Alarme" entsprechend angepasst — Quelle ist jetzt die einsaetze-Tabelle statt veralteter Mantis- Aera-Log-Pattern. Plus neuer Block „Seit letztem ETB-Reset: 🚒 Einsätze gesamt: N".
  • SP-Dispo-Dropdown-Trennung: Einsatz- und Abschnitts-Disponent- Dropdowns enthalten jetzt nur klassische Dispos (User::canBeEinsatzDispo()), Schwerpunkt-Disponent-Dropdowns enthalten beide Rollen (isAnyDispo()). Filter-Dropdowns (ETB-Übersicht, PDF-Export) zeigen weiterhin beide.
  • Konsistenter Display-Name „Schwerpunkt-Dispo" über alle Dropdowns, Pills und Modal-JS (statt teilweise „SP-Dispo" als Kurzform).
  • Pill-Farbe für sp_dispo in /admin/users.php ergänzt (war vorher grau wie „Gast", was wie „Rolle nicht übernommen" aussah).
  • Admin-Index: Kachel „Schema-Check" von Konfiguration nach Aktionen verschoben — semantisch eine Repair-Aktion, keine Einstellung.

Behoben

  • Schwerpunkt-Dispo-Rolle ließ sich nicht speichern — Ursache war ein ENUM auf users.role aus dem alten Migrations-SQL (kannte sp_dispo nicht). Schema-Migration zieht jetzt automatisch auf VARCHAR(32) um, wenn der Reparatur-Knopf geklickt wird.
  • SP-Marker-Info-Leak auf der Hauptkarte (/api/mapdata.php) — SP-Dispo sah dort alle aktiven SP-Marker. Jetzt nur die eigenen, analog zu SchwerpunktService::listForUser.
  • System-Kommentar-Schutz im Service-Layer für alle drei Kommentar- Services (Einsatz, Abschnitt, Schwerpunkt). canEdit() schützte nur die UI; ein direkter edit()-Aufruf auf einen System-Kommentar (author_user_id = NULL) wäre durchgegangen.
  • Hilfe-Topic-Links wurden vom Markdown-Renderer als relative URLs generiert (z. B. 01-installation), führten in der in-App-Hilfe ins Leere. Neuer HelpService::rewriteTopicLinks() schreibt sie auf /hilfe.php?topic=<slug> um.
  • Handbuch-Pfade korrigiert: /admin/geocode-admin.php/geocode-admin.php (Datei lag schon immer unter /, nicht unter /admin/).
  • Setting-Doku auto_delete_sp_dispo_on_closesp_dispo_delete_on_reset (das Setting existiert tatsächlich, hat aber andere Semantik — greift beim ETB-Reset, nicht beim SP-Close).

Sicherheit / Härtung

  • Konsolidierungs-Schlüssel im AlarmProcessor für Unwetter-Blöcke angepasst: ein eindeutiger Schlüssel pro Block (UW:<ts>:<idx>:<strasse>|<ort>) verhindert, dass mehrere Blöcke mit identischem Stichwort + Timestamp zu einer Gruppe konsolidiert werden.

Migration / Upgrade-Hinweise

  1. /admin/schema-check.php öffnen → „Reparieren" — legt fehlende Tabellen (alarm_rule, alarm_rule_followup), Indizes, veraltete Spalten-Migrationen und fehlende Defaults (Wichtigkeit bereitstellung, UW-ERSTALARM-Regel) in einem Rutsch an.
  2. Falls SP-Dispo-User mit jetzt leerer Rolle existieren (durch die alte ENUM-Sperre): unter /admin/users.php einmal bearbeiten, Rolle nochmal setzen.
  3. Auf /admin/alarm-regeln.php prüfen, dass die UW-ERSTALARM-Regel da ist. LG-Felder der Folge-Einsätze bleiben absichtlich leer — wachen-spezifisch eintragen.
  4. Komplett additiv ansonsten — kein Code-Update nötig, keine Bestandsdaten betroffen.

2.1.0 — 2026-05-26

Handbuch — In-App-Hilfe + Wiki

Das ETB hatte bisher keine zusammenhängende Bedienungsanleitung. Diese Version liefert ein vollständiges Handbuch mit 20 Topics (~50 Seiten), zugänglich auf zwei Wegen — und beide aus derselben Quelle gespeist.

Neu

  • In-App-Hilfe über den neuen Sidebar-Eintrag „📖 Hilfe" (/hilfe.php) — für alle eingeloggten User sichtbar, Gast inkl.
  • 20 Markdown-Topics unter docs/handbuch/, gruppiert nach Einstieg, Tagesbetrieb, Rollen & Berechtigungen, Admin-Bereich, Betrieb und Referenz.
  • TOC-Layout mit linker Themen-Spalte und rechter Content-Spalte, inkl. Vorheriges/Nächstes-Navigation am Ende jedes Topics.
  • Branding-Platzhalter (Freiwillige Feuerwehr Wachtberg, FFW Wachtberg, http://einsatz.ffwachtberg.de, Einsatztagebuch) werden aus BrandingService ersetzt — White-Label-tauglich.
  • Wiki-Sync via scripts/wiki-sync.ps1: PowerShell-Skript klont das Wiki-Repo, spiegelt die Markdown-Dateien, transformiert interne Links ins Wiki-Format und pusht.
  • HelpService liest die Topics, parst Front-Matter (erste H1 = Titel, Dateinamens-Prefix = Sortier-Order und Gruppen-Bucket), rendert via Parsedown.
  • Parsedown als Single-File-Lib unter src/lib/Parsedown.php (MIT-Lizenz, kein Composer nötig).

Topics im Überblick

Gruppe Topics
Einstieg Übersicht, Installation, Setup-Wizard
Tagesbetrieb Einsätze, Abschnitte, Schwerpunkte, Lagekarte, Einsatzmittel, Hydrantenplan
Rollen & Berechtigungen Die 6 Rollen, Permission-Matrix administrieren
Admin-Bereich Admin-Übersicht, Konfiguration, Stammdaten, Telegram, Diagnose
Betrieb Cron & Mail-Verarbeitung, Backup & Updates
Referenz FAQ (~30 Q&A), Glossar

Migration / Upgrade-Hinweise

  • Komplett additiv — kein DB-Schema-Update, keine Konfigwerte- Migration. Pull + Reload, fertig.
  • Der Sidebar-Eintrag „📖 Hilfe" erscheint automatisch für alle eingeloggten User.
  • Master-Quelle für die Inhalte sind die Markdown-Dateien im Repo. Für das Wiki führst du nach jedem Inhalts-Update einmalig pwsh scripts/wiki-sync.ps1 aus (manuell, keine Auto-Sync per CI-Job).
  • Bei privaten Repos kommt der Wiki-Sync später dran, sobald das Repo public ist — die In-App-Hilfe funktioniert unabhängig davon sofort.

2.0.0 — 2026-05-26

Rollen-/Permission-Architektur — administrierbare Berechtigungen

Die Berechtigungen sind nicht mehr hartcodiert in User::can(), sondern werden über eine DB-gestützte Häkchen-Matrix pro Rolle gepflegt. Die 6 Rollen (admin, lage, einsatzleiter, dispo, sp_dispo, gast) bleiben fix; ihre Permissions sind über /admin/rollen.php administrierbar.

PermissionCatalog (36 atomare Permissions, 7 Gruppen)
  ↓
PermissionService (DB-Lookup, Per-Request-Cache)
  ↓
User::can('permission_key') → bool

Neu

  • PermissionCatalog mit 36 atomaren Permission-Keys in 7 Gruppen (einsatz, abschnitt, schwerpunkt, em, anhang, admin, karten).
  • Admin-UI /admin/rollen.php als Häkchen-Matrix mit Scope-Banner, „Reset auf Default"-Button und Audit-Log pro Änderung.
  • 3-Layer-Failsafe:
    • ROLE_ADMIN bekommt in userCan() immer true — verhindert Selbst-Aussperren auch bei kaputter DB.
    • Locked-Permissions (z. B. schwerpunkt.view für sp_dispo) können weder via UI noch via API abgewählt werden.
    • ROLE_SPECIFIC_PERMS (z. B. einsatz.view_all) sind nur bei der jeweiligen Rolle sichtbar — andere Rollen sehen die Option gar nicht und können sie nicht versehentlich setzen.
  • RoleAuditService loggt jede Permission-Änderung mit Diff + ausführender User-ID.
  • Schema-Auto-Migration: Neue Seite /admin/schema-check.php zeigt fehlende Tabellen + Indizes und legt sie auf Knopfdruck an. Schema-Banner in der Sidebar (rollen-abhängig sichtbar) warnt proaktiv bei inkonsistentem DB-Stand.
  • SetupStatus::missingTables() mit 1 h Session-Cache verhindert Bounce auf jeder Seite.

Modal-Dialog-Library

  • Dialog.confirm/alert/prompt-API mit info/warn/danger- Severities, globalem Background-Klick-Schließen, ESC-Handling und Auto-Wiring via data-confirm-Attributen.
  • Ersetzt alle ~40 nativen confirm()/alert()-Aufrufe in der gesamten App — konsistentes Design, kein Browser-Modal mehr.

Schwerpunkt-Historie

  • Neue Seite /schwerpunkte/history.php mit Stammdaten, EM-Pool-Snapshot, Einsatzliste und chronologischer Audit-Liste.
  • „🕓 Historie"-Button im SP-Banner zwischen Edit und Export.
  • Auto-Logging in EinsatzMittelAssignmentService für em_add / em_remove / anzahl_change / kontakt_change — jede EM-Mutation im SP-Kontext landet im SP-Audit (via Setter- Injection, damit keine zyklische Service-Abhängigkeit entsteht).
  • PDF-Export mit SP-Cover (Stammdaten + komplette Audit-Tabelle) wenn ?schwerpunkt=<id> mitgegeben wird.

Lagekarte-Verbesserungen

  • Einsatznummer als permanenter Leaflet-Tooltip im tooltipPane (z-Index 650, also über allen Markern). Vorher konnten taktische 96×96-Symbole, Fahrzeug-Icons und SP-Pills die Einsatznummer überdecken — der Tooltip rendert jetzt strukturell darüber.
  • Tooltip-Background in Wichtigkeits-Farbe, Textfarbe via YIQ-Lesbarkeits-Formel (weiß auf dunklem, schwarz auf hellem Hintergrund). Tooltip-Offset [0, 8] — nah am Marker.
  • Cluster on/off Toggle in der Topbar, persistiert in localStorage. Klick wechselt zwischen L.markerClusterGroup und L.layerGroup ohne Page-Reload.
  • Heatmap-Gradient warm (`#ffeb99 → #ffcc33 → #ff9933 →

    ff5500 → #cc0000,minOpacity: 0.45`). Der Leaflet-Default

    grün→blau→gelb war auf OSM-Wald-/Wasser-Tiles praktisch unsichtbar. SP-Heatmap nutzt jetzt denselben warmen Gradient für visuelle Konsistenz.

Geändert

  • System-Kommentare (Autor NULL) sind in allen drei Kommentar-Services (Einsatz, Abschnitt, Schwerpunkt) jetzt revisionsfest — der explizite Null-Check blockiert das Editieren komplett, auch für Admins.
  • SP-Personal-Aggregation deduplizieren: Ein EM, das mehreren Einsätzen eines Schwerpunkts zugewiesen ist, wird im SP-Personal-Pill jetzt nur einmal gezählt (per em_name, höchste Personenzahl gewinnt) — vorher wurde es pro Zuweisung mehrfach addiert.
  • SP-Edit-Page: Disponent-Dropdown unterscheidet jetzt Name (Dispo) vs. Name (SP-Dispo). Neuer Button „+ SP-Dispo anlegen" öffnet ein Inline-Modal mit hartcodierter Rollenzuweisung server-seitig.
  • Einsatzmittel-Sidebar auf der Einsatz-Detail-Page filtert jetzt korrekt auf den SP-Pool, wenn der Einsatz einem Schwerpunkt zugewiesen ist. EMs außerhalb des Pools sind ausgeblendet, damit das EM-Management mit der SP-Logik konsistent bleibt.
  • N+1-Fix in der ETB-Übersicht: neuer Bulk-Lookup forAbschnitte() ersetzt die per-Abschnitt-Schleife mit einer einzigen Query.

Behoben

  • 500er auf /admin/rollen.php bei fehlenden DB-Tabellen: Defensives try/catch in PermissionService::getAllRoles() und automatische Migration via SchemaProvider::createAll() beim ersten Aufruf.
  • SP-Banner fehlte auf der SP-Historie-Page — jetzt im SP-Kontext sichtbar (Header-Streifen wie auf allen anderen SP-Sub-Pages).

Intern (Refactoring)

  • ~50 hartcodierte Rollen-Checks ($me->role === ROLE_X / in_array($me->role, […])) durch Permission-Checks ersetzt.
  • dispoScopeApplies($me)-Helper im bootstrap.php: respektiert die neue einsatz.view_all-Permission als Scope-Override für Dispo-User (im Standardfall greift der Eigentums-Filter; mit view_all sieht der Dispo alle Einsätze).
  • Scope-Filter bleiben Code-Logik: Dispo-Eigentums-Filter und SP-Scope sind NICHT permission-konfigurierbar (Sicherheits- Sweetspot — kein Häkchen kann die Schwerpunkt-Beschränkung des SP-Dispo aufheben).
  • Neue Service-Klassen: PermissionCatalog, PermissionService, RoleAuditService.
  • 3 neue Tabellen via SchemaProvider: roles, role_permissions, role_audit (mit Composite-Soft-Delete- Indizes für die bestehenden Tabellen).

Migration / Upgrade-Hinweise

  • Die neuen Tabellen werden beim ersten Aufruf einer beliebigen Admin-Seite automatisch angelegt. Falls die Auto-Migration nicht greift: /admin/schema-check.php öffnen und „Jetzt anlegen" klicken.
  • Die Default-Permission-Belegung pro Rolle entspricht dem alten hartcodierten Mapping — bestehendes Verhalten bleibt erhalten.
  • Admin kann nach dem Upgrade unter /admin/rollen.php einzelne Permissions umkonfigurieren. „Reset auf Default" stellt jederzeit den Auslieferungsstand wieder her.
  • Empfohlene Prüfschritte: Als Admin einloggen, einmal jede Rolle durchklicken (oder Test-User mit der Rolle erstellen), prüfen, dass Permissions wie gewohnt greifen.

1.5.0 — 2026-05-25

Schwerpunkte — Großlagen-Gruppierung mehrerer Einsätze

Neue Strukturebene über den Einsätzen für die Koordination von Großlagen (Unwetter, Flächenbrand, Großübung). Ein Schwerpunkt bündelt mehrere Einsätze unter einem dedizierten Disponenten mit eigenem EM-Pool, eigener Lagekarte und eigenem „Schwerpunkttagebuch"-Modus.

Schwerpunkt (n)         ← NEU
  └── Einsatz (1..n)
        └── Abschnitt (0..n)

Neu

  • Schwerpunkt-Wizard (/schwerpunkte/new.php) mit 4 Schritten: Stammdaten + Disponent (mit Inline-User-Anlage), Modus-Auswahl (Orte vs. konkrete Einsätze), Einsatz-Auswahl mit Konflikt-Markierung, Einsatzmittel-Pool (vorbefüllt aus den schon zugewiesenen EMs).
  • Schwerpunkt-Übersicht (/schwerpunkte/index.php) mit Filterung nach Status (aktiv/pausiert/geschlossen/archiviert).
  • Schwerpunkt-Tabelle im Haupt-ETB oberhalb der Einsatz-Liste mit 3-stufiger Expansion: Schwerpunkt → Einsatz → Abschnitt.
  • Schwerpunkttagebuch-Modus via ?schwerpunkt=<id> — alle Sub-Pages (Einsatzliste, Lagekarte, Einsatzmittel, Hydrantenplan, Links, Geocode-Admin) filtern auf den jeweiligen Schwerpunkt; die Sidebar wechselt in den SP-Modus mit Banner und „← Zurück zum ETB".
  • Einsatzmittel-Pool als n:m-Beziehung pro Schwerpunkt. Entfernen eines EMs aus dem Pool kaskadiert in alle SP-Einsätze und ihre Abschnitte und schreibt einen System-Kommentar in jeden betroffenen Einsatz — alles transaktional.
  • Automatische Einsatz-Zuweisung an Schwerpunkte: Neue Einsätze (auch via Mail-Parser) werden anhand ihres Orts dem passenden aktiven Schwerpunkt im Modus „Orte" zugewiesen.
  • Status-Lifecycle: aktivpausiert (Auto-Zuweisung aus) → geschlossen (mit Sperre solange offene Einsätze enthalten sind) → archiviert (aus Listen verborgen).
  • Personal-Aggregation pro Schwerpunkt: „GF/TF/EK/Gesamt"-Summen über alle EM-Zuweisungen im Schwerpunkt, mit Doppel-Unterstreichung der Gesamt-Zahl in ETB-Übersicht, SP-Liste und SP-Banner.
  • Lagekarte im SP-Modus: SP-Einsätze werden standardmäßig als Dichte-Visualisierung (Heatmap) statt als N einzelne Marker gerendert, mit Toggle „Alle Einsätze anzeigen" / „SP-Marker aus" und Auto-Fit auf die SP-Bounding-Box.
  • Schwerpunkt-Marker auf der Hauptlagekarte für eine schnelle Übersicht aller aktiven Schwerpunkte.
  • PDF-Export pro Schwerpunkt (/schwerpunkte/export.php) und „Alle-mit-SP-Gruppen"-Modus im Admin-PDF-Export.
  • Bulk-Zuweisung zu Schwerpunkten direkt aus der ETB-Übersicht (Mehrfach-Auswahl + Aktionsbar).
  • Drag&Drop von EMs aus der Sidebar direkt auf einen Schwerpunkt in der ETB-Übersicht — fügt das EM dem Pool hinzu.

Neue Rolle: SP_DISPO (Schwerpunkt-Disponent)

  • Eigene Rolle für Disponenten, die nur Einsätze und Abschnitte aus „ihren" Schwerpunkten sehen und bearbeiten dürfen.
  • Zentrale Scope-Prüfung via spDispoCanAccessEinsatz() in src/bootstrap.php, durchgehend an 13 API-Endpoints angebunden.
  • Disponenten-Dropdowns (Reassign-Selects, Bulk-Editor) berücksichtigen die neue Rolle via User::isAnyDispo().

Geändert

  • Einsatz-Reset (EinsatzResetService): löscht jetzt auch alle Schwerpunkte und ihre Tabellen mit (Abschnitte und Einsätze waren bereits abgedeckt).
  • Sidebar (MainNavSidebar) zeigt das „Schwerpunkte"-Item nur, wenn aktive Schwerpunkte existieren — sonst bleibt sie aufgeräumt.
  • EM-Sidebar im SP-Modus: zeigt nur EMs aus dem Pool des aktiven Schwerpunkts, flach (ohne üÖrt-Sentinel-Gruppe).
  • Einsatz-Detail-Page: neuer Button „Schwerpunkt zuweisen" mit Modal, das auch die EM-Zuordnung zum Pool mitanbieten kann.
  • Lagekarte-Popup: Einsatz-Links erhalten den ?schwerpunkt=<id>- Parameter, wenn der Klick aus dem SP-Tagebuch kam.

Behoben

  • Anhang-Download für Abschnitts-Kommentare: Der Endpoint /api/anhang-download.php kannte den kind=abschnitt-Parameter nicht und suchte immer in der Einsatz-Anhang-Tabelle — Downloads von Abschnitts-Anhängen schlugen still fehl. Jetzt zweigleisig mit getrennten MIME-Whitelists und Permission-Checks pro Variante.
  • Status-Blacklist im Bulk-Editor (/api/einsatz-bulk.php): Die Sperre für „Abschluss beantragen"/„Abgeschlossen" griff nur für DISPO, nicht für SP_DISPO.
  • Erledigt-Sperre an Abschnitten (abschnitt-em-assign.php, abschnitt-comment.php): griff nur für DISPO — SP_DISPO konnte weiter editieren.
  • 7 Dispo-Dropdown-Filter blendeten SP_DISPO aus und konnten ihm keine Einsätze/Abschnitte als Dispo zuweisen.
  • Nested-Transaction-Bug in SchwerpunktService::setOrte() und SchwerpunktEmService::unassign(): führten bei verschachtelten Aufrufen zu PDO-Fehlern.

Sicherheit

  • Session-Cookie: SameSite=Lax explizit dokumentiert als CSRF-Schutz für die JSON-AJAX-Endpoints. Cross-Site-POSTs werden vom Browser blockiert (Auth-Cookie geht nicht mit); GET-Top-Level- Navigationen aus externen Quellen (Telegram-Push-Links) funktionieren weiter.

Intern (Refactoring)

  • buildUrl() aus einsaetze/index.php und admin/export.php in zentralen Helper in src/bootstrap.php ausgelagert.
  • SchwerpunktService::sumAnzahlStrings() als public static — beseitigt das Personal-Aggregat-Code-Duplikat zwischen view.php und dem Service.
  • Neue Service-Klassen: SchwerpunktService, SchwerpunktStatusService, SchwerpunktEinsatzAssignmentService, SchwerpunktEmService, SchwerpunktKommentarService, SchwerpunktAnhangService, SchwerpunktAuditService.
  • 8 neue Tabellen via SchemaProvider (keine separaten SQL-Migrationen): schwerpunkte, schwerpunkt_status, einsatz_schwerpunkt, schwerpunkt_einsatzmittel, schwerpunkt_ort, schwerpunkt_kommentar, schwerpunkt_anhang, schwerpunkt_audit.

Migration / Upgrade-Hinweise

  • Die neuen Tabellen werden beim nächsten Aufruf automatisch via SchemaProvider::createAll() angelegt — kein manueller SQL-Schritt nötig.
  • Bestehende Einsätze, Abschnitte, User und Konfiguration bleiben unverändert. Das Feature ist additiv: Wer keine Schwerpunkte anlegt, sieht das Verhalten wie in v1.0.0.
  • Die neue Rolle SP_DISPO ist optional. Bestehende Dispo-User behalten ihre Rolle.
  • Empfohlene Prüfschritte nach dem Upgrade: einmal als Admin einloggen, einen Schwerpunkt anlegen (Wizard), einen Einsatz zuweisen, EM-Pool testen.

1.0.0 — 2026-05-23

Erste produktiv eingesetzte Version des Einsatztagebuchs.

Funktionsumfang

  • Einsatz-Verwaltung: Mail-Parser für eingehende Alarm-Mails, Detailseite mit Kommentaren + Anhängen + Audit-Historie, Status- Lebenszyklus (offen → in Bearbeitung → Abschluss beantragt → abgeschlossen), PDF-Export.
  • Abschnitte: Größere Einsätze in operative Abschnitte unterteilen, jeder mit eigenem Leiter, Funk-Rufgruppe, Disponent, Status; n:m EM-Zuweisung; Abschluss-Sperre auf Einsatz-Ebene.
  • Karten & Geo: Lagekarte (Leaflet/OSM), Hydrantenplan mit Foto-Upload, Geocoding-Service mit DB-Cache.
  • Telegram-Alarmierung: Push in mehrere Chats, IuK-Sondernachricht, Antwort-Webhook landet als Kommentar.
  • Rollen: admin, lage, einsatzleiter, dispo, gast mit Dispo-Restriction (Disponent sieht nur eigene/zugewiesene Einsätze).
  • Setup-Wizard für die Erst-Konfiguration; Branding-Assets, Geocoding-Suffix, Karten-Center konfigurierbar.
  • Mehrmandanten-Fähigkeit via Tabellen-Präfix pro Instanz.

Vollständige Beschreibung im Release v1.0.0.