From 8d8d957884f228b643e493697e7b49963e9ec5a0 Mon Sep 17 00:00:00 2001 From: Kevin Adametz Date: Fri, 12 Jun 2026 09:20:22 +0000 Subject: [PATCH] Doku: Status-Sync 11./12.06., Decision-Update Preisstruktur und Phase-9-Plan - Decision-Update Preisstruktur & Veroeffentlichungs-Flow aufgenommen (Launch-Tarife, Slot-Verbrauch bei Veroeffentlichung, Submit-Gate, Launch-Credits) inkl. Klarstellung 12.06.: Gelb geht direkt live, keine manuelle Pruef-Queue, nur Rot wird abgelehnt - Alle Status-Dokumente auf den Code-Stand gezogen: README-Index, STATUS-ABGLEICH (KI-Pipeline, Bilder/Lizenzen, Pricing), Checkliste (KI- und Titelbild-Bloecke, Launch-To-dos), Admin-User, user-zusammenhaenge (Datenmodell-Delta), Entwicklungsplan KI-Pruefung (Phase 0 abgehakt, Decision-Abgleich) - Ueberschriebene Tarif-Abschnitte in Konzept-Update 1/2 und Relaunch-Konzept mit Superseded-/IST-Hinweisen markiert - Neues Plan-Dokument PHASE-9-FLOW-UND-TARIFE-PLAN.md (9A-9J) - Phase-8-Roadmap-Doku (20-PHASE-8-USER-PANEL.md) + PROGRESS-Eintraege Co-Authored-By: Claude Fable 5 --- .../hub-flux/20-PHASE-8-USER-PANEL.md | 103 ++++ dev/frontend/hub-flux/PROGRESS.md | 61 ++ ... Preisstruktur & Veröffentlichungs-Flow.md | 179 ++++++ docs/PHASE-8-USER-PANEL-PLAN.md | 33 +- docs/PHASE-9-FLOW-UND-TARIFE-PLAN.md | 224 ++++++++ docs/README.md | 66 ++- docs/STATUS-ABGLEICH-USER-PANEL.md | 117 ++-- ...ept-Update 1 – Überarbeitete Abschnitte.md | 39 +- .../Konzept-Update 2 – Score-Stufen-System.md | 12 +- ...– Multi-Brand-Architektur (Hub & Spoke).md | 327 +++++++++++ docs/user-admin/Admin-User.md | 31 +- ...splan KI-Pruefung und Veroeffentlichung.md | 524 ++++++++++++++++++ docs/user-admin/Lizenztyp Bildupload.md | 207 +++++++ .../Presseportal – Konzept für Relaunch.md | 89 +-- ...Bearbeitung Titelbild Veroeffentlichung.md | 277 +++++++++ docs/user-admin/checkliste-user-backend.md | 88 ++- docs/user-admin/user-zusammenhaenge.md | 26 +- 17 files changed, 2231 insertions(+), 172 deletions(-) create mode 100644 dev/frontend/hub-flux/20-PHASE-8-USER-PANEL.md create mode 100644 docs/Decision-Update Preisstruktur & Veröffentlichungs-Flow.md create mode 100644 docs/PHASE-9-FLOW-UND-TARIFE-PLAN.md create mode 100644 docs/konzept/Konzept-Update 3 – Multi-Brand-Architektur (Hub & Spoke).md create mode 100644 docs/user-admin/Entwicklungsplan KI-Pruefung und Veroeffentlichung.md create mode 100644 docs/user-admin/Lizenztyp Bildupload.md create mode 100644 docs/user-admin/Umsetzung Pressemitteilung Bearbeitung Titelbild Veroeffentlichung.md diff --git a/dev/frontend/hub-flux/20-PHASE-8-USER-PANEL.md b/dev/frontend/hub-flux/20-PHASE-8-USER-PANEL.md new file mode 100644 index 0000000..d95e934 --- /dev/null +++ b/dev/frontend/hub-flux/20-PHASE-8-USER-PANEL.md @@ -0,0 +1,103 @@ +# Phase 8 · User-Panel-Konsolidierung & PM-Lifecycle + +Stand: 2026-05-29 · **abgeschlossen** + +Plan-Doc: [`docs/PHASE-8-USER-PANEL-PLAN.md`](../../../docs/PHASE-8-USER-PANEL-PLAN.md) +Abgleich: [`docs/STATUS-ABGLEICH-USER-PANEL.md`](../../../docs/STATUS-ABGLEICH-USER-PANEL.md) + +Folge-Initiative nach Phase 7 (PM-Form-Refactor). Ziel: das User-Panel +produktionsreif abrunden — Show-Page-Lücken, Firmen-Liste auf +Mockup-Niveau, durchgängige PM-Titelbilder, rechtssichere Bild-Lizenzen +und ein bewusster Veröffentlichungs-Flow mit Kontingent-Vorbereitung. + +## Päckchen-Übersicht + +| ID | Thema | Status | +|---|---|---| +| 8A | Show-Page-Lücken (subtitle, scheduling, embargo, boilerplate_override) — Customer + Admin | ✅ | +| 8B | Listen-Indikatoren für Scheduling/Embargo | ✅ | +| 8C | Pressekontakt-Warn-Box in der Form-Sidebar | ✅ | +| 8D | Doku-Sync (`docs/user-admin/*`, `STATUS-ABGLEICH`) | ✅ | +| 8E | Firmen-Liste auf Mockup-Niveau (Counter-Strip, Saved-Views, Filter-Chips, Toggle, Rollen-Legende) | ✅ | +| 8F | SVG-Titelbild-Platzhalter-Set + Anzeige-Komponente + Picker-Modal | ✅ | +| 8G | Titelbild-Schema (`placeholder_variant`) + Cover-Resolver | ✅ | +| 8H | Bild-Upload mit Lizenz-Pflichtfeldern | ✅ | +| 8I | Veröffentlichungs-Modal (Rechtshinweis + Kontingent) | ✅ | +| 8J | Quota-Stub im Datenmodell + monatlicher Reset-Command | ✅ | +| 8K | Tests, Pint, Build, Doku-Abschluss | ✅ | + +## Wichtigste Code-Artefakte (8F–8J, neu in dieser Phase) + +**Enums** +- `app/Enums/PressReleasePlaceholder.php` — 9 SVG-Varianten (Default, + Seed-deterministisch, Labels, Asset-Pfad). +- `app/Enums/ImageLicenseType.php` — 5 Lizenztypen, `requiresLicenseUrl()`. + +**Assets / Komponenten** +- `public/images/press-release-placeholders/01..09-*.svg` (1600×900, + 3 Muster × 3 Hub-Farben). +- `resources/views/components/portal/press-release-placeholder.blade.php` — + rendert Bild/Platzhalter mit optionalem Titel-Overlay. +- `resources/views/livewire/components/press-release-placeholder-picker.blade.php` — + FluxUI-Modal mit 3×3-Grid, dispatcht `placeholder-selected`. + +**Services** +- `app/Services/PressRelease/PressReleaseCoverImage.php` — `coverUrl()`, + `coverIsPlaceholder()`, `placeholder()`. Bevorzugt `is_preview`-Bild, + fällt sonst auf den SVG-Platzhalter zurück. + +**Schema (additive, nullable/Default-Migrationen)** +- `press_releases.placeholder_variant` (string 32, nullable). +- `press_release_images`: `author`, `license_type`, `license_url`, + `persons_consent` (default false), `rights_confirmed_at`. +- `users`: `press_release_quota` (default 3), + `press_release_quota_used_this_month` (default 0). + +**Models** +- `PressRelease`: Cast + `creating`-Hook setzt deterministisch eine + Platzhalter-Variante, wenn keine gesetzt ist. +- `PressReleaseImage`: Lizenz-Felder + `license_type`-Enum-Cast. +- `User`: `pressReleaseQuotaRemaining()`. + +**Service-Hook & Command** +- `PressReleaseService::submitForReview()` zählt + `press_release_quota_used_this_month` des Autors hoch (Stub). +- `app/Console/Commands/ResetMonthlyPressReleaseQuota.php` + + Scheduler-Eintrag (`monthlyOn(1, '00:05')`) in `routes/console.php`. + +**Views** +- Customer-Show + Admin-Show: Hero-Titelbild via Cover-Resolver. +- Customer Create/Edit: Platzhalter-Vorschau + Picker-Einbindung + (`#[On('placeholder-selected')]`). +- Customer-Show: Veröffentlichungs-Modal (`confirm-submit-review`) mit + Rechts-Platzhalter, Kontingent-Badge und 3 Bestätigungs-Checkboxen + (Submit-Button via Alpine disabled bis alle gesetzt). +- Image-Manager: Lizenz-Felder + Anzeige in der Bild-Kachel. + +## Tests (neu) + +- `tests/Feature/PressReleasePlaceholderTest.php` (8) — Enum, Assets, + Picker, Cover-Resolver (Platzhalter + echtes Bild). +- `tests/Feature/PressReleaseImageLicenseTest.php` (3) — Pflichtfelder, + CC-ohne-URL, vollständiger Upload + `rights_confirmed_at`. +- `tests/Feature/PressReleaseQuotaTest.php` (3) — Remaining-Berechnung, + Increment bei Submit, monatlicher Reset. +- `tests/Feature/PressReleasePublishModalPhase8iTest.php` (2) — Modal-Inhalt + (Rechtshinweis + Kontingent), Submit-Flow. + +Gesamt-Suite nach Phase 8: **375 passed, 4 skipped**. Pint clean, +`npm run build:portal` clean. + +## Bewusste Abweichungen / offene Folge-Themen + +- **8H — Upload-Control**: `flux:input type=file` statt `flux:file-upload` + (Pro-Dropzone mit aufwändigem Slot-Aufbau). Funktion identisch, kein + Risiko für den Upload-Flow. Dropzone-Optik ggf. separat nachziehen. +- **8I — Rechtstext** ist ein **Platzhalter** und vor Go-Live anwaltlich + zu prüfen. +- **8J — Quota** ist ein Stub. Die Schnittstelle + `User::pressReleaseQuotaRemaining()` bleibt stabil; das echte + Tarif-/Credit-Modul löst Spalten + Decrement-Logik später ab. +- Offen (Phase 2/3): Stock-/KI-Bildquellen, Wasserzeichen-Check, + Magic-Link-Flow für Pressekontakte, Statistik-/Abrechnungs-Tabs, + Anhänge-Reaktivierung (Security-Audit). diff --git a/dev/frontend/hub-flux/PROGRESS.md b/dev/frontend/hub-flux/PROGRESS.md index 44d252b..b654dc1 100644 --- a/dev/frontend/hub-flux/PROGRESS.md +++ b/dev/frontend/hub-flux/PROGRESS.md @@ -5,6 +5,67 @@ --- +## 2026-05-29 · Phase 8 · User-Panel-Konsolidierung abgeschlossen (8F–8K) ✅ + +Abschluss von Phase 8. Die erste Hälfte (8A–8E: Show-Page-Lücken, +Listen-Indikatoren, Pressekontakt-Warnung, Firmen-Liste auf Mockup-Niveau) +war bereits im Commit „Optimierung der User und Admin Panels" enthalten, +aber undokumentiert. Heute der zweite Block plus Doku-Sync. + +Roadmap-Doc: `20-PHASE-8-USER-PANEL.md`. Plan: `docs/PHASE-8-USER-PANEL-PLAN.md`. + +**8D — Doku-Sync**: `docs/user-admin/checkliste-user-backend.md`, +`docs/STATUS-ABGLEICH-USER-PANEL.md` und `Admin-User.md` auf den +echten IST-Stand gezogen (8A–8E waren als „offen" markiert, sind +aber umgesetzt). + +**8F — SVG-Titelbild-Platzhalter** +- 9 Varianten (3 Muster × 3 Hub-Farben) in + `public/images/press-release-placeholders/`. +- `App\Enums\PressReleasePlaceholder` (Default, Seed-deterministisch). +- `` + Picker-Modal + (`components.press-release-placeholder-picker`, dispatcht + `placeholder-selected`). + +**8G — Titelbild-Schema + Cover-Resolver** +- Migration `placeholder_variant` auf `press_releases` (nullable). +- Model-`creating`-Hook setzt deterministisch eine Variante. +- `App\Services\PressRelease\PressReleaseCoverImage` + (`coverUrl`/`coverIsPlaceholder`). +- Hero-Bild in Customer-/Admin-Show; Vorschau + Picker in Create/Edit. + +**8H — Bild-Upload mit Lizenz-Pflichtfeldern** +- Migration: `author`, `license_type`, `license_url`, + `persons_consent`, `rights_confirmed_at` auf `press_release_images`. +- `App\Enums\ImageLicenseType` (CC/kommerziell erzwingen Lizenz-URL). +- Image-Manager: Urheber (Pflicht), Lizenztyp (Pflicht), Lizenz-URL + (bedingt), Personen-Einwilligung, Rechte-Bestätigung (Pflicht). +- Abweichung: Upload-Control bleibt `flux:input type=file` statt + `flux:file-upload` (Stabilität). Lizenzerfassung vollständig. + +**8J — Quota-Stub (vor 8I, damit Modal darauf aufsetzt)** +- Migration: `users.press_release_quota` (3), + `..._used_this_month` (0). +- `User::pressReleaseQuotaRemaining()`, + Decrement in `PressReleaseService::submitForReview()`. +- Command `press-releases:reset-monthly-quota` + Scheduler + (`monthlyOn(1, '00:05')`). + +**8I — Veröffentlichungs-Modal (Customer-Show)** +- „Zur Prüfung einreichen" öffnet jetzt ein FluxUI-Modal statt + `wire:confirm`: Rechtshinweis (Platzhalter, anwaltlich zu prüfen), + Kontingent-Badge, 3 Bestätigungs-Checkboxen (Submit via Alpine + disabled bis alle gesetzt) → ruft das bestehende `submitForReview()`. + +**8K — Abschluss** +- Neue Tests: `PressReleasePlaceholderTest` (8), + `PressReleaseImageLicenseTest` (3), `PressReleaseQuotaTest` (3), + `PressReleasePublishModalPhase8iTest` (2). +- Suite: **375 passed, 4 skipped**. Pint clean. + `npm run build:portal` clean. + +--- + ## 2026-05-29 · Wartung · Test-Regression-Fix + Phase-7-Doku nachgezogen Review der Gesamt-Umsetzung. Zwei Befunde behoben: diff --git a/docs/Decision-Update Preisstruktur & Veröffentlichungs-Flow.md b/docs/Decision-Update Preisstruktur & Veröffentlichungs-Flow.md new file mode 100644 index 0000000..a57b534 --- /dev/null +++ b/docs/Decision-Update Preisstruktur & Veröffentlichungs-Flow.md @@ -0,0 +1,179 @@ +# Decision-Update · Preisstruktur & Veröffentlichungs-Flow (Launch) + +**Version:** Juni 2026 **Datum:** 11.06.2026 **Status:** Abgestimmt – bereit zur Integration ins Konzept-/Decision-Log **Scope:** Launch-Preisstruktur, PM-Kontingente, Launch-Credit-Umfang, Veröffentlichungs-Flow. Ersetzt die betroffenen Stellen früherer Tarif-Festlegungen (insb. `konzept/Konzept-Update 1` §8–10 und `user-admin/Presseportal – Konzept für Relaunch` §8–10). + +> **IST-Stand 11.06.2026**: Reines Entscheidungs-Dokument, noch nicht +> umgesetzt. Im Code existieren bisher nur der Quota-Stub +> (`users.press_release_quota`, zählt aktuell beim **Einreichen** statt bei +> der Veröffentlichung) und die KI-Klassifikation (Rot/Gelb/Grün, siehe +> `user-admin/Entwicklungsplan KI-Pruefung und Veroeffentlichung.md`). +> Zahlung/Tarife, Submit-Gate hinter Buchung, Slot-Verbrauch bei +> Veröffentlichung, Tageslimit, Einzel-PM und die drei Credit-Posten sind +> offen — siehe Abgleich in `STATUS-ABGLEICH-USER-PANEL.md` §3.5. + +--- + +## 1. Kontext + +Dieses Update bündelt die in der Abstimmung getroffenen Entscheidungen zur Preisstruktur und zum Veröffentlichungs-Flow für den Relaunch. Leitlinie blieb durchgängig die Anti-Zombie-Positionierung: keine versteckten Gebühren, keine künstliche Verknappung, kein Bezahlen für Leistungen, die nicht erbracht wurden. Mehrere ältere Festlegungen wurden bewusst überschrieben (siehe Abschnitt 5). + +--- + +## 2. Finalisierte Tarifstruktur (Launch) + +|Tier|Monatlich|Jährlich|PMs/Monat|Pro PM| +|---|---|---|---|---| +|**Starter**|29 €|290 €|3|9,67 €| +|**Business**|49 €|490 €|10|4,90 €| +|**Pro**|99 €|990 €|25|3,96 €| +|**Agency**|199 €|1.990 €|60|3,32 €| + +**Einzel-PM:** 19 € einmalig – geführt als **separater No-Abo-Block** neben dem Tarif-Raster, nicht als linke/billigste Spalte. Kommunikation über das No-Commitment-Argument („Einmal veröffentlichen, kein Abo, keine Kündigung"), nicht über den Preis. + +**Enterprise:** sichtbar, aber als **dezenter Sales-Hinweis unterhalb der Tabelle** („Größere Mengen oder mehrere Marken? → Kontakt"). Keine eigene Preisspalte, individuelles Pricing. + +--- + +## 3. Mechaniken & Regeln + +### 3.1 Jahrespreis-Kommunikation + +Die Jahrespreise entsprechen exakt **10 Monatsbeiträgen** → kommuniziert als **„2 Monate gratis"** statt als Prozent-Rabatt. Numerisch identisch zu den Bestandszahlen, nur die Darstellung ändert sich. Der konkrete Hebel zieht psychologisch stärker und passt zur Ehrlichkeits-Linie. + +### 3.2 PM-Kontingent: Verbrauch + +**Der PM-Slot zählt ausschließlich bei Veröffentlichung runter, nicht bei der Prüfung.** + +- Rot (abgelehnt) → **kein** Slot verbraucht +- Gelb/Grün (veröffentlicht) → Slot zählt runter + +Begründung: Wer nichts veröffentlicht bekommt, zahlt keinen Slot. Schützt insbesondere ehrliche Nutzer, deren PM erst nach Nachbesserung durchgeht (relevant ab Phase 2). + +### 3.3 Tageslimit (Flut-Schutz) + +Schützt die redaktionelle Glaubwürdigkeit des Portals gegen Dumping, nicht den Umsatz. Greift realistisch nur in den oberen Tiers. + +|Tier|PMs/Monat|Max./Tag| +|---|---|---| +|Starter|3|–| +|Business|10|2| +|Pro|25|3| +|Agency|60|5| + +Das Tageslimit gilt **auch für nachgekaufte Extra-PMs** – sonst würde Extra-PM zum „Spam freikaufen". Höherer Tagesdurchsatz = Enterprise-Fall. + +### 3.4 Einzel → Abo-Brücke + +Wer als Einzel-Käufer innerhalb von 30 Tagen ein Abo abschließt, bekommt die 19 € auf den ersten Monat angerechnet. Schützt das Einmal-Segment und bietet einen sauberen Upgrade-Pfad. + +--- + +## 4. Launch-Credit-System (klein gehalten) + +Zum Launch greifen genau drei Credit-Posten – alle ohne KI-Abhängigkeit, alle mit echtem Nutzen ab Tag 1: + +|Posten|Status|Mechanik| +|---|---|---| +|**Extra-PM**|✅ Launch|Monatskontingent voll → einzelne PM nachkaufbar (faire Alternative zum Zwangs-Upgrade)| +|**Boost / Platzierung**|✅ Launch|Nur für **grüne** PMs, nachträglich kaufbar| +|**Veröffentlichungsnachweis (PDF)**|✅ Launch|Kleiner Mitnahme-Posten, PR-Beleg fürs Reporting| + +**Credit-Anker:** 1 Credit = 1 € (Listenpreis), Volumenrabatt über Pakete. + +**Bewusst ausgeschlossen:** Verkaufte Dofollow-Backlinks. Verstoßen gegen Googles Link-Spam-Richtlinien (Presse-Links gehören auf `nofollow`/`sponsored`) und widersprechen der Ehrlichkeits-Positionierung frontal. + +--- + +## 5. Veröffentlichungs-Flow (Launch) + +``` +Schreiben & „Speichern" → buchen → „Speichern & zur Prüfung einreichen" + (frei) (gegated hinter Buchung) + │ + KI-Prüfung (Red-Flag) + │ + ┌──────────────────────────┼──────────────────────────┐ + ROT GELB GRÜN + abgelehnt veröffentlicht veröffentlicht + kein Slot weg Slot −1 Slot −1 + (Boost nachkaufbar) +``` + +### 5.0 Klarstellung Gelb-Routing (Entscheidung 12.06.2026) + +**Gelb geht zum Launch direkt live — es gibt keine manuelle Prüf-Queue.** +Die Klassifikation kennt nur zwei Ausgänge: + +- **Rot** = Inhalte, die rechtlich oder inhaltlich **nicht veröffentlichbar** + sind → Ablehnung mit Meldung/Begründung an den Autor, kein Slot-Verbrauch. +- **Gelb/Grün** = veröffentlichbar → der Beitrag geht in der ersten Phase + direkt online (sofort bzw. zum geplanten Termin), Slot −1. + +Gelb bleibt als interne Markierung erhalten (z. B. nicht boostbar, Signal +für den Admin), löst aber **keinen** manuellen Review-Schritt aus. Nach dem +Relaunch sind **Vorabprüfungen** geplant (Phase 2, siehe Abschnitt 7), die +Usern die Möglichkeit geben, ihren Beitrag vor der Einreichung zu +korrigieren. + +### 5.1 Zwei-Button-Logik + +- **„Speichern"** – immer frei, auch ohne Buchung. Entwürfe schreiben/ablegen reibungslos, auch _vor_ der Buchung (Conversion-Vorteil: fertige PM senkt Kaufhürde). +- **„Speichern & zur Prüfung einreichen"** – sichtbar, aber gegated. Ohne aktive Buchung öffnet das Modal einen Buchungs-Hinweis statt des Prüf-Flows. Der Button konvertiert, er verschwindet nicht. + +Begründung für den Gate: Die Prüfung ist die erste kostenpflichtige KI-Ressource. Kein gebuchtes Produkt → kein Ressourcenverbrauch. + +### 5.2 Kein Re-Check zum Launch + +Einreichen ist zum Launch eine **Einbahnstraße**: Die PM geht durch (gelb/grün → live) oder wird abgelehnt (rot). Es gibt **keinen** „nachbessern und erneut prüfen"-Loop, weil Redigieren/Vorab-Prüfung erst Phase 2 sind. + +Konsequenz: Pro PM gibt es genau **eine** Prüfung, untrennbar an die Veröffentlichung gekoppelt. Eine eingereichte PM = eine Prüfung = (bei gelb/grün) eine Veröffentlichung. Damit existiert zum Launch **kein Prüf-Abuse-Vektor** → der komplette Prüfzähler-Mechanismus ist zum Launch nicht nötig. + +### 5.3 Keine Gratis-Test-Prüfung + +Harter Gate zum Launch. Eine kostenlose Vorab-Prüfung würde den Flow nur verkomplizieren (wenn eine PM durchgeht, wird sie ohnehin veröffentlicht) und einen Abuse-Vektor öffnen (Wegwerf-Accounts). Eine kontrollierte Test-Prüfung (z. B. pro verifizierter Domain) bleibt als spätere Option offen. + +--- + +## 6. Überschriebene Entscheidungen + +|Bereich|Alt|Neu|Grund| +|---|---|---|---| +|**PM-Kontingent Pro**|60/Monat|**25/Monat**|60 unrealistisch hoch → Overage-System griff nie, Kontingent wirkte faktisch „unbegrenzt"| +|**PM-Kontingent Agency**|150/Monat|**60/Monat**|dito; Kontingente jetzt an realistischer PR-Frequenz kalibriert| +|**Jahrespreis-Kommunikation**|„ca. 17 % Rabatt"|**„2 Monate gratis"**|gleicher Preis, stärkerer psychologischer Hebel, klarer| +|**Bonus-Credits in Tarif-Tabelle**|12/30/60/120 als Tarif-Argument|**entfernt** (→ Phase 2 als Prüf-Kontingent)|bewarb zum Launch eine Leistung ohne Verbrauchsmöglichkeit| + +--- + +## 7. Auf Phase 2 verschoben + +|Punkt|Warum verschoben| +|---|---| +|**Vorab-KI-Prüfung**|erzeugt erst die Situation „prüfen ohne (noch) zu veröffentlichen"| +|**Redigieren / Nachbearbeiten**|setzt Re-Check-Loop voraus| +|**Prüfzähler** (freie Prüfungen/Monat, z. B. 12/30/60/120, eigener Zähler)|erst mit Re-Check relevant; deckelt dann „prüfen ohne veröffentlichen"| +|**Credit-Overflow für Prüfungen**|Prüfzähler leer → weitere Prüfungen ziehen aus echter Credit-Wallet| +|**Klon-/Abuse-Schutz über Account-Monatslimit**|aggregiertes Limit pro Account statt Klon-Erkennung; greift erst bei Re-Check| +|**Score-Feinstufung für Boost**|„nur Geprüft/Hochwertig boostbar" – setzt vollen Content-Score voraus| +|**Tier-gestaffelte Prüf-Versuche**|als „BALD" markiert; zum Launch flach| + +**Designprinzip für Phase 2 festgehalten:** Eigener **Prüf-Zähler** (getrennt von der Credit-Wallet), damit „Prüfungen inklusive" ein sauberes Versprechen bleibt und Prüf-Budget nicht versehentlich für Boost/PDF verbraucht wird. Abuse-Schutz über aggregiertes Account-Monatslimit + Prüf-Tageslimit – nicht über Klon-Erkennung. + +--- + +## 8. Offene Stellschrauben (vor Phase-2-Bau zu entscheiden) + +- **Boost-Nachkaufpreis** relativ zum inkludierten PM-Preis – klar darüber (treibt Upgrade) oder nur leicht darüber (bequemer, schwächerer Upgrade-Sog). +- **Höhe des Prüf-Kontingents** je Tier final bestätigen, sobald Vorab-Prüfung gebaut wird (Ausgangsvorschlag 12/30/60/120). +- **Credit-Paketliste** auf Konsistenz prüfen (vom Nutzer angekündigt, separat einzubringen). + +--- + +## 9. Anti-Zombie-Check (dieser Stand) + +- ✅ Keine versteckten Gebühren – Extra-PM und Boost sind sichtbare, optionale Zukäufe +- ✅ Keine künstliche Verknappung – Kontingente decken den Normalfall bequem; Limits greifen nur bei echtem Power-/Abuse-Verhalten +- ✅ Kein Bezahlen für nicht erbrachte Leistung – rot abgelehnte PM verbraucht keinen Slot +- ✅ Tageslimit als Qualitätsschutz fürs Portal begründet, nicht als Verkaufstrick +- ✅ Kein verkaufter Dofollow-Backlink +- ✅ Free schreiben, Gate erst beim Einreichen – Friktion an der richtigen Stelle \ No newline at end of file diff --git a/docs/PHASE-8-USER-PANEL-PLAN.md b/docs/PHASE-8-USER-PANEL-PLAN.md index 05a997b..2839012 100644 --- a/docs/PHASE-8-USER-PANEL-PLAN.md +++ b/docs/PHASE-8-USER-PANEL-PLAN.md @@ -1,8 +1,15 @@ # Phase 8 · User-Panel-Konsolidierung & Pressemitteilungs-Lifecycle -Stand: 2026-05-21 +Stand: 2026-05-29 — **abgeschlossen** (alle Päckchen 8A–8K umgesetzt). Vorgänger: Phase 7 (Press-Release-Form-Refactor — abgeschlossen) Abgleich-Doku: [`docs/STATUS-ABGLEICH-USER-PANEL.md`](./STATUS-ABGLEICH-USER-PANEL.md) +Roadmap-Abschluss: [`dev/frontend/hub-flux/20-PHASE-8-USER-PANEL.md`](../dev/frontend/hub-flux/20-PHASE-8-USER-PANEL.md) + +> **Status 29.05.2026**: Alle Sub-Päckchen abgeschlossen. Bewusste +> Abweichung in 8H: Upload-Control bleibt `flux:input type=file` statt +> `flux:file-upload` (Stabilität); die Lizenz-Pflichtfelder sind vollständig +> umgesetzt. Der Rechtstext im Veröffentlichungs-Modal (8I) ist ein +> Platzhalter und vor Go-Live anwaltlich zu prüfen. --- @@ -579,18 +586,18 @@ und Schema-Änderungen mitbringen. ## 6. Akzeptanzkriterien Phase 8 gesamt -- [ ] Customer-Show + Admin-Show stellen alle Phase-7-Felder dar -- [ ] PM-Listen markieren Scheduling und Embargo -- [ ] Pressekontakt-Sidebar warnt bei leerer Auswahl -- [ ] `docs/user-admin/*` ist mit dem Code synchron -- [ ] Firmen-Liste entspricht dem Mockup zu ≥ 90 % -- [ ] Jede PM hat ein sichtbares Hero-Bild (echtes oder Platzhalter) -- [ ] Image-Upload erfasst Urheber + Lizenz-Typ + Rechte-Bestätigung -- [ ] „Zur Prüfung einreichen" erfordert eine bewusste Modal-Bestätigung -- [ ] Quota-Counter inkrementiert pro Einreichung, resettet monatlich -- [ ] Tests grün (außer pre-existing `ApiDocumentationTest`) -- [ ] Pint clean, Build clean -- [ ] Roadmap-Eintrag und `PROGRESS.md`-Block geschrieben +- [x] Customer-Show + Admin-Show stellen alle Phase-7-Felder dar +- [x] PM-Listen markieren Scheduling und Embargo +- [x] Pressekontakt-Sidebar warnt bei leerer Auswahl +- [x] `docs/user-admin/*` ist mit dem Code synchron +- [x] Firmen-Liste entspricht dem Mockup zu ≥ 90 % +- [x] Jede PM hat ein sichtbares Hero-Bild (echtes oder Platzhalter) +- [x] Image-Upload erfasst Urheber + Lizenz-Typ + Rechte-Bestätigung +- [x] „Zur Prüfung einreichen" erfordert eine bewusste Modal-Bestätigung +- [x] Quota-Counter inkrementiert pro Einreichung, resettet monatlich +- [x] Tests grün (375 passed, 4 skipped — inkl. pre-existing `ApiDocumentationTest`) +- [x] Pint clean, Build clean +- [x] Roadmap-Eintrag und `PROGRESS.md`-Block geschrieben --- diff --git a/docs/PHASE-9-FLOW-UND-TARIFE-PLAN.md b/docs/PHASE-9-FLOW-UND-TARIFE-PLAN.md new file mode 100644 index 0000000..cbb5600 --- /dev/null +++ b/docs/PHASE-9-FLOW-UND-TARIFE-PLAN.md @@ -0,0 +1,224 @@ +# Phase 9 · Veröffentlichungs-Flow (Launch) & Tarif-Modul + +Stand: 2026-06-12 — **in Umsetzung** (Block 1: 9A–9C zuerst, dann Review-Stopp, +dann Block 2: 9D–9J). +Vorgänger: Phase 8 (User-Panel-Konsolidierung) + KI-Prüf-Pipeline (beide abgeschlossen). +Verbindliche Entscheidungen: [`docs/Decision-Update Preisstruktur & Veröffentlichungs-Flow.md`](./Decision-Update%20Preisstruktur%20&%20Ver%C3%B6ffentlichungs-Flow.md) +Abgleich-Doku: [`docs/STATUS-ABGLEICH-USER-PANEL.md`](./STATUS-ABGLEICH-USER-PANEL.md) + +--- + +## 0. Worum es geht + +Phase 9 setzt das Decision-Update vom 11./12.06.2026 um — in zwei Blöcken: + +1. **Block 1 — Veröffentlichungs-Flow (9A–9C)**: Die Flow-Regeln, die + unabhängig vom Tarif-Modul gelten und auf denen das Tarif-Modul aufsetzt. + Funktioniert vollständig mit dem vorhandenen Quota-Stub. +2. **Block 2 — Tarif-Modul (9D–9I)**: Zahlung, Tarife, Einzel-PM, Tageslimit + und die drei Launch-Credit-Posten. Löst den Quota-Stub ab. + +**Leitplanken aus dem Decision-Update:** + +- Gelb geht zum Launch **direkt live** wie Grün — keine manuelle Prüf-Queue. + Nur Rot wird abgelehnt (Meldung mit Begründung an den Autor). +- Der PM-Slot zählt **bei Veröffentlichung** runter, nicht bei der Prüfung. + Rot verbraucht keinen Slot. +- „Speichern" bleibt immer frei; „Speichern & zur Prüfung einreichen" ist + hinter eine aktive Buchung gegated (der Button konvertiert, er verschwindet + nicht). +- Kein Re-Check zum Launch: eine Einreichung = eine Prüfung = (bei Gelb/Grün) + eine Veröffentlichung. Vorab-Prüfung/Redigieren sind Phase 2. + +--- + +## 1. Sub-Päckchen-Übersicht + +| ID | Thema | Größe | Risiko | +|---|---|---|---| +| **9A** | Gelb-Routing auf Direkt-Live umstellen (Routing, Scheduler, Tests) | S | gering | +| **9B** | Slot-Verbrauch von Einreichung auf Veröffentlichung umstellen (Rot = kein Slot) | M | mittel (Idempotenz) | +| **9C** | Submit-Gate-Schnittstelle (`hasActiveBooking()`-Stub, Modal-Hinweis, Server-Guard) | M | gering | +| — | **Review-Stopp mit User** | | | +| **9D** | Tarif-Datenmodell: Pläne, Subscriptions, Einzel-PM-Käufe; Quota-Stub ablösen | L | hoch (Datenmodell) | +| **9E** | Stripe-Anbindung (Laravel Cashier — **Dependency-Freigabe nötig**) | L | mittel | +| **9F** | Tarif-Seite + Checkout-UI (Raster, Einzel-PM-Block, „2 Monate gratis", Enterprise-Hinweis) | M | gering | +| **9G** | Tageslimit je Tier (Business 2 / Pro 3 / Agency 5; gilt auch für Extra-PMs) | S | gering | +| **9H** | Einzel-PM-Kauf (19 €) + Einzel→Abo-Brücke (Anrechnung 30 Tage) | M | mittel | +| **9I** | Launch-Credits: Extra-PM, Boost (nur Grün), Veröffentlichungsnachweis-PDF | L | mittel | +| **9J** | Abschluss: Tests, Pint, Build, Doku-Sync, PROGRESS-Eintrag | S | keine | + +Nach jedem Päckchen Review-Stopp mit dem User; vor 9D ein größerer +(Datenmodell-Entscheidungen + Cashier-Freigabe). + +--- + +## 2. Block 1 — Veröffentlichungs-Flow + +### 9A · Gelb-Routing auf Direkt-Live + +**Entscheidung (12.06.2026)**: Rot = nicht veröffentlichbar (rechtlich/ +inhaltlich) → Ablehnung mit Meldung. Gelb/Grün = veröffentlichbar → geht in +der ersten Phase direkt online. Gelb bleibt als interne Markierung erhalten +(nicht boostbar, Admin-Signal), löst aber keine manuelle Prüfung aus. + +**Anpassungen:** + +- `PressReleaseService::routeByClassification()`: Gelb durchläuft denselben + Auto-Publish-Pfad wie Grün (`autoPublishGreen()` → generalisiert zu + `autoPublishApproved()`); Verzögerungsfenster + (`scoring.classification.green_delay_minutes`) gilt für beide. +- `PublishScheduledPressReleases`: Kandidaten-Query von + `classification = green` auf `classification IN (green, yellow)`. +- Admin-Review-Queue bleibt als **Fallback** bestehen: unklassifizierte PMs + (Job noch nicht gelaufen / KI-Ausfall ohne Fallback-Ergebnis) bleiben in + `review` und sind manuell behandelbar. KI-Badge und Klassifikations-Filter + im Admin bleiben unverändert. + +**Tests:** `PressReleaseClassificationJobTest` (Gelb-sofort → published, +Gelb-geplant → bleibt review bis Termin), `PressReleaseSchedulingTest` +(gelbe fällige PM wird publiziert). + +### 9B · Slot-Verbrauch bei Veröffentlichung + +**Regel:** Der Slot zählt genau einmal pro PM, beim **ersten** Übergang zu +`published`. Rot abgelehnte PMs verbrauchen nichts. + +**Anpassungen:** + +- `submitForReview()`: Increment von `press_release_quota_used_this_month` + **entfernen**. Stattdessen Guard: Einreichen erfordert + `pressReleaseQuotaRemaining() > 0` (sonst würde eine grüne PM ohne + verfügbaren Slot veröffentlicht). +- `publish()`: Increment beim Statuswechsel auf `published`, idempotent — + nur wenn die PM zuvor noch nie veröffentlicht war (Prüfung über + `press_release_status_logs`, kein neues Schema-Feld). Zählt auf den + PM-Eigentümer (`user_id`). +- Veröffentlichungs-Modal: Text von „wird bei Einreichung verbraucht" auf + „wird bei Veröffentlichung verbraucht; abgelehnte PMs kosten keinen Slot". + +**Tests:** Submit verbraucht keinen Slot; Publish (Admin, Auto-Publish, +Scheduler) verbraucht genau einen; Rot → kein Verbrauch; Archivieren + +erneutes Publizieren zählt nicht doppelt; Submit bei 0 Rest-Slots blockiert. + +### 9C · Submit-Gate-Schnittstelle + +**Ziel:** Das Gate aus dem Decision-Update §5.1, gebaut gegen eine schmale +Schnittstelle, die zunächst ein Stub bedient und in 9D/9E vom Tarif-Modul +implementiert wird — Modal und Service müssen dann nicht mehr angefasst werden. + +**Anpassungen:** + +- `User::hasActiveBooking(): bool` — Launch-Schnittstelle. Stub-Verhalten + über `config/billing.php` (`billing.enforce_booking`, Default `false`): + solange das Tarif-Modul fehlt, gibt die Methode `true` zurück; mit + aktiviertem Flag (und später echter Subscription-Prüfung) greift das Gate. +- Einreichungs-Modal (`press-release-submit-modal`): ohne aktive Buchung + zeigt das Modal statt des Prüf-Flows einen Buchungs-Hinweis mit CTA + („Buchung erforderlich" → Tarif-Seite). Der Button bleibt sichtbar. +- Server-Guard: `submitForReview()` wirft ohne aktive Buchung eine Exception + (UI allein reicht nicht); API-Submit-Route antwortet mit **402**. + +**Tests:** Gate aus (Default) → Verhalten unverändert; Gate an → +Modal-Hinweis statt Checkboxen, `submitForReview` wirft, API gibt 402. + +--- + +## 3. Block 2 — Tarif-Modul (nach Review-Stopp) + +### 9D · Tarif-Datenmodell + +- Tabellen (Arbeitsstand, final beim Review-Stopp vor 9D): + `plans` (Starter/Business/Pro/Agency: Preis mtl./jährl., PMs/Monat, + Tageslimit), `subscriptions` (User, Plan, Zyklus, Status, Periodenstart/-ende), + `single_purchases` (Einzel-PM, Extra-PM, Boost, PDF — Typ, Preis, Status, + `applied_to_press_release_id`). +- `User::hasActiveBooking()` prüft echte Subscription oder offenen Einzel-PM-Kauf. +- Slot-Logik wechselt von `users.press_release_quota` auf Plan-Kontingent + + Periodenzähler; Stub-Spalten werden nach Migration entfernt. +- Kontingent-Anzeige (Modal, Editor) liest aus der neuen Quelle — + Schnittstelle `pressReleaseQuotaRemaining()` bleibt stabil. + +### 9E · Stripe (Laravel Cashier) + +- **Vor Start freizugeben:** `laravel/cashier` als neue Dependency. +- Checkout für Abo (monatlich/jährlich) und Einmalzahlung (Einzel-PM, Credits). +- Webhooks (Subscription-Status, Zahlungsausfall) + lokale Spiegelung. +- Rechnungen an bestehende `invoices`-Struktur anbinden (Klärung beim Review). + +### 9F · Tarif-Seite + Checkout-UI + +- Raster mit 4 Tiers; Einzel-PM als separater No-Abo-Block (nicht als + billigste Spalte); Enterprise als dezenter Sales-Hinweis unter der Tabelle. +- Jahrespreis kommuniziert als „2 Monate gratis". +- Einstieg aus dem Submit-Gate-Hinweis (9C) und aus „Buchungen & Add-ons". + +### 9G · Tageslimit + +- `plans.daily_limit` (Starter ohne Limit); Prüfung beim Veröffentlichen + (nicht beim Einreichen), zählt veröffentlichte PMs des Users pro Kalendertag + (Europe/Berlin); gilt auch für Extra-PMs. Überschreitung → PM bleibt in + `review` mit Hinweis, Veröffentlichung am Folgetag durch den Scheduler. + +### 9H · Einzel-PM + Abo-Brücke + +- Einzel-PM-Kauf 19 € → genau eine Einreichung/Veröffentlichung. +- Brücke: Abo-Abschluss innerhalb 30 Tagen rechnet 19 € auf den ersten + Monat an (Stripe-Coupon oder Rabatt-Position). + +### 9I · Launch-Credits + +- Credit-Wallet (1 Credit = 1 € Listenpreis, Pakete mit Volumenrabatt). +- Posten: **Extra-PM** (Kontingent voll → einzelne PM nachkaufen), + **Boost** (nur für grün klassifizierte PMs, nachträglich), + **Veröffentlichungsnachweis-PDF**. +- Kein Dofollow-Backlink-Verkauf (bewusst ausgeschlossen). + +### 9J · Abschluss + +- Volle Suite grün, Pint clean, `npm run build` clean. +- Doku-Sync: `STATUS-ABGLEICH`, `checkliste-user-backend.md`, dieses Dokument, + `PROGRESS.md`-Eintrag. + +--- + +## 4. Was außerhalb von Phase 9 bleibt + +- Vorab-KI-Prüfung, Redigieren/Re-Check-Loop, Prüfzähler, Credit-Overflow + (Decision-Update §7 — Phase 2) +- Score-Feinstufung für Boost („nur Geprüft/Hochwertig boostbar") +- Magic-Link-Flow, Statistik-/Abrechnungs-Tabs, Anhänge-Reaktivierung, + Trust-Score, Notice-and-Action + +--- + +## 5. Risiken & Annahmen + +- **Idempotenz Slot-Verbrauch (9B)**: Prüfung über Status-Logs statt neuem + Feld — bei Alt-Daten mit unvollständigen Logs schlimmstenfalls ein + doppelter Zähler; akzeptabel für den Stub, wird mit 9D-Periodenzähler + sauber. +- **Gate-Stub (9C)**: `enforce_booking=false` als Default hält das System + bis zum Tarif-Modul voll funktionsfähig; das Flag erlaubt Tests und + frühe Aktivierung. +- **9D/9E Datenmodell + Cashier**: größter Block, eigener Review-Stopp davor; + Stub-Ablösung (`press_release_quota`-Spalten entfernen) erst nach + verifizierter Migration. +- **Rechtstexte** (Einreichungs-Modal) sind weiterhin Platzhalter — + anwaltliche Prüfung läuft parallel, unabhängig von Phase 9. +- **Betrieb**: Queue-Worker für `classification` in Produktion bleibt + Go-Live-Voraussetzung (unabhängig von Phase 9). + +--- + +## 6. Akzeptanzkriterien Phase 9 gesamt + +- [ ] Gelb klassifizierte PMs gehen ohne manuelle Prüfung live (sofort/Termin) +- [ ] Rot verbraucht keinen Slot; Slot zählt genau einmal, bei Veröffentlichung +- [ ] Einreichen ohne aktive Buchung zeigt Buchungs-Hinweis (UI) und wird + serverseitig abgelehnt (Gate aktiviert) +- [ ] Tarife buchbar (4 Tiers, monatlich/jährlich), Einzel-PM kaufbar +- [ ] Tageslimit greift je Tier, auch für Extra-PMs +- [ ] Extra-PM, Boost (nur Grün) und PDF-Nachweis als Credits kaufbar +- [ ] Quota-Stub vollständig abgelöst, `pressReleaseQuotaRemaining()` stabil +- [ ] Tests grün, Pint clean, Build clean, Doku synchron diff --git a/docs/README.md b/docs/README.md index 5901995..75f55bf 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,8 @@ # `docs/` — Konzept- und Status-Dokumente -Stand: 21.05.2026 — nach Phase 7 (PM-Form-Refactor) und vor Phase 8 (User-Panel-Konsolidierung). +Stand: 11.06.2026 — Phase 8 (User-Panel-Konsolidierung) und die KI-Prüf-Pipeline +(Klassifikation + Content-Score, Phasen 0–5) sind abgeschlossen. Nächster großer +Block: Zahlung/Tarife + Veröffentlichungs-Flow laut Decision-Update. Diese README ist der schnellste Einstieg in den `docs/`-Ordner. Sie verlinkt die zentralen Dokumente und sortiert sie nach „Was ist der aktuelle Stand?" vs. „Was ist konzeptueller Zielzustand?". @@ -10,55 +12,67 @@ Sie verlinkt die zentralen Dokumente und sortiert sie nach „Was ist der aktuel | Frage | Doku | |---|---| | Was ist im Code, was ist Konzept, was fehlt? | [`STATUS-ABGLEICH-USER-PANEL.md`](./STATUS-ABGLEICH-USER-PANEL.md) | -| Wie geht es als Naechstes weiter? | [`PHASE-8-USER-PANEL-PLAN.md`](./PHASE-8-USER-PANEL-PLAN.md) | -| Was ist Phase 1 + Phase 7 (User Backend, Pressemitteilungs-Form)? | [`user-admin/checkliste-user-backend.md`](./user-admin/checkliste-user-backend.md) | +| Was gilt für Preise, Kontingente und den Veröffentlichungs-Flow zum Launch? | [`Decision-Update Preisstruktur & Veröffentlichungs-Flow.md`](./Decision-Update%20Preisstruktur%20&%20Ver%C3%B6ffentlichungs-Flow.md) | +| Wie wird das umgesetzt (aktueller Plan)? | [`PHASE-9-FLOW-UND-TARIFE-PLAN.md`](./PHASE-9-FLOW-UND-TARIFE-PLAN.md) | +| Wie funktioniert die KI-Prüfung (Klassifikation, Score, Audit)? | [`user-admin/Entwicklungsplan KI-Pruefung und Veroeffentlichung.md`](./user-admin/Entwicklungsplan%20KI-Pruefung%20und%20Veroeffentlichung.md) | +| Was ist pro Phase erledigt, was offen? | [`user-admin/checkliste-user-backend.md`](./user-admin/checkliste-user-backend.md) | | Welche Hub-Flux-Phasen sind durch? | [`../dev/frontend/hub-flux/PROGRESS.md`](../dev/frontend/hub-flux/PROGRESS.md) | -| Was ist die Phase-7-Detail-Doku? | [`../dev/frontend/hub-flux/19-PHASE-7-PRESS-RELEASE-FORM.md`](../dev/frontend/hub-flux/19-PHASE-7-PRESS-RELEASE-FORM.md) | ## Aufbau -### `user-admin/` +### Top-Level — Status & Entscheidungen -Konzept und Status-Dokumentation fuer das User- und Admin-Backend. -Jede Seite hat oben einen Verweis auf den aktuellen Code-Stand und referenziert den Abgleich. +- [`STATUS-ABGLEICH-USER-PANEL.md`](./STATUS-ABGLEICH-USER-PANEL.md) — Konzept-vs-Code-Vergleich pro Page. **Erste Anlaufstelle.** +- [`Decision-Update Preisstruktur & Veröffentlichungs-Flow.md`](./Decision-Update%20Preisstruktur%20&%20Ver%C3%B6ffentlichungs-Flow.md) — **Verbindlicher Launch-Stand** für Tarife, PM-Kontingente, Credits und Veröffentlichungs-Flow. Überschreibt die Tarif-Abschnitte (§8–10) in `Konzept-Update 1` und im Relaunch-Konzept. +- [`PHASE-9-FLOW-UND-TARIFE-PLAN.md`](./PHASE-9-FLOW-UND-TARIFE-PLAN.md) — **Aktueller Umsetzungsplan**: Veröffentlichungs-Flow (9A–9C) + Tarif-Modul (9D–9J). +- [`PHASE-8-USER-PANEL-PLAN.md`](./PHASE-8-USER-PANEL-PLAN.md) — Plan der Phase 8 (abgeschlossen 29.05.2026, als Referenz erhalten). +- [`Echte öffentliche Unterseiten.md`](./Echte%20%C3%B6ffentliche%20Unterseiten.md) — Sitemap-Konzept, jede Seite mit IST-Notiz. +- [`KI-UND-ENTWICKLER-WORKFLOW.md`](./KI-UND-ENTWICKLER-WORKFLOW.md) — Workflow für KI-/Entwickler-Sessions. -- [`Admin-User.md`](./user-admin/Admin-User.md) — Hauptdokument zum User-/Admin-Backend, Phase 1 + Phase 7 zusammengefasst, Phase 8 verlinkt. -- [`checkliste-user-backend.md`](./user-admin/checkliste-user-backend.md) — Erledigt/Offen-Liste pro Phase. +### `user-admin/` — User-/Admin-Backend + +Konzept und Status-Dokumentation für das User- und Admin-Backend. + +- [`Admin-User.md`](./user-admin/Admin-User.md) — Hauptdokument zum User-/Admin-Backend (Navigation, Firmen-Detail, Rollen). +- [`checkliste-user-backend.md`](./user-admin/checkliste-user-backend.md) — Erledigt/Offen-Liste pro Phase (1, 7, 8, KI-Pipeline). +- [`Entwicklungsplan KI-Pruefung und Veroeffentlichung.md`](./user-admin/Entwicklungsplan%20KI-Pruefung%20und%20Veroeffentlichung.md) — KI-Klassifikation (Rot/Gelb/Grün), Content-Score, Audit-Log; Phasen 0–5 umgesetzt (11.06.2026). +- [`Umsetzung Pressemitteilung Bearbeitung Titelbild Veroeffentlichung.md`](./user-admin/Umsetzung%20Pressemitteilung%20Bearbeitung%20Titelbild%20Veroeffentlichung.md) — Umsetzungs-Notiz (11.06.2026): Titelbild/Cover, Lizenzformular, Zeitzonen-Handling, vereinfachte Veröffentlichungs-Box. +- [`Lizenztyp Bildupload.md`](./user-admin/Lizenztyp%20Bildupload.md) — Fachvorgabe für die Lizenz-/Rechtefelder beim Bildupload (umgesetzt). - [`user-zusammenhaenge.md`](./user-admin/user-zusammenhaenge.md) — Datenmodell-Mapping, Models, Services und Commands. -- [`Presseportal – Konzept für Relaunch.md`](./user-admin/Presseportal%20%E2%80%93%20Konzept%20f%C3%BCr%20Relaunch.md) — Zielzustand der Plattform (KI-Workflow, Bilder, Notice-and-Action, DSGVO, Magic-Link, Tarife, Korrektur-Modell). Jeder Abschnitt hat eine **IST-Stand-Box**. +- [`Presseportal – Konzept für Relaunch.md`](./user-admin/Presseportal%20%E2%80%93%20Konzept%20f%C3%BCr%20Relaunch.md) — Zielzustand der Plattform (KI-Workflow, Bilder, Notice-and-Action, DSGVO, Magic-Link, Tarife, Korrektur-Modell). Jeder Abschnitt hat eine **IST-Stand-Box**; die Tarif-Abschnitte sind durch das Decision-Update überschrieben. -### `konzept/` +### `konzept/` — Strategie & Marke Strategische Konzepte und Updates. Sie beschreiben Themen, die teilweise oder noch gar nicht gebaut sind. Jedes Update hat oben einen IST-Stand-Hinweis. +- [`Konzept Presseportal – Marktposition & Hebel.md`](./konzept/Konzept%20Presseportal%20%E2%80%93%20Marktposition%20&%20Hebel.md) — Marktanalyse und Positionierung (Anti-Zombie-Linie). - [`Entwicklungs-Konzept - Frontend-Komponenten Multi-Brand.md`](./konzept/Entwicklungs-Konzept%20-%20Frontend-Komponenten%20Multi-Brand.md) — Multi-Brand-Architektur (umgesetzt). -- [`Konzept-Update 1 – Überarbeitete Abschnitte.md`](./konzept/Konzept-Update%201%20%E2%80%93%20%C3%9Cberarbeitete%20Abschnitte.md) — Tarife, Credits, Score (noch nicht umgesetzt). -- [`Konzept-Update 2 – Score-Stufen-System.md`](./konzept/Konzept-Update%202%20%E2%80%93%20Score-Stufen-System.md) — Drei-Stufen-Score (noch nicht umgesetzt). - -### Top-Level - -- [`STATUS-ABGLEICH-USER-PANEL.md`](./STATUS-ABGLEICH-USER-PANEL.md) — Konzept-vs-Code-Vergleich pro Page. -- [`PHASE-8-USER-PANEL-PLAN.md`](./PHASE-8-USER-PANEL-PLAN.md) — Detail-Plan der naechsten Sub-Paeckchen. -- [`Echte öffentliche Unterseiten.md`](./Echte%20%C3%B6ffentliche%20Unterseiten.md) — Sitemap-Konzept, jede Seite mit IST-Notiz. -- [`KI-UND-ENTWICKLER-WORKFLOW.md`](./KI-UND-ENTWICKLER-WORKFLOW.md) — Workflow fuer KI-/Entwickler-Sessions. +- [`Konzept-Update 1 – Überarbeitete Abschnitte.md`](./konzept/Konzept-Update%201%20%E2%80%93%20%C3%9Cberarbeitete%20Abschnitte.md) — Tarife/Credits (§8–10 **überschrieben durch Decision-Update**), Score-Architektur §15 (Klassifikation + Content-Score umgesetzt, Trust-Score offen), Boost §16, Tool-Loop §17. +- [`Konzept-Update 2 – Score-Stufen-System.md`](./konzept/Konzept-Update%202%20%E2%80%93%20Score-Stufen-System.md) — Drei-Stufen-Score (Backend umgesetzt; öffentliche Badges im Web-Frontend offen). +- [`Konzept-Update 3 – Multi-Brand-Architektur (Hub & Spoke).md`](./konzept/Konzept-Update%203%20%E2%80%93%20Multi-Brand-Architektur%20(Hub%20&%20Spoke).md) — Hub-&-Spoke-Markenarchitektur. +- [`Konzept-Update 4 - Positionierung + Markenversprechen.md`](./konzept/Konzept-Update%204%20-%20Positionierung%20+%20%20Markenversprechen.md) — Positionierung und Markenversprechen. +- [`Konzept-X - Brand-Landing.md`](./konzept/Konzept-X%20-%20Brand-Landing.md) — Brand-Landing-Konzept. ## Lesehilfe -In den ueberarbeiteten Dokumenten finden sich folgende Markierungen: +In den überarbeiteten Dokumenten finden sich folgende Markierungen: | Marker | Bedeutung | |---|---| -| **IST-Stand JJJJ-MM-TT** | Kompakte Notiz oben am Abschnitt, was im Code tatsaechlich umgesetzt ist. | -| Phase 1 / Phase 7 / Phase 8 | Verweis auf die aktuelle Roadmap. Phase 1 = Grund-User-Backend; Phase 7 = PM-Form-Refactor; Phase 8 = User-Panel-Konsolidierung. | +| **IST-Stand JJJJ-MM-TT** | Kompakte Notiz oben am Abschnitt, was im Code tatsächlich umgesetzt ist. | +| Phase 1 / Phase 7 / Phase 8 | Abgeschlossene Roadmap-Blöcke: Grund-User-Backend, PM-Form-Refactor, User-Panel-Konsolidierung. | +| KI-Pipeline (Phasen 0–5) | Klassifikation, Routing, Content-Score — abgeschlossen 11.06.2026, siehe Entwicklungsplan. | | Hub-Flux | Visuelle Migrationsphase des User Backends, gepflegt in `dev/frontend/hub-flux/`. | -| Phase 2 / Phase 3 | Spaeter — Magic-Link-Flow, KI-Vorpruefung, Tarif-Modul, Score, Notice-and-Action. | +| Phase 2 / Phase 3 | Später — Magic-Link-Flow, Re-Check/Redigieren, Trust-Score, Notice-and-Action, Statistik. | +| Launch-Block (offen) | Zahlung/Tarife, Submit-Gate, Slot-Verbrauch bei Veröffentlichung — siehe Decision-Update. | ## Wie pflegen wir die Doku? -- Wenn sich der Code so weit aendert, dass ein Konzept-Abschnitt nicht mehr stimmt, kommt eine **IST-Stand-Box** an den Abschnitt, statt den Konzept-Text zu loeschen. So bleibt die urspruengliche Zielvorstellung lesbar. +- Wenn sich der Code so weit ändert, dass ein Konzept-Abschnitt nicht mehr stimmt, kommt eine **IST-Stand-Box** an den Abschnitt, statt den Konzept-Text zu löschen. So bleibt die ursprüngliche Zielvorstellung lesbar. +- Entscheidungen, die frühere Konzept-Festlegungen ersetzen, kommen als eigenes **Decision-Update** auf Top-Level; die überschriebenen Abschnitte bekommen einen Verweis darauf. - Jeder Phasen-Abschluss aktualisiert - `user-admin/checkliste-user-backend.md` (Erledigt-Block), - `STATUS-ABGLEICH-USER-PANEL.md` (Abgleich), - `dev/frontend/hub-flux/PROGRESS.md` (Tagebuch), - und ggf. die Detail-Doku in `dev/frontend/hub-flux/`. -- Neue grosse Themen bekommen ein eigenes Plan-Dokument auf `docs/`-Top-Level (z. B. `PHASE-8-USER-PANEL-PLAN.md`). +- Neue große Themen bekommen ein eigenes Plan-Dokument auf `docs/`-Top-Level (z. B. `PHASE-8-USER-PANEL-PLAN.md`). diff --git a/docs/STATUS-ABGLEICH-USER-PANEL.md b/docs/STATUS-ABGLEICH-USER-PANEL.md index a537ab1..ecb6eb4 100644 --- a/docs/STATUS-ABGLEICH-USER-PANEL.md +++ b/docs/STATUS-ABGLEICH-USER-PANEL.md @@ -1,6 +1,9 @@ # Status-Abgleich · User Panel -Stand: 2026-05-21 +Stand: 2026-06-11 (Phase 8 vollständig abgeschlossen; KI-Prüf-Pipeline +Phasen 0–5 umgesetzt; Titelbild-/Lizenz-/Zeitzonen-Umbau vom 10./11.06. +eingearbeitet. Preise & Veröffentlichungs-Flow: siehe +[`Decision-Update Preisstruktur & Veröffentlichungs-Flow.md`](./Decision-Update%20Preisstruktur%20&%20Ver%C3%B6ffentlichungs-Flow.md)) > Dieses Dokument vergleicht die Konzept-Dokumente im Ordner `docs/` mit dem > tatsächlichen Code-Stand. Es dient als Single Source of Truth für die @@ -52,7 +55,7 @@ Stand: 2026-05-21 | Filter ohne Firma, Status, Portal | `statusFilter`, `portalFilter`, `companyFilter` aktiv | ✅ | | Filter-Presets (`user_filter_presets`) | **fehlt** | 📝 (in Phase 2 lt. Doku — bleibt pending) | | PM-Detail Tab „Verlauf" aus `press_release_status_logs` | als „Status & Verlauf"-Card eingebaut, nicht als eigener Tab | 🔄 (Doku-Anpassung: Card statt Tab; funktional gleichwertig) | -| Hinweis Scheduling/Embargo in der Liste | **fehlt** | 📝 (s. eigener Gap-Block unten) | +| Hinweis Scheduling/Embargo in der Liste | umgesetzt (Sub-Label „geplant · …" / „Embargo bis …" in der Datums-Spalte, `index.blade.php` Z. 505–514) | ✅ (Phase 8B) | ### Pressemitteilungs-Forms @@ -62,10 +65,12 @@ Stand: 2026-05-21 | Pflichtfeld `company_id` für Customer | Validation `required` | ✅ | | Portal aus Firma abgeleitet (Customer) | `updatedCompanyId()` setzt `portal` aus `company->portal` | ✅ | | `subtitle`-Feld | seit Phase 7 da | ❓ (im Konzept nicht erwähnt, aber sinnvoll) | -| `scheduled_at`, `embargo_at`-Felder im Form | seit Phase 7F da | ❓ (im Konzept nicht beschrieben) | +| `scheduled_at`, `embargo_at`-Felder im Form | `scheduled_at` da (Datum via `flux:date-picker` + Uhrzeit via `flux:time-picker`, Eingabe/Anzeige in Europe/Berlin, Speicherung UTC). **Embargo aus der Form-UI entfernt** (11.06.) — `embargo_at` bleibt im Schema, wird beim Speichern auf `null` geführt | 🔄 (bewusste Vereinfachung; Doku: `Umsetzung Pressemitteilung Bearbeitung Titelbild Veroeffentlichung.md`) | +| Titelbild pro PM | ein einzelnes Cover-Bild (1280×580) oder SVG-Platzhalter; Upload-Form einklappbar, Platzhalter-Picker | ✅ (Phase 8F/8G + Umbau 11.06.) | +| Einreichungs-Modal in allen Customer-Ansichten | `confirm-submit-review`-Modal in Show, Create **und** Edit (KI-Plan Phase 0) | ✅ | | HTML-Sanitizer auf Save | `PressReleaseHtmlSanitizer` (mews/purifier) | ❓ (Konzept-Punkt 2/Bilder nennt KI-Check, aber keinen HTML-Sanitizer — sollte dokumentiert werden) | | Boilerplate-Override pro PM | seit Phase 7 als optionaler Override-Text | ❓ (im Konzept nicht erwähnt) | -| Pressekontakt-Zuordnung Single-Select (1 pro PM, n:m beibehalten) | seit Phase 7, jetzt optional/Warnung | 🔄 (Konzept-Punkt: Pressekontakt war ursprünglich „mehrere möglich", jetzt 1 pro PM optional) | +| Pressekontakt-Zuordnung Single-Select (1 pro PM, n:m beibehalten) | seit Phase 7, jetzt optional; Warn-Box in der Sidebar-Card, wenn kein Kontakt gewaehlt (`create`/`edit.blade.php`) | ✅ (Phase 8C; Konzept-Punkt: war ursprünglich „mehrere möglich", jetzt 1 pro PM optional) | | Attachment-Manager | **temporär deaktiviert wegen Security-Review** | ⚠️ (Konzept beschreibt Anhänge, Code hat es auskommentiert) | ### Pressemitteilungs-Detail (Customer Show) @@ -76,20 +81,20 @@ Stand: 2026-05-21 | Zugeordnete Pressekontakte | umgesetzt | ✅ | | Rejection-Begründung sichtbar | umgesetzt | ✅ | | Vorschau-Link für externe Reviewer | `generateShareLink` via Magic-Link-Token | ✅ | -| Anzeige Subtitle / `scheduled_at` / `embargo_at` / `boilerplate_override` | **fehlt** (nur Admin-Show hat scheduled/embargo) | 📝 (offener Punkt aus letzter Diskussion) | +| Anzeige Subtitle / `scheduled_at` / `embargo_at` / `boilerplate_override` / `no_export` | umgesetzt — Subtitle unter H1, Scheduling/Embargo als Cards im „Status & Verlauf"-Block, Boilerplate-Override als eigene Card (`customer/press-releases/show.blade.php`) | ✅ (Phase 8A; Admin-Show analog) | ### Firmen-Liste (`customer/press-kits/index.blade.php`) | Konzept-Aussage / Mockup | IST | Status | |---|---|---| -| Karten-Grid pro Firma mit Logo, Status, Portal, Rolle, KPIs | Karten vorhanden, aber **deutlich schlichter** als Mockup | 📝 (Hauptthema Phase 8) | -| Counter-Strip (X Firmen, X aktiv, X PMs total, X Kontakte) | **fehlt** | 📝 | -| Saved-View-Tabs (Alle / Aktiv / In Anlage / Inaktiv / Mit mir geteilt) | **fehlt** | 📝 | -| Filter-Chips (Status / Portal / Rolle / Branche) | **nur Volltext-Suche** | 📝 | -| Seg-Toggle Karten/Liste | **fehlt** | 📝 | -| Empty-States (keine Firma / Filter ohne Treffer) | nur generischer Empty-State | 📝 | -| Rollen-Legende (Admin / Redakteur / Beobachter) | **fehlt** | 📝 | -| „Firma anlegen"-CTA | derzeit zeigt nur „Firma anlegen anfragen" → Profil; Mockup hat direkten Anlage-Flow | 🔄 (Firma-Self-Service ist Phase-2-Thema laut Doku, im Mockup aber wie Phase-1 dargestellt) | +| Karten-Grid pro Firma mit Logo, Status, Portal, Rolle, KPIs | umgesetzt auf Mockup-Niveau (`.firm-card`, deterministische Logo-Varianten, Status-Badge, Portal-Pills, Rolle-Pill, KPIs) | ✅ (Phase 8E) | +| Counter-Strip (X Firmen, X aktiv, X PMs total, X Kontakte) | umgesetzt | ✅ (Phase 8E) | +| Saved-View-Tabs (Alle / Aktiv / In Anlage / Inaktiv / Mit mir geteilt) | umgesetzt mit Live-Counts; „In Anlage" bewusst noch leer (Phase-2-Heuristik) | ✅ (Phase 8E) | +| Filter-Chips (Status / Portal / Rolle / Branche) | Portal + Rolle via FluxUI-Dropdown + URL-Sync umgesetzt | ✅ (Phase 8E) | +| Seg-Toggle Karten/Liste | umgesetzt (`?mode=list`) | ✅ (Phase 8E) | +| Empty-States (keine Firma / Filter ohne Treffer) | umgesetzt (3-Schritt-Onboarding + Reset-CTA) | ✅ (Phase 8E) | +| Rollen-Legende (Admin / Redakteur / Beobachter) | umgesetzt als `panel-warm` | ✅ (Phase 8E) | +| „Firma anlegen"-CTA | zeigt „Firma anlegen anfragen" → Profil (Add-Tile); Self-Service-Anlage bleibt Phase-2-Thema | 🔄 (bewusst, Firma-Self-Service ist Phase 2) | ### Firmen-Detail (`customer/press-kits/show.blade.php`) @@ -129,17 +134,26 @@ Stand: 2026-05-21 ### 3.1 KI-Freigabe-Workflow -**Konzept-Stand**: `Presseportal – Konzept für Relaunch.md` Abschnitt 1. +**Konzept-Stand**: `Presseportal – Konzept für Relaunch.md` Abschnitt 1 + §15. +**Umsetzungs-Doku**: `user-admin/Entwicklungsplan KI-Pruefung und Veroeffentlichung.md` (Phasen 0–5 ✅, 11.06.2026). | Punkt | Code-Stand | |---|---| -| KI-Vorprüfung mit JSON-Antwort | **nicht implementiert** | -| Drei-Stufen-Ergebnis grün/gelb/rot | nur „review"/„published"/„rejected" via Admin-Flow | -| Logging der KI-Antworten | **fehlt** | -| Trust-Score | **fehlt** | -| Blacklist-Wort-Check | **vorhanden** über `PressReleaseService::submitForReview` mit `BlacklistViolationException` | +| KI-Prüfung mit JSON-Antwort | **umgesetzt** — `ClassifyPressRelease`-Job (Queue `classification`), OpenAI-Treiber + deterministischer Fallback, provider-agnostische Architektur unter `app/Services/PressRelease/Classification/` | +| Drei-Stufen-Ergebnis grün/gelb/rot | **umgesetzt** — `press_releases.classification`; Routing aktuell: Rot → `rejected` + Mail, Gelb → manuelle Admin-Queue, Grün → Auto-Publish. ⚠️ **Entscheidung 12.06.2026**: Gelb geht zum Launch **direkt live** wie Grün (Umstellung in Phase 9A) | +| Logging der KI-Antworten | **umgesetzt** — `ki_audits`-Tabelle (append-only, inkl. Provider/Modell/Begründung/Raw-Response) | +| Content-Score 0–100 → Stufe | **umgesetzt** — `content_score`/`content_tier` (`ScorePressRelease`-Job), Editor-Panel, Admin-Badges, öffentliches Stufen-Badge in Customer-Show | +| Re-Klassifikation bei Änderung | **umgesetzt** — `reclassifyIfClassified()`/`rescoreIfScored()` bei Titel-/Text-Änderung (Customer, Admin, API) | +| Admin-On-Demand-Prüfung | **umgesetzt** — „Prüfung"-Button + Modal im Admin-Editor (Re-Check ohne Statusänderung) | +| API-Absicherung | **umgesetzt** — API kann `status` nicht mehr setzen; eigene Submit-Route läuft durch denselben Funnel | +| Trust-Score | **fehlt** (Phase 3 / KI-Plan Phase 6) | +| Blacklist-Wort-Check | **vorhanden** als synchroner Hard-Filter vor der KI-Klassifikation | -**Bewertung**: 📝 — Konzept-Vision für Phase 2/3, im Code nur die rudimentäre Blacklist-Variante. +**Bewertung**: ✅ — Kern-Pipeline produktionsbereit. ⚠️ Betriebs-Voraussetzung: +Queue-Worker für `classification` in Produktion (Test-Drain: +`php artisan classification:work`). 📝 verbleibend: Trust-Score, Live-Update +des Ergebnisses in der UI (aktuell erst nach Reload sichtbar), Stufen-Badges +im öffentlichen Web-Frontend. ### 3.2 Bilder & Lizenzen @@ -147,16 +161,16 @@ Stand: 2026-05-21 | Punkt | Code-Stand | |---|---| -| Upload-Workflow (Eigenes / Stock / KI) | Nur „Eigenes Bild" via `press-release-images-manager` | -| Pflichtfelder (Urheber, Lizenztyp, Lizenz-URL, Personen-Einwilligung, Rechte-Bestätigung) | Nur `title` + `copyright` (Freitext) — **deutlich unter Konzept** | +| Upload-Workflow (Eigenes / Stock / KI) | Nur „Eigenes Bild" via `press-release-images-manager`; auf **ein Titelbild pro PM** begrenzt, Cover-Variante 1280×580, Original wird nach Variantenerzeugung gelöscht (Stock/KI weiterhin offen) | +| Pflichtfelder (Urheber, Lizenztyp, Lizenz-URL, Personen-Einwilligung, Rechte-Bestätigung) | umgesetzt (Phase 8H, erweitert 10./11.06. nach `Lizenztyp Bildupload.md`) — `author`, `license_type` (7 Typen, `App\Enums\ImageLicenseType`), `license_detail`, `license_url` (bedingt Pflicht), `source_url`, `people_rights_status`, `property_rights_status`, `rights_notes`, `rights_confirmed_at`; Risikohinweise bei unklaren Lizenzfällen | | KI-Wasserzeichen-Check | **fehlt** | | Unsplash/Pexels-API | **fehlt** | | KI-Bildgenerierung | **fehlt** | | `is_preview`-Flag für Titelbild | im Modell vorhanden, im Manager toggelbar | | Bild-Varianten (thumb/medium/large) | `ImageService::PRESS_RELEASE_IMAGE_VARIANTS` generiert sie automatisch | -| SVG-Platzhalter, falls keine Bilder | **inline in Landing-Page-Komponenten (z. B. `focus-hero`, `feed-top-item`), kein zentrales Set** | +| SVG-Platzhalter, falls keine Bilder | umgesetzt (Phase 8F/8G) — zentrales Set in `public/images/press-release-placeholders/`, `App\Enums\PressReleasePlaceholder`, `PressReleaseCoverImage`-Resolver, Hero in Customer-/Admin-Show | -**Bewertung**: 📝 — Großthema für Phase 8 (siehe Plan). Lizenzfelder + SVG-Platzhalter sind Pflicht, bevor Bild-Upload produktiv geht. +**Bewertung**: ✅ für Lizenzfelder + SVG-Platzhalter (Phase 8). 📝 verbleibend: Stock-/KI-Quellen, Wasserzeichen-Check (Phase 2/3). ### 3.3 Notice-and-Action (Meldung durch Dritte) @@ -187,19 +201,27 @@ Stand: 2026-05-21 ### 3.5 Pricing / Tarife / Credits -**Konzept-Stand**: `Presseportal – Konzept für Relaunch.md` Abschnitt 8 + 9, `Konzept-Update 1.md`. +**Verbindlicher Konzept-Stand**: [`Decision-Update Preisstruktur & Veröffentlichungs-Flow.md`](./Decision-Update%20Preisstruktur%20&%20Ver%C3%B6ffentlichungs-Flow.md) +(11.06.2026 — überschreibt §8–10 in `Konzept-Update 1` und im Relaunch-Konzept). -| Punkt | Code-Stand | +| Punkt (laut Decision-Update) | Code-Stand | |---|---| -| Tarif-Tabellen (Einzel/Starter/Business/Pro/Agency) | **nicht im Datenmodell** | -| PM-Kontingent pro Tarif | **fehlt** | -| Bonus-Credits monatlich | **fehlt** | -| Credit-Pakete | **fehlt** | -| Auto-Refill | **fehlt** | -| Stripe-Integration | **fehlt** | +| Tarif-Raster Starter/Business/Pro/Agency (29/49/99/199 €, 3/10/25/60 PMs) | **nicht im Datenmodell** | +| Einzel-PM 19 € (No-Abo-Block) + Einzel→Abo-Brücke | **fehlt** | +| Zahlung/Checkout (Stripe) | **fehlt** | +| Slot-Verbrauch **bei Veröffentlichung** (Rot = kein Slot) | ⚠️ **abweichend** — Quota-Stub zählt aktuell beim **Einreichen** (`submitForReview`); muss auf Veröffentlichung umgestellt werden | +| Submit-Gate: „Zur Prüfung einreichen" gegated hinter Buchung | **fehlt** — Einreichen ist aktuell frei (Quota-Stub 3/Monat) | +| Tageslimit (Business 2 / Pro 3 / Agency 5) | **fehlt** | +| Launch-Credits: Extra-PM, Boost (nur grün), Veröffentlichungsnachweis-PDF | **fehlt** | +| Jahrespreis als „2 Monate gratis" | Kommunikations-Regel, greift mit Tarif-UI | | `user_payment_options`-Tabelle | **vorhanden** (Pivot zu Companies da, aber kein aktiver Flow) | -**Bewertung**: 📝 — Phase 2/3, größtes ungebautes Feature. Für Phase 8 ist relevant: bei PM-Einreichung wird **konzeptuell** Quota dekrementiert; die UI-Anzeige im Veröffentlichungs-Modal kann darauf vorbereitet werden, das echte Decrement-Verhalten kommt aber erst mit dem Tarif-Modul. +**Bewertung**: 📝 — der **Launch-Block** und damit das größte ungebaute Feature. +Vorhandene Anschlusspunkte: Quota-Stub (`users.press_release_quota`, +`pressReleaseQuotaRemaining()`), Veröffentlichungs-Modal (zeigt Kontingent), +KI-Klassifikation (liefert das Rot/Gelb/Grün für den Slot-Verbrauch). +Bewusst **nicht** zum Launch: Re-Check-Loop, Vorab-Prüfung, Prüfzähler +(alles Phase 2, siehe Decision-Update §7). ### 3.6 Korrektur-Modell & Tombstones @@ -221,11 +243,14 @@ Stand: 2026-05-21 | Punkt | Code-Stand | |---|---| -| User-Score-Tabelle | **fehlt** | -| Firmen-Score | **fehlt** | -| Auto-Publishing in Abhängigkeit vom Score | **fehlt** | +| Content-Score 0–100 → Stufe (Standard/Geprüft/Hochwertig) | **umgesetzt** (KI-Plan Phase 5) — `content_score`/`content_tier`, Schwellen kalibrierbar in `config/scoring.php` (Geprüft ≥ 60, Hochwertig ≥ 80) | +| Stufen-Badges im Backend + Customer-Ansicht | **umgesetzt** (Standard wird laut Konzept nicht beworben) | +| Stufen-Badges im öffentlichen Web-Frontend | **fehlt** (Folgearbeit) | +| Trust-Score (User-/Firmen-Ebene) | **fehlt** (Phase 3 / KI-Plan Phase 6) | +| Auto-Publishing in Abhängigkeit vom Score | Klassifikations-basiert umgesetzt (Grün → Auto-Publish); Trust-Score-Lockerung fehlt | +| Boost-Eligibilität nach Stufe | **fehlt** — zum Launch gilt laut Decision-Update: Boost nur für **grüne** PMs, Score-Feinstufung ist Phase 2 | -**Bewertung**: 📝 — Phase 3, vollständig im Konzept. +**Bewertung**: ✅ Content-Score-Kern da; 📝 Trust-Score + öffentliche Badges + Boost-Stufung. --- @@ -236,7 +261,9 @@ Stand: 2026-05-21 | Phase-7-Schema-Erweiterungen (`press_releases.subtitle`, `scheduled_at`, `embargo_at`, `boilerplate_override`, `no_export`) | Migrationen `2026_05_20_*` | Im Konzept ergänzen, dass PMs Untertitel + Scheduling/Embargo unterstützen | | `mews/purifier` für HTML-Sanitization | `PressReleaseHtmlSanitizer` | Im Konzept-Abschnitt zu Editor erwähnen | | `press_release_attachments`-Tabelle + Model | Migration `2026_05_20_143424_*` | UI auskommentiert, Tabelle bleibt → Doku-Anker für spätere Reaktivierung | -| Background-Job für scheduled publishing | `app/Console/Commands/PublishScheduledPressReleases.php`, alle 5 Min via Scheduler | Im Konzept als „automatische Veröffentlichung zum geplanten Termin" hinzufügen | +| Background-Job für scheduled publishing | `app/Console/Commands/PublishScheduledPressReleases.php`, alle 5 Min via Scheduler; publiziert seit der KI-Anbindung nur noch **grün klassifizierte** fällige PMs | Im Konzept als „automatische Veröffentlichung zum geplanten Termin" hinzufügen | +| Zeitzonen-Handling für geplante Termine | `PressRelease::DISPLAY_TIMEZONE` (Europe/Berlin), `scheduledAtLocal()`/`embargoAtLocal()`; Eingabe Berlin, Speicherung UTC | dokumentiert in `Umsetzung Pressemitteilung Bearbeitung Titelbild Veroeffentlichung.md`; `published_at`/`created_at` weiterhin UTC-Anzeige (Folgeschritt) | +| Monatlicher Quota-Reset | `press-releases:reset-monthly-quota` (Scheduler, 1. des Monats) | Stub — wird vom Tarif-Modul (Decision-Update) abgelöst | | FluxUI Toast für UX-Feedback | `Flux::toast()` durchgehend in Customer-Forms | Konzept-übergreifend, kein Konzept-Update nötig | | Smooth-Scroll zu Validation-Errors | `resources/js/portal-form-hooks.js` | UX-Detail, keine Konzept-Doku | | Pre-Submit-Check-Liste in PM-Forms | computed `presubmitChecks` | Im Konzept als „Pre-Submit-Check senkt Support-Aufwand" ergänzen | @@ -251,14 +278,14 @@ Stand: 2026-05-21 Diese Punkte habe ich beim Review der Phase-7-Forms gefunden, sie sind weder in den Konzept-Dokumenten erfasst noch in einem Plan: -| Lücke | Betroffene Dateien | Empfehlung | +| Lücke | Betroffene Dateien | Status | |---|---|---| -| Customer-Show zeigt weder `subtitle` noch `scheduled_at`/`embargo_at`/`boilerplate_override` | `customer/press-releases/show.blade.php` | Phase 8 | -| Admin-Show zeigt weder `subtitle` noch `boilerplate_override` | `admin/press-releases/show.blade.php` | Phase 8 | -| Liste-Indikator für Scheduling/Embargo | `customer/press-releases/index.blade.php`, `admin/press-releases/index.blade.php` | Phase 8 | -| Pressekontakt-Sidebar zeigt keine Warn-Box, wenn kein Kontakt gewählt | `customer/press-releases/create.blade.php`, `edit.blade.php` | Phase 8 | -| Anhang-Tests laufen ins Leere | `tests/Feature/PressReleaseAttachmentsManagerTest.php`, Teile von `PressReleasePhase7SchemaTest.php` | Phase 8 → `->skip(...)` mit Verweis auf Security-Review | -| Roadmap-Doku `19-PHASE-7-PRESS-RELEASE-FORM.md` ist nicht mehr aktuell | Letzte 3 große Änderungen fehlen | Phase 8-Doku-Block | +| Customer-Show zeigt weder `subtitle` noch `scheduled_at`/`embargo_at`/`boilerplate_override` | `customer/press-releases/show.blade.php` | ✅ erledigt (8A) | +| Admin-Show zeigt weder `subtitle` noch `boilerplate_override` | `admin/press-releases/show.blade.php` | ✅ erledigt (8A) | +| Liste-Indikator für Scheduling/Embargo | `customer/press-releases/index.blade.php`, `admin/press-releases/index.blade.php` | ✅ erledigt (8B) | +| Pressekontakt-Sidebar zeigt keine Warn-Box, wenn kein Kontakt gewählt | `customer/press-releases/create.blade.php`, `edit.blade.php` | ✅ erledigt (8C) | +| Anhang-Tests laufen ins Leere | `tests/Feature/PressReleaseAttachmentsManagerTest.php`, Teile von `PressReleasePhase7SchemaTest.php` | ✅ via `->skip(...)` mit Verweis auf Security-Review | +| Roadmap-Doku `19-PHASE-7-PRESS-RELEASE-FORM.md` ist nicht mehr aktuell | Letzte 3 große Änderungen fehlen | offen → wird im Phase-8-Abschluss (8K) als `20-PHASE-8-…md` dokumentiert | --- diff --git a/docs/konzept/Konzept-Update 1 – Überarbeitete Abschnitte.md b/docs/konzept/Konzept-Update 1 – Überarbeitete Abschnitte.md index 7c03081..8ca2a32 100644 --- a/docs/konzept/Konzept-Update 1 – Überarbeitete Abschnitte.md +++ b/docs/konzept/Konzept-Update 1 – Überarbeitete Abschnitte.md @@ -1,17 +1,22 @@ Stand: Mai 2026 Zweck: Ersatz bzw. Ergänzung der Abschnitte 8, 9, 10 sowie neue Abschnitte zur Score-Architektur, Boost-Eligibilität und zum Tool-Loop. Datenmodell-Ergänzungen am Ende. -> **IST-Stand 21.05.2026**: Dieses Update beschreibt Phase-2/3-Themen. -> Aktuell ist im Code **nichts** davon umgesetzt: +> **IST-Stand 11.06.2026**: > -> - Keine Tarif-Stufen, kein Kontingent, keine Stripe-Anbindung. -> - Kein Score, keine Boost-Eligibilitaet, kein Tool-Loop. -> - Kein Auto-Refill, keine Credit-Pakete. -> -> Phase 8 baut lediglich einen **Quota-Stub** auf `users.press_release_quota` -> und `press_release_quota_used_this_month` als Vorbereitung fuer das -> Veroeffentlichungs-Modal. Das echte Tarif-Modul ersetzt diese Felder -> spaeter. Plan-Doku: `docs/PHASE-8-USER-PANEL-PLAN.md`. +> - **§8–10 (Tarife, Credits, Preisliste) sind ueberschrieben** durch das +> [`Decision-Update Preisstruktur & Veröffentlichungs-Flow`](../Decision-Update%20Preisstruktur%20&%20Ver%C3%B6ffentlichungs-Flow.md) +> (11.06.2026): neue Kontingente (Pro 25 statt 60, Agency 60 statt 150), +> Jahrespreis als „2 Monate gratis", Bonus-Credits aus der Tarif-Tabelle +> entfernt, Launch-Credits auf Extra-PM/Boost/PDF-Nachweis reduziert. +> Die Abschnitte unten bleiben als urspruengliche Zielvorstellung lesbar. +> - **§15.1 (Klassifikations-Score) und §15.2 (Content-Score) sind umgesetzt** +> (11.06.2026, siehe `docs/user-admin/Entwicklungsplan KI-Pruefung und +> Veroeffentlichung.md`). §15.3 (Trust-Score), §16 (Boost) und §17 +> (Tool-Loop) sind weiterhin offen. +> - Zahlung/Stripe, Tarif-Datenmodell, Credit-Pakete und Auto-Refill sind +> **nicht** umgesetzt. Im Code existiert nur der Phase-8-**Quota-Stub** +> (`users.press_release_quota`, zaehlt beim Einreichen — laut +> Decision-Update kuenftig bei Veroeffentlichung). --- @@ -23,13 +28,13 @@ Alle Tarife enthalten ein Kontingent an Pressemitteilungen sowie monatlich ausge ### Tier-Struktur -|Tier|Preis|PMs|Bonus-Credits/Mo.|Effektiver PM-Preis|Besonderheiten| -|---|---|---|---|---|---| -|**Einzel**|19 € / Stück|1|4 (verfallend nach 30 T)|19,00 €|Pay-as-you-go| -|**Starter**|19 €/Mo. (190 €/Jahr)|3|12|6,30 €|Free-Stock, KI-Quality-Check| -|**Business**|49 €/Mo. (490 €/Jahr)|10|30|4,90 €|Erweiterte Statistiken, optionaler Newsroom| -|**Pro**|99 €/Mo. (990 €/Jahr)|unbegrenzt (Fair Use)|60|< 2 €|Eigener Newsroom, Priority, volles Statistik-Dashboard| -|**Agency**|199 €/Mo. (1.990 €/Jahr)|unbegrenzt für 5 Marken|120|< 1 €|Multi-Redakteur-Workflow, API-Zugang, je weitere Marke 29 €/Mo.| +| Tier | Preis | PMs | Bonus-Credits/Mo. | Effektiver PM-Preis | Besonderheiten | +| ------------ | ------------------------ | ----------------------- | ------------------------ | ------------------- | --------------------------------------------------------------- | +| **Einzel** | 19 € / Stück | 1 | 4 (verfallend nach 30 T) | 19,00 € | Pay-as-you-go | +| **Starter** | 29 €/Mo. (290 €/Jahr) | 3 | 12 | 9,67 € | Free-Stock, KI-Quality-Check | +| **Business** | 49 €/Mo. (490 €/Jahr) | 10 | 30 | 4,90 € | Erweiterte Statistiken, optionaler Newsroom | +| **Pro** | 99 €/Mo. (990 €/Jahr) | unbegrenzt (Fair Use) | 60 | < 2 € | Eigener Newsroom, Priority, volles Statistik-Dashboard | +| **Agency** | 199 €/Mo. (1.990 €/Jahr) | unbegrenzt für 5 Marken | 120 | < 1 € | Multi-Redakteur-Workflow, API-Zugang, je weitere Marke 29 €/Mo. | Jahrespreise mit ca. 17 % Rabatt eingebaut. Fair Use im Pro-Tarif: Soft-Cap 50 PMs/Monat. diff --git a/docs/konzept/Konzept-Update 2 – Score-Stufen-System.md b/docs/konzept/Konzept-Update 2 – Score-Stufen-System.md index 77520e8..4fcfd2c 100644 --- a/docs/konzept/Konzept-Update 2 – Score-Stufen-System.md +++ b/docs/konzept/Konzept-Update 2 – Score-Stufen-System.md @@ -2,9 +2,15 @@ Stand: Mai 2026 Zweck: Ersetzt die Außenkommunikation des Content-Scores durch ein dreistufiges System. Aktualisiert Abschnitt 15.2 (Content-Score) und Abschnitt 16 (Boost-Eligibilität) aus dem ersten Konzept-Update. -> **IST-Stand 21.05.2026**: Score-System und Stufen-Anzeige sind nicht -> implementiert. Im Code gibt es weder ein `user_score`- noch ein -> `company_score`-Modell. Das Thema bleibt fuer Phase 3. +> **IST-Stand 11.06.2026**: Der Content-Score mit Stufen-System ist +> **umgesetzt** (siehe `docs/user-admin/Entwicklungsplan KI-Pruefung und +> Veroeffentlichung.md`, Phase 5): `content_score`/`content_tier` auf +> `press_releases`, Schwellen Geprueft ≥ 60 / Hochwertig ≥ 80 kalibrierbar +> in `config/scoring.php`, Editor-Score-Panel, Admin-Badges und +> oeffentliches Stufen-Badge in der Customer-Ansicht (Standard ohne Badge). +> Offen: Stufen-Badges im oeffentlichen Web-Frontend, Boost-Eligibilitaet +> nach Stufe (zum Launch laut Decision-Update: Boost nur fuer gruene PMs) +> sowie User-/Firmen-Trust-Score (Phase 3). --- diff --git a/docs/konzept/Konzept-Update 3 – Multi-Brand-Architektur (Hub & Spoke).md b/docs/konzept/Konzept-Update 3 – Multi-Brand-Architektur (Hub & Spoke).md new file mode 100644 index 0000000..5c25c23 --- /dev/null +++ b/docs/konzept/Konzept-Update 3 – Multi-Brand-Architektur (Hub & Spoke).md @@ -0,0 +1,327 @@ + + +Stand: Mai 2026 Zweck: Festlegung der Plattform-Architektur mit zentralem Hub (presseportale.com) und mehreren öffentlichen Brand-Portalen. Dokumentation der strategischen, technischen und Branding-Entscheidungen für die Entwicklung. + +--- + +## Architektur-Entscheidung + +Die Plattform folgt einem **Hub-and-Spoke-Modell**: + +- **Ein zentraler Hub** für alle Verwaltungs-, Veröffentlichungs- und Abrechnungs-Funktionen +- **Mehrere öffentliche Brand-Portale**, die unabhängige redaktionelle Marken mit eigener Zielgruppe und eigener Editorial-Anmutung darstellen +- **Eine gemeinsame Codebase und Datenbank** im Hintergrund + +Das Modell entspricht der Architektur, mit der etablierte Verlagsgruppen (Axel Springer, Hubert Burda Media) ihre Markenportfolios technisch organisieren: ein zentrales Redaktions- und Tool-System, viele Frontend-Marken. + +### Strategische Vorteile + +- **Effiziente Entwicklung:** Eine Codebase für alle Portale, Updates an Tools/Editor/Credit-System wirken portal-übergreifend +- **Multi-Portal-Publishing:** Publisher können Pressemitteilungen mit einem Klick auf mehreren Portalen veröffentlichen (verkaufbares Premium-Feature) +- **Datenkonsistenz:** Ein Account, ein Credit-Stand, eine Statistik-Aggregation über alle Portale +- **Skalierbarkeit:** Weitere Portale (z.B. branchenspezifisch) können als reine Frontend- und Konfigurations-Erweiterung hinzugefügt werden +- **Saubere Trennung Marke vs. Funktion:** Brand-Portale optimieren für Editorial-Glaubwürdigkeit, Hub für Funktion und Effizienz + +--- + +## Domain- und Verantwortungs-Aufteilung + +### presseportale.com – Hub (Publisher Hub) + +**Marke:** Publisher Hub (mit Subline "Mein Pressekonto") + +**Funktion:** + +- User-Panel: Editor, Dashboard, Statistiken, Credit-Verwaltung, Newsroom-Konfiguration +- Admin-Panel: Review-Queue, Moderation, Inventory-Verwaltung, Editorial-Picks, User-Verwaltung +- Magic-Link-Bereich für Pressekontakte +- Account-Setup und Tarif-Auswahl (zentraler Veröffentlichungs-Funnel) +- Stripe-Integration, Rechnungen, Buchhaltung +- Alle KI-Tools (Lektorat, Pressetext-Optimierung, Bildgenerierung, etc.) + +**Branding:** Neutrale, eigenständige Marke. Sauberes Tool-Design (aktuell Flux UI). Funktionsfokussiert. Brand-Kontext der Portale wird über Banner/Hinweise vermittelt, nicht über Farbadaption. + +**Zielgruppe:** Publisher (Unternehmen, PR-Agenturen, Pressekontakte), Admins. + +--- + +### businessportal24.com – Brand-Portal + +**Marke:** businessportal24 + +**Funktion:** + +- Öffentliche Pressemitteilungs-Plattform +- Editorial-Anmutung mit Fokus auf Wirtschaft, B2B, Branchen-Tiefe +- Kein eigener User-Login-Bereich +- Reichweiten-Generierung über Newsletter, SEO, Branchenseiten + +**Branding:** Eigenständige Editorial-Identität (Anthrazit + Orange-Akzent). Wirkt wie ein Wirtschaftsmedium, nicht wie ein Pressedienst. + +**Zielgruppe:** Wirtschaftsjournalisten, Mediaplaner, B2B-Entscheider, Branchen-Experten. + +--- + +### presseecho.de – Brand-Portal + +**Marke:** presseecho + +**Funktion:** Wie businessportal24, aber mit anderer Markenidentität und potentiell anderer Zielgruppen-Ausrichtung. Konzeption folgt in eigener Iteration. + +**Branding:** Eigenständig, klar unterscheidbar von businessportal24 (eigener Akzentton, eventuell anderer Editorial-Schwerpunkt). + +**Zielgruppe:** noch zu definieren / komplementär zu businessportal24. + +--- + +## Login- und Session-Mechanik + +### Grundregel + +**Alle Authentifizierung läuft ausschließlich über presseportale.com.** Brand-Portale haben keine eigenen Login-Formulare oder Auth-Bereiche. + +### Verhalten in den Brand-Portalen + +- "Anmelden"-Button im Header eines Brand-Portals → Redirect auf presseportale.com (Login-Seite mit Rück-Redirect nach erfolgreicher Anmeldung) +- "Veröffentlichen"-Button → kurzer Brand-spezifischer Landing-Inhalt, dann Übergang auf presseportale.com für Account-Setup und Veröffentlichungs-Funnel +- Wenn der User über die Brand-Domain eingeloggt erkannt wird (über Cross-Domain-Mechanismus, siehe unten), erscheint im Header ein "Mein Account"-Element, das auf presseportale.com führt + +### Cross-Domain-Session + +Da die Brand-Portale und der Hub auf unterschiedlichen Top-Level-Domains laufen (.com / .de), ist Cookie-basiertes Session-Sharing nicht möglich. Notwendige Lösung: + +**Variante A (empfohlen):** Token-basierter Auth-Mechanismus über Laravel Sanctum + +- Hub gibt nach Login ein API-Token aus +- Brand-Portale prüfen über API gegen den Hub den Login-Status +- Vorteil: sauber, standardkonform, skalierbar + +**Variante B:** Lightweight-Cookie-Sync über Cross-Domain-Redirect bei Pageload (analog zu wie Single-Sign-On-Lösungen es machen) + +- Komplexer, fehleranfälliger +- Nur zu empfehlen, falls Variante A nicht umsetzbar + +Empfehlung: Variante A, da sie zum Laravel-Stack ohnehin passt und auch für die API-Anbindung von Distribution-Partnern (connektar etc.) wiederverwendbar ist. + +### Magic-Link-Flow + +Magic-Links für Pressekontakte zeigen _immer_ auf presseportale.com mit Brand-Kontext-Hinweis: + +> _„Sie verwalten eine Pressemitteilung, die auf businessportal24 veröffentlicht wurde."_ + +Brand-Logo und -Name werden im Hub-Header angezeigt, damit der Pressekontakt versteht, wo seine PM erscheint. Funktional bleibt der Flow zentral. + +--- + +## E-Mail-Strategie + +Saubere Trennung nach Funktion: + +### System-Mails (von presseportale.com) + +- Login, Password-Reset, Account-Bestätigung +- Magic-Link für Pressekontakte +- Stripe-Zahlungs-Bestätigungen, Rechnungen +- Credit-Aufladung-Bestätigungen, Auto-Refill-Hinweise +- Wartungs-/System-Benachrichtigungen + +**Absender:** `noreply@presseportale.com` oder `support@presseportale.com` + +### Editorial- und Brand-Mails (von der jeweiligen Brand-Domain) + +- "Ihre Pressemitteilung wurde auf businessportal24 veröffentlicht" +- Branchen-Newsletter (Tageszusammenfassung, Wochenrückblick, Branchen-Alerts) +- Newsroom-Update-Benachrichtigungen +- Reichweiten-Statistiken pro PM + +**Absender:** `redaktion@businessportal24.com`, `newsletter@businessportal24.com`, analog für presseecho.de + +### Begründung + +Diese Trennung stärkt das Branding der Portale (Editorial-Mails kommen "vom Magazin"), während Verwaltungs-Funktionen klar dem zentralen Hub zugeordnet bleiben. Funktional sind beide Domains technisch identisch hinterlegt (gleicher Mail-Service, gleiche Templates), nur die Absender-Konfiguration unterscheidet sich. + +--- + +## Datenmodell-Implikationen + +Die Hub-and-Spoke-Architektur erfordert eine zentrale Tabelle für die Brand-/Portal-Zugehörigkeit: + +``` +brands (oder portals) + - id, slug, name, domain + - primary_color, accent_color + - logo_url + - editorial_email, newsletter_email + - is_active, created_at + +press_releases (Ergänzung) + - + brand_id (FK auf brands) + - + cross_published_to (JSON array of brand_ids, für Multi-Portal-Veröffentlichung) + +placements (Ergänzung) + - + brand_id (FK auf brands) + - Placements gelten pro Portal, da Inventory portal-spezifisch ist + +newsletters (Ergänzung) + - + brand_id + +accounts + - Bleiben portal-übergreifend + - Eine Person hat einen Account, kann auf allen Portalen veröffentlichen + - Sub-Berechtigungen pro Brand möglich (für Agency-Tarif: Marke X nur auf Portal Y) + +credit_accounts + - Bleiben portal-übergreifend, ein Credit-Pool für alles +``` + +### Wichtige Logiken + +- Pressemitteilungen sind immer einem Brand zugeordnet (`brand_id`), können aber zusätzlich auf andere Brands "cross-published" werden +- Branchen, Kategorien und Tags können entweder portal-spezifisch oder portal-übergreifend definiert sein – Empfehlung: portal-übergreifender Stamm, mit Möglichkeit zur portal-spezifischen Untergliederung +- Placements/Boost-Slots sind grundsätzlich portal-spezifisch (jeder Top-Slot auf businessportal24 ist ein anderer Slot als auf presseecho) +- Aggregierte Statistiken im Dashboard zeigen alle Brands eines Publishers zusammen, mit Filter-Möglichkeit pro Brand + +--- + +## Brand-übergreifende Features + +### Aktuell (Migrations-Phase) + +Im Dashboard werden Pressemitteilungen aktuell **gefiltert nach Portal** angezeigt. Hintergrund: Die beiden Portale kommen aus separater Legacy-Entwicklung, eine getrennte Sicht erleichtert die Migration. + +### Mittelfristig + +**Cross-Sichtbarkeit als Standard:** + +- Dashboard zeigt alle PMs eines Publishers portal-übergreifend +- Filter-Möglichkeit pro Portal vorhanden, aber nicht Standard +- Statistiken aggregieren über alle Portale + +**Multi-Portal-Veröffentlichung als Premium-Feature:** + +- Beim Einreichen einer PM kann der Publisher auswählen, auf welchen Portalen sie erscheinen soll +- Standard: Hauptportal des Publishers +- Optional: Zusatz-Portale (kostet zusätzliche Credits oder ist in höheren Tarifen inkludiert) +- Wettbewerber können das nicht – starkes Verkaufsargument + +**Portal-übergreifender Newsroom:** + +- Premium-Publisher haben einen Newsroom auf jedem Portal, gepflegt aus einem zentralen Profil im Hub +- Logo, Beschreibung, Kontakt einmal pflegen – auf allen Portalen aktuell + +--- + +## Implikationen für die Veröffentlichen-Landingpage + +Aus der Architektur folgt die Aufteilung der Veröffentlichen-Seite in zwei Ebenen: + +### Auf businessportal24.com/veroeffentlichen (Brand-Landing) + +- Hero mit _brand-spezifischem_ Wertversprechen (Wirtschafts-Fokus, B2B-Reichweite, Branchen-Tiefe) +- Konkrete Reichweiten-Zahlen _für businessportal24_ (Newsletter-Abos, Branchen-Traffic, ISIN-Coverage) +- Differenzierungs-Punkte speziell für dieses Portal +- Tarif-Teaser ("Ab 19 € pro Pressemitteilung", mit Link auf volle Übersicht) +- Soziale Beweise (Logos von Publishern, die businessportal24 nutzen) +- Direkter CTA "Jetzt veröffentlichen →" → zur zentralen Plattform auf presseportale.com + +### Auf presseportale.com/veroeffentlichen (Zentrale Funnel-Seite) + +- Volle Tarif-Tabelle (Einzel / Starter / Business / Pro / Agency) +- Tool-Showcase (Lektorat, KI-Bilder, etc.) +- Erklärung des Multi-Portal-Konzepts ("Ein Account, mehrere Portale") +- Portal-Auswahl im Anmelde-Prozess ("Auf welchen Portalen möchten Sie veröffentlichen? businessportal24 / presseecho / beide") +- FAQ +- Account-Setup-Funnel + +### Analoge Struktur für presseecho.de + +presseecho.de/veroeffentlichen folgt demselben Pattern, mit brand-spezifischem Inhalt und Übergang zum zentralen Funnel. + +--- + +## Footer-Verlinkung zwischen Hub und Brand-Portalen + +### Auf Brand-Portalen (Footer) + +Im Footer-Bereich von businessportal24 und presseecho ein dezenter Link: + +> **Für Publisher** → Publisher Hub | Pressemitteilung einreichen | Tarife & Pakete + +Bestehende Kunden steigen so direkt in den Hub ein, ohne sich die Hub-Domain merken zu müssen. + +### Auf dem Hub (Footer) + +Im Footer von presseportale.com Verlinkung auf alle Brand-Portale: + +> **Unsere Portale** → businessportal24 (Wirtschaft & Branchen) | presseecho (...) + +Schafft Transparenz und Vertrauen – sichtbar, dass es eine Plattform-Familie ist. + +--- + +## Branding-Strategie pro Bereich + +|Bereich|Primärfarbe|Anmutung|Charakter| +|---|---|---|---| +|**presseportale.com**|neutral (z.B. Anthrazit + zurückhaltender Akzent)|Tool / SaaS|sachlich, funktional, effizient| +|**businessportal24.com**|Anthrazit + Orange|Editorial / Wirtschaftsmedium|seriös, datendicht, B2B| +|**presseecho.de**|eigene Palette (z.B. Anthrazit + Blau oder Bordeaux)|Editorial / anderer Schwerpunkt|klar differenziert von businessportal24| + +Wichtig: Die Brand-Portale müssen optisch klar unterscheidbar sein, damit Leser nicht den Eindruck gewinnen, es sei "dasselbe in zwei Versionen". Empfehlung: gemeinsame typografische Sprache (Editorial-Serif für Headlines, gleiche Sans für UI), aber klar unterschiedliche Akzentfarben und sekundäre visuelle Elemente. + +Der Hub bekommt eine _eigene_ visuelle Sprache, die sich von beiden Brand-Portalen abhebt. Tendenziell: weniger Farbe, mehr Whitespace, Tool-orientierte Komponenten (Tabellen, Dashboards, Form-Bausteine). Aktuell auf Flux UI basierend – soll noch eigene Identität bekommen, ohne den Funktions-Charakter zu verlieren. + +--- + +## Migration und Roadmap + +### Phase 1 (laufend) + +- Backend-Migration zu Laravel +- Zentrale `brands`-Tabelle als Grundlage anlegen +- Bestehende PMs der beiden Portale werden mit `brand_id` versehen +- Dashboard zeigt portal-getrennt (Migrations-Komfort) + +### Phase 2 + +- Hub auf presseportale.com mit User-Panel produktiv +- Magic-Link-Flow zentral aufgesetzt +- Erste Brand-Portal-Iteration (businessportal24) im neuen Design live +- Cross-Domain-Auth über Sanctum + +### Phase 3 + +- Zweites Brand-Portal (presseecho) im neuen Design live +- Cross-Sichtbarkeit im Dashboard +- Multi-Portal-Veröffentlichung als Feature aktiv + +### Phase 4 (mittelfristig) + +- Aggregierte Statistiken portal-übergreifend +- Portal-übergreifender Newsroom +- Vorbereitung für drittes Portal (falls relevant) + +--- + +## Skalierungs-Argument + +Die Architektur ist explizit auf Wachstum ausgelegt. Wenn in 12–24 Monaten ein drittes Portal sinnvoll wird (z.B. ein branchenspezifisches wie "energieportal.com" oder ein regional fokussiertes wie "presseportal-bayern.de"), bedeutet das technisch: + +- Keine neue Codebase +- Keine neue Datenbank +- Kein neuer Auth-Mechanismus +- Kein neues Credit-System +- Nur: Frontend, Konfiguration in `brands`-Tabelle, Editorial-Setup + +Damit wird die Investition in den Hub heute strukturell verteidigt – jede Stunde, die in den Hub investiert wird, zahlt auf jedes zukünftige Portal mit ein. + +--- + +## Offene Punkte / nächste Entscheidungen + +- **Cross-Domain-Auth final festlegen:** Sanctum-Implementierung details, Token-Lebensdauer, Refresh-Strategie +- **presseecho-Konzept:** Markenidentität, Zielgruppe, Differenzierung zu businessportal24 klären +- **Multi-Portal-Veröffentlichung – Pricing:** wie wird Cross-Publishing verrechnet? Pro zusätzlichem Portal X Credits? In höheren Tarifen inkludiert? Wie sehen die Tier-Grenzen aus? +- **Hub-Design eigenständig schärfen:** aktuelles Flux-UI-Setup soll mehr Eigenständigkeit bekommen, ohne den funktionalen Charakter zu verlieren – eigenes Mini-Briefing nötig +- **Footer-Verlinkungen zwischen den Portalen:** konkrete Texte und Platzierungen finalisieren +- **Übergang in den Brand-Portalen markieren:** wenn ein User von businessportal24 auf den Hub springt – sichtbarer Übergangs-Indikator (Banner oben "Sie sind im Publisher Hub" mit Rück-Link)? Oder unauffällig? UX-Entscheidung steht aus \ No newline at end of file diff --git a/docs/user-admin/Admin-User.md b/docs/user-admin/Admin-User.md index 1530590..9598290 100644 --- a/docs/user-admin/Admin-User.md +++ b/docs/user-admin/Admin-User.md @@ -1,8 +1,8 @@ # User Backend und Admin Backend -> **Stand der Doku**: 21.05.2026 — Phase 1 + Phase 7 (PM-Form-Refactor) sind umgesetzt. +> **Stand der Doku**: 11.06.2026 — Phase 1, Phase 7 (PM-Form-Refactor), Phase 8 (User-Panel-Konsolidierung) und die KI-Pruef-Pipeline (Klassifikation + Content-Score) sind abgeschlossen. > Aktueller Code-vs-Konzept-Abgleich: [`docs/STATUS-ABGLEICH-USER-PANEL.md`](../STATUS-ABGLEICH-USER-PANEL.md). -> Plan der naechsten Schritte: [`docs/PHASE-8-USER-PANEL-PLAN.md`](../PHASE-8-USER-PANEL-PLAN.md). +> Naechster Block (Zahlung/Tarife, Veroeffentlichungs-Flow): [`docs/Decision-Update Preisstruktur & Veröffentlichungs-Flow.md`](../Decision-Update%20Preisstruktur%20&%20Ver%C3%B6ffentlichungs-Flow.md). Dieses Konzept beschreibt das gemeinsame Backend aus zwei Perspektiven: @@ -66,16 +66,27 @@ Zusammenfassung: - **Background-Job** `php artisan press-releases:publish-scheduled` veröffentlicht geplante PMs (alle 5 Minuten via Scheduler). - **UX**: `Flux::toast()` für alle Erfolg/Fehler-Meldungen, Smooth-Scroll zum ersten Validation-Fehler nach Save, `presubmitChecks` als kompakte Pflichtfeld-Übersicht im Sidebar. -## Geplante Phase 8 +## Phase 8 (abgeschlossen 29.05.2026) Plan-Doku: `docs/PHASE-8-USER-PANEL-PLAN.md`. Schwerpunkte: -1. Show-Page-Lücken aus Phase 7 schließen (Subtitle, Scheduling, Embargo, Boilerplate-Override). -2. Listen-Indikatoren für geplante Veröffentlichung und Embargo. -3. Firmen-Liste auf Mockup-Niveau (Counter-Strip, Saved-Views, Filter-Chips, Card/List-Toggle, Rollen-Legende). -4. SVG-Platzhalter-Set für PM-Titelbilder + Auswahl-Modal. -5. FluxUI `flux:file-upload` im Image-Manager inkl. Pflichtfeldern für Urheber/Lizenz/Rechte. -6. Veröffentlichungs-Modal mit rechtlichen Hinweisen und einem Kontingent-Stub (das echte Tarif-System kommt später). +1. ✅ Show-Page-Lücken aus Phase 7 schließen (Subtitle, Scheduling, Embargo, Boilerplate-Override) — Customer + Admin (8A). +2. ✅ Listen-Indikatoren für geplante Veröffentlichung und Embargo (8B). +3. ✅ Pressekontakt-Warn-Box in der Form-Sidebar, wenn kein Kontakt gewählt (8C). +4. ✅ Firmen-Liste auf Mockup-Niveau (Counter-Strip, Saved-Views, Filter-Chips, Card/List-Toggle, Rollen-Legende) (8E). +5. ✅ SVG-Platzhalter-Set für PM-Titelbilder + Auswahl-Modal + Cover-Resolver (8F/8G). +6. ✅ Image-Manager mit Lizenz-Pflichtfeldern (Urheber/Lizenztyp/Lizenz-URL/Rechte-Bestätigung) (8H). +7. ✅ Veröffentlichungs-Modal mit rechtlichen Hinweisen und Kontingent-Stub (8I/8J; das echte Tarif-System kommt später). + +## KI-Prüfung & Veröffentlichung (abgeschlossen 11.06.2026) + +Detail-Doku: `Entwicklungsplan KI-Pruefung und Veroeffentlichung.md`. Kurzfassung: + +- Jede Einreichung (Customer-Form **und** API) läuft durch denselben Funnel: Blacklist-Hard-Filter → asynchrone KI-Klassifikation (Rot/Gelb/Grün, OpenAI mit deterministischem Fallback) → Status-Routing. +- Rot → abgelehnt + Begründung per Mail; Gelb → manuelle Admin-Review-Queue; Grün → Auto-Publish (sofort oder zum geplanten Termin). +- Jede KI-Entscheidung wird in `ki_audits` protokolliert; Admin sieht Badge, Begründung und kann nach Klassifikation filtern. On-Demand-Prüfung über den „Prüfung"-Button im Admin-Editor. +- Zusätzlich Content-Score 0–100 → Stufe Standard/Geprüft/Hochwertig mit Editor-Panel und Badges. +- Parallel umgesetzt (10./11.06.): ein Titelbild pro PM (Cover 1280×580), erweitertes Lizenz-/Rechteformular, Termine in Europe/Berlin (Speicherung UTC), Embargo aus der Form-UI entfernt — siehe `Umsetzung Pressemitteilung Bearbeitung Titelbild Veroeffentlichung.md`. ## Topbar @@ -123,7 +134,7 @@ Stand 21.05.2026: - **Anhaenge** sind im UI deaktiviert (Security-Review). Tabelle `press_release_attachments` und Service `PressReleaseAttachmentStorage` bleiben erhalten. - **Filter-Presets** sind weiterhin **Gelb** (Tabelle existiert, UI noch nicht aktiv). -Phase: **Gruen** fuer Liste, Detail, Statusverlauf, Firmenpflicht, Untertitel, Scheduling, Embargo und Boilerplate-Override. **Gelb** fuer Filter-Presets. **Rot/Spaeter** fuer KI-Vorpruefung, Notice-and-Action und Korrektur-/Update-Hinweis-System (siehe `Presseportal – Konzept für Relaunch.md`). +Phase: **Gruen** fuer Liste, Detail, Statusverlauf, Firmenpflicht, Untertitel, Scheduling und Boilerplate-Override. **Umgesetzt (11.06.)**: KI-Pruefung bei Einreichung (Klassifikation + Content-Score, siehe `Entwicklungsplan KI-Pruefung und Veroeffentlichung.md`); Embargo wurde aus der Form-UI entfernt. **Gelb** fuer Filter-Presets. **Rot/Spaeter** fuer Vorab-KI-Pruefung ohne Einreichung, Notice-and-Action und Korrektur-/Update-Hinweis-System (siehe `Presseportal – Konzept für Relaunch.md`). **3. Firmen** Klar strukturierter Detailbereich pro Firma, weil hier am meisten dranhängt: diff --git a/docs/user-admin/Entwicklungsplan KI-Pruefung und Veroeffentlichung.md b/docs/user-admin/Entwicklungsplan KI-Pruefung und Veroeffentlichung.md new file mode 100644 index 0000000..4a90214 --- /dev/null +++ b/docs/user-admin/Entwicklungsplan KI-Pruefung und Veroeffentlichung.md @@ -0,0 +1,524 @@ +# Entwicklungsplan: KI-Prüfung & Veröffentlichungs-Pipeline + +Stand: 11.06.2026 — **Phasen 0–5 abgeschlossen**, Phase 6 (Trust-Score) offen. + +Dieser Plan definiert die schrittweise Umsetzung der automatisierten Prüfung +und Veröffentlichung von Pressemitteilungen (PM). Er ist so geschnitten, dass +jede Phase einzeln umgesetzt, getestet und ausgeliefert werden kann. + +> **Abgleich mit dem Decision-Update (11.06.2026)**: Das +> [`Decision-Update Preisstruktur & Veröffentlichungs-Flow`](../Decision-Update%20Preisstruktur%20&%20Ver%C3%B6ffentlichungs-Flow.md) +> setzt auf dieser Pipeline auf und ergänzt zum Launch drei noch offene +> Flow-Regeln, die **nicht** Teil dieses Plans waren: +> +> 1. **Submit-Gate**: „Zur Prüfung einreichen" wird hinter eine aktive +> Buchung gelegt (das Modal zeigt ohne Buchung einen Buchungs-Hinweis). +> 2. **Slot-Verbrauch bei Veröffentlichung** statt bei Einreichung — +> rot abgelehnte PMs verbrauchen keinen Slot. Der aktuelle Quota-Stub +> zählt noch beim Einreichen (`submitForReview`) und muss umgestellt werden. +> 3. **Kein Re-Check zum Launch**: eine Einreichung = eine Prüfung; +> Nachbessern + erneut prüfen kommt erst in Phase 2. +> 4. **Gelb-Routing geändert (Entscheidung 12.06.2026)**: Gelb geht zum +> Launch **direkt live** wie Grün — keine manuelle Review-Queue mehr. +> Nur Rot wird abgelehnt (mit Begründung an den Autor). Phase 4 unten +> beschreibt das ursprünglich gebaute Verhalten (Gelb → manuelle Queue); +> die Umstellung erfolgt im Phase-9-Plan +> (`docs/PHASE-9-FLOW-UND-TARIFE-PLAN.md`, Päckchen 9A). + +## Ziel & Leitprinzip + +Jede eingehende PM wird **automatisch von einer KI geprüft**. Nur in +**äußersten Fällen** erfolgt eine manuelle redaktionelle Prüfung. Zwei +Einreichungsstellen müssen denselben Prüf-Pfad durchlaufen: + +1. **Web-Formular** (Customer- und Admin-Editor) +2. **API** (`/api/v1/press-releases`) + +Es gibt zwei voneinander unabhängige Bewertungen (Konzept-Update 1, Abschnitt 15): + +- **Klassifikations-Score (Grün/Gelb/Rot)** — der „Red Flag": entscheidet, ob + überhaupt veröffentlicht wird. **Jetzt umzusetzen.** +- **Content-Score (0–100) → Stufe (Standard/Geprüft/Hochwertig)** — die + Qualitätsbewertung („Scoring"). **Spätere Phase.** + +## Konzept-Grundlage + +- `docs/konzept/Konzept-Update 1 – Überarbeitete Abschnitte.md`, §15.1 + (Klassifikations-Score) und §15.2 (Content-Score). +- `docs/konzept/Konzept-Update 2 – Score-Stufen-System.md` (Stufen-Mapping, + `content_tier`, Außenkommunikation). + +Klassifikations-Score laut Konzept §15.1: + +| Klassifikation | Bedeutung | Auswirkung | +|---|---|---| +| **Grün** | unauffällig | direkte Veröffentlichung (optional 5–10 Min. Verzögerung) | +| **Gelb** | unklar/grenzwertig | manuelle Review-Queue (nicht boostbar) | +| **Rot** | unzulässig | zurück an Autor mit Begründung, keine Veröffentlichung | + +Faktoren (Red Flags): Werbung statt PM, beleidigend/diskriminierend, rechtlich +heikel, Spam-Muster, unseriöse Versprechen. Speicherung laut Konzept: +`press_releases.classification` plus Audit-Log `ki_audits`. + +## Ist-Zustand (Bestandsaufnahme) + +- **Statuswerte** (`App\Enums\PressReleaseStatus`): `draft`, `review`, + `published`, `rejected`, `archived`. +- **Web-Einreichung**: `App\Services\PressRelease\PressReleaseService::submitForReview()` + prüft nur eine wortbasierte Blacklist (`config/blacklist.php` via + `BlacklistService`), setzt sonst Status `review`, erhöht das Quota und + schreibt ein `PressReleaseStatusLog`. +- **Veröffentlichung**: `PressReleaseService::publish()` (Admin-Aktion) und der + Cron `App\Console\Commands\PublishScheduledPressReleases` (publiziert + `review`-PMs mit fälligem `scheduled_at`). Beide prüfen erneut nur die + Blacklist. +- **API**: `App\Http\Controllers\Api\V1\PressReleaseController::store()` / + `update()` schreiben `status` direkt aus dem Request (erlaubt: `draft`, + `review`) und rufen `submitForReview` **nicht** auf. Eine API-PM mit + `status=review` landet damit **ohne** Blacklist-/Quota-/Log-Prüfung in der + Queue. +- **UI-Einreichung (Prozess-Start)**: + - Detailansicht ([show.blade.php]): vollständiges Modal `confirm-submit-review` + mit rechtlichen Hinweisen, Quota-Anzeige und Bestätigungs-Checkboxen → + ruft `submitForReview`. + - Bearbeiten ([edit.blade.php]): Button „Speichern & zur Prüfung" mit nur + `wire:confirm` (Browser-Dialog), **kein** Modal. + - Erstellen ([create.blade.php]): Button „Zur Prüfung senden" ohne Modal. +- **Kein** Datenmodell für Klassifikation/Score: keine Spalten + `classification`, `content_score`, `content_tier`, keine Tabelle `ki_audits`. + +## Lücken & Risiken + +- **L1 — API-Bypass**: Einreichung über die API umgeht jede Prüfung. +- **L2 — Keine echte Inhaltsprüfung**: nur eine triviale Wort-Blacklist; keine + Erkennung von Werbung, Spam, rechtlich heiklen oder unseriösen Inhalten. +- **L3 — Auto-Publish ohne Klassifikation**: geplante PMs werden vom Cron + veröffentlicht, ohne dass eine inhaltliche Bewertung stattgefunden hat. +- **L4 — Uneinheitlicher Prozess-Start**: das Bestätigungs-Modal existiert nur + in der Detailansicht, nicht beim Bearbeiten/Erstellen. +- **L5 — Kein Audit**: KI-Entscheidungen wären ohne `ki_audits` nicht + nachvollziehbar (DSGVO / Nachweispflicht). + +## Zielarchitektur + +``` +Einreichung (Formular ODER API) + │ + ▼ + SubmissionService.submit() ← ein einziger Funnel + │ + ├─ Hard-Filter: Blacklist (synchron, deterministisch) + ▼ + ClassificationService.classify() ← KI (Claude), mit Fallback + │ + ├─ Rot → status=rejected, Begründung an Autor + ├─ Gelb → status=review (manuelle Queue, „äußerste Fälle") + └─ Grün → Veröffentlichungspfad (sofort / geplant) + │ + ▼ + ki_audits (vollständiges Audit-Log jeder KI-Entscheidung) + + + press_releases.classification / classified_at + + + (später) content_score / content_tier +``` + +Kernregeln: + +- Formular **und** API rufen ausschließlich `SubmissionService.submit()` auf. + Die API darf `status` nicht mehr frei setzen; `published` ist über die API + nie erreichbar. +- Re-Klassifikation bei jeder Änderung einer PM (Konzept §15.1: „Bei Änderung + der PM wird neu klassifiziert"). +- Schwellen/Verhalten sind konfigurierbar (`config/scoring.php`), damit sie + ohne Code-Änderung kalibriert werden können. + +--- + +## Entwicklungsschritte + +### Phase 0 — Prozess-Start im UI vereinheitlichen — ✅ erledigt (11.06.2026) + +**Ziel:** Das bestehende Einreichungs-Modal erscheint überall dort, wo eine PM +eingereicht wird — auch beim Bearbeiten (Button „Speichern & zur Prüfung") und +beim Erstellen (Button „Zur Prüfung senden"). Reiner UI-Schritt, kein Backend. + +**Umsetzung:** Das Modal `confirm-submit-review` (rechtliche Hinweise, Quota, +Bestätigungs-Checkboxen) wird in Customer-Show, -Create **und** -Edit über +`flux:modal.trigger` geöffnet; bestätigt ruft es wie geplant +`submitForReview` bzw. `saveAndSubmit`/`save('review')`. + +**Umfang:** + +- Modal `confirm-submit-review` aus `show.blade.php` in eine wiederverwendbare + Blade-/Volt-Komponente extrahieren (z. B. + `resources/views/livewire/components/press-release-submit-modal.blade.php`). +- In `edit.blade.php` den `wire:confirm`-Button durch einen + `flux:modal.trigger` ersetzen; bei Bestätigung wird wie bisher + `saveAndSubmit` ausgeführt (erst speichern, dann einreichen). +- In `create.blade.php` denselben Modal-Trigger vor `save('review')` schalten. +- Texte/Checkboxen identisch zur Detailansicht halten (rechtliche Hinweise, + Quota, Bestätigungen). + +**Betroffene Dateien:** `resources/views/livewire/customer/press-releases/{show,edit,create}.blade.php`, +neue Komponente unter `resources/views/livewire/components/`. + +**Done:** In allen drei Ansichten (Customer: show/edit/create) öffnet derselbe +Bestätigungsdialog; Tests für Edit/Create-Submit grün. + +**Admin-Editor (`/admin/press-releases/`) — bewusst ausgenommen:** Der +Admin-Editor behält sein bisheriges Verhalten (`wire:confirm`). Begründung: Wenn +eine PM beim Admin landet, hat die vorgelagerte User-Prüfung (Einreichungs-Modal +im Customer-Flow) bereits stattgefunden. Der Admin braucht hier keinen erneuten +Bestätigungsdialog. Stattdessen erhält der Admin-Editor in einer späteren Phase +einen zusätzlichen **„Prüfung"-Button** (siehe Phase 4: On-Demand-KI-Prüfung). + +**Tests:** Volt-Tests, die das Öffnen des Modals und den Submit-Pfad +(`saveAndSubmit` / `save('review')`) abdecken. + +### Phase 1 — Einreichungs-Funnel & API-Absicherung — ✅ erledigt (11.06.2026) + +**Ziel:** Beide Einreichungsstellen laufen durch einen Pfad; die API-Lücke (L1) +wird geschlossen. Noch ohne KI — nur Vereinheitlichung. + +**Umsetzung:** + +- `PressReleaseService::submitForReview()` ist der alleinige Einreichungs-Einstieg + (Web-Formular **und** API rufen dieselbe Methode). Auf eine separate + `SubmissionService`-Fassade wurde bewusst verzichtet — `submitForReview` ist + bereits die stabile Schnittstelle, in die Phase 3 die KI-Klassifikation + einhängt. +- API: `status` aus den Validierungsregeln von `StorePressReleaseRequest` und + `UpdatePressReleaseRequest` entfernt (inkl. ungenutzter Imports). `store()` + erzeugt jetzt **immer** `PressReleaseStatus::Draft`; ein übergebenes `status` + wird ignoriert. `update()` kann den Status nicht mehr setzen. +- Neue explizite Route `POST /api/v1/press-releases/{pressRelease}/submit` + (`press-releases.submit`) → `PressReleaseController::submit()`. Diese prüft + `press-releases:write`, Ownership und erlaubt nur `draft`/`rejected` + (sonst 409); ruft `submitForReview()`; eine `BlacklistViolationException` + wird als **422** mit Begründung zurückgegeben. Damit greifen Blacklist-, + Quota- und Status-Log-Behandlung auch für API-Einreichungen. +- `published` ist über die API weiterhin nie erreichbar (nur Admin-Aktion/Cron). + +**Betroffene Dateien:** `app/Http/Controllers/Api/V1/PressReleaseController.php`, +`app/Http/Requests/Api/V1/{Store,Update}PressReleaseRequest.php`, +`routes/api.php`. `PressReleaseService` blieb unverändert (Schnittstelle +ausreichend). + +**Done:** API kann keine PM mehr ungeprüft in `review` heben; eine PM-Einreichung +verhält sich über API und Formular identisch. + +**Tests:** `tests/Feature/Api/V1/PressReleaseSubmitApiTest.php` (Create erzeugt +immer Draft & ignoriert `status`; Submit-Route hebt nach `review`, zählt Quota, +schreibt Log; Blacklist → 422 + `rejected`; fehlende Schreibrechte → 403; +bereits in `review` → 409; fremde PM → 403). Alle grün. + +### Phase 2 — Datenmodell & Audit — ✅ erledigt (11.06.2026) + +**Ziel:** Persistenz für Klassifikation und vollständiges KI-Audit. Noch ohne +Verhaltensänderung (alle Felder nullable). + +**Umsetzung:** + +- Migration `add_classification_to_press_releases`: Spalten `classification` + (string(16), nullable, nach `status`) und `classified_at` (timestamp, + nullable) plus Index auf `classification`. `content_score`/`content_tier` + bewusst **erst in Phase 5** (siehe Datenmodell-Anhang). +- Migration `create_ki_audits_table`: `press_release_id` (FK, cascade), + `type`, `provider` (nullable), `model` (nullable), `result` (nullable), + `reason` (text, nullable), `raw_response` (json, nullable), + `created_at` (useCurrent), Index `(press_release_id, type)`. Kein + `updated_at` (append-only Log). +- Model `App\Models\KiAudit` (`$timestamps = false`, Cast `raw_response` → + array, Konstanten `TYPE_CLASSIFICATION`/`TYPE_CONTENT_SCORE`, Relation + `pressRelease()`), Relation `PressRelease::kiAudits()` (neueste zuerst). +- Enum `App\Enums\PressReleaseClassification` (Green/Yellow/Red + `label()`), + in `PressRelease::casts()` für `classification` registriert. +- `config/scoring.php`: Anbieter/Modell-Auswahl (`CLASSIFICATION_PROVIDER`, + Default `deterministic`, `CLASSIFICATION_MODEL`), Timeout, Grün-Verzögerung + (Minuten), Gelb→manuelle-Queue-Flag sowie Content-Score-Stufen-Schwellen + (Phase 5). +- `KiAuditFactory` mit States `classification()` / `contentScore()`. + +**Betroffene Dateien:** zwei neue Migrationen unter `database/migrations/`, +`app/Models/PressRelease.php`, `app/Models/KiAudit.php`, +`app/Enums/PressReleaseClassification.php`, `config/scoring.php`, +`database/factories/KiAuditFactory.php`. + +**Done:** Migrationen laufen; Modelle/Casts/Relation vorhanden; keine bestehende +Funktionalität verändert (alle Felder nullable). + +**Tests:** `tests/Feature/PressReleaseClassificationModelTest.php` (Enum-/ +Datetime-Cast, Default null, `kiAudits()`-Reihenfolge, `raw_response`-Array-Cast ++ Relation, Cascade-Delete). Alle grün. + +### Phase 3 — KI-Klassifikation (Red Flag) — ✅ erledigt (11.06.2026) + +**Ziel:** Echte inhaltliche Prüfung jeder Einreichung; Ergebnis asynchron als +Klassifikation gespeichert und auditiert. + +**Entscheidungen (11.06.2026):** Erster aktiver Anbieter ist **OpenAI** (Key/ +Budget vorhanden); Anthropic/Gemini folgen über dieselbe Treiber-Schnittstelle. +Klassifikation läuft **asynchron über die Queue** (synchron wäre später nicht +handelbar). Zum Testen ohne Dauer-Worker gibt es einen Drain-Befehl. + +**Umsetzung:** + +- **Provider-agnostische Treiber-Architektur** unter + `app/Services/PressRelease/Classification/`: + - Interface `Contracts\ClassificationDriver::classify(PressRelease): ClassificationResult`. + - `ClassificationResult` (Value Object: Enum-Klassifikation, `reasons[]`, + `provider`, `model`, `rawResponse`, `reasonText()`). + - `Drivers\OpenAiClassificationDriver` — OpenAI Chat-Completions via + `Http`-Client, liest `config/services.openai` (Key/URL/Modell/Timeout), + erzwingt `response_format: json_object` und parst + `{classification, reasons[]}`. Wirft bei fehlendem Key / HTTP-Fehler / + ungültigem JSON. + - `Drivers\DeterministicClassificationDriver` — Blacklist → Rot/Grün + (nie Gelb), als Fallback ohne externe API. + - `ClassificationManager` (Laravel-Manager) löst den Treiber aus + `config('scoring.classification.provider')` auf + (`createOpenaiDriver`/`createDeterministicDriver`). +- **Asynchroner Job** `app/Jobs/ClassifyPressRelease` (Queue `classification`, + `tries=3`): klassifiziert über den aktiven Treiber, bei Ausfall **Fallback** + auf den deterministischen Treiber (mit `Log::warning`), schreibt + `press_releases.classification`/`classified_at` und einen `ki_audits`-Eintrag + (inkl. `provider`/`model`/`reason`/`raw_response`). +- **Einbindung in den Funnel:** `PressReleaseService::submitForReview()` stößt + nach dem synchronen Blacklist-Hard-Filter und dem Statuswechsel den Job an + (`ClassifyPressRelease::dispatch(...)->onQueue('classification')`). Greift für + Formular **und** API (gemeinsamer Einstieg aus Phase 1). +- **Drain-Befehl** `php artisan classification:work` (Option `--once`): arbeitet + die Queue einmalig ab und beendet sich (`queue:work --stop-when-empty`) — zum + Testen ohne permanenten Worker. +- **Konfig:** `config/scoring.php` Default-Provider auf `openai` gesetzt + (`CLASSIFICATION_PROVIDER`); Modell leer ⇒ `config('services.openai.model')`. +- **Test-Isolation:** `phpunit.xml` erzwingt `CLASSIFICATION_PROVIDER=deterministic` + und leeren `OPENAI_API_KEY`, damit die Suite keine echten OpenAI-Calls macht; + der OpenAI-Pfad wird gezielt mit `Http::fake()` getestet. + +**Noch offen (bewusst):** Re-Klassifikation bei jeder PM-Änderung (Update über +Formular/API) ist noch **nicht** verdrahtet — Phase 3 klassifiziert beim +Einreichen. Nachzuziehen, wenn das Status-Routing (Phase 4) steht. Anthropic-/ +Gemini-Treiber + SDK folgen separat. + +**Betroffene Dateien:** `app/Services/PressRelease/Classification/*`, +`app/Jobs/ClassifyPressRelease.php`, +`app/Console/Commands/RunClassificationQueue.php`, +`app/Services/PressRelease/PressReleaseService.php`, `config/scoring.php`, +`phpunit.xml`. + +**Done:** Jede Einreichung (Formular + API) stößt asynchron eine Klassifikation +an, erzeugt einen `ki_audits`-Eintrag; bei KI-Ausfall greift der deterministische +Fallback nachvollziehbar. Status-Routing folgt in Phase 4. + +**Tests:** `tests/Feature/PressReleaseClassificationJobTest.php` (OpenAI grün/gelb +mit `Http::fake`, Fallback bei HTTP-500, deterministisch Rot bei Blacklist, +Dispatch auf Queue `classification` via `Queue::fake`). Alle grün; volle Suite +416 grün (2 vorbestehende WIP-Failures unverändert). + +### Phase 4 — Routing, Auto-Publish & Review-Queue — ✅ erledigt (11.06.2026) + +**Ziel:** Die Klassifikation steuert den Status. Manuelle Prüfung nur noch bei +Gelb. + +**Umsetzung:** + +- **Routing im Job** über `PressReleaseService::routeByClassification()` + (vom `ClassifyPressRelease`-Job nach dem Klassifizieren aufgerufen): + - **Rot** → `reject(..., source: 'ki')`: `status=rejected`, KI-Begründung per + Mail an den Autor (`PressReleaseRejected`, wie bei Blacklist). + - **Gelb** → keine Aktion, bleibt `review` (manuelle Admin-Queue). + - **Grün** → `autoPublishGreen()`: ohne Termin sofort veröffentlichen, + optional mit Sicherheitsfenster `scoring.classification.green_delay_minutes` + (über `published_at`-Override); mit zukünftigem `scheduled_at` bleibt die PM + in `review` und der Scheduler publiziert zum Termin. + - Greift nur, solange die PM noch `review` ist (manuelle Admin-Eingriffe haben + Vorrang). `publish()` erhielt einen `?Carbon $publishedAtOverride`-Parameter, + `reject()` einen `string $source`-Parameter. +- **Scheduler** `PublishScheduledPressReleases`: Kandidaten-Query um + `where('classification', 'green')` erweitert — nur **grüne** fällige PMs + werden automatisch publiziert; gelbe warten immer auf den Admin. Geplante + Termine werden weiterhin respektiert. +- **Admin-Review-Queue:** Index- und Show-Ansicht zeigen ein KI-Klassifikations- + Badge (grün/gelb/rot); der Index hat einen **Klassifikations-Filter** + (`classificationFilter`, inkl. URL-Param, Active-Chip, Reset) — damit „nur + Gelb" filterbar. Die Show-Ansicht blendet im Review-Block den **KI-Hinweis** + (Begründung aus dem jüngsten `ki_audits`-Eintrag) ein. + +**Test-Isolation (wichtig):** Da Tests mit `sync`-Queue den Job inline ausführen, +wurde der Klassifikations-Job in den „submit→review"-Tests via `Queue::fake()` +entkoppelt (Workflow, PublishModal, API-Submit). Die Scheduler-Tests setzen jetzt +`classification = green` für Publish-Kandidaten; neuer Test: fällige **gelbe** PM +bleibt `review`. + +**Betroffene Dateien:** `app/Services/PressRelease/PressReleaseService.php`, +`app/Jobs/ClassifyPressRelease.php`, +`app/Console/Commands/PublishScheduledPressReleases.php`, Admin-Views +`resources/views/livewire/admin/press-releases/{index,show}.blade.php`. + +**Done:** Grüne PMs gehen automatisch live (sofort/zum Termin), rote werden +abgelehnt + Autor benachrichtigt, nur gelbe landen in der manuellen Queue; Admin +sieht Klassifikation + KI-Begründung und kann nach Gelb filtern. + +**Tests:** Routing in `PressReleaseClassificationJobTest` (Rot→rejected+Mail, +Grün-sofort→published+Mail, Grün-geplant→bleibt review, Gelb→bleibt review); +Scheduler in `PressReleaseSchedulingTest` (grün fällig→published, gelb +fällig→review); Admin-UI in `PressReleaseIndexPhase8bTest` (KI-Badge, +Klassifikations-Filter). Volle Suite 423 grün (2 vorbestehende WIP-Failures). + +**Admin „Prüfung"-Button (On-Demand-KI-Prüfung)** — ✅ erledigt (11.06.2026): + +- Im Admin-Editor gibt es oben den Button **„Prüfung"**, der ein Modal + `admin-ki-check` öffnet: auswählbare Klassifikation (Content-Score als + „in Vorbereitung" deaktiviert) und ein **Anbieter-Override** (Konfiguriert / + OpenAI / Deterministisch). +- `runKiCheck()` dispatcht `ClassifyPressRelease` auf der Queue `classification` + **mit `route: false`** und optionalem `providerOverride`. Das ist eine + nachgelagerte Re-Check-Prüfung: sie aktualisiert nur `classification` + + `ki_audits`, **ohne** den Status zu ändern (kein Auto-Publish/Reject) — die + Entscheidung bleibt beim Admin (Ergebnis sichtbar in der Detailansicht). +- Dafür erhielt `ClassifyPressRelease` die Parameter `bool $route = true` und + `?string $providerOverride = null`. + +**Tests:** `tests/Feature/Admin/AdminKiCheckTest.php` (Button/Modal sichtbar; +Dispatch mit `route=false` + Provider-Override; Abbruch ohne Auswahl; +Re-Check-Job aktualisiert Bewertung, lässt Status unverändert). + +**Re-Klassifikation bei Änderung** (Konzept §15.1) — ✅ erledigt (11.06.2026): + +- Neue Service-Methode `reclassifyIfClassified()`: dispatcht – nur wenn die PM + bereits klassifiziert ist – `ClassifyPressRelease` mit `route: false` + (Re-Check ohne Statusänderung). +- Eingehängt überall dort, wo Inhalt geändert wird, und nur bei tatsächlicher + Änderung von Titel/Text (`wasChanged(['title', 'text'])`): + Customer-Editor `save()`, Admin-Editor `save()`, API `update()`. + Beim Einreichen übernimmt weiterhin `submitForReview` die (routende) + Klassifikation. + +**Tests:** `tests/Feature/PressReleaseReclassifyTest.php` (Service dispatcht nur +bei vorhandener Klassifikation; API-Update klassifiziert neu bei Text-Änderung, +nicht bei reiner Keyword-Änderung). + +**Noch offen / Folgearbeiten:** + +- **Live-Aktualisierung der Ansicht** nach Abschluss des Hintergrund-Jobs + (Polling/Event) wäre ein optionales UX-Upgrade; aktuell erscheint das Ergebnis + nach Reload/Navigation. +- **Content-Score-Option** im Prüfungs-Modal — ✅ mit Phase 5 aktiviert (s. u.). + +### Phase 5 — Content-Score & Stufen — ✅ erledigt (11.06.2026) + +**Ziel:** Qualitätsbewertung 0–100 → Stufe Standard/Geprüft/Hochwertig +(Konzept-Update 2). + +**Umsetzung:** + +- **Datenmodell:** Migration `add_content_score_to_press_releases` — + `content_score` (tinyint, nullable), `content_tier` (string, nullable, Index), + `scored_at`. Enum `App\Enums\PressReleaseContentTier` + (Standard/Geprueft/Hochwertig) mit `fromScore()` (Schwellen aus + `config/scoring.php`), `label()` und `isPubliclyBadged()` (Standard wird laut + Update 2 nicht beworben). In `PressRelease` als Cast registriert. +- **Schwellen** (`config/scoring.php`): Geprüft ≥ 60, Hochwertig ≥ 80 (Update 2), + kalibrierbar; plus Anbieter/Modell/Timeout für den Score. +- **Treiber-Architektur** unter `app/Services/PressRelease/ContentScore/` + analog zur Klassifikation: `Contracts\ContentScoreDriver`, `ContentScoreResult`, + `Drivers\OpenAiContentScoreDriver` (gewichtete Faktoren §15.2 als JSON + `{score, breakdown}`), `Drivers\DeterministicContentScoreDriver` + (regelbasierte Heuristik: Länge, Bild, Quelle, Headline, Vollständigkeit), + `ContentScoreManager`. +- **Job** `app/Jobs/ScorePressRelease` (Queue `classification`, Fallback auf + deterministisch): schreibt `content_score` + abgeleitete `content_tier` + + `scored_at` und `ki_audits` (type=content_score). Optionaler + `providerOverride`. +- **Berechnung** bei Einreichung (`submitForReview` dispatcht Klassifikation + **und** Score) und bei Inhaltsänderung (`rescoreIfScored()` in Customer-/ + Admin-Editor und API-`update()`, analog zur Re-Klassifikation). +- **Anzeige:** + - Customer-Editor: Score-Panel (Punktzahl, Stufe, „noch X Punkte bis zur + nächsten Stufe") — der produktive Editor-Score laut Update 2. + - Admin-Index & -Show: Stufen-/Score-Badge (intern inkl. Punktzahl). + - Customer-Detailansicht: öffentliches Stufen-Badge (✓ Geprüft / ★ Hochwertig; + Standard ohne Badge). +- **Admin-Prüfungs-Modal:** Content-Score-Option aktiviert; `runKiCheck()` + dispatcht zusätzlich `ScorePressRelease`. + +**Done:** Score wird bei Einreichung/Änderung berechnet, Stufe abgeleitet, +auditiert und überall sichtbar. + +**Tests:** `tests/Feature/PressReleaseContentScoreTest.php` (Tier-Mapping, +öffentliche Badges, OpenAI-Score→Tier+Audit, Fallback, Dispatch bei Submit, +Re-Score nur wenn bereits bewertet); Editor-Panel in +`CustomerPressReleaseEditPhase7Test`; Stufen-Badge in `PressReleaseIndexPhase8bTest`; +Content-Score-Dispatch in `AdminKiCheckTest`. Volle Suite 440 grün. + +**Noch offen / Folgearbeiten:** + +- **Public Web-Frontend** (presseecho/businessportal24): Stufen-Badges in den + öffentlichen Listen/Detailseiten gemäß Update 2 ergänzen (bisher nur im + Portal/Backend und der Customer-Ansicht). +- **Score-History & Breakdown-Ansicht** (Publisher-Dashboard) und Boost- + Eligibilität (Abschnitt 16) sind eigene spätere Ausbaustufen. + +### Phase 6 — Trust-Score (später) + +Account-/Firmen-Ebene (Konzept §15.3): lockert die KI-Freigabe-Schwelle für +zuverlässige Publisher. Eigene spätere Ausbaustufe; hier nur als Ausblick +vermerkt. + +--- + +## Datenmodell-Anhang (Zielzustand) + +``` +press_releases (Ergänzungen) + + classification enum(green,yellow,red) NULL + + classified_at timestamp NULL + + content_score tinyint NULL (Phase 5) + + content_tier enum(standard,gepruft,hochwertig) NULL (Phase 5) + +ki_audits (neu) + - id + - press_release_id FK + - type enum(classification,content_score) + - provider string (z. B. anthropic) + - model string (z. B. claude-opus-4-8) + - result string/json + - reason text NULL + - raw_response json/longtext + - created_at timestamp +``` + +## Offene Entscheidungen + +- **Anbieter & Modell** — ✅ entschieden (11.06.2026): Erster aktiver Anbieter + ist **OpenAI** (`CLASSIFICATION_PROVIDER=openai`, Modell aus + `config/services.openai`). Architektur provider-agnostisch; Anthropic/Gemini + folgen. Offen bleibt, ob später mehrere Anbieter parallel (Primär + Fallback + jenseits des deterministischen) laufen sollen. +- **Synchron vs. Queue** — ✅ entschieden (11.06.2026): **Queue** (asynchron, + Queue-Name `classification`). Drain zum Testen: `php artisan classification:work`. +- **Dependency**: OpenAI-Treiber nutzt den nativen `Http`-Client (kein neues + Composer-Paket). Anthropic PHP-SDK (`anthropic-ai/sdk`) ist **freigegeben**; + für Gemini je ein offizielles/etabliertes SDK oder HTTP-Client bei Umsetzung + des Treibers. +- **Grün-Verzögerung**: 0 Min. (sofort) oder 5–10 Min. (Konzept-Option) als + Sicherheitsfenster — konfigurierbar über + `scoring.classification.green_delay_minutes`, Default noch festzulegen. +- **Gelb-Verhalten**: ausschließlich manuelle Queue, oder zusätzlich + automatische Benachrichtigung des Autors. +- **DSGVO**: Aufbewahrung/Anonymisierung der `raw_response` in `ki_audits`. + +## Nächste Schritte + +Phasen 0–5 sind umgesetzt (Suite grün). Es folgen: + +1. **Launch-Block aus dem Decision-Update** (siehe Abgleich-Box oben): + Submit-Gate hinter Buchung, Slot-Verbrauch bei Veröffentlichung, + Tarif-/Zahlungs-Modul. +2. **Betrieb**: Queue-Worker für `classification` im Produktions-Setup + (Test-Drain: `php artisan classification:work`). +3. **Folgearbeiten**: Live-Aktualisierung des KI-Ergebnisses in der UI, + Stufen-Badges im öffentlichen Web-Frontend, Anthropic-/Gemini-Treiber. +4. **Phase 6**: Trust-Score (eigene Ausbaustufe). diff --git a/docs/user-admin/Lizenztyp Bildupload.md b/docs/user-admin/Lizenztyp Bildupload.md new file mode 100644 index 0000000..ff81b6b --- /dev/null +++ b/docs/user-admin/Lizenztyp Bildupload.md @@ -0,0 +1,207 @@ +Ich würde das Formular inhaltlich klarer machen und stärker gegen typische Bildrechts-Probleme absichern. Der aktuelle Ansatz ist gut, aber bei Presseportalen würde ich etwas präziser zwischen **Urheberrecht**, **Nutzungsrecht**, **Personenrechten** und **Quelle/Nachweis** unterscheiden. + +## **1. Lizenztyp-Auswahl überarbeiten** + +Aktuell hast du: + +- Eigene Aufnahme +- CC-Lizenz +- Kommerzielle Lizenz erworben +- Einwilligung des Urhebers +- Sonstiges + +Ich würde daraus eher machen: + +### **Empfohlene Lizenztypen** + +|**Option**|**Wann verwenden?**| +|---|---| +|**Eigene Aufnahme**|Der Uploadende hat das Bild selbst erstellt| +|**Vom Urheber / Fotografen freigegeben**|Direkte schriftliche Erlaubnis liegt vor| +|**Agentur-/Stockbild-Lizenz**|Bild wurde z. B. über Adobe Stock, Shutterstock, Getty etc. lizenziert| +|**Creative-Commons-Lizenz**|Bild steht unter CC BY, CC BY-SA, CC0 etc.| +|**Presse-/PR-Bild mit Nutzungsfreigabe**|Bild wurde z. B. von Unternehmen, Veranstaltern, Agenturen oder Pressestellen bereitgestellt| +|**Gemeinfrei / Public Domain / CC0**|Keine oder sehr weitgehende Nutzungsbeschränkungen| +|**Sonstige Lizenz / Sondervereinbarung**|Freitext erforderlich| + +„Einwilligung des Urhebers“ würde ich nicht als eigenen Lizenztyp stehen lassen, sondern eher als **„Vom Urheber/Fotografen freigegeben“** formulieren. Das ist verständlicher. + +## **2. Bei Creative Commons zusätzliche Felder anzeigen** + +Wenn jemand **CC-Lizenz** auswählt, sollte nicht nur „CC-Lizenz“ gespeichert werden. Du brauchst genauer: + +- CC0 +- CC BY +- CC BY-SA +- CC BY-ND +- CC BY-NC +- CC BY-NC-SA +- CC BY-NC-ND + +Wichtig: **NC** bedeutet „nicht-kommerziell“ und kann für ein Presseportal problematisch sein, besonders wenn die Seite werbefinanziert ist oder kommerziell betrieben wird. **ND** erlaubt keine Bearbeitung, also eventuell auch keinen Beschnitt als Titelbild. + +Daher würde ich bei CC-Lizenzen automatisch Hinweise anzeigen, zum Beispiel: + +Diese Lizenz kann Einschränkungen enthalten. Bitte prüfen, ob kommerzielle Nutzung, Bearbeitung und Veröffentlichung als Titelbild erlaubt sind. + +## **3. „Urheber / Fotograf“ verpflichtender machen** + +Das Feld **Urheber / Fotograf** sollte in den meisten Fällen Pflicht sein, außer vielleicht bei eigener Aufnahme, wenn der Name des Uploadenden automatisch hinterlegt wird. + +Besser wäre: + +**Urheber / Fotograf / Rechteinhaber** + +Denn nicht immer ist der Fotograf auch der Rechteinhaber. Bei Agenturen oder Unternehmen können die Rechte woanders liegen. + +## **4. „Copyright / Quelle“ klarer benennen** + +Das Feld „Copyright / Quelle“ ist etwas gemischt. Ich würde es aufteilen oder klarer formulieren: + +- **Copyright-Hinweis / Bildnachweis** +- **Quelle des Bildes** +- **Lizenz- oder Nachweis-URL** + +Beispiel: + +**Bildnachweis, wie er angezeigt werden soll** +`Foto: Max Mustermann / Beispiel GmbH` + +**Quelle / Fundstelle** +`https://...` + +**Lizenz-URL / Nachweis-URL** +`https://creativecommons.org/licenses/by/4.0/` oder Link zur Stocklizenz / Presseseite + +So vermeidest du, dass jemand nur „Internet“ oder „Google“ einträgt. + +## **5. Datei-Upload um Pflicht-Hinweise ergänzen** + +Beim Upload würde ich neben Dateityp und Größe noch einen kurzen Warnhinweis ergänzen: + +Bitte laden Sie nur Bilder hoch, für die Sie die erforderlichen Nutzungsrechte besitzen. Bilder aus Google, Social Media, Messenger-Gruppen oder fremden Websites dürfen nicht ohne ausdrückliche Erlaubnis verwendet werden. + +Das ist sehr hilfreich, weil genau dort viele Fehler passieren. + +## **6. Personenrechte besser abfragen** + +Dein Feld „Einwilligung abgebildeter Personen liegt vor“ ist gut, aber ich würde es differenzierter machen. + +Statt nur einem Schalter: + +**Sind Personen auf dem Bild erkennbar?** + +- Nein +- Ja, und die Einwilligung liegt vor +- Ja, aber es handelt sich um eine öffentliche Veranstaltung / redaktionelle Berichterstattung +- Unsicher + +Wenn „Ja“ oder „Unsicher“ gewählt wird, kannst du einen Hinweis anzeigen: + +Bei erkennbaren Personen können zusätzlich Persönlichkeits- oder Datenschutzrechte betroffen sein. Bitte stellen Sie sicher, dass eine Veröffentlichung zulässig ist. + +Der aktuelle Toggle „Einwilligung liegt vor“ ist gut, aber er setzt voraus, dass der Nutzer selbst erkennt, ob Personenrechte relevant sind. + +## **7. Property Rights / Marken / Kunstwerke ergänzen** + +Neben Personen sind auch diese Fälle kritisch: + +- Logos und Marken +- Kunstwerke +- private Innenräume +- Gebäude, Architektur, Museen +- Fahrzeuge mit Kennzeichen +- Veranstaltungsplakate oder Screenshots + +Ich würde daher ergänzen: + +**Enthält das Bild erkennbare Marken, Kunstwerke, geschützte Werke oder private Orte?** + +- Nein +- Ja, Rechte/Nutzung sind geklärt +- Unsicher + +Das schützt besonders bei PR-, Event- und Pressebildern. + +## **8. Rechtebestätigung präziser formulieren** + +Aktuell: + +Ich bestätige, dass ich zur Nutzung dieses Bildes berechtigt bin und alle Rechte geklärt sind. + +Ich würde es ausführlicher und rechtlich klarer machen: + +Ich bestätige, dass ich über die erforderlichen Rechte zur Veröffentlichung dieses Bildes verfüge. Dies umfasst insbesondere Urheberrechte, Nutzungsrechte, Persönlichkeitsrechte abgebildeter Personen sowie gegebenenfalls Marken-, Eigentums- oder sonstige Rechte Dritter. Ich bin berechtigt, das Bild auf diesem Presseportal veröffentlichen zu lassen. + +Optional zusätzlich: + +Mir ist bewusst, dass ich für fehlerhafte oder unvollständige Angaben verantwortlich bin. + +Je nach Portal kannst du das etwas freundlicher formulieren, aber inhaltlich sollte es klar sein. + +## **9. Lizenznachweis als Datei-Upload ermöglichen** + +Sehr sinnvoll wäre ein optionaler Upload: + +**Nachweis / Freigabe hochladen** + +Zum Beispiel: + +- Lizenzbestätigung +- E-Mail-Freigabe +- Model Release +- Vertrag +- Screenshot der Lizenzseite +- Pressefreigabe + +Das muss nicht öffentlich sichtbar sein, aber intern gespeichert werden. + +## **10. Sichtbarer Bildnachweis im Frontend** + +Ich würde im Formular klar anzeigen: + +**Dieser Bildnachweis wird öffentlich angezeigt:** +`Foto: Max Mustermann / Beispiel GmbH` + +Viele Nutzer verstehen besser, was sie eintragen müssen, wenn sie sehen, wo es später erscheint. + +## **11. Meine empfohlene Struktur** + +So würde ich das Formular aufbauen: + +1. **Bild hochladen** +2. **Titel / Alt-Text** +3. **Bildnachweis, öffentlich sichtbar** +4. **Urheber / Fotograf / Rechteinhaber** +5. **Lizenztyp** +6. **Lizenzdetails je nach Auswahl** +7. **Quelle / Lizenz-URL** +8. **Personen auf dem Bild?** +9. **Marken, Kunstwerke oder private Orte sichtbar?** +10. **Nachweis/Freigabe hochladen** +11. **Rechte bestätigen** + +Zusätzlich würde ich **Alt-Text** ergänzen. Nicht primär wegen Recht, sondern wegen Barrierefreiheit und SEO. + +## **Konkrete Anpassung deiner Felder** + +Aus deinem Screenshot würde ich ändern: + +**„Copyright / Quelle“**→ **„Öffentlicher Bildnachweis“** + +**„Urheber / Fotograf“**→ **„Urheber / Fotograf / Rechteinhaber“** + +**„Lizenz-URL optional“**→ **„Quelle oder Lizenznachweis-URL“** + +**„Einwilligung abgebildeter Personen liegt vor“** +→ ersetzen durch Auswahl: +**„Sind erkennbare Personen abgebildet?“** + +**„Bildrechte bestätigt“** +→ Pflicht-Checkbox mit ausführlicher Bestätigung. + +## **Besonders wichtig** + +Ich würde **„Sonstiges“ nie ohne Pflicht-Freitext erlauben**. Wenn jemand „Sonstiges“ wählt, sollte zwingend erklärt werden müssen, warum die Nutzung erlaubt ist. + +Außerdem würde ich bei riskanten Angaben wie **CC-NC**, **CC-ND**, **Unsicher**, **Sonstiges** oder fehlender Lizenz-URL entweder eine Warnung anzeigen oder eine manuelle Prüfung durch die Redaktion auslösen. \ No newline at end of file diff --git a/docs/user-admin/Presseportal – Konzept für Relaunch.md b/docs/user-admin/Presseportal – Konzept für Relaunch.md index 6201e05..46867f7 100644 --- a/docs/user-admin/Presseportal – Konzept für Relaunch.md +++ b/docs/user-admin/Presseportal – Konzept für Relaunch.md @@ -1,12 +1,14 @@ -> **Stand der Doku**: 21.05.2026 — dieses Konzept beschreibt den Zielzustand -> der Plattform. Mehrere Themen (KI-Vorprüfung, externe Meldungen, Tarife, -> Magic-Link-Flow, Korrektur-Hinweise, Score-System) sind konzeptuell hier -> ausgearbeitet, aber noch nicht oder nur rudimentär gebaut. Welcher Teil -> in welchem Zustand ist, steht jeweils in einer **„IST-Stand"-Box** am -> Anfang des betroffenen Abschnitts. +> **Stand der Doku**: 11.06.2026 — dieses Konzept beschreibt den Zielzustand +> der Plattform. Umgesetzt sind inzwischen die KI-Prüfung (§1, §15.1/15.2) +> und Bilder/Lizenzen (§2); offen bleiben externe Meldungen, Magic-Link-Flow, +> Korrektur-Hinweise und Trust-Score. Welcher Teil in welchem Zustand ist, +> steht jeweils in einer **„IST-Stand"-Box** am Anfang des Abschnitts. +> +> **Für Tarife/Credits (§8–10) gilt das +> [`Decision-Update Preisstruktur & Veröffentlichungs-Flow`](../Decision-Update%20Preisstruktur%20&%20Ver%C3%B6ffentlichungs-Flow.md).** > > Aktueller Code-vs-Konzept-Abgleich: [`docs/STATUS-ABGLEICH-USER-PANEL.md`](../STATUS-ABGLEICH-USER-PANEL.md). @@ -14,14 +16,21 @@ ## 1. KI-Freigabe-Workflow für Pressemitteilungen -> **IST-Stand 21.05.2026**: Die hier beschriebene KI-Vorpruefung ist noch -> nicht implementiert. Aktuell laeuft beim Submit zur Pruefung lediglich ein -> Blacklist-Check (`PressReleaseService::submitForReview` wirft -> `BlacklistViolationException` bei Treffern). Die Freigabe selbst erfolgt -> manuell durch einen Admin/Editor ueber die Admin-PM-Show-Page (Status: -> `draft → review → published | rejected | archived`). -> Der hier beschriebene Drei-Stufen-Workflow mit KI-Klassifikation, -> JSON-Antwort und Logging ist ein Phase-2/3-Thema. +> **IST-Stand 11.06.2026**: Der Drei-Stufen-Workflow ist **umgesetzt** +> (Detail-Doku: `Entwicklungsplan KI-Pruefung und Veroeffentlichung.md`, +> Phasen 0–5): +> +> - Jede Einreichung (Formular + API) laeuft durch den Blacklist-Hard-Filter +> und wird anschliessend asynchron KI-klassifiziert (Rot/Gelb/Gruen, +> OpenAI-Treiber mit deterministischem Fallback, Queue `classification`). +> - Routing: Rot → `rejected` + Mail mit Begruendung, Gelb → manuelle +> Admin-Queue, Gruen → Auto-Publish (sofort oder zum geplanten Termin). +> - Jede Entscheidung wird in `ki_audits` protokolliert (Provider, Modell, +> Begruendung, Raw-Response); Re-Klassifikation bei Titel-/Text-Aenderung. +> - Zusaetzlich umgesetzt: Content-Score 0–100 → Stufe (§15.2). +> +> Offen: Trust-Score (§15.3), Live-Anzeige des Ergebnisses ohne Reload, +> DSGVO-Aufbewahrungsregel fuer `raw_response`. ### Ziel @@ -90,19 +99,19 @@ KI-Prüfungen müssen nachvollziehbar sein, dürfen aber nicht unbegrenzt und un ## 2. Bilder & Lizenzen -> **IST-Stand 21.05.2026**: Der Bild-Upload ist nur teilweise umgesetzt. -> Aktuell: +> **IST-Stand 11.06.2026**: Lizenz-/Rechteerfassung und Titelbild sind +> umgesetzt (Phase 8F–8H + Umbau 10./11.06., Detail-Doku: +> `Umsetzung Pressemitteilung Bearbeitung Titelbild Veroeffentlichung.md`, +> Fachvorgabe: `Lizenztyp Bildupload.md`): > -> - Nur Quelle „Eigenes Bild hochladen". Stock und KI sind nicht angebunden. -> - Im `press-release-images-manager` werden bisher nur `title` und -> `copyright` als Freitext erfasst — die im folgenden geforderten -> Pflichtfelder (Urheber, Lizenz-Typ, Lizenz-URL, Personen-Einwilligung, -> Rechte-Bestaetigung) sind in Phase 8H eingeplant. -> - Variantenbildung (`thumb` / `medium` / `large`) erfolgt automatisch -> ueber `App\Services\Image\ImageService`. -> - `is_preview`-Flag im Modell `PressReleaseImage` ist da; jede PM kann -> genau ein Vorschaubild haben. Default-SVG-Platzhalter fuer PMs ohne -> Titelbild sind in Phase 8F/8G in Planung. +> - Ein **Titelbild pro PM** (Cover-Variante 1280×580, Original wird nach +> Verarbeitung geloescht) oder SVG-Platzhalter aus dem zentralen Set +> (`App\Enums\PressReleasePlaceholder`, `PressReleaseCoverImage`-Resolver). +> - Vollstaendiges Rechteformular: Urheber, 7 Lizenztypen, Lizenzdetails, +> Lizenz-/Quell-URL, Personen- und Sachrechte-Status, interne Notizen, +> Rechte-Bestaetigung; bedingte Pflichtfelder + Risikohinweise. +> - Nur Quelle „Eigenes Bild hochladen". **Stock und KI sind nicht +> angebunden** (weiterhin offen, ebenso der KI-Wasserzeichen-Check). ### Upload-Workflow @@ -515,19 +524,24 @@ Eigene Statistiken trennen: ## 8. Preismodell – Tarife (überarbeitet) -> **IST-Stand 21.05.2026**: Das Tarif- und Credit-System ist noch nicht +> **⚠️ Ueberschrieben (11.06.2026)**: Die Abschnitte 8, 9 und 10 sind durch +> das [`Decision-Update Preisstruktur & Veröffentlichungs-Flow`](../Decision-Update%20Preisstruktur%20&%20Ver%C3%B6ffentlichungs-Flow.md) +> ersetzt. Wichtigste Aenderungen: Kontingente Pro 25 / Agency 60 (statt +> 60/150), Jahrespreis als „2 Monate gratis", Bonus-Credits aus der +> Tarif-Tabelle entfernt, Launch-Credits auf Extra-PM / Boost / +> PDF-Nachweis reduziert, Slot-Verbrauch erst bei Veroeffentlichung. +> Der folgende Text bleibt als urspruengliche Zielvorstellung erhalten. +> +> **IST-Stand 11.06.2026**: Das Tarif- und Credit-System ist noch nicht > implementiert. Es gibt: > > - Eine Tabelle `user_payment_options` (mit Pivot zu `companies`). > - Eine Tabelle `invoices` (aktuell + Legacy ueber `legacy_invoices`). -> - Keine Tarif-Stufen, kein Kontingent-Counter pro User, keine -> Stripe-Anbindung, kein Auto-Refill. -> -> Phase 8 (siehe `docs/PHASE-8-USER-PANEL-PLAN.md`) bereitet die -> Kontingent-Anzeige im Veroeffentlichungs-Modal vor — mit zwei -> temporaeren Spalten auf `users` (`press_release_quota`, -> `press_release_quota_used_this_month`) als Stub, damit das echte -> Tarif-Modell spaeter ohne UI-Aenderung andocken kann. +> - Keine Tarif-Stufen, keine Stripe-Anbindung, kein Auto-Refill. +> - Den Phase-8-**Quota-Stub** auf `users` (`press_release_quota`, +> `press_release_quota_used_this_month`) samt Kontingent-Anzeige im +> Veroeffentlichungs-Modal — zaehlt aktuell beim Einreichen, laut +> Decision-Update kuenftig bei Veroeffentlichung. ### Grundlogik @@ -854,6 +868,11 @@ retention_policies ## Abschnitt 15: Score-Architektur +> **IST-Stand 11.06.2026**: §15.1 (Klassifikations-Score Rot/Gelb/Grün) und +> §15.2 (Content-Score 0–100 → Stufe) sind **umgesetzt** — siehe +> `Entwicklungsplan KI-Pruefung und Veroeffentlichung.md` (Phasen 2–5). +> §15.3 (Trust-Score) ist weiterhin offen (Phase 3). + Die Plattform arbeitet mit drei voneinander unabhängigen Scores. Sie haben unterschiedliche Funktionen, werden unterschiedlich berechnet und an unterschiedlichen Stellen wirksam. Die Trennung ist zentral, weil sie unterschiedliche Datenmodelle und Update-Logiken betrifft. ### 15.1 Klassifikations-Score (Eintritts-Filter) diff --git a/docs/user-admin/Umsetzung Pressemitteilung Bearbeitung Titelbild Veroeffentlichung.md b/docs/user-admin/Umsetzung Pressemitteilung Bearbeitung Titelbild Veroeffentlichung.md new file mode 100644 index 0000000..d2b13bd --- /dev/null +++ b/docs/user-admin/Umsetzung Pressemitteilung Bearbeitung Titelbild Veroeffentlichung.md @@ -0,0 +1,277 @@ +# Umsetzung Pressemitteilung bearbeiten: Titelbild, Rechte, Veröffentlichung + +Stand: 11.06.2026 + +Diese Notiz dokumentiert die zuletzt umgesetzten Anpassungen an der Bearbeitung von Pressemitteilungen im User Panel und an den parallel genutzten Admin-Formularen. + +## Betroffener Bereich + +- Customer Create/Edit: `resources/views/livewire/customer/press-releases/create.blade.php` +- Customer Edit: `resources/views/livewire/customer/press-releases/edit.blade.php` +- Admin Create/Edit: `resources/views/livewire/admin/press-releases/create.blade.php`, `resources/views/livewire/admin/press-releases/edit.blade.php` +- Show/Index (Customer + Admin) für die Termin-Anzeige: `resources/views/livewire/customer/press-releases/{show,index}.blade.php`, `resources/views/livewire/admin/press-releases/{show,index}.blade.php` +- Model (Zeitzonen-Konstante + Accessoren): `app/Models/PressRelease.php` +- Titelbild-Manager: `resources/views/livewire/components/press-release-images-manager.blade.php` +- Platzhalter-Auswahl: `resources/views/livewire/components/press-release-placeholder-picker.blade.php` +- Platzhalter-Dateien: `public/images/press-release-placeholders` +- Layout-CSS: `resources/css/shared/hub-components.css` + +## Titelbild-Platzhalter + +Die Platzhalter für Pressemitteilungs-Titelbilder wurden erweitert. + +- Die Varianten werden über `App\Enums\PressReleasePlaceholder` verwaltet. +- Die SVG-Dateien liegen lokal unter `public/images/press-release-placeholders`. +- Der Picker lädt die lokalen Varianten in `resources/views/livewire/components/press-release-placeholder-picker.blade.php`. +- Das Modal wurde für mehr Varianten verbreitert und mit einer scrollbaren Grid-Darstellung versehen. + +Ziel: Wenn noch kein eigenes Titelbild vorhanden ist, kann ein optisch passender Platzhalter gewählt werden. + +## Titelbild-Upload + +Der Upload wurde auf ein einzelnes Titelbild begrenzt. + +- Es kann vorerst nur ein Titelbild pro Pressemitteilung hochgeladen werden. +- Wenn ein Titelbild vorhanden ist, wird die Platzhalter-Card ausgeblendet. +- Das Upload-Formular wird ebenfalls ausgeblendet, solange ein Titelbild existiert. +- Das vorhandene Titelbild wird in einer eigenen Bild-Card angezeigt. +- In der Bild-Card werden Titel, Größe und Bildnachweis/Copyright angezeigt. +- Das Titelbild kann gelöscht werden; danach erscheinen Platzhalter und Upload-Formular wieder. + +Das Upload-Formular ist einklappbar: + +- Im Ausgangszustand erscheint nur der Hinweis, dass ein Titelbild fehlt. +- Über „Eigenes Titelbild hochladen" wird das Formular geöffnet. +- Über „Abbrechen" wird das Formular wieder geschlossen und zurückgesetzt. + +## Bildverarbeitung und Speicherverhalten + +Die Bildverarbeitung wurde auf die Titelbild-Nutzung optimiert. + +- Erlaubte Formate: JPG, PNG, WebP. +- Maximale Dateigröße: 16 MB. +- Nicht previewfähige Dateien wie TIFF lösen keine Livewire-Preview-Exception mehr aus; sie werden über die Validierung abgefangen. +- Für Pressemitteilungsbilder wird eine Cover-Variante erzeugt: 1280 x 580 px. +- Der kanonische Bildpfad zeigt auf die Cover-Variante. +- Das Original wird nach der Variantenerzeugung gelöscht, um Speicherplatz zu sparen. +- Breite und Höhe in der Oberfläche beziehen sich auf die gespeicherte Cover-Version, nicht auf das Original. + +Relevante Datei: `app/Services/Image/ImageService.php`. + +## Lizenz- und Rechteformular + +Das Formular wurde an die Vorgaben aus `docs/user-admin/Lizenztyp Bildupload.md` angepasst. + +Erfasste Felder: + +- Titel / Alt-Text über das bestehende `title`-Feld. +- Öffentlicher Bildnachweis über das bestehende `copyright`-Feld. +- Urheber / Fotograf / Rechteinhaber über `author`. +- Lizenztyp über `license_type`. +- Lizenzdetails über `license_detail`. +- Lizenz-URL über `license_url`. +- Quelle / Fundstelle über `source_url`. +- Personenrechte über `people_rights_status`. +- Marken, Kunstwerke, geschützte Werke oder private Orte über `property_rights_status`. +- Interne Notizen über `rights_notes`. +- Rechtebestätigung über `rights_confirmed_at`. + +Lizenztypen: + +- Eigene Aufnahme +- Creative-Commons-Lizenz +- Agentur-/Stockbild-Lizenz +- Vom Urheber / Fotografen freigegeben +- Presse-/PR-Bild mit Nutzungsfreigabe +- Gemeinfrei / Public Domain / CC0 +- Sonstige Lizenz / Sondervereinbarung + +Wichtige Regeln: + +- „Bitte wählen" ist der Ausgangszustand. +- „Unsicher" wurde aus den Auswahlmöglichkeiten entfernt. +- Am Ende muss der Uploadende die Verantwortung für die Rechte bestätigen. +- Creative-Commons-Lizenzen erfassen zusätzlich die konkrete CC-Variante. +- CC-, Stock-/Agentur- und Presse-/PR-Lizenzen verlangen eine Lizenz- oder Nachweis-URL. +- „Sonstige Lizenz / Sondervereinbarung" verlangt einen Pflicht-Freitext. +- Risikohinweise werden bei eingeschränkten oder unklaren Lizenzfällen angezeigt. + +Relevante Dateien: + +- `app/Enums/ImageLicenseType.php` +- `app/Models/PressReleaseImage.php` +- `database/migrations/2026_06_10_154249_add_rights_detail_fields_to_press_release_images_table.php` +- `resources/views/livewire/components/press-release-images-manager.blade.php` + +## Veröffentlichung + +Die Veröffentlichungs-Box wurde vereinfacht. + +Sichtbar sind nur noch: + +- Sofort nach Freigabe +- Geplanter Termin + +Embargo / Sperrfrist wurde in den Formularen aus der Oberfläche entfernt, weil es aktuell noch keine sinnvolle Anwendung im User-Flow gibt. + +Technisches Verhalten: + +- `scheduled_at` bleibt erhalten und wird weiterhin gespeichert. +- `embargo_at` wird in den betroffenen Formularen nicht mehr gesetzt und beim Speichern auf `null` geführt. +- Für den geplanten Termin wird `flux:date-picker` für das Datum verwendet. +- Für die Uhrzeit wird `flux:time-picker` verwendet. +- Intern werden Datum und Uhrzeit wieder zu `scheduledAt` kombiniert. +- Der geplante Termin muss mindestens 5 Minuten in der Zukunft liegen. +- Bei zu frühem Termin wird direkt ein Fehler gesetzt; beim Speichern greift die Validierung ebenfalls. + +Betroffene Properties: + +- `scheduledDate` +- `scheduledTime` +- `scheduledAt` + +## Zeitzonen-Handling für geplante Veröffentlichung + +Stand: 11.06.2026 (nachgezogen) + +Die Anwendung läuft serverseitig in UTC (`config/app.php` → `timezone = 'UTC'`). +Geplante Termine werden aber von Redaktion und Kunden in **deutscher Zeit** +gedacht. Vorher wurde die im Formular eingegebene Uhrzeit naiv als UTC +interpretiert, wodurch die Veröffentlichung um den Berlin-Offset (im Sommer ++2 h) verschoben stattfand. Das ist behoben. + +Grundprinzip: + +- Eingabe und Anzeige erfolgen in **Europe/Berlin**. +- Gespeichert wird weiterhin **UTC**. +- Wichtig: Laravel konvertiert beim Speichern **nicht** automatisch nach UTC. + Deshalb wird der eingegebene Wert beim Parsen explizit als Berlin + interpretiert und mit `->utc()` umgewandelt; beim Laden wird umgekehrt von + UTC nach Berlin gewandelt. + +Zentrale Stelle: + +- `App\Models\PressRelease::DISPLAY_TIMEZONE` (`'Europe/Berlin'`) ist die + Single Source of Truth. +- `PressRelease::scheduledAtLocal()` und `PressRelease::embargoAtLocal()` + liefern die Termine in der Anzeige-Zeitzone für alle Views. + +Verhalten in den Formularen (Customer **und** Admin, Create **und** Edit): + +- Helper `scheduledAtUtc()`: parst die naiven Eingabefelder als Berlin und + gibt den UTC-Zeitpunkt für die Speicherung zurück. +- Die „mind. 5 Minuten in der Zukunft"-Prüfung läuft jetzt über eine + zeitzonenbewusste Closure-Regel statt über die naive `after:`-Regel. +- Beim Bearbeiten (`mount`) wird `scheduled_at` von UTC nach Berlin gewandelt, + bevor Datum/Uhrzeit in die Eingabefelder gefüllt werden. + +Anzeige (lokalisiert auf Berlin): + +- Customer-Show/-Index und Admin-Show/-Index: geplanter Termin und Embargo + werden über `scheduledAtLocal()` / `embargoAtLocal()` ausgegeben. + +Bewusst (noch) nicht umgestellt: + +- `published_at`, `created_at` und die Status-Log-Zeitstempel werden weiterhin + in UTC angezeigt. Eine vollständige Anzeige-Lokalisierung dieser Felder ist + als Folgeschritt vorgesehen. + +## Aufräumung: Scheduling-Logik und Queries + +Im Zuge der Zeitzonen-Umstellung wurden zwei Altlasten in allen vier +PM-Formularen bereinigt: + +- **Doppelte Termin-Synchronisierung entfernt:** Die Termin-Logik lief vorher + sowohl im generischen `updated()`-Hook als auch in den spezifischen + `updated{PublishMode,ScheduledDate,ScheduledTime}`-Hooks – also doppelt. + `updated()` enthält jetzt nur noch die generische Re-Validierung bereits + fehlerhafter Felder; die Synchronisierung liegt ausschließlich in den + spezifischen Hooks. +- **Redundante Queries reduziert:** Im Customer-Edit wird die geladene + Pressemitteilung pro Request memoisiert (`mount()`, `with()` und `save()` + greifen sonst jeweils mit einer eigenen Query auf dieselbe PM zu). + +## Responsive Layout + +Das Layout der Pressemitteilungsformulare wurde entkoppelt von der globalen Sidebar-Logik. + +Die globale Flux-Sidebar bleibt im stabilen Standardzustand: + +- `flux:sidebar sticky stashable` +- Header- und Toggle-Sichtbarkeit weiter über `lg:hidden` + +Das eigentliche Formularlayout wird über eigene Klassen gesteuert: + +- `.pr-editor-layout` +- `.pr-editor-side` + +Regel in `resources/css/shared/hub-components.css`: + +```css +@media (min-width: 1180px) { + .pr-editor-layout { + grid-template-columns: minmax(0, 1fr) 360px; + } + + .pr-editor-side { + position: sticky; + top: 1rem; + } +} +``` + +Verhalten: + +- Unter 1180 px steht die rechte Formularbox unterhalb des Hauptinhalts. +- Ab 1180 px steht die rechte Formularbox wieder rechts. +- Die rechte Box wird ab 1180 px sticky. +- Die globale linke Navigation bleibt davon unberührt. + +## Button-Varianten + +Sekundäre `variant="ghost"`-Buttons in Blade-Views wurden breit auf `variant="filled"` umgestellt, weil die Ghost-Buttons optisch zu wenig als Buttons erkennbar waren. + +Umfang: + +- Alle Blade-Views unter `resources/views` wurden auf verbleibende `variant="ghost"` geprüft. +- Markdown-Dokumentation wurde dabei nicht als UI geändert. + +## Tests und Verifikation + +Ergänzte bzw. angepasste Tests: + +- `tests/Feature/PressReleasePlaceholderTest.php` +- `tests/Feature/PressReleaseImageLicenseTest.php` +- `tests/Feature/CustomerPressReleaseSchedulingFormTest.php` +- `tests/Feature/Admin/AdminPressReleaseSchedulingTest.php` + +Für die Zeitzonen-Umstellung zusätzlich angepasst (Assertions auf +Berlin-Werte umgestellt): + +- `tests/Feature/PressReleaseShowPhase8aTest.php` +- `tests/Feature/Admin/AdminPressReleaseShowTest.php` + +Zuletzt erfolgreich ausgeführte Checks: + +- `php artisan test --compact tests/Feature/CustomerPressReleaseSchedulingFormTest.php tests/Feature/Admin/AdminPressReleaseSchedulingTest.php tests/Feature/Admin/AdminPressReleaseShowTest.php tests/Feature/PressReleaseShowPhase8aTest.php tests/Feature/PressReleaseIndexPhase8bTest.php` +- `vendor/bin/pint --dirty --format agent` +- Volle Suite: 400 passed (die zwei roten Tests `PressReleaseImageApiTest` und + `CustomerPressReleaseCreatePhase7Test` sind vorbestehende, unabhängige WIP- + Failures – per Stash-Test verifiziert, dass sie auch ohne diese Änderungen + scheitern). + +Vorher zusätzlich grün gelaufen: + +- `php artisan test --compact tests/Feature/PressReleasePlaceholderTest.php tests/Feature/PressReleaseImageLicenseTest.php tests/Feature/CustomerPressReleaseEditPhase7Test.php` +- Phase-8-nahe Show-/Index-/Attachment-/Admin-Tests. + +## Bewusst noch nicht umgesetzt + +- Optionaler Upload von Lizenznachweisen oder Freigabe-Dokumenten. +- Reaktivierung des separaten Anhang-Managers. +- Manuelle redaktionelle Prüf-Workflows für riskante Lizenzfälle. +- Vollständige Medienbibliothek statt einzelnes Titelbild. +- Frontend-Ausgabe des Bildnachweises außerhalb der Bearbeitungsoberfläche, sofern noch nicht separat angebunden. +- Anzeige-Lokalisierung von `published_at`, `created_at` und Status-Log-Zeitstempeln (aktuell weiterhin UTC). +- Klärung/Anpassung der Auto-Publish-Policy: geplante PMs (Status `review` + fälliger `scheduled_at`) werden vom Scheduler-Command automatisch veröffentlicht – ohne separate redaktionelle Freigabe. Wird in einem eigenen Schritt geprüft. + diff --git a/docs/user-admin/checkliste-user-backend.md b/docs/user-admin/checkliste-user-backend.md index eac641f..96e6f2c 100644 --- a/docs/user-admin/checkliste-user-backend.md +++ b/docs/user-admin/checkliste-user-backend.md @@ -1,13 +1,16 @@ # Checkliste User Backend -Stand: 21.05.2026 (Phase 7 abgeschlossen, Phase 8 in Planung) +Stand: 11.06.2026 (Phase 7 + Phase 8 + KI-Pruef-Pipeline abgeschlossen; naechster Block: Zahlung/Tarife + Veroeffentlichungs-Flow laut Decision-Update) Diese Checkliste fasst den aktuellen Stand des User Backends zusammen und trennt erledigte Punkte von den naechsten sinnvollen Umsetzungsschritten. Begleitende Dokumente: - `docs/STATUS-ABGLEICH-USER-PANEL.md` — Konzept-vs-Code-Abgleich pro Page. -- `docs/PHASE-8-USER-PANEL-PLAN.md` — Detail-Plan der naechsten Sub-Paeckchen. +- `docs/Decision-Update Preisstruktur & Veröffentlichungs-Flow.md` — verbindliche Launch-Entscheidungen zu Tarifen, Kontingenten und Flow. +- `docs/user-admin/Entwicklungsplan KI-Pruefung und Veroeffentlichung.md` — KI-Klassifikation + Content-Score (Phasen 0–5 erledigt). +- `docs/user-admin/Umsetzung Pressemitteilung Bearbeitung Titelbild Veroeffentlichung.md` — Titelbild/Lizenzformular/Zeitzonen-Umbau (10./11.06.). +- `docs/PHASE-8-USER-PANEL-PLAN.md` — Phase-8-Plan (abgeschlossen). - `dev/frontend/hub-flux/19-PHASE-7-PRESS-RELEASE-FORM.md` — Phase-7-Abschluss. - `dev/frontend/hub-flux/PROGRESS.md` — Tagebuch der Hub-Migration. @@ -71,42 +74,83 @@ Begleitende Dokumente: - [x] Smooth-Scrolling zum ersten Validation-Fehler nach Save (`resources/js/portal-form-hooks.js`). - [x] Pre-Submit-Check-Liste (`@computed presubmitChecks`) zeigt vor dem Einreichen offene Pflichtfelder und Empfehlungen. -## Phase 8 — User-Panel-Konsolidierung (in Planung) +## Phase 8 — User-Panel-Konsolidierung (abgeschlossen) -Vollstaendiger Plan: `docs/PHASE-8-USER-PANEL-PLAN.md`. +Vollstaendiger Plan: `docs/PHASE-8-USER-PANEL-PLAN.md`. Roadmap-Abschluss: +`dev/frontend/hub-flux/20-PHASE-8-USER-PANEL.md`. -- [ ] Show-Page-Luecken schliessen (Subtitle, Scheduling, Embargo, Boilerplate-Override) — Customer + Admin (8A). -- [ ] Listen-Indikatoren fuer geplante Veroeffentlichung und Embargo (8B). -- [ ] Pressekontakt-Warn-Box in Sidebar-Card, wenn kein Kontakt gewaehlt (8C). -- [ ] Doku-Pflege: `docs/user-admin/*` an IST-Stand ziehen (8D, dieses Dokument). -- [ ] Firmen-Liste auf Mockup-Niveau (Counter-Strip, Saved-Views, Filter-Chips, Card/List-Toggle, Rollen-Legende) (8E). -- [ ] Set wiederverwendbarer SVG-Platzhalter fuer PM-Titelbilder + Auswahl-Modal (8F). -- [ ] Titelbild-Schema in `press_releases` (Default-Platzhalter pro PM, `PressReleaseCoverImage`-Resolver) (8G). -- [ ] FluxUI `flux:file-upload` im Image-Manager inkl. Pflichtfelder fuer Urheber, Lizenz-Typ, Lizenz-URL, Rechte-Bestaetigung (8H). -- [ ] Veroeffentlichungs-Modal mit rechtlichen Hinweisen + Kontingent-Anzeige (Customer) (8I). -- [ ] Kontingent-Stub im Datenmodell (Spalten auf `users`, monatlicher Reset-Command) als Vorbereitung fuer das Tarif-Modul (8J). -- [ ] Tests, Pint, Build, Roadmap-Update (8K). +- [x] Show-Page-Luecken schliessen (Subtitle, Scheduling, Embargo, Boilerplate-Override) — Customer + Admin (8A). +- [x] Listen-Indikatoren fuer geplante Veroeffentlichung und Embargo (8B). +- [x] Pressekontakt-Warn-Box in Sidebar-Card, wenn kein Kontakt gewaehlt (8C). +- [x] Doku-Pflege: `docs/user-admin/*` an IST-Stand ziehen (8D, dieses Dokument). +- [x] Firmen-Liste auf Mockup-Niveau (Counter-Strip, Saved-Views, Filter-Chips, Card/List-Toggle, Rollen-Legende) (8E) — Tests: `CustomerPressKitIndexPhase8eTest`, `CustomerPressKitCreatePhase8eTest`. +- [x] Set wiederverwendbarer SVG-Platzhalter fuer PM-Titelbilder + Auswahl-Modal (8F) — `App\Enums\PressReleasePlaceholder`, ``, Picker `components.press-release-placeholder-picker`. +- [x] Titelbild-Schema in `press_releases` (`placeholder_variant`, deterministischer Default, `PressReleaseCoverImage`-Resolver, Hero in Customer-/Admin-Show) (8G). +- [x] Bild-Upload mit Lizenz-Pflichtfeldern (Urheber, Lizenz-Typ, Lizenz-URL bedingt, Personen-Einwilligung, Rechte-Bestaetigung) im Image-Manager (8H). Hinweis: Upload-Control bleibt `flux:input type=file` statt `flux:file-upload` (Stabilitaet); Lizenzerfassung vollstaendig. +- [x] Veroeffentlichungs-Modal mit rechtlichen Hinweisen (Platzhalter, anwaltlich zu pruefen) + Kontingent-Anzeige (Customer-Show) (8I). +- [x] Kontingent-Stub im Datenmodell (`users.press_release_quota` + `..._used_this_month`, Decrement in `submitForReview`, monatlicher `press-releases:reset-monthly-quota`-Command) (8J). +- [x] Tests, Pint, Build, Roadmap-Update (8K). + +## KI-Pruef-Pipeline — Klassifikation & Content-Score (abgeschlossen 11.06.2026) + +Vollstaendiger Plan mit Phasen-Details: `docs/user-admin/Entwicklungsplan KI-Pruefung und Veroeffentlichung.md`. + +- [x] Einreichungs-Modal vereinheitlicht: `confirm-submit-review` in Customer-Show, -Create und -Edit (Phase 0). +- [x] API-Absicherung: `status` nicht mehr per API setzbar, eigene Submit-Route durch denselben Funnel (Phase 1). +- [x] Datenmodell: `press_releases.classification`/`classified_at`, `ki_audits`-Audit-Tabelle (Phase 2). +- [x] KI-Klassifikation Rot/Gelb/Gruen, asynchron ueber Queue `classification`, OpenAI-Treiber + deterministischer Fallback (Phase 3). +- [x] Status-Routing: Rot → abgelehnt + Mail, Gelb → manuelle Admin-Queue, Gruen → Auto-Publish (sofort/zum Termin); Scheduler publiziert nur gruene PMs (Phase 4). +- [x] Admin: KI-Badge + Klassifikations-Filter im Index, KI-Begruendung in der Show, On-Demand-„Pruefung"-Button mit Anbieter-Override. +- [x] Re-Klassifikation und Re-Score bei Titel-/Text-Aenderung (Customer, Admin, API). +- [x] Content-Score 0–100 → Stufe Standard/Geprueft/Hochwertig inkl. Editor-Panel und Badges (Phase 5). + +## Titelbild, Lizenzen & Termin-Handling (abgeschlossen 10./11.06.2026) + +Details: `docs/user-admin/Umsetzung Pressemitteilung Bearbeitung Titelbild Veroeffentlichung.md`. + +- [x] Upload auf ein Titelbild pro PM begrenzt; Cover-Variante 1280×580, Original wird nach Verarbeitung geloescht. +- [x] Lizenz-/Rechteformular nach `Lizenztyp Bildupload.md` erweitert (7 Lizenztypen, Personen-/Sachrechte-Status, Quelle, Notizen, Risikohinweise). +- [x] Veroeffentlichungs-Box vereinfacht: nur „Sofort nach Freigabe" und „Geplanter Termin"; Embargo aus der Form-UI entfernt (`embargo_at` bleibt im Schema). +- [x] Zeitzonen-Handling: Eingabe/Anzeige Europe/Berlin, Speicherung UTC (`PressRelease::DISPLAY_TIMEZONE`, `scheduledAtLocal()`). +- [x] PM-Editor-Layout responsive entkoppelt (`.pr-editor-layout`); Ghost-Buttons auf `filled` umgestellt. + +## Naechster Block — Zahlung, Tarife & Veroeffentlichungs-Flow (Launch) + +Verbindliche Entscheidungen: `docs/Decision-Update Preisstruktur & Veröffentlichungs-Flow.md`. Umsetzungsplan: `docs/PHASE-9-FLOW-UND-TARIFE-PLAN.md`. + +- [ ] Gelb-Routing auf Direkt-Live umstellen (Entscheidung 12.06.: Gelb geht wie Gruen online, keine manuelle Queue; nur Rot wird abgelehnt). +- [ ] Tarif-Datenmodell + Checkout/Zahlung (Starter/Business/Pro/Agency, Einzel-PM 19 €, Jahrespreis „2 Monate gratis"). +- [ ] Submit-Gate: „Speichern & zur Pruefung einreichen" hinter aktiver Buchung; „Speichern" bleibt immer frei. +- [ ] Slot-Verbrauch von Einreichung auf **Veroeffentlichung** umstellen (Rot = kein Slot-Verbrauch); Quota-Stub abloesen. +- [ ] Tageslimit je Tier (Business 2 / Pro 3 / Agency 5), gilt auch fuer Extra-PMs. +- [ ] Launch-Credits: Extra-PM, Boost (nur gruene PMs), Veroeffentlichungsnachweis-PDF; Credit-Anker 1 Credit = 1 €. +- [ ] Einzel→Abo-Bruecke (19 € Anrechnung innerhalb 30 Tagen). +- [ ] Rechtstexte im Einreichungs-Modal anwaltlich pruefen lassen (Platzhalter, Go-Live-Blocker). +- [ ] Queue-Worker fuer `classification` im Produktions-Setup verankern. ## Phase 2 / spaeter +- [ ] Vorab-KI-Pruefung, Redigieren/Nachbessern + Re-Check-Loop, Pruefzaehler und Credit-Overflow (Decision-Update §7). - [ ] Magic-Link-Zugriff fuer Firmen-E-Mail-Adressen konzipieren und umsetzen. - [ ] Separate `token_requests`-Tabelle fuer nicht-userbasierte Zugriffe anlegen. - [ ] Zugriff per Firmen-E-Mail so begrenzen, dass nur passende Firmen und Pressemitteilungen sichtbar werden. -- [ ] Trust Score fuer User/Firmen konzipieren und im Admin Backend justierbar machen. -- [ ] Moderationslogik an Trust Score und Freigabeprozess anbinden. -- [ ] Aufbewahrungsfristen fuer Magic Links, Token Requests, API Logs und Statuslogs definieren und technisch absichern. +- [ ] Trust Score fuer User/Firmen konzipieren und im Admin Backend justierbar machen (KI-Plan Phase 6). +- [ ] Moderationslogik an Trust Score anbinden (Klassifikations-Routing existiert bereits). +- [ ] Stufen-Badges (Geprueft/Hochwertig) im oeffentlichen Web-Frontend ausgeben. +- [ ] Aufbewahrungsfristen fuer Magic Links, Token Requests, API Logs, Statuslogs und `ki_audits`-Raw-Responses (DSGVO) definieren und technisch absichern. - [ ] Admin-editierbare Textvorlagen fuer neutrale Tombstone-/Entfernungs- und Systemtexte einbauen. - [ ] API-Nutzungs-Log im User Backend sichtbar machen. - [ ] Benachrichtigungen und Newsletter-Abos im Konto-Bereich ausbauen. - [ ] Zahlungsarten und firmenbezogene Zahlungsoptionen im User Backend aktivieren. -- [ ] Credits, Tarife und Add-ons an ein echtes Preismodell anbinden. - [ ] Statistikbereich fuer Firmen und Pressemitteilungen umsetzen. - [ ] Medienbereich aus vorhandenen Pressemitteilungsbildern ableiten; spaeter echte Medienbibliothek pruefen. - [ ] Team-/Rollenverwaltung fuer Firmen im User Backend ergaenzen. +- [ ] Anzeige-Lokalisierung von `published_at`, `created_at` und Status-Log-Zeitstempeln (aktuell UTC). ## Hinweise -- Phase 1 ist funktional abgeschlossen; Phase 7 (PM-Form-Refactor) ebenfalls — siehe Plan-Doku oben. -- Phase 8 fokussiert das User-Panel: Firmen-Liste auf Mockup-Niveau, PM-Titelbilder mit SVG-Platzhaltern und Veroeffentlichungs-Modal mit rechtlichen Hinweisen. -- Die Admin-Oberflaeche bekommt in Phase 8 nur die Phase-7-Parallelitaeten (Show-Page-Felder, Listen-Indikatoren); groessere Admin-Aenderungen kommen erst mit Phase 2. +- Phase 1, Phase 7 (PM-Form-Refactor), Phase 8 (User-Panel-Konsolidierung) und die KI-Pruef-Pipeline (Phasen 0–5) sind abgeschlossen — siehe Plan-Dokus oben. +- Fuer Preise, Kontingente und den Veroeffentlichungs-Flow gilt ausschliesslich das Decision-Update vom 11.06.2026; aeltere Tarif-Tabellen in `Konzept-Update 1` und im Relaunch-Konzept sind ueberschrieben. +- Der Quota-Stub (3 PM/Monat, zaehlt beim Einreichen) bleibt bis zum Tarif-Modul aktiv; die Umstellung auf Slot-Verbrauch bei Veroeffentlichung ist Teil des Launch-Blocks. +- Die KI-Klassifikation laeuft asynchron — in Produktion wird ein Queue-Worker fuer die Queue `classification` benoetigt (Test-Drain: `php artisan classification:work`). - Anhaenge sind aktuell aus Sicherheitsgruenden deaktiviert, Tabelle und Komponente bleiben aber erhalten und werden in einem separaten Audit-Track reaktiviert. diff --git a/docs/user-admin/user-zusammenhaenge.md b/docs/user-admin/user-zusammenhaenge.md index 97fd11b..4561ea2 100644 --- a/docs/user-admin/user-zusammenhaenge.md +++ b/docs/user-admin/user-zusammenhaenge.md @@ -1,9 +1,33 @@ # User-Admin: Zusammenhänge und relevante Daten -Stand: 2026-05-21 (aktualisiert nach Phase 7) +Stand: 2026-06-11 (aktualisiert nach Phase 8 + KI-Pipeline) Diese Notiz beschreibt den User als fachlichen Mittelpunkt für die weitere Konzeption des Admin-User-Bereichs. Grundlage sind die aktuellen Models und Migrationen im Laravel-Projekt. +> **Was seit Phase 8 + KI-Pipeline dazugekommen ist (29.05.–11.06.2026)**: +> +> - `press_releases`: `placeholder_variant` (SVG-Titelbild-Platzhalter, 8G), +> `classification`/`classified_at` (KI-Klassifikation Rot/Gelb/Grün), +> `content_score`/`content_tier`/`scored_at` (Content-Score). +> - `press_release_images`: Lizenz-/Rechtefelder `author`, `license_type`, +> `license_detail`, `license_url`, `source_url`, `people_rights_status`, +> `property_rights_status`, `rights_notes`, `persons_consent`, +> `rights_confirmed_at` (8H + Erweiterung 10.06.). +> - `users`: Quota-Stub `press_release_quota` + +> `press_release_quota_used_this_month` (8J; wird vom Tarif-Modul abgelöst). +> - Neue Tabelle `ki_audits` (Modell `KiAudit`, append-only Audit-Log jeder +> KI-Entscheidung) mit Relation `PressRelease::kiAudits()`. +> - Neue Enums: `PressReleasePlaceholder`, `ImageLicenseType`, +> `PressReleaseClassification`, `PressReleaseContentTier`. +> - Neue Services/Jobs: `PressReleaseCoverImage` (Cover-Resolver), +> Treiber-Architektur unter `Services/PressRelease/Classification/` und +> `…/ContentScore/`, Jobs `ClassifyPressRelease`/`ScorePressRelease` +> (Queue `classification`), Konfiguration in `config/scoring.php`. +> - Neue Commands: `press-releases:reset-monthly-quota` (Scheduler, 1. des +> Monats), `classification:work` (Queue-Drain zum Testen). +> - Zeitzonen-Konstante `PressRelease::DISPLAY_TIMEZONE` (Europe/Berlin) mit +> `scheduledAtLocal()`/`embargoAtLocal()` für alle Termin-Anzeigen. + > **Was sich seit dem ursprünglichen Stand (2026-05-05) geändert hat**: > > - Pressemitteilungen haben zusätzliche Felder: `subtitle`, `scheduled_at`,