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 <noreply@anthropic.com>
This commit is contained in:
parent
a000238ca8
commit
8d8d957884
17 changed files with 2231 additions and 172 deletions
103
dev/frontend/hub-flux/20-PHASE-8-USER-PANEL.md
Normal file
103
dev/frontend/hub-flux/20-PHASE-8-USER-PANEL.md
Normal file
|
|
@ -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).
|
||||
|
|
@ -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).
|
||||
- `<x-portal.press-release-placeholder>` + 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:
|
||||
|
|
|
|||
179
docs/Decision-Update Preisstruktur & Veröffentlichungs-Flow.md
Normal file
179
docs/Decision-Update Preisstruktur & Veröffentlichungs-Flow.md
Normal file
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
224
docs/PHASE-9-FLOW-UND-TARIFE-PLAN.md
Normal file
224
docs/PHASE-9-FLOW-UND-TARIFE-PLAN.md
Normal file
|
|
@ -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
|
||||
|
|
@ -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`).
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -24,9 +29,9 @@ 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|
|
||||
| **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. |
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
207
docs/user-admin/Lizenztyp Bildupload.md
Normal file
207
docs/user-admin/Lizenztyp Bildupload.md
Normal file
|
|
@ -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.
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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`, `<x-portal.press-release-placeholder>`, 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.
|
||||
|
|
|
|||
|
|
@ -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`,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue