Changelog: Verbessert
Public: Der Changelog ist auf pressekonto.com über die Navigation und den Footer erreichbar.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die Mail „Ihre Pressemitteilung wird persönlich geprüft“ verlinkte auch
bei API-Meldungen in den Kundenbereich. Empfänger ohne Konto landeten auf
der Passwort-Anmeldung. Wie in der Veröffentlichungs- und Ablehnungsmail
schickt jetzt ein Klick einen Anmeldelink an die Adresse der Mail; die
Zugangsseite übernimmt die Herkunft mail_review für den Funnel.
Changelog: Verbessert
Public: Auch die Mail zur persönlichen Prüfung führt Pressekontakte ohne Passwort zu ihrer Meldung.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Decision-Update Changelog, Stufen 1 bis 3:
- changelog:collect liest die Commits zwischen zwei Tags und legt aus den
Zeilen Changelog:/Public: Entwürfe an (ganze Nachricht, nicht nur der
Trailer-Block); ohne Changelog-Zeile intern, Sicherheit als eine
Sammelzeile je Release, Sicherheitsbegriffe im Titel stufen hoch, ohne
Public-Satz ein markierter Vorschlag aus dem Titel; idempotent.
- changelog:backfill trägt die Neuerungen seit dem Relaunch als Entwurf nach.
- Admin ▸ Changelog (settings:manage): gegenlesen, bearbeiten, Rubrik,
artikelwürdig, freigeben/verwerfen, Tag gesammelt freigeben, Eintrag von Hand.
- pressekonto.com/changelog und /changelog/feed (RSS), auf den Portalen
301 zum Hub; Kundenmenü „Was ist neu“ mit Neu-Kennzeichen (14 Tage).
Changelog: Neu
Public: Unter pressekonto.com/changelog steht, was sich auf pressekonto, presseecho und businessportal24 ändert – auch als RSS-Feed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Roadmap 6.18, Entscheidung 14.10.2026: Der Pressekontakt überarbeitet eine
abgelehnte API-Meldung über den Anmeldelink selbst und gibt sie erneut zur
Prüfung frei; die Ablehnungsmail sagt das jetzt so. Kostenlos, weil ein Slot
erst bei der Veröffentlichung und einmal je Meldung verbraucht wird.
Behoben: Das Mail-Routing las die Herkunft aus dem LETZTEN Review-Übergang.
Nach einer Wiedereinreichung im Kundenbereich galt die Meldung nicht mehr als
API-Meldung, und Veröffentlichungs- bzw. Ablehnungsmail wären an das Konto
des Einlieferers (connektar) gegangen statt an den Kontakt. Jetzt zählt jeder
Review-Übergang aus der API, wie schon in der Indexierungsauswertung.
Changelog: Verbessert
Public: Wird eine Pressemitteilung abgelehnt, die über einen Verteiler kam, kann der Pressekontakt sie selbst überarbeiten und kostenlos erneut einreichen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Roadmap 6.17. Veröffentlichungs- und Ablehnungsmails zu API-Meldungen gehen
an Pressekontakt oder Firmen-E-Mail — Empfänger ohne (bekanntes) Konto. Die
Mail sagte „in Ihrem Konto … mit Passwort oder Magic-Link“, gelesen wurde
„geht nicht“. Jetzt ein Kasten mit der Adresse und dem Knopf „Anmeldelink
anfordern“: signierter Link (30 Tage, Adresse verschlüsselt) auf /zugang,
ein Klick schickt den Anmeldelink, die Anmeldung landet auf der Meldung.
Ablehnung zu API-Meldungen: nur ansehen, neu eingereicht wird auf dem
ursprünglichen Weg. Kunden mit Konto: Knopf „Im pressekonto öffnen“.
Stufen 2 und 3 des Trichters messen die neue Seite mit.
Changelog: Verbessert
Public: Wer eine Veröffentlichungs- oder Ablehnungsmail bekommt, erhält mit einem Klick einen Anmeldelink an genau diese Adresse – ohne Konto und ohne Passwort.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Im Backend heißt der Datensatz weiter „Firma“, öffentlich ist er der
Newsroom. Kunden- und Admin-Firmenseite heißen „Firma & Newsroom“ und zeigen
unter dem Namen die Newsroom-Links je Portal oder den Hinweis, dass der
Newsroom erst mit der ersten Meldung erscheint (Company::publicNewsroomLinks).
Changelog: Verbessert
Public: Die Firmenseite im Kundenbereich verlinkt jetzt direkt auf den öffentlichen Newsroom.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Roadmap 6.1/6.16: Block 1 bis 3 mit Ist, zeitanteiligem Soll, Schwelle und
Status, Trichter seit 17.09., Transparenzseiten aus Umami. Neue Befehle
growth:report und umami:report. Zugang über UMAMI_API_* (View-only-Benutzer).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Roadmap 6.16. Bisher stand jede Einlösung ohne Firma im Trichter (Stufe
"Magic Link eingelöst" immer 0 Firmen), zwischen Mail-Klick und Einlösung
fehlten "Verwaltungsseite geöffnet" und "Anmeldelink angefordert", und
die Erstbuchung stand immer auf organic. Die Leiter hat jetzt sieben Stufen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Admin ▸ Pressemitteilung zeigt laufende Boosts; „Boost beenden“ verlangt
einen Grund und billing:manage, beendet laufende und angeschlossene
Zeiträume, verwirft die Seiten-Caches und protokolliert „Boost beendet“.
Credits werden nicht zurückgebucht.
audit:admins listet alle Konten mit Rechten über den Kundenbereich hinaus
(Super-Admin, Rollen außer customer/api-only, direkte Permissions), auch
gesperrte und gelöschte, als Markdown mit 2FA, Passkeys, Tokens und letztem
Sitzungswiderruf. E-Mail standardmäßig nur mit Domain (Nachweis BN-02).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Label „Gebuchte Platzierung“ (en „Booked placement“) statt „Top-Platzierung“
auf Start- und Branchenseite. Die Erklärung „Das Unternehmen hat diesen Platz
gebucht …“ erscheint am Desktop beim Überfahren und auf Mobil per Tipp, ohne
den umgebenden Link zu öffnen; Screenreader lesen sie mit. Kopfzeile über dem
Aufmacher „Aktuell“ statt „Top-Auswahl“ (automatische Auswahl, keine
Redaktion). Preisseite nennt die Kennzeichnung (Rechtspaket U10).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nachtrag zu v1.8.0, beim Prüfen nach dem Deploy gefunden: Meta-Beschreibungen
und Taglines der drei Marken (config/domains.php), Tarifvorteil „Starter“ im
PlanSeeder, Platzhalter im Admin. Der Wächtertest prüft jetzt auch config/
und database/seeders/. Live steht der Tarifvorteil in der Datenbank und wird
im Admin geändert (Seeder überschreibt sonst alle Tarifdaten).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Decision-Update Bildrechte 3.6 / Plan D.6: keine Siegel- oder
Redaktionszusage. Startseiten-Meta, CTA, Veröffentlichen-Seite (DE/EN),
Preisseite, Dashboard. „Qualitätsgeprüft seit 2012“ war sachlich falsch →
„Im Archiv seit :year“. Wächtertest gegen Rückfälle (Roadmap 3.7).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Der Endpunkt legte Abos ohne Bestätigungsweg an, die Spezifikation versprach
ein Double-Opt-in; seit dem Go-Live kein Aufruf. Antwortet jetzt mit 410,
die Ability ist für neue Tokens nicht mehr wählbar (Roadmap 4.3).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Beide Tabellen hatten keine Frist; activity_events trägt Namen und Adressen
im Klartext, api_usage_logs IP und User-Agent. MassPrunable, täglich 04:05
über model:prune, Fristen in config/monitoring.php (Roadmap 4.2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ErrorReportScrubber entfernt die Daten aller Breadcrumbs und bereinigt ihre
Nachrichten; Livewire-Breadcrumbs standardmäßig aus — das SDK hängt dort
Formularwerte und Properties an (Roadmap 4.9). Bestand in GlitchTip geprüft:
keine Formular- oder Passwortdaten.
- SessionRevocation::legacyCachedMark() entfernt (Übergang bis v1.6.0)
Changelog: Sicherheit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die Liste „Aktive Sessions“ las die sessions-Tabelle, Live speichert Sessions
in Redis — sie war immer leer. Jetzt: „Dieses Gerät“ (seit wann angemeldet)
und die letzten fünf Anmeldungen mit Anmeldeweg aus dem Aktivitätsverlauf,
ohne IP; Kachel „Anmeldungen in 30 Tagen“ (Roadmap 4.1).
Changelog: Verbessert
Public: Die Sicherheitsseite zeigt Ihre letzten Anmeldungen und wie Sie sich jeweils angemeldet haben.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Turnstile für Gäste und unbestätigte Konten (TurnstileVerifier,
<x-turnstile>); ist Cloudflare nicht erreichbar, wird durchgelassen und
im Verlauf, in der Kontakt-Queue und in der Betriebsüberwachung markiert
- Inhaltsfilter des Kontaktformulars (fremde Links, Floskel mit
Seitentitel, Zeichensalat, Sperrliste, Absenden unter 3 Sekunden);
Treffer landen in der Spam-Quarantäne ohne Mail, Löschung nach 30 Tagen
- Admin: Filter „Spam“, Sammelaktion, „Kein Spam“ holt die Mail nach
- Registrierung lehnt Zufallsnamen ab; users:prune-bot-registrations
(täglicher Lauf erst mit USERS_PRUNE_BOT_REGISTRATIONS=true)
- contact-messages:quarantine-spam für den Altbestand
- CSP erlaubt challenges.cloudflare.com, Log-Kanal spam
- Datenschutzerklärung: Abschnitt 6a Cloudflare Turnstile (Vorschlag)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
Restliche Phase 4 aus dem Sicherheitsaudit 07.10.2026:
- Sicherheitsseite: „Andere Geräte abmelden“ rotiert remember_token und
beendet alle anderen Sessions, die aktuelle bleibt (nicht während einer
Impersonation).
- LoginIpThrottle: 20 Fehlversuche je IP in 15 Minuten über alle Konten.
Gezählt über das Failed-Event, damit Livewire-Login und Fortifys
POST /login denselben Zähler teilen; Erfolg setzt ihn nicht zurück.
- Sperrmarke für Sessions in users.sessions_revoked_at_ms statt nur im
Cache — übersteht cache:clear. Die alte Cache-Marke zählt übergangsweise
mit und kann im nächsten Release entfallen.
- Neue und geänderte Passwörter: mindestens 12 Zeichen, in Produktion
zusätzlich uncompromised() (HIBP, k-Anonymität). Bestehende bleiben gültig.
- Content-Security-Policy-Report-Only in Produktion; Meldungen über
/csp-report nach storage/logs/csp-*.log, je Meldung höchstens einmal pro
Stunde, ohne Query und tokenartige Pfadsegmente.
Migration: users.sessions_revoked_at_ms (users hat FULLTEXT, 25 MB, Sekunden).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bisher blieb ein einmal erstellter Token gültig, auch wenn Abo bzw. Buchung
längst beendet waren. EnsureApiAccessIsBooked prüft jetzt bei jeder Anfrage
(v1 und /service/…-Altpfade), ob das Konto API-Zugang hat
(ApiAccessEligibilityService::hasApiAccess), sonst 403. Die Tokens bleiben
erhalten und funktionieren nach erneuter Buchung wieder.
Kunden können beim Erstellen optional ein Ablaufdatum setzen (bis 5 Jahre);
die Token-Liste zeigt „Gültig bis“ und einen Hinweis, wenn der Zugang
pausiert ist. sanctum:prune-expired räumt abgelaufene Tokens nach 30 Tagen
täglich ab. API-Doku (public/api/v1.yml) ergänzt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Live-Prüfung 08.10.2026: nginx beantwortet die Anfragen direkt (kein CDN,
kein vorgeschalteter Proxy), die App vertraute aber jedem Proxy
(trustProxies at '*'). Jeder Client konnte per X-Forwarded-For seine IP
vorgeben und damit IP-Limits bei Login und Passwort-Reset umgehen sowie
IP-Protokolle fälschen. Jetzt steuert config/trustedproxy.php das Vertrauen:
lokal (Traefik) weiterhin '*', sonst keinem Proxy; ein späteres CDN kommt
über TRUSTED_PROXIES dazu.
HSTS fehlte auf Live. SecurityHeaders setzt Strict-Transport-Security auf
HTTPS-Antworten, standardmäßig nur in Produktion (max-age 1 Jahr, bewusst
ohne includeSubDomains/preload).
phpunit.xml leert MONITORING_NTFY_*, damit Testläufe keine echten
Push-Nachrichten mehr auslösen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Auf Live meldete memberships:resync-auto nach v1.4.0 „vorher 19607, nachher 9":
syncMembershipsForEmail() entzog Konten ohne email_verified_at alle
automatischen Rechte, und 19.597 davon gehören Bestandskonten aus dem
Altsystem. Jetzt wird nur entzogen, was keine E-Mail-Grundlage mehr hat —
unabhängig vom Kontostatus (S-03 bleibt wirksam); neue Rechte weiterhin nur
für aktive, verifizierte Konten (F01).
memberships:resync-auto läuft in einer Transaktion, kennt --dry-run und rollt
zurück, wenn mehr als 5 % (mindestens 50) der Rechte wegfallen würden
(--force zum Erzwingen). Probelauf gegen die Live-Kopie: 19.607 → 19.316.
Wiederherstellung: storage/app/private/restore-company-user-auto-2026-10-07.sql
(nicht versioniert, INSERT IGNORE, idempotent).
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>
Anlass 06.10.2026: Nach dem Deploy von v1.3.0 hat queue:restart den Worker
beendet, Supervisor lief nicht, über eine Stunde blieben KI-Prüfungen und
Mails liegen, ohne dass es auffiel.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Auf Live kamen seit dem 05.10. rund 250 Versuche am Tag aus über 50 Quellen,
alle mit unbekannter Adresse — verteiltes Durchprobieren fremder
Zugangsdaten, das im Verlauf die relevanten Einträge verdeckte. Neue Tabelle
failed_login_tallies (Tag × Einstieg × IP-Hash), model:prune täglich 04:05.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Kundenwunsch 06.10.2026: Ein Kunde kam über die Stripe-Rechnungsseite nicht
an seine Rechnung und fragte nach Belegen und einer Rechnungs-E-Mail.
- Profil ▸ Rechnungsadresse ▸ Rechnungsversand: Schalter „Rechnungs-PDF an
die Konto-E-Mail" (Standard an), optionale „E-Mail für Rechnungen" mit
Schalter „Rechnungen als PDF an diese Adresse senden" (Standard an).
Neue Spalten an billing_addresses (klein, ohne FULLTEXT).
- InvoiceDelivery entscheidet Empfänger und Anhang; gleiche Adresse wie das
Konto ergibt eine Mail mit PDF.
- Zahlungsbestätigung (STR) und Bestandskunden-Rechnung/-Erinnerung (MAN)
folgen der Einstellung; die Fassung an die Rechnungs-E-Mail nennt das
Konto, ohne Blindkopie und ohne Login-Button.
- StripeInvoicePdf holt das Stripe-PDF einmal und legt es lokal ab
(storage/app/private/invoices/stripe); Mailversand wiederholt bei
Stripe-Ausfall (5 Versuche).
- Rechnungsseite: „PDF öffnen" aus pressekonto, „Beleg bei Stripe" für den
Zahlungsbeleg auf der Stripe-Seite.
Suite 2.340 grün, einer übersprungen; Larastan und Pint ohne Meldung.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Am 06.10.2026 hing die URL Inspection API zeitweise: 28 Zeitüberschreitungen
und 4 × 500, jede einzeln als Fehler gemeldet, der Lauf zog sich über 1¾
Stunden. Neu: SearchConsoleUnavailable für Timeout/5xx/429 (Warnung, Meldung
bleibt fällig), echte Fehler (401/403/400) weiter über report(); FAILURE —
und damit ein Betriebs-Alert — nur bei Abbruch oder ≥ 50 % Fehlern.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seit der lokalen DSN landeten absichtlich provozierte Fehler aus den Tests
(„Queue weg“, „Datenbank nicht erreichbar“, SQLite „no such table“,
fehlende Rolle `customer`, Wasserstandsmarke) als Issues in GlitchTip.
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>
Livewire 4.4.7 rendert ModelNotFoundException im Testhelfer als 404 statt
sie zu werfen — zwei Tests auf assertNotFound() umgestellt, Laufzeitverhalten
unverändert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- B-01/B-02: Startseiten-Feed, Card-Helfer und Nachweis-PDF nur mit
isPubliclyDeliverable()
- B-03: Livewire-Temp-Upload 16 MiB
- N09: Snapshot je Bytes- und Metadaten-Hash inkl. OG-Variante, put()
geprüft, alle Fassungen ins Archiv
- O03: published_ever_at in der Freigabetransaktion
(markPublishedIfNowPublic) — Kundenbestätigung, Vorab-Sichtung, Korrektur
- B-04/B-14: Bestätigung an Bild-ID und SHA gebunden, unter Sperre
- B-05/B-06: Entfernen unter Sperre mit frischem Stand und Archivauftrag;
Korrektur archiviert über den Auftrag, Nacharbeiten abgesichert
- B-07: precheck_withheld_at getrennt von withheld_at (Migration + Übernahme)
- B-08, B-09, B-11, B-12: published_ever_at nur bei Status published,
Admin-Eigentümer mit Kundenregel, Sweep verwaister Originale,
Verarbeitungsfehler als Formularmeldung
- K-02-Teil: nach Kundenbestätigung erneut routen
- OPT-3 bis OPT-5: pingImage für JPEG, Hash durchgereicht, erstes Frame
Admin-PM-Detailseite enthält zusätzlich K-06 (Autorisierung) und A-08
(Nachweis per POST), weil die Datei ungeteilt committet ist.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A-01/A-02/A-04: archive_pending_jobs je Vorgang (ArchivePendingQueue),
Depublikationsstand am Auftrag festgehalten, Nachholer ohne Schlüssel
FAILURE; archive_pending_at nur noch Sammelmarker
- O07: Direktweg und Nachholer beanspruchen den Auftrag unter Zeilensperre
- O08: fehlende Snapshot-Datei → Verweis auf den image_removed-Eintrag oder
offener Auftrag, nie ein still unvollständiger Nachweis
- A-03/A-06: Sweep verschiebt in die Quarantäne, Pause beim Restore,
archive:reregister; Restore-Abgleich löscht Anwendungskopien erneut
- O04/O05: Restore ordnet über den Payload-Pfad zu; unsignierte Exporte nur
mit --accept-unsigned, reregister bricht bei ungültigem/fehlendem Export ab
- A-05, A-07 bis A-15: Altbestand als möglicherweise veröffentlicht, Hold-
Historie, Zweck per POST, Nachweise gelöschter Bilder nur mit
compliance:manage, Anhänge auf ihrer Disk, Schlüssel-ID und
ARCHIVE_PREVIOUS_KEYS, HMAC per HKDF, archive:verify-export
- 5.1 d: Depublikation im Meldeverfahren trägt legal_request_id
PressReleaseService.php enthält zusätzlich K-01 (Prüfung im Publish-Lock),
N19 (archive() gibt Kopien frei) und N09 (markImagesPublished nur für
auslieferbare Bilder), weil die Datei ungeteilt committet ist.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- K-01: publish-scheduled filtert manual_review_required_at; publish() prüft
für ki/scheduler unter der Sperre (ManualReviewRequiredException)
- K-02: Kontingent- und Bildsperre sind fachliche Ausgänge (Exit 0, einmaliger
Verlaufseintrag); KI-Job ohne Retry bei Bildsperre
- O06: Kandidaten per Cursor (scheduled_at, id), Limit zählt bearbeitete
Meldungen, Blockaden nur ein Scan-Budget
- K-05: KI-Job lädt vor dem Routing neu, überholter Status ohne Retry; backoff
- K-06: Admin-Aktionen mit Permission-Prüfung und Fehlermeldung statt 500
- K-09: withoutOverlapping() mit kurzer Sperrdauer, purge-events 03:50,
neuer Wochenlauf press-release-images:sweep-orphan-originals (So 04:45)
- E9: NEWSLETTER_SENDING_ENABLED (Standard aus) sperrt Start, Resume und Job
- OPT-9: ExpireGrandfathering prüft die Queue-Voraussetzung aus E18
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- R-02/K-03: Aufrufaggregation und Merge ändern updated_at nicht mehr; neue
Spalte press_releases.content_changed_at (INSTANT), contentModifiedAt()
für Sitemap-lastmod, dateModified und article:modified_time
- R-03: Sitemap und Legacy-view_url mit /en/ für englische Meldungen
- R-04/O01: X-Pk-Ref je Empfänger per HMAC signiert; auf eine Sperre zählt —
hart wie weich — nur ein gültig signierter Rückläufer, unsignierte
standardmäßig nur zur Sichtung (BOUNCE_UNSIGNED_KIND=policy)
- R-05/R-06: Unmerge setzt nur unveränderte Füllwerte zurück
(company_merge_moves.merged_value), Canonical-Neubewertung nach Merge und
Unmerge, assignAll setzt veraltete Verweise zurück
- R-07 bis R-11: Crawler zählen nicht als Aufruf, Mail-Klick gedrosselt und
verzögert geschrieben, Claim-Zähler erst nach Versand, email_bounces nach
395 Tagen gelöscht, Canonical-Portal über Kategorie-ID, llms-Cache geleert,
Feed-Teaser ohne Doppel-Escaping, Merge-Ketten aufgelöst
- N17/N18: kein falsches „gelistet seit", Rollen im Indexbericht wie Sitemap
- OPT-1/OPT-2: topFeeds in SQL, purge-events löscht nach Grenz-ID
Enthält aus PressRelease.php auch die Card-Bild-Helfer (B-01) und
wasEverPublished()/neverPublished() (A-05), weil die Datei ungeteilt
committet ist.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- R-01: ApiNewsroomAssignment hängt an eine bestehende Firma nur noch Owner,
Mitglieder oder Nutzer aus NEWSROOM_API_ASSIGNMENT_USER_IDS; Pivot mit
granted_via = api; Befehl company-memberships:api-assignments (Liste,
--remove mit Vorschau)
- K-04: OAuth-Verifikation eines offenen Kontos verwirft Passwort,
remember_token und Sanctum-Tokens; SessionRevocation + Middleware
EnsureSessionIsNotRevoked widerruft alte Sessions (Redis-tauglich)
- K-08: LoginCompletion für Passwort, Magic Link und Google — last_login_at
und Anmeldemethode auch nach 2FA, Landeziel über die Challenge, Google
ohne erzwungenes remember, magic-login ohne guest für eigene Links
- B-10: eigener Magic-Link-Zweck image_confirmation (Migration)
- K-07: legalAcceptanceVersions #[Locked], Versionswechsel beim Absenden
wird abgelehnt, Gate-Abfragen je Request zwischengespeichert
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- makeCustomerForShowPhase8a() nach tests/Pest.php — die Suite läuft damit
auch parallel (--parallel) und dateiweise grün
- phpunit.xml leert DB_URL, der Guard in TestCase::setUpTraits() bricht bei
gesetzter url ab, bevor RefreshDatabase eine Verbindung öffnet
- HasUniqueSlug ohne widersprüchliche @var-Annotation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bilder (N01, N05, N07, N08): gemeinsamer Freigabezustand
PressReleaseImage::isPubliclyDeliverable() für Seiten, OG und Medienroute
(Bestand bleibt sichtbar, v2 nur mit Bestätigung, Admin-Upload bis zum
Kundenklick nicht öffentlich); eigene Ability confirmImageRights nur für den
Kontoinhaber, ohne Super-Admin-Kurzschluss, Identität und ausstehende
Bestätigung auch im Service; Status-Regel unter der PM-Sperre; Cache-Flush
nach dem Commit außerhalb der Dateibereinigung; Snapshot nach Bestätigung an
veröffentlichter PM; Bestätigungstexte an die gezeigte Kennung gebunden.
Beweisarchiv (N02, N10, N11, N12, N13, 5.1): Tombstone unter Zeilensperre mit
erneuter Hold-/Fristprüfung; Dateioperationen ausgewertet, Commands mit
FAILURE; record() über .tmp + move; Marker archive_pending_at mit
archive:retry-pending und archive:sweep-orphans; Anonymisierung entfernt Bilder
über den Remover mit Antragsbezug; Draft-Purge räumt Medien nie
veröffentlichter abgelehnter Einreichungen; App-Kopien fallen mit dem
Archiv-Tombstone; label_corrected nur für veröffentlichte Bilder;
archive_entries.legal_request_id; FileDeletion-Helfer; Systemstatus-Checks.
KI und Hintergrund (N03, N04, N14, N20, N21): Ergebnis-UPDATE und Audit in
einer Transaktion; erwarteter Hash bis in reject()/holdForManualReview();
Ablaufmail per beanspruchtem Marker in einer Transaktion; strikte
Schemaprüfung der Vision-Antwort; Fortschrittsmarke ungecacht.
Berichte und Canonical (N15–N19, 5.2): lückenlose Alterskohorten;
Feed-Identität mit Portal und Sprache; Sitemap-Rolle in der Kundenansicht;
Indexverteilung auf einer Grundgesamtheit; Kopien nach Wegfall der
Erstquelle neu bewertet; Kategorie-Admin leert Seiten-Caches; Dry-Run
zählt alle Tabellen.
Gesamtsuite: 2.122 Tests grün, einer übersprungen; Larastan und Pint sauber.
Zwei Migrationen (nullable Spalten, INSTANT). N09 offen.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- Tests\TestCase prüft die Standardverbindung in setUpTraits(), also vor
RefreshDatabase — bisher erst nach dem Refresh (N22). Eigener Test.
- phpunit.xml pinnt IMAGE_RIGHTS_V2, IMAGE_PRECHECK(_STAGE) und
LEGAL_ACCEPTANCE_GATE auf die Vorgaben aus .env.example; die Suite hing
sonst an der lokalen .env (Audit Abschnitt 6).
- Zustimmungsgate: die Livewire-Komponenten tragen die beim Rendern gezeigten
Fassungen (Trait-Hook rendering); weicht die aktuelle Fassung beim Absenden
ab, wird die Annahme abgelehnt und der neue Wortlaut gezeigt. Ein fehlendes
Pflichtdokument ist bei aktivem Gate ein Konfigurationsfehler (N06).
- Audit vom 25.09., Decision-Update vom 22.09. und Plan Fassung 2 versioniert;
die Antwortkopie „…-211.md" entfernt; U10-Formulierung im Plan präzisiert.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Decision-Update Abschnitt 12 (E15, S24): Sichtung auf offensichtliche
Probleme, keine Rechteprüfung, öffentlich weiterhin „automatisierte Prüfung".
- ImagePrecheckManager mit openai- und deterministic-Treiber (Muster der
Text-Prüfstrecke), Bild auf 1024 px, Metadaten gestrippt, JPEG als Data-URI,
Antwortschema 12.4; Fehler → Ausgang `error`, durchlassen mit Vermerk.
- Auswertung 12.3: reject (Stock-Wasserzeichen, Nacktheit/Gewalt, Dokument
ab 0,85), queue (Screenshot, fremdes Logo, Kennzeichen ab 0,6 sowie
Ablehnungskategorien 0,6–0,85), hint (Personen, „wirkt KI" nur bei „ohne
KI", technischer Mangel). Stufe 1 wertet nur das Wasserzeichen; die KI setzt
nie die Kennzeichnung (E9). Herabstufung per Config (12.8).
- Uploader: Check vor jedem Schreiben, Ablehnung speichert nichts und
landet als ki_audits `image_precheck` an der PM; Hash-Bindung zwischen
Vorprüfung im Formular und Speichern; Spalten precheck*, Snapshot
`precheck_snapshot` im Bestätigungsprotokoll, Archiv-Payload erweitert.
- Queue: Bild zurückgehalten (withheld_at), Meldung läuft weiter; Admin
entscheidet mit Vermerk (Freigabe/Ablehnung → ki_audits
`image_precheck_review`); Ansicht „Bild-Sichtung" in der PM-Liste,
Sichtungsblock auf der PM-Seite, Systemstatus-Zähler.
- Formular v2: Ablehnungsgrund unter dem Dateifeld, Hinweise nach der
Dateiauswahl, „wird kurz gesichtet" an der Karte; API 422 mit Grund,
Warnung `image_under_review`.
- Config images.precheck (IMAGE_PRECHECK aus, STAGE 1); 17 Tests.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- legal_document_acceptances (insert-only), LegalAcceptanceGate, Pflicht-Schalter im Einreichungs-Modal über den gemeinsamen Trait; API: GET/POST /api/v1/legal/acceptances, submit antwortet 428 mit den geforderten Fassungen; LEGAL_ACCEPTANCE_GATE
- ImageService: og-Variante (1200×630) mit halbtransparentem Balken und Inter SemiBold, regenerateOgVariant() für Korrekturen und Bestand; Fokuspunkt/Letterbox getestet
- Uploader brennt den Nachweis beim Upload ein, ImageCorrectionService baut die OG-Variante nach einer Korrektur neu; Artikelseite nutzt og für og:image
- Teaser: Nachweis in alt/title (Feed, Hero, Kategorie, Newsroom), Unterschrift am Hero-Bild; PressRelease::cardImageCredit()
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- publish()/changeStatusFromAdmin(): kein Bild aus Formular v2 ohne gültige Bestätigung (ImageRightsConfirmationRequiredException, Admin-Seite meldet es); published_ever_at an PM und Bildern; PublishedImageSnapshot (Cover + JSON mit Nachweis/Kennzeichnung)
- deleteFromAdmin() und press-releases:purge-drafts löschen Bilder nie veröffentlichter Meldungen samt Original und Bestätigung sofort (E4, O1)
- press-releases:backfill-published-ever (Status-Log), press-release-images:purge-inactive-legacy (E-B11, Trockenlauf Standard)
- Admin-Route für Beweisoriginal und veröffentlichte Fassung nur mit Zweck, ActivityType EvidenceAccess; Architekturtest: original_path nur in vier Dateien
- ImageCorrectionService + image_declaration_corrections (insert-only), withheld_at blendet das Bild öffentlich aus (publiclyVisible-Scope), Korrekturpanel auf der Admin-Seite
- Systemstatus: fehlgeschlagene Herkunftsprüfungen der letzten 7 Tage
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- App\Support\ImageCredit: Foto/Quelle-Zeile, KI-Hinweis mit Herkunft, Verantwortlich-Zeile nur mit Protokoll, sichere Links; PDF-Zeilen mit Bestätigungskennung
- Artikelseite: Overlay (eigenes i-Zeichen, Alpine ohne Plugin, Bottom-Sheet auf Mobil) mit Nachweis, Lizenz, Quelle, KI-Hinweis, Verantwortlich-Zeile, „Bild melden"
- Richtlinien 0.2: Prüfung als automatisiert beschrieben, Abschnitt „Bilder" (Decision-Update 3.5); Taglines, Suche, Newsrooms, Startseiten-CTA, Mails ohne „qualitätsgeprüft"
- Cache-Invalidierung bei Bildwechsel an veröffentlichten Meldungen; PHPStan-Baseline für das Resource bereinigt
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- StorePressReleaseImageRequest: copyright, rights_confirmed, confirm_text_version Pflicht; 422 mit aktueller Kennung; 16 MiB
- PressReleaseImageController über den gemeinsamen Uploader, Löschen über den Remover; Resource mit Portalkennzeichnung, Kundenangabe, Herkunft, Bestätigung und warnings[]
- POST /service/pressreleases/{id}/images antwortet 410 mit Hinweis auf v1 (E-B4)
- API-Seite und Sprachdateien: Felder und Rechtehinweis mit aktiver Textkennung; Paritätsdokument ergänzt
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- press-release-images-manager-v2 hinter IMAGE_RIGHTS_V2: drei Blöcke, Vorbelegung aus Metadaten, Bestätigung mit archiviertem Wortlaut, Bild-Bindung über Hash, Fokuspunkt und Letterbox, Zustände absent/prefilled/error
- CustomerImageConfirmation: Magic-Link an den Kontoinhaber, Karte auf der Kundenseite, Kanal magic_link
- PressReleaseImageRemover: nie veröffentlicht = alles sofort weg, veröffentlicht = Soft Delete, Original bleibt
- ConversionSource::MailImageConfirmation
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>