Auf Live fehlte die PHP-Erweiterung imagick: Herkunftsprüfung und
KI-Vorab-Check der Bilder scheiterten still und ließen jedes Bild durch.
AdminSystemHealth zeigt jetzt die Zeile „PHP-Erweiterung Imagick“ (rot bei
eingeschaltetem Vorab-Check, sonst gelb).
GlitchTip server-pressekonto, Issues 38 und 39: gebaute Livewire-Anfragen
setzen gesperrte Properties (portal/language im Meldungs-Feed und in der
Suche) oder schicken Uploads an Komponenten ohne Upload. Livewire weist sie
korrekt ab; statt 500 bzw. 419 (das als „Seite abgelaufen“ gemeldet wurde)
antworten sie jetzt mit 400 und werden nicht mehr gemeldet.
Browser (Issue 18): Alpine bricht x-transition-Übergänge mit
{isFromCancelledTransition: true} ab — keine Fehlermeldung mehr.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Audit: dev/sicherheit/SICHERHEITSAUDIT-2026-10-07.md, Plan und Entscheidungen:
dev/sicherheit/ENTWICKLUNGSPLAN-SICHERHEIT-2026-10-07.md.
- S-01 Legacy-Rechnungen fremder Kunden nur mit billing:manage (auch Kundenroute).
- S-02 Kontaktzuordnung auf der Firmenanzeige verlangt companies:write, $id gesperrt.
- S-03 CompanyMembershipObserver: automatische Firmenrechte werden bei jeder
Adress-/Zuordnungsänderung sofort neu bewertet; memberships:resync-auto.
- S-04 Passwortwechsel beendet alle anderen Sessions (PasswordChanger), Reset
alle Sessions und offene Login-Links; Fortify PUT /user/password abgeschaltet.
API-Tokens bleiben bestehen.
- S-05 Google: email_verified Pflicht, feste Bindung über die Provider-ID;
Erstverknüpfung bestehender Konten außerhalb gmail/hd nur per Bestätigungslink
in derselben Browser-Session.
- S-06 Frischer Identitätsnachweis (Passwort, App-Code, E-Mail-Code oder
Passkey) vor E-Mail-Wechsel, erster 2FA-Einrichtung und Token-Erzeugung;
Hinweis-Mails an die (bisherige) Kontoadresse.
- Entscheidung 5: Passkeys (Fortify, @laravel/passkeys) für alle; Super-Admins
und Admins bestätigen die Session für den Admin-Bereich per Passkey oder
App-Code (EnsureStrongAdminAuthentication, Notfallschalter
AUTH_REQUIRE_STRONG_ADMIN); Reset des zweiten Faktors durch Super-Admins.
Neue Migration: create_passkeys_table. Suite 2.403 grün (1 übersprungen),
Larastan ohne Meldung.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- GlitchTip über die Sentry-SDKs; Datenschutzfilter (nur User-ID, keine
Request-Bodys, Tokens aus URL/Query/Referer, E-Mails aus Meldungen).
Browser-SDK erst beim ersten Fehler nachgeladen.
- ReportErrorSignals: tote interne Links (404 mit eigenem Referrer), 403/429
für Angemeldete, 419 als gedrosselte Warnung.
- /health (Bearer-Token): DB, Cache, Queue-Rückstau, Scheduler-Herzschlag,
Plattenplatz → 200/503; Scheduler und Plattenplatz auch im Systemstatus.
- OperationalAlert zusätzlich per ntfy (JSON-POST), unabhängig von der Mail.
- Verlauf: login_failed (Grund unbekannt/kein Passwort/falsch),
login_lockout, two_factor_failed; IP nur als gekürzter HMAC.
- Umami: Kundenbereich mit eigenem Schalter und identify('user-<id>'),
nie im Admin/bei Impersonation; Query-Filter auch auf den Webseiten
(signierte Links gingen bisher an Umami).
- queue:prune-failed nach 30 Tagen.
- Versionsnummer: config('app.version') aus APP_VERSION oder Datei RELEASE
(git describe --tags), in GlitchTip, /health, Systemstatus, artisan about.
Plan: dev/betrieb/monitoring-plan.md (Entscheidungen M1–M9).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Zwei Bugs im Scroll-zum-Fehler-Helper: '[wire\:submit]' matchte das
<form> selbst, sodass jeder Klick in ein Feld den Scroll armierte
(sichtbar beim USt-ID-Live-Check im Profil); und der leere, versteckte
Flux-Error-Container unter jedem Feld galt wegen Whitespace als
':not(:empty)' — fokussiert wurde dadurch grundlos das erste Feld.
Enter-Submit wird jetzt über das submit-Event erkannt, Fehlerfelder
nur noch bei echtem Fehlertext.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Archiv-Suche lief auf grossen Datenbestaenden langsam und war im Browser
komplett tot: app.js startete ein eigenes Alpine, Livewire injizierte
zusaetzlich seins - der DOM-Morph brach mit "Alpine.transaction is not a
function" ab (keine Rubrik klickbar, Suchbegriff nicht aenderbar).
- app.js buendelt jetzt Livewire + Alpine aus livewire.esm,
@livewireScriptConfig im Web-Layout stoppt die Auto-Injektion
- MySQL-Volltext-Index (Boolean-Mode, +wort*) statt LIKE ueber alles;
LIKE-Fallback fuer SQLite-Tests und kurze Tokens
- Firmen-/Rubrik-Treffer als ID-Listen statt orWhereHas (OR + EXISTS
hebelte den Volltext-Index aus)
Co-authored-by: Cursor <cursoragent@cursor.com>