presseportale/dev/release/entwicklungsplan-release.md
Kevin Adametz f5bf282027 Deploy: .env.example vervollstaendigt + Deploy-Runbook (R5.1/R5.2)
Alle projektspezifischen Env-Keys dokumentiert (Multi-Domain, Legacy-DBs,
Stripe/Billing, KI, Sanctum, Newsletter, Vite); Runbook fuers neue
Laravel-System mit Prod-.env-Solltabelle, Release-Schritten,
Queue-Worker (classification), Cron-Tasks inkl. Ausfall-Folgen,
Stripe-Webhook, Erst-Einrichtung, Smoke-Test und Rollback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 12:38:24 +00:00

20 KiB
Raw Blame History

Entwicklungsplan: Release-Fertigstellung Pressekonto

Konsolidiert aus vier Analysen vom 03.07.2026 (dev-Doku-Abgleich, Web-Frontend-Bestandsaufnahme, Backend-Baustellen, Deploy-Readiness). Reihenfolge nach Risiko/Nutzen: erst Korrektheit & kaputte Pfade, dann Release-Entscheidungen (Billing), dann Frontend-Fertigstellung, dann Aufräumen, dann Deploy/QA. Ergänzt dev/optimize/entwicklungsplan.md (Phasen 0–5 dort abgeschlossen; dessen Phase 6 ist hier als R4 aufgenommen).


Stand & Wiedereinstieg (zuletzt: 03.07.2026)

Phase R0 komplett; R1 bis auf [EXTERN] fertig; R2.1 erledigt. Erledigt: R0.1–R0.5 (Variant-Routen raus, gdpr_consent_at in allen drei Registrierungspfaden, Newsletter-Binding config-aware + fail-fast, Seeder produktionssicher inkl. PlanSeeder + Dev-User-Guard, Fehlerseiten 403/404/419/500/503 self-contained) · R1.1 (Gate safe-by-default true, Legacy-/Grandfathered-Pfade per Test festgeschrieben, Scope-Logik war korrekt) · R1.3 (Quota-Reset als finales Tarif-Modell-Verhalten dokumentiert). Offen in R1 (alle [EXTERN]): R1.2 Stripe-Live-Sync, R1.4 Preisfreigabe, R1.5 Refund-Entscheidung. R2.1 Kontaktformular komplett (Backend + Web-Form, Brand-Empfaenger via CONTACT_EMAIL_-Keys [EXTERN: echte Adressen]). Bonus-Fix: legal-request-Honeypot nickt Bots wieder still ab (size:0-Regel verriet die Falle). 03.07. nachmittags (User-Vorgaben): Preise/Limits der Buchungsseite sind die abgestimmte Wahrheit; Pipeline verifiziert: admin/payments/plans pflegt Plan-DB (inkl. Vorteile zeilenweise) -> erscheint auf Buchungsseite, oeffentlicher Preise-Seite, pricing-teaser UND (neu) Hub. Vorteilstexte selbst sind noch nicht final [EXTERN: User passt sie im Admin-UI an — schlaegt automatisch ueberall durch]. R2.2+R2.3 erledigt: Hub-Landing komplett ueberarbeitet (datengetriebenes Tarif-Grid aus Plan::active() via neuem HubPageData, echte Plattform-Kennzahlen statt erfundener, Fake-Kundenliste raus, alle toten Links beseitigt, unhaltbare Claims entschaerft, Footer-Rechtslinks auf /de/-Seiten der Hub-Domain). Hub-Rechtsseiten sind erreichbar, brauchen aber weiterhin finale Texte (R3.1). Naechste Schritte: R2.4 (Sitemap/robots/meta) ohne User-Input machbar; R3 Inhalte + R1.2 Stripe-Live [EXTERN].


Ausgangslage (Stand 03.07.2026)

  • Testsuite komplett grün: 838 passed, 1 skipped (3.678 Assertions, ~70 s).
  • Branch: fix/zeitzone-europe-berlin, 73 Commits vor main, 62 davon ungepusht. main hat nichts Neues → Merge/Push ist Teil des Release (R6.5).
  • Keine Debug-Reste (dd/dump/Test-Routen) im Backend; Mailables vollständig mit Views; Scheduler (5 Tasks) angeschlossen.
  • Wichtig: dev/migration 2026/12-NAECHSTE-SCHRITTE.md ist teilweise veraltet — Stripe/Billing (dort „Phase 8 komplett offen") ist laut dev/frontend/hub-flux/PROGRESS.md seit 12.06. umgesetzt (Checkout, Webhooks, Tarif-Admin, Grandfathering). Restaufwand-Schätzungen von dort nicht übernehmen.
  • Nachgelagert (User-Entscheidung 03.07.): kompletter getesteter Flow fürs User-Panel — bewusst NICHT Teil dieses Plans.

Arbeitsregeln (für jeden Schritt)

  • Test-First bei Korrektheits-/Verhaltensänderungen (R0–R2): erst Pest-Test, dann ändern.
  • Tests gezielt laufen: php artisan test --compact --filter=<Name> (wir sind bereits im Sail-Container).
  • Nach PHP-Änderungen: Pint (--dirty).
  • Web-Frontend (resources/views/web/**, components/web/**) gehört dem User → separat committen, vor jedem Löschen bestätigen lassen.
  • resources/views/components/layouts/app/sidebar.blade.php gehört dem User und bleibt aus allen Commits ausgeschlossen (git reset -q -- … vor jedem git add).
  • Jeder Schritt = ein eigener, fokussierter Commit.
  • Punkte mit [EXTERN] brauchen Input vom User/Auftraggeber (Texte, Entscheidungen, Zugänge) — früh anstoßen, parallel weiterarbeiten.

Phase R0 — Korrektheit & kaputte Pfade (klein, sofort, Test-First)

  • R0.1 Variant-Routen reparieren — routes/web.php:211-227: /variant-1 + /variant-2 verweisen für die Businessportal-Domain auf web.businessportal24-variant-float-glow / -glass-gradient — diese Views existieren nicht → 500. Entscheidung: Routen entfernen (Design-Experimente sind abgeschlossen) oder auf web.businessportal24 zurückfallen. Regressionstest.
  • R0.2 gdpr_consent_at im Registrierungsflow befüllen — Feld existiert (Model-Cast + Migration), wird aber nirgends geschrieben (verifiziert 03.07.). Bei Registrierung (Fortify CreateNewUser), Magic-Link-/Social-Provisioning (CustomerAccountProvisioner) setzen. DSGVO-relevant. Test-First. (= rev-1 aus migration-Doku)
  • R0.3 Newsletter-Sync-Binding ehrlich machen — AppServiceProvider.php:47 bindet NewsletterSyncClient unconditional an NullNewsletterSyncClient; NEWSLETter_SYNC_ENABLED=true bewirkt nichts, das Admin-UI (admin/newsletter/sync) suggeriert aber eine funktionierende Sync. Fürs Release: No-Op bleibt (echte Sync ist nachgelagert), aber Binding config-aware machen und im Admin-UI den Placeholder-Status sichtbar ausweisen. Test.
  • R0.4 Seeder produktionssicher machen —
    • PlanSeeder (Starter/Business/Pro/Agency) wird von DatabaseSeeder nicht aufgerufen → in den Produktions-Seed-Pfad aufnehmen (eigener ProductionSeeder oder Aufnahme + Guard).
    • PaymentOptionSeeder schreibt Platzhalter (prod_placeholder_monthly, price_placeholder_monthly, …) → echte IDs via billing:sync-stripe-plans bzw. Seed anpassen (R1.2-Abhängigkeit).
    • Test-User (admin@pressekonto.test, test@example.com, Passwort password) in DatabaseSeeder nur noch in local/testing anlegen.
  • R0.5 Fehlerseiten erstellen — resources/views/errors/ existiert nicht → 404/500/503 (mind. 404 + 503 theme-/domain-aware fürs Web, neutrale Variante fürs Portal). Render-Tests.

Phase R1 — Backend-Release-Entscheidungen (Billing/Gates)

  • R1.1 Buchungs-/Tarif-Gate prüfen & bereinigen (User-Vorgabe 03.07.) — Das Gate muss vollständig geprüft und bereinigt werden; Legacy-Buchungen müssen funktionieren (Bestandskunden mit Alt-Abo/Grandfathering dürfen veröffentlichen). Ist-Stand beim Testen: ohne gebuchtes Paket keine Veröffentlichung möglich (Gate lokal scharf via .env: BILLING_ENFORCE_BOOKING=true) — Soll-Verhalten bestätigt. Teilschritte:
    • Alle Gate-Pfade durchgehen: User::hasActiveBooking(), hasUnlimitedPressReleaseQuota, openSinglePurchaseCount(), UserPaymentOption::scopeActiveNow()/scopeGrandfatheredNow(), Submit-Gate im PressReleaseService.
    • Legacy-Buchungen end-to-end testen: migrierter User mit Alt-Abo (grandfathered, gültiges grandfathered_until) kann einreichen/veröffentlichen; abgelaufener Bestandsschutz wird korrekt geblockt (NULL = abgelaufen, Entscheidung 19.06.).
    • Config-Default absichern: config/billing.php default false — bei vergessenem Prod-Env-Key liefert hasActiveBooking() für alle true → Default auf true drehen oder Runbook-Pflichtkey; .env.example korrigieren.
    • Suite + manueller Submit-Flow (mit/ohne Buchung, mit Legacy-Buchung) gegengetestet.
  • R1.2 Stripe produktiv vorbereiten — billing:sync-stripe-plans gegen Live-Mode ausführen (bislang nur Test-Mode); STRIPE_PRICE_SINGLE_PM setzen (sonst ist Einzel-PM-Checkout stumm deaktiviert, CheckoutController.php:58); Plan-stripe_price_id_monthly/_yearly gepflegt (sonst Abo-Checkout deaktiviert). Danach Checkout-Smoke-Test inkl. Webhook. [EXTERN: Live-Stripe-Zugang]
  • R1.3 Quota-Reset-Provisorium festschreiben — ResetMonthlyPressReleaseQuota ist als „temporärer Stub bis zum echten Tarif-/Credit-Modul" markiert, läuft aber monatlich per Scheduler. Prüfen ob das Verhalten fürs Release korrekt ist (Zusammenspiel mit Credit-Wallet/Add-ons); Doc-Kommentar aktualisieren oder Logik ersetzen.
  • R1.4 Preise/Lineup final abstimmen — PreisePageData.php:44 TODO („Lineup/Preise hängen am Bookings-/Magic-Link-Rework"): öffentliche Preisseite (correction/update/depublish-Pfade) gegen finale Preisliste prüfen. [EXTERN: Preisfreigabe]
  • R1.5 Refund-Workflow: Entscheidung — laut hub-flux offen. Empfehlung: nachgelagert (Refunds initial direkt im Stripe-Dashboard), Entscheidung dokumentieren.

Phase R2 — Web-Frontend funktional fertigstellen

  • R2.1 Kontaktformular anbinden — kontakt.blade.php:52 TODO: aktuell nur mailto:, kein Form/Handler; Telefon/Adresse sind Fake-Daten. Umsetzung analog LegalRequestController (POST-Controller + Validierung + Honeypot + throttle + Mailversand an konfigurierbare Adresse). Feature-Tests. Echte Kontaktdaten [EXTERN].
  • R2.2 Hub-Pricing datengetrieben — pressekonto.blade.php:401/469/538: 3 hartcodierte Pricing-<article>s (0 €/49 €/149 €) → <x-web.pricing-teaser> (iteriert Plan::active(), wird von beiden Spokes schon genutzt). Beseitigt Drift-Risiko zum Plan-Katalog. (= alt Phase 6.1)
  • R2.3 Tote href="#"-Links in Live-Seiten fixen — pressekonto (16×, u. a. Kundenlogos + Support-/Datenschutz-Links), release-detail (3×, Share-Aktionen), hub/top-utility-bar (3×), events-week/highlight-card. Echte Ziele setzen oder Elemente entfernen.
  • R2.4 SEO-Basics — Erledigt 03.07.: Host-aware sitemap.xml (Hub: Landing + Rechts-/Info-Seiten; Spokes: zusätzlich Kategorien, öffentliche Newsrooms, alle im Archiv sichtbaren PMs des Portals; 1h-Cache pro Host). robots.txt jetzt dynamische Route mit Sitemap-Verweis + Disallow (/admin, /login, /register, Suche) — die statische public/robots.txt wurde entfernt (Deploy-Hinweis: nicht wieder anlegen, sie würde die Route verschatten). karriere/partner/presse/team: Brand pro Request via WebPortalContext (statt hartcodiert „Business Portal 24") + Meta-Descriptions; bp24-Home auf config-getriebenes meta_title/meta_description-Muster vereinheitlicht. Sitemap listet bewusst nur die de-Edition (en-Entscheidung offen, s. Rechtstexte-Doku O3) und lässt Suche + Marketing-Platzhalterseiten (R3.2) draußen. Tests: SitemapRobotsTest.
  • R2.5 legal-request-Hinweistexte finalisieren — legal-request.blade.php:8/65: Texte je Anfragetyp als „ENTWURF" markiert. [EXTERN: finale Texte]

Phase R3 — Inhalte [EXTERN, früh anstoßen, parallelisierbar]

  • R3.0 Online-Widerruf (gesetzlicher Widerrufsbutton) — Erledigt 03.07.: „Vertrag widerrufen"-Button im Hub-Footer → zweistufiges Modal (nur Zuordnungsdaten, kein Grund) → POST /widerruf (host-agnostisch) persistiert withdrawal_requests + sofortige automatische Eingangsbestätigung per Mail an den Verbraucher + interne Benachrichtigung an die Brand-Adresse. Admin-Queue in Recht & Compliance erledigt. Offen als Follow-up: Button ggf. auch auf den Spoke-Footern platzieren (Verträge werden nur über den Hub geschlossen — rechtlich prüfen lassen).
  • R3.0b Kündigungsbutton § 312k BGB — Erledigt 03.07.: „Verträge hier kündigen"-Button im Hub-Footer (ständig verfügbar) → öffentliche Bestätigungsseite /de/kuendigung ohne Login (Art der Kündigung ordentlich/außerordentlich mit Grund, Zuordnungsdaten, Beendigungszeitpunkt, Bestätigungsschaltfläche „jetzt kündigen") → persistiert termination_requests + sofortige automatische Zugangsbestätigung per Mail (§ 312k Abs. 4) + Betreiber-Mail. Kündigungen laufen in der Recht-&-Compliance-Queue unter den Widerrufen auf (K-Vorgänge, eigener Filter, Erledigt/Wieder-öffnen).
  • R3.0c Erlöschens-Checkbox im Publikationsflow — Erledigt 03.07.: Vierte Bestätigung im Einreichungs-Modal („sofortige Ausführung, Widerrufsrecht erlischt mit vollständiger Vertragserfüllung", § 356 Abs. 4/5 BGB); Zeitpunkt wird beim Submit als withdrawal_waiver_consented_at an der PM protokolliert. Index-Schnell-Submit (wire:confirm) durch das gemeinsame Modal ersetzt — der Pfad umging bisher alle rechtlichen Bestätigungen. Formulierung der Klausel vor Go-Live anwaltlich prüfen (O1).
  • R3.1 Rechtstexte final — Architektur beschlossen (03.07., docs/legal/Rechtstexte-Architektur.md): Single-Source-Rechtstexte in der Hub-DB (legal_documents + legal_document_sections, versioniert, Portal-Flags, Platzhalter-Variablen), auf allen drei Domains nativ gerendert; AGB-Zustimmung mit agb_version_id protokollieren; neue Seiten Widerrufsbelehrung+Musterformular (nur Hub), Meldeverfahren (DSA), Redaktionsrichtlinien. Erlöschens-Checkbox (R3.0c) und Kündigungsbutton § 312k (R3.0b) sind bereits umgesetzt. Inhalte formuliert der User gerade aus — Umsetzung des Datenmodells + Admin-Pflege, sobald erste Texte vorliegen. Vorarbeit erledigt: Hub-Gerüst auf den statischen Seiten (Rechtsseiten/API/FAQ rendern host-aware Hub-Header/-Footer). — agb, datenschutz, impressum, cookies sind explizit als „Platzhalter — vor Go-Live ersetzen" markiert. Ohne finale Texte kein Go-Live (Abmahnrisiko). Cookie-Consent-Setup klären.
  • R3.2 Marketing-Seiten: Inhalt oder Rückbau — presse (erfundener Pressekontakt „Lisa Müller"), team (erfundene Personen), karriere (Bewerben-Buttons ohne Ziel), partner, hilfe (dünn), ueber-uns (Platzhalter-Kennzahlen) sind live geroutet. Pro Seite entscheiden: echte Inhalte liefern oder Route + Navigation vorerst entfernen. Empfehlung: lieber weniger Seiten, aber ehrlich.

Phase R4 — Web-Frontend aufräumen (= alt Phase 6; vor jedem Löschen bestätigen)

Kontext (User, 03.07.): Bei der Frontend-Entwicklung gab es eine alte Version — es können noch Fragmentseiten aus dieser Version herumliegen. Die Funde unten (examples/, altes engl. Header/Footer-Layout, welcome, brand-mark, Variant-Views) passen dazu; beim Aufräumen gezielt nach weiteren Alt-Fragmenten suchen (auch in components/web/** und ungerouteten Blades).

  • R4.1 Tote Dateien entfernen — web/examples/ (4 Demo-Views mit Lorem/Mustermann), welcome.blade.php, brand-mark.blade.php, layouts/web-master-test.blade.php, layouts/footer.blade.php + layouts/header.blade.php (altes englisches Layout, 38 tote Links) — alle nirgends geroutet/inkludiert (verifiziert per grep; dynamische Auflösung vor Löschen nochmal prüfen).
  • R4.2 Tote Komponenten entfernen — 12 ungenutzte x-web-Komponenten: category-strip, dossier-card, events-week, hero-banner, highlights-slider, home-hero, press-release-list-item, presseecho-release-card, sidebar-categories, sidebar-companies, sidebar-newsletter, sidebar-rss. (events-week erst nach Entscheidung R2.3/Konzept „echte Datenquellen".)
  • R4.3 Dedup (optional, nice-to-have) — Release-Card-Vereinheitlichung, Industrie-Icon-Map → Config, Inline-SVGs → Icon-Set, <x-web.container> (alt 6.2/6.3). Nur wenn Zeit; kein Release-Blocker.

Phase R5 — Deploy-Readiness

  • R5.1 .env.example vervollständigen — Erledigt 03.07.: alle projektspezifischen Keys ergänzt und dokumentiert (Multi-Domain APP_PORTAL_*/APP_PRESSEECHO_*/APP_BUSINESSPORTAL_*/APP_PROTOCOL, SANCTUM_STATEFUL_DOMAINS, Legacy-DBs, Stripe/Cashier/Billing inkl. STRIPE_PRICE_SINGLE_PM + BILLING_OWN_VAT_ID, KI OPENAI_*/CLASSIFICATION_*/CONTENT_SCORE_*, NEWSLETTER_SYNC_*, VITE_DEV_SERVER_URL, SESSION_SECURE_COOKIE-Prod-Hinweis). Werte selbst (Live-Keys, Adressen) bleiben [EXTERN].
  • R5.2 Deploy-Runbook schreiben — Erledigt 03.07.: dev/release/deploy-runbook.md — Server-Voraussetzungen, Prod-.env-Solltabelle, Build-/Release-Schritte (composer, npm run build, storage:link, migrate --force, Stammdaten-Seeder, Caches, queue:restart), Queue-Worker (Queue classification, systemd-Beispiel), Cron/Scheduler (5 Tasks mit Ausfall-Folgen), Stripe-Webhook, Erst-Einrichtung (Legacy-Import-Reihenfolge), Smoke-Test-Checkliste, Rollback. Enthält den robots.txt-Deploy-Hinweis aus R2.4.
  • R5.3 Monitoring/Alerting entscheiden — kein Sentry o. ä. installiert; Scheduler-/Queue-Failure-Alerting fehlt. Minimalvorschlag: schedule-onFailure-Mail + Log-Rotation; optional Sentry. [EXTERN: Entscheidung]
  • R5.4 Favicons je Domain — domains:generate-favicons erzeugt bewusst leere Platzhalter-Dateien; echte Favicons für pressekonto/presseecho/businessportal24 deployen. [EXTERN: Assets]

Phase R6 — QA & Go-Live (teils extern/Ops)

  • R6.1 Manuelle QA-Checkliste durcharbeiten — dev/migration 2026/06-FEATURES-SCOPE.md §15 (komplett offen): Logins inkl. 2FA + Magic-Link, Portal-Scoping, PM-Workflow Admin+Customer, Image-Upload, Blacklist, Stripe-Checkout inkl. Webhook + Invoice-PDF, Grandfathering, Legacy-Rechnungen, API (Sanctum + Abweisung alter api_key), Thumbnail-Redirect, Scheduler. Dabei auch verifizieren, was die (veraltete) Frontend-Konzept-Doku noch als offen führt (Branchen-/Kategorieseite, Veröffentlichen-Landing — im Code existieren KategorieController/VeroeffentlichenController bereits → visuell abnehmen statt neu bauen).
  • R6.2 Security-Review — CSRF/CORS (keine config/cors.php → Framework-Default prüfen), Rate-Limits, Upload-Handling, Magic-Link-TTL, SESSION_SECURE_COOKIE/same_site (Multi-Domain!), BasicAuth-Strategie für Staging. (= P10.5)
  • R6.3 Staging-Import-Rehearsal — Datenimport gegen produktiven Legacy-Snapshot auf Staging (mehrfach als der offene Vollständigkeitsnachweis referenziert, P6.10/P11.3). Achtung: mysql_businessportal-Verbindung lokal ist nur ein ~April-Snapshot — fürs Rehearsal echten aktuellen Dump ziehen. [EXTERN: Server/Snapshot]
  • R6.4 Go-Live-Kette — Go-Live-Mailing (Passwort-Reset) + API-Kunden-Mailing: Code fertig, finale Texte + Freigabeliste [EXTERN]; DNS-Cutover pressekonto.de; Legacy-System read-only während Final-Import; alte Symfony-Server abschalten. (= P11.x)
  • R6.5 Git-Hygiene — Branch fix/zeitzone-europe-berlin (73 Commits vor main) pushen und nach main mergen; danach Release-Tag. Die drei user_filter_presets-Migrations zusammenführen (rev-5, „Hygiene vor Go-Live") optional davor.
  • R6.6 Doku-Sync — dev/migration 2026/12-NAECHSTE-SCHRITTE.md + 08-PROGRESS.md auf den echten Stand bringen (Phase 8/Stripe als erledigt markieren), damit die Doku nicht weiter in die Irre führt.

Bewusst NACHGELAGERT (kein Teil dieses Release-Plans)

  • Kompletter getesteter User-Panel-Flow (User-Entscheidung 03.07.2026).
  • Echte Newsletter-Sync-Implementierung (No-Op bleibt, R0.3 macht es nur ehrlich); Newsletter-Subscriber-Admin/CSV (P3.7, vertagt).
  • Coupons (UI-Skeleton, D-16 vertagt), Google-Login (Socialite), Regionen-Übersichten /region/{slug} (301-Redirect bleibt), Blacklist-Admin-UI (Config reicht), PM-Nice-to-haves (Inline-Edit, Bulk, In-App-Notifications, Permission-Granularität).
  • Legacy-Logging/-Performance-Deployments (betreffen nur das Alt-System als Überbrückung bis zum Cutover).
  • Performance-Polishing aus 11-NOCH-ZU-TUN-OPTIMIERUNGEN.md (Slow-Query-Auswertung braucht echte Live-Daten).
  • Coverage-Ziel 70 % / arch()-Tests / test --parallel (P10.1–10.3) — Suite ist grün, Ausbau nachgelagert.

Reihenfolge-Empfehlung (TL;DR)

  1. R0 sofort — kaputte Pfade, DSGVO, Seeder, Fehlerseiten (alles klein, Test-First).
  2. [EXTERN]-Punkte parallel anstoßen — Rechtstexte (R3.1), Stripe-Live-Zugang (R1.2), Enforce-Booking-Entscheidung (R1.1), Kontaktdaten (R2.1), Mailing-Texte (R6.4). Das sind die längsten Wartezeiten.
  3. R1 + R2 — Billing scharf + Frontend funktional (Kern der Fertigstellung).
  4. R4 + R5 — Aufräumen + Deploy-Runbook, sobald R1/R2 stehen.
  5. R6 — QA, Security, Rehearsal, Cutover.