presseportale/.env.example
Kevin Adametz 6b8728242f admin: Indexierungsstatus aus der Search Console, Kundenansicht vorbereitet und zu (Anhang 1: 1c.4, E8)
press-releases:check-index-status fragt täglich je Portal ein Kontingent
veröffentlichter Meldungen über die URL Inspection API ab, nach Alter
gestaffelt, nie geprüfte zuerst. Jede Antwort wird als Momentaufnahme in
press_release_index_checks gespeichert; der reduzierte Befund (IndexState)
trennt „noch nicht gecrawlt" von „gecrawlt, nicht indexiert".

Client authentifiziert sich als Service-Konto über ein selbst signiertes
JWT — kein Google-SDK. Admin ▸ Reports ▸ Indexierung zeigt die Verteilung
je Portal getrennt nach Direkteinreichung und Syndikation (Status-Log
source=api; Altbestand ohne Log zählt als direkt).

Das Kundenpanel heißt jetzt „Auslieferung", zeigt Sitemap-Datum und die
Abrufe durch Such- und KI-Dienste mit dem Satz „Ein Abruf ist kein Zitat";
der Google-Index-Block hängt an GSC_CUSTOMER_VISIBLE (false).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 14:21:51 +00:00

264 lines
9.2 KiB
Text
Raw 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
# Prod: auf `daily` stellen — der `single`-Channel wächst sonst unbegrenzt.
# Der daily-Channel rotiert mit LOG_DAILY_DAYS (Default 14, siehe Runbook).
LOG_STACK=single
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
# ---------------------------------------------------------------------------
# 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=
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
# 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
# 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.de
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=