presseportale/.env.example
Kevin Adametz 4a7e496d1b dev: Umsetzungsaudits 29.09. und 02.10., Entwicklungsplan Blöcke 9 und 10 mit bestätigten Entscheidungen E19–E34 und Deploy-Plan, Runbook ergänzt
- UMSETZUNGSAUDIT-2026-09-29.md (Bestandsaufnahme) und -2026-10-02.md
- ENTWICKLUNGSPLAN.md: Block 9 und 10, Entscheidungen E19–E34 vom Betreiber
  am 02.10.2026 bestätigt (E25 revidiert), Deploy-Plan A–E, Protokoll
- deploy-runbook.md: vollständige Scheduler-Tabelle, Restore-Schritte mit
  --accept-unsigned/--without-export, Zugangsdaten aus Abschnitt 7 entfernt
  (stehen weiter in der Historie — Passwort wird rotiert)
- Bildplan-Protokoll mit Korrektur zu „Altbestand geschützt" (A-05)
- dev/README.md und dev/roadmap.md verweisen auf den aktuellen Stand
- .env.example: neue Schlüssel aus Block 9/10

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 13:09:01 +00:00

324 lines
12 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

APP_NAME=Pressekonto
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=https://pressekonto.test
APP_LOCALE=de
APP_FALLBACK_LOCALE=de
APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database
# HTTP Basic Auth Gate (Staging-Schutz). Nur erzwungen, wenn aktiviert
# UND BASIC_AUTH_USER/BASIC_AUTH_PASSWORD gesetzt sind.
BASIC_AUTH_ENABLED=true
BASIC_AUTH_USER=
BASIC_AUTH_PASSWORD=
PHP_CLI_SERVER_WORKERS=4
BCRYPT_ROUNDS=12
LOG_CHANNEL=stack
# `daily`: eine Datei je Tag (laravel-YYYY-MM-DD.log), Rotation nach
# LOG_DAILY_DAYS. Fachliche Meldungen liegen daneben in eigenen Tagesdateien
# je Thema (billing-, ki-, monitoring-, market-, admin-slow-*.log) —
# siehe config/logging.php. `single` nur noch als Notnagel, wächst unbegrenzt.
LOG_STACK=daily
LOG_DAILY_DAYS=14
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
# Betriebs-Alerts (R5.3): fehlgeschlagene Scheduler-Tasks/Queue-Jobs werden als
# `critical` geloggt und – wenn aktiviert – zusätzlich an MONITORING_ALERT_EMAIL
# gemeldet (Fallback: LEGAL_CONTACT_EMAIL). In Prod echten Mailer voraussetzen.
MONITORING_ALERTS_ENABLED=true
MONITORING_ALERT_EMAIL=
# ---------------------------------------------------------------------------
# Multi-Domain-Setup (config/domains.php)
# Hub: pressekonto (Portal-Backend + Hub-Landing) — Spokes: presseecho,
# businessportal24. Prod: .test durch echte Domains ersetzen
# (pressekonto.de, presseecho.de, businessportal24.com).
# ---------------------------------------------------------------------------
APP_PROTOCOL="https://"
APP_PORTAL_NAME="pressekonto.test"
APP_PORTAL_URL="https://pressekonto.test"
APP_PORTAL_PRIMARY="#526266"
APP_PORTAL_SECONDARY="#82a0a7"
# APP_PORTAL_ASSET_URL=
APP_PRESSEECHO_NAME=presseecho.test
APP_PRESSEECHO_URL=https://presseecho.test
APP_PRESSEECHO_PRIMARY="#345636"
APP_PRESSEECHO_SECONDARY="#6b8f71"
APP_BUSINESSPORTAL_NAME=businessportal24.test
APP_BUSINESSPORTAL_URL=https://businessportal24.test
APP_BUSINESSPORTAL_PRIMARY="#cf3628"
APP_BUSINESSPORTAL_SECONDARY="#f0834a"
# Sanctum: Hosts, die stateful (Session-Cookie) auf die API zugreifen dürfen.
# Prod: echte Domains kommasepariert eintragen.
SANCTUM_STATEFUL_DOMAINS=pressekonto.test,presseecho.test,businessportal24.test
DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=
# Wartezeit auf Tabellen-Sperren in Sekunden (siehe config/database.php).
# Migrationen auf großen Tabellen ggf. mit DB_LOCK_WAIT_TIMEOUT=300 starten.
DB_LOCK_WAIT_TIMEOUT=10
# Aufbewahrung des PM-Ereignis-Logs in Tagen (siehe config/press_releases.php).
# Bestimmt zugleich die Tiefe der Verlaufsanzeige. 395 = 13 Monate.
PRESS_RELEASE_EVENTS_RETENTION_DAYS=395
# Aufbewahrung der Konversions-Ereignisse in Tagen (siehe config/conversion.php).
# Bewusst derselbe Horizont wie oben. 395 = 13 Monate.
CONVERSION_EVENTS_RETENTION_DAYS=395
# Mail-Link-Klick (Stufe 1): derselbe Klick je IP und Meldung zählt höchstens
# einmal in diesem Fenster (Minuten). Audit 29.09.2026, R-08.
CONVERSION_MAIL_CLICK_THROTTLE_MINUTES=30
# ---------------------------------------------------------------------------
# Legacy-Datenbanken (Alt-Systeme, read-only für Migration/Abgleich).
# Die businessportal-Verbindung ist ein Snapshot-Dump, nicht live.
# ---------------------------------------------------------------------------
DB_HOST_BUSINESSPORTAL=127.0.0.1
DB_DATABASE_BUSINESSPORTAL=
DB_USERNAME_BUSINESSPORTAL=
DB_PASSWORD_BUSINESSPORTAL=
DB_HOST_PRESSEECHO=127.0.0.1
DB_DATABASE_PRESSEECHO=
DB_USERNAME_PRESSEECHO=
DB_PASSWORD_PRESSEECHO=
SESSION_DRIVER=redis
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null
# Prod: true setzen (Cookies nur über HTTPS).
# SESSION_SECURE_COOKIE=true
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database
CACHE_STORE=redis
# CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
# Prod: echten Mailer konfigurieren — Default `log` versendet NICHTS.
MAIL_MAILER=log
MAIL_SCHEME=null
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
# Bounce-Behandlung (Roadmap 1b.6): Envelope-Sender für Rückläufer — MUSS auf
# der From-Domain liegen (SPF-Ausrichtung), z. B. bounce@pressekonto.com.
# Leer = From-Adresse. Schwellen siehe config/bounces.php.
MAIL_RETURN_PATH=
# IMAP-Zugang zum Bounce-Postfach für `mail:fetch-bounces` (alle 10 Minuten).
# Leer = der Befehl tut nichts.
BOUNCE_IMAP_HOST=
BOUNCE_IMAP_PORT=993
BOUNCE_IMAP_ENCRYPTION=ssl
BOUNCE_IMAP_USERNAME=
BOUNCE_IMAP_PASSWORD=
# Signatur der Bounce-Referenz X-Pk-Ref (Audit 29.09.2026, R-04). Leer = aus
# APP_KEY abgeleitet. Ein Wechsel entwertet nur Signaturen bereits versendeter
# Mails (deren Rückläufer zählen dann weich).
BOUNCE_SIGNING_KEY=
# Bounce OHNE Signatur (hart wie weich): policy = nur protokollieren (sicher,
# Standard); soft = zählt auf den Schwellwert und ist damit fälschbar.
BOUNCE_UNSIGNED_KIND=policy
# Aufbewahrung der Rückläufer-Ereignisse (email_bounces) in Tagen; gelöscht von
# conversion:purge-events. Die Sperrliste bleibt.
BOUNCE_RETENTION_DAYS=395
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"
# Lokaler Vite-Dev-Server (dual-port Setup, siehe VITE-SETUP.md).
VITE_DEV_SERVER_URL=https://assets.pressekonto.test
# ---------------------------------------------------------------------------
# Stripe / Billing (Laravel Cashier)
# Prod: Live-Keys + Live-Preis-IDs eintragen [EXTERN: R1.2].
# ---------------------------------------------------------------------------
STRIPE_KEY=
STRIPE_SECRET=
STRIPE_WEBHOOK_SECRET=
# Stripe-Preis-ID des Einzelkaufs (eine PM, 19 €).
STRIPE_PRICE_SINGLE_PM=
CASHIER_CURRENCY=eur
CASHIER_CURRENCY_LOCALE=de_DE
# Umsatzsteuer/Rechnungsangaben.
# BILLING_VAT_RATE=0.19
# BILLING_DEFAULT_CURRENCY=EUR
# BILLING_MANUAL_DUE_DAYS=14
BILLING_OWN_VAT_ID=
# Abo-/Bestandsschutz-Gate (WS-5). Default (auch ohne Env-Key) ist true:
# Einreichen zur Prüfung erfordert ein aktives Abo, einen bezahlten Einzelkauf
# oder Bestandsschutz (grandfathered) — siehe User::hasActiveBooking().
# Nur für lokale Entwicklung bewusst auf false setzen (Gate offen für alle).
BILLING_ENFORCE_BOOKING=true
# ---------------------------------------------------------------------------
# KI: Klassifikation (Red-Flag-Gate) + Content-Score (config/scoring.php).
# Ohne OPENAI_API_KEY laufen die Jobs nicht — Queue-Worker erforderlich.
# ---------------------------------------------------------------------------
OPENAI_API_KEY=
# OPENAI_API_URL=
# OPENAI_MODEL=
# OPENAI_TIMEOUT=30
# CLASSIFICATION_PROVIDER=openai
# CLASSIFICATION_MODEL=
# CLASSIFICATION_TIMEOUT=15
# CLASSIFICATION_GREEN_DELAY=0
# CLASSIFICATION_YELLOW_MANUAL=true
# CONTENT_SCORE_PROVIDER=openai
# CONTENT_SCORE_MODEL=
# CONTENT_SCORE_TIMEOUT=30
# CONTENT_SCORE_HOCHWERTIG=80
# CONTENT_SCORE_GEPRUEFT=60
# ---------------------------------------------------------------------------
# Newsletter-Sync (config/newsletter.php). Provider `placeholder` bindet den
# Null-Client; enabled=true mit anderem Provider wirft bewusst, bis eine
# echte Anbindung implementiert ist.
# ---------------------------------------------------------------------------
NEWSLETTER_SYNC_ENABLED=false
NEWSLETTER_SYNC_PROVIDER=placeholder
NEWSLETTER_SYNC_ENDPOINT=
NEWSLETTER_SYNC_API_KEY=
# NEWSLETTER_SYNC_TIMEOUT=10
# Drosselung interner Newsletter-Kampagnen: Wellen à batch_size Mails im
# Abstand von batch_interval_minutes (SMTP-Limit/Spam-Schutz).
# NEWSLETTER_CAMPAIGN_BATCH_SIZE=50
# NEWSLETTER_CAMPAIGN_BATCH_INTERVAL_MINUTES=15
# Kampagnen-Versand freischalten (E9-Schalter, Audit 29.09.2026). Standard
# aus, bis U05–U07 umgesetzt sind; Entwürfe, Test-Mails und Abmeldung gehen
# immer.
NEWSLETTER_SENDING_ENABLED=false
# Google-Login (Laravel Socialite). Die Redirect-URI muss in der Google Cloud
# Console EXAKT der Callback-URL der Portal-Domain entsprechen (Login läuft auf
# dem Portal-Host, nicht zwingend APP_URL). Prod: https://pressekonto.com/...
# Hinweis: Google akzeptiert keine .test-Domains – lokal nur localhost oder ein
# https-Tunnel; der echte Round-Trip wird auf Staging/Live getestet.
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT_URI=https://pressekonto.com/auth/google/callback
# Empfänger des öffentlichen Kontaktformulars je Brand. Ohne Wert fällt der
# Versand auf MAIL_FROM_ADDRESS zurück. [EXTERN: echte Adressen eintragen]
CONTACT_EMAIL_PRESSEKONTO=
CONTACT_EMAIL_PRESSEECHO=
CONTACT_EMAIL_BUSINESSPORTAL=
# Depublikation (T12): Netto-Preis in Cent fuer die freiwillige Entfernung
# einer veroeffentlichten PM aus der oeffentlichen Ansicht (Tombstone bleibt).
# Default 3500 (35 EUR netto, Entscheidung O6 vom 06.07.2026); 0 deaktiviert.
BILLING_DEPUBLICATION_PRICE_CENTS=3500
# Selbst gehostete Umami-Webanalyse (sys.adametz.media; IDs je Brand in
# config/domains.php). Erst beim Go-Live der Webseiten auf true setzen —
# die Datenschutzerklärung (Abschnitt 5) beschreibt den Einsatz bereits.
UMAMI_ENABLED=false
# Haupt-E-Mail für alle rechtlichen Anliegen (Impressum, Datenschutz, AGB,
# Meldeverfahren, Richtlinien) — auf allen drei Domains identisch.
# Ohne Wert gilt der Default info@pressekonto.com (config/legal.php).
LEGAL_CONTACT_EMAIL=
# Optionales separates DSA-Melde-Postfach je Brand (Impressum + /melden).
# Ohne Wert fällt die Anzeige auf LEGAL_CONTACT_EMAIL zurück.
REPORT_EMAIL_PRESSEKONTO=
REPORT_EMAIL_PRESSEECHO=
REPORT_EMAIL_BUSINESSPORTAL=
# Crawler-Abruf-Protokoll (Roadmap 1c.0): Tag, ab dem Abrufe durch Such- und
# KI-Dienste je Meldung erfasst werden — auf den Deploy-Tag setzen.
CRAWLER_HITS_RECORDED_SINCE=2026-09-18
# Abruf-Protokoll der RSS-Feeds (Roadmap 3.1): beim Deploy auf den Deploy-Tag setzen.
FEED_FETCHES_RECORDED_SINCE=2026-09-21
# Google Search Console, URL Inspection API (Roadmap 1c.4). Läuft nur mit
# Service-Konto (JSON-Schlüssel außerhalb von public/), das in beiden
# Properties als Nutzer eingetragen ist. Kundenansicht bleibt zu (E8).
GSC_ENABLED=false
GSC_SERVICE_ACCOUNT_FILE=
GSC_PROPERTY_PRESSEECHO=sc-domain:presseecho.de
GSC_PROPERTY_BUSINESSPORTAL24=sc-domain:businessportal24.com
GSC_DAILY_BUDGET=300
GSC_CUSTOMER_VISIBLE=false
# Transparenzseite „kostenlos veröffentlichen": Prüfdatum der Portalliste
# (Einträge in config/transparency.php). Leer = Abschnitt erscheint nicht.
TRANSPARENCY_FREE_PORTALS_CHECKED_AT=
# Doppelveröffentlichung (Roadmap Anhang 2, 1c.8): zweite Fassung verweist per
# rel=canonical auf die Erstquelle, Zuordnung je Kategorie in config/canonical.php
# (E9, entschieden 18.09.2026 — Standard an). Aus = jede Fassung bleibt ihr
# eigenes Canonical. ACHTUNG Reihenfolge beim ersten Deploy: migrate →
# press-releases:hash-content → press-releases:assign-canonicals.
CANONICAL_ASSIGNMENT_ENABLED=true
CANONICAL_FALLBACK=first
# Anmeldelinks „Diesen Newsroom verwalten" je Newsroom und Tag (nur versendete
# zählen). Audit 29.09.2026, R-09: 3 → 5.
NEWSROOM_CLAIM_LINKS_PER_DAY=5
# API-Zuordnung neuer Firmen zu einem bestehenden Newsroom (Roadmap 1a.4,
# Audit 29.09.2026, R-01): nur für diese User-IDs (kommagetrennt, z. B. das
# connektar-Konto) — sonst nur, wenn der Nutzer der Firma schon angehört.
# Leer = keine Freischaltung.
NEWSROOM_API_ASSIGNMENT_USER_IDS=
# --- Bildkennzeichnung (Formular v2) und Beweisarchiv (Block F) ---
# IMAGE_RIGHTS_V2: Formular v2 im Bildmanager und in der API; false = Verhalten wie vor der Umstellung.
IMAGE_RIGHTS_V2=false
# Eigener Schlüssel für die IP-Ableitung im Bestätigungsprotokoll (Fallback APP_KEY).
CONFIRMATION_IP_KEY=
# Beweisarchiv: eigener Schlüssel (php artisan archive:key), getrennt sichern — ohne ihn ist das Archiv unlesbar.
ARCHIVE_KEY=
ARCHIVE_PREVIOUS_KEYS=
ARCHIVE_RETENTION_YEARS=3
ARCHIVE_QUARANTINE_DAYS=30
ARCHIVE_SWEEP_PAUSED=false
# Zustimmungsgate vor jeder Einreichung (Block G) — erst mit AGB v0.7 einschalten.
LEGAL_ACCEPTANCE_GATE=false
# IMAGE_PRECHECK: KI-Vorab-Check für Titelbilder (Sichtung auf offensichtliche Probleme, Block K).
# Erst nach AVV mit dem Anbieter und DSE-Absatz einschalten. STAGE 1 = nur Stock-Wasserzeichen, 2 = alle Kategorien.
IMAGE_PRECHECK=false
IMAGE_PRECHECK_STAGE=1
# IMAGE_PRECHECK_MODEL=
# IMAGE_PRECHECK_DOWNGRADE=