Legacy-API-Kunden mit Keys beider Altportale — vor allem connektar — senden
jede Meldung an presseecho.de UND businessportal24.de. Weil die Firma ihr
Portal vom User und die Meldung es von der Firma erbte, landeten beide Kopien
im selben Portal, die zweite mit Slug-Suffix "-2". Verifiziert wurde das über
die Token-Hashes gegen die Legacy-Datenbanken.
Das Portal wird jetzt in fester Reihenfolge aufgelöst: expliziter
portal-Parameter, sonst die aufgerufene Domain, sonst das Portal des
Firmenprofils, zuletzt Portal::Both — genau der Default, den beide Spalten
ohnehin tragen. Die Auflösung ist damit nicht-nullbar; vorher konnte sie null
liefern, was als SQL-Fehler und damit als 500er beim Alt-Client gelandet wäre.
Ein Update über die v1-API verschiebt eine bestehende Meldung ausschließlich
über den expliziten Parameter, nie über die aufgerufene Domain.
press-releases:fix-api-portal-duplicates repariert die Altdaten: Es findet
Paare (gleicher User, Titel, Sprache und Portal, beide per API eingereicht,
kurz nacheinander) und verschiebt die zweite Kopie samt ihrer exklusiven Firma
ins jeweils andere Portal, mit neu vergebenem Slug. Web-Doppel-Submits ohne
Status-Log source=api und Legacy-Sync-Daten mit gesetzter legacy_id werden
geschont. Auf Live ausgeführt und verifiziert.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- trustHosts erlaubt nur die konfigurierten Domains (plus localhost/IP
für Health-Checks) und verwirft fremde Host-Header, sodass
X-Forwarded-Host keine URL-Generierung mehr vergiften kann (H5).
- Legacy-API-Keys nur noch per Header (Bearer/X-ApiKey); die alte
Query-/Body-Übergabe wird nicht mehr zur Auth akzeptiert, erhält aber
weiterhin den 410-Migrationshinweis statt eines opaken 401 (M11).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Neue PM-Bilder/Anhänge liegen auf der privaten local-Disk; Auslieferung
über kontrollierte Media-Routen mit gemeinsamer Zugriffslogik
(AuthorizesPressReleaseMediaAccess). Öffentliche Medien werden aus den
geladenen Modellen ermittelt (weniger Queries) und länger gecacht.
- Anonyme Token-Vorschau lädt Bilder über temporär signierte URLs (Fix#5).
- API-Resource baut Variant-URLs über die Media-Route statt /storage
(Fix#4). Storage-Schicht prüft zusätzlich den serverseitigen MIME-Type (M5).
- press-releases:privatize-media migriert Bestandsmedien.
Deployment: einmalig `php artisan press-releases:privatize-media` ausführen.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Publish/Reject/Archive und changeStatus erzwingen konsistent
press-releases:publish; changeStatus schloss die Lücke, über die das
Status-Modal die Prüfung umging (Fix#1/H2).
- publish()/changeStatusFromAdmin sperren PM- und User-Zeile
transaktional; QuotaExceededException wird in Admin-Publish und im
Auto-Publish-Job abgefangen (Warnung statt 500 / bleibt in Review, Fix#3/M2).
- Slug-Erzeugung nur noch über HasUniqueSlug (generateUniqueSlug +
saveWithUniqueSlugRetry), redundanter Controller-Helper entfernt (M3).
- API-/Legacy-Text wird vor der Persistenz sanitisiert (M6);
Scheduler/Legacy-Tracking ignorieren soft-gelöschte PMs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Der Kontotyp ist kein verlaesslicher Marker (connektar ist agency,
nicht apiuser) — submitForReview traegt jetzt die Quelle ('customer'
Panel, 'api' Legacy/v1) ins Status-Log, notifyAuthor prueft den
letzten Review-Uebergang. Kein Schema-Change noetig.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>