cms.c2sgmbh/docs/CLAUDE_REFERENCE.md
2026-02-17 21:06:27 +00:00

20 KiB

Payload CMS - Detaillierte Subsystem-Referenz

Diese Datei enthält detaillierte Dokumentation zu den Subsystemen des Projekts. Kurzübersicht und Schlüsseldateien: siehe CLAUDE.md.

E-Mail-System

Multi-Tenant E-Mail-System mit tenant-spezifischer SMTP-Konfiguration.

Architektur:

  • Globaler SMTP als Fallback (via .env)
  • Tenant-spezifische SMTP in Tenants Collection
  • Transporter-Caching mit automatischer Invalidierung
  • EmailLogs Collection für Audit-Trail

Tenant E-Mail-Konfiguration:

Tenants → email → fromAddress, fromName, replyTo
       → email → useCustomSmtp (Checkbox)
       → email → smtp → host, port, secure, user, pass

API-Endpoint /api/send-email:

curl -X POST https://pl.porwoll.tech/api/send-email \
  -H "Content-Type: application/json" \
  -H "Cookie: payload-token=..." \
  -d '{
    "to": "empfaenger@example.com",
    "subject": "Betreff",
    "html": "<p>Inhalt</p>",
    "tenantId": 1
  }'

Sicherheit:

  • Authentifizierung erforderlich
  • Tenant-Zugriffskontrolle (User muss Tenant-Mitglied sein)
  • Rate-Limiting: 10 E-Mails/Minute pro User
  • SMTP-Passwort nie in API-Responses

Dateien:

  • src/lib/email/tenant-email-service.ts - Haupt-Service
  • src/lib/email/payload-email-adapter.ts - Payload-Integration
  • src/hooks/invalidateEmailCache.ts - Cache-Invalidierung

Troubleshooting: Tenant SMTP Save hängt im Admin

Stand: 17. Februar 2026

Symptom:

  • Beim Speichern eines Tenants mit aktivem email.useCustomSmtp bleibt das Admin Panel bei "wird aktualisiert" hängen.
  • SMTP-Werte werden nicht zuverlässig in tenants persistiert.

Ursachen (behoben):

  • Die SMTP-Felder lagen in einer conditional Group (email.smtp), während required: true auf Unterfeldern (host, user) serverseitig weiterhin greifen konnte.
  • Feld-Validierungen nutzten teilweise siblingData mit falschem Scope in der verschachtelten Struktur.
  • afterChange im Tenant-Audit-Log wartete synchron auf payload.create() für audit-logs und konnte die Admin-Response blockieren.

Implementierter Fix:

  • Konditionale Pflichtvalidierung auf Gruppenebene email.smtp.validate verschoben (Prüfung gegen email.useCustomSmtp).
  • required: true von email.smtp.host und email.smtp.user entfernt; stattdessen explizite Group-Validierung.
  • Tenant-Audit-Hooks auf Fire-and-Forget umgestellt (.catch(...) statt await), analog zu User-Audit-Hooks.

Relevante Dateien:

  • src/collections/Tenants.ts
  • src/hooks/auditTenantChanges.ts

Newsletter (Double Opt-In)

DSGVO-konformes Newsletter-System mit Double Opt-In.

Flow:

  1. User meldet sich an → Status: pending, Token wird generiert
  2. Double Opt-In E-Mail wird automatisch gesendet
  3. User klickt Bestätigungs-Link → Status: confirmed
  4. Willkommens-E-Mail wird gesendet
  5. Abmeldung jederzeit über Link in E-Mails möglich

API-Endpoints:

# Anmeldung
POST /api/newsletter/subscribe
{"email": "...", "firstName": "...", "tenantId": 1, "source": "footer"}

# Bestätigung (via Link aus E-Mail)
GET /api/newsletter/confirm?token=<uuid>

# Abmeldung (via Link aus E-Mail)
GET /api/newsletter/unsubscribe?token=<uuid>

Features:

  • Token-Ablauf nach 48 Stunden
  • Rate-Limiting: 5 Anmeldungen/10 Minuten pro IP
  • Erneute Anmeldung nach Abmeldung möglich

Dateien:

  • src/lib/email/newsletter-service.ts - Service-Logik
  • src/lib/email/newsletter-templates.ts - E-Mail-Templates
  • src/hooks/sendNewsletterConfirmation.ts - Hook

BullMQ Job Queue

Asynchrone Job-Verarbeitung mit Redis als Backend.

Queue-Worker: Läuft als separater PM2-Prozess (pm2 logs queue-worker).

Email Queue

import { queueEmail } from '@/lib/queue'

await queueEmail({
  tenantId: 1,
  to: 'empfaenger@example.com',
  subject: 'Betreff',
  html: '<p>Inhalt</p>',
  source: 'form-submission'
})

PDF Queue

# PDF aus HTML generieren
POST /api/generate-pdf
{"source": "html", "html": "<h1>Test</h1>", "filename": "test.pdf"}

# Job-Status abfragen
GET /api/generate-pdf?jobId=abc123
import { queuePdfFromHtml, queuePdfFromUrl, getPdfJobStatus } from '@/lib/queue'

const job = await queuePdfFromHtml('<h1>Test</h1>', { filename: 'test.pdf' })
const job2 = await queuePdfFromUrl('https://example.com', { format: 'A4' })
const status = await getPdfJobStatus(job.id)

Worker-Konfiguration

Über ecosystem.config.cjs:

  • QUEUE_EMAIL_CONCURRENCY: Parallele E-Mail-Jobs (default: 3)
  • QUEUE_PDF_CONCURRENCY: Parallele PDF-Jobs (default: 2)
  • QUEUE_RETENTION_CONCURRENCY: Parallele Retention-Jobs (default: 1)
  • QUEUE_DEFAULT_RETRY: Retry-Versuche (default: 3)
  • QUEUE_REDIS_DB: Redis-Datenbank für Queue (default: 1)
  • REDIS_PASSWORD: Redis-Authentifizierung (Pflicht)

Dateien:

  • src/lib/queue/queue-service.ts - Zentrale Queue-Verwaltung
  • src/lib/queue/jobs/email-job.ts - E-Mail-Job
  • src/lib/queue/jobs/pdf-job.ts - PDF-Job
  • src/lib/queue/workers/email-worker.ts - E-Mail-Worker
  • src/lib/queue/workers/pdf-worker.ts - PDF-Worker
  • scripts/run-queue-worker.ts - Worker-Starter

Data Retention

Automatische Datenbereinigung für DSGVO-Compliance und Speicheroptimierung.

Retention Policies

Collection Retention Umgebungsvariable
email-logs 90 Tage RETENTION_EMAIL_LOGS_DAYS
audit-logs 90 Tage RETENTION_AUDIT_LOGS_DAYS
consent-logs 3 Jahre RETENTION_CONSENT_LOGS_DAYS
media (orphans) 30 Tage RETENTION_MEDIA_ORPHAN_MIN_AGE_DAYS

Scheduler: Täglich 03:00 Uhr (RETENTION_CRON_SCHEDULE).

API-Endpoint /api/retention

# Konfiguration abrufen
GET /api/retention

# Job-Status
GET /api/retention?jobId=abc123

# Manueller Job
POST /api/retention
{"type": "full"}                                    # Alle Policies
{"type": "collection", "collection": "email-logs"}  # Einzelne Collection
{"type": "media-orphans"}                           # Nur Media-Orphans

Architektur:

Scheduler (Cron) → Retention Queue (BullMQ) → Retention Worker
  → Email-Logs (createdAt) + Audit-Logs (createdAt) + Consent-Logs (expiresAt)
  → Media-Orphan-Cleanup

Dateien:

  • src/lib/retention/retention-config.ts - Zentrale Konfiguration
  • src/lib/retention/cleanup-service.ts - Lösch-Logik
  • src/lib/queue/jobs/retention-job.ts - Job-Definition
  • src/lib/queue/workers/retention-worker.ts - Worker
  • src/app/(payload)/api/retention/route.ts - API-Endpoint

Redis Caching

Redis erfordert Authentifizierung (REDIS_PASSWORD). Eviction-Policy: noeviction (BullMQ-Anforderung — verhindert Datenverlust bei Queue-Jobs).

import { redis } from '@/lib/redis'

await redis.set('key', JSON.stringify(data), 'EX', 60)  // TTL in Sekunden
const cached = await redis.get('key')
await redis.keys('posts:*').then(keys => keys.length && redis.del(...keys))  // Pattern-Invalidierung

FormSubmissions CRM

Die FormSubmissions Collection wurde zu einem leichtgewichtigen CRM erweitert.

Multi-Tenant Kontaktformular-System:

  • forms und form-submissions sind tenant-scoped (via multiTenantPlugin mit customTenantField: true)
  • Formulare werden in der CMS Admin-UI pro Tenant erstellt (Forms Collection)
  • E-Mail-Empfänger werden pro Formular konfiguriert (Built-in Plugin Feature)
  • ContactFormBlock referenziert ein Formular aus der Forms Collection (statt hardcoded E-Mail)
  • Frontends posten an /api/form-submissions mit der formId aus dem Block

Hooks:

  • setSubmissionTenant (beforeChange): Kopiert den Tenant automatisch vom Formular auf die Einsendung
  • sendFormNotification (afterChange): Sendet E-Mail-Benachrichtigungen via Tenant-SMTP an konfigurierte Empfänger
  • formSubmissionBeforeChange: Auto-Markierung als gelesen, Auto-Autor bei Notizen

Status-Workflow: Neu → Gelesen → In Bearbeitung → Warten → Erledigt → Archiviert

Features:

  • Priorität (Hoch/Normal/Niedrig)
  • Zuständigkeits-Zuweisung an User
  • Interne Notizen mit Auto-Autor und Zeitstempel
  • Antwort-Tracking (Methode, Zeitstempel, Zusammenfassung)
  • Tags zur Kategorisierung
  • Auto-Markierung als gelesen beim ersten Öffnen

Dateien:

  • src/collections/FormSubmissionsOverrides.ts - Feld-Definitionen + Tenant-Feld
  • src/hooks/setSubmissionTenant.ts - Auto-Tenant-Zuweisung von Form → Submission
  • src/hooks/sendFormNotification.ts - E-Mail-Benachrichtigung via Tenant-SMTP
  • src/hooks/formSubmissionHooks.ts - Automatisierungen (Gelesen-Status, Notiz-Autor)
  • src/blocks/ContactFormBlock.ts - Block mit Formular-Referenz + Anzeigeoptionen

Community Management System

Plattformübergreifendes Community Management für YouTube, Facebook und Instagram.

Architektur

Admin UI (Inbox + Analytics)
  → /api/community/* (sync, stats, reply, generate-reply, export, stream)
    → UnifiedSyncService
      → YouTube Sync + Facebook Sync + Instagram Sync
        → CommunityInteractions (einheitliche Collection)

Admin UI

Community Inbox (/admin/community/inbox):

  • Einheitliche Ansicht aller Kommentare (YouTube + Facebook + Instagram)
  • Filter nach Plattform, Status, Priorität, Sentiment, Flags
  • AI-generierte Antwort-Vorschläge (Claude)
  • Echtzeit-Updates via SSE (/api/community/stream)
  • Export als CSV/JSON

Community Analytics (/admin/community/analytics):

  • KPI-Cards, Sentiment-Trend, Topic-Cloud, Response-Metriken, Kanal-Vergleich

Meta (Facebook + Instagram) Integration

OAuth-Flow:

  1. Admin öffnet /api/auth/meta?socialAccountId=X&accountType=both
  2. Redirect zu Facebook OAuth (12 Scopes)
  3. Callback: Short-Lived → Long-Lived Token (60 Tage)
  4. Facebook Pages + Instagram Business Accounts werden geladen
  5. Token + Account-Daten in SocialAccounts gespeichert

Scopes:

  • Facebook: pages_show_list, pages_read_engagement, pages_manage_posts, pages_read_user_content, pages_manage_engagement, pages_messaging
  • Instagram: instagram_basic, instagram_manage_comments, instagram_manage_messages, instagram_content_publish

API-Endpoints

Endpoint Methode Beschreibung
/api/community/sync POST Manueller Sync (alle Plattformen)
/api/community/sync GET Sync-Status
/api/community/sync-status GET Detaillierter Status mit Account-Stats
/api/community/stats GET Interaktions-Statistiken
/api/community/reply POST Antwort senden
/api/community/generate-reply POST AI-Antwort generieren (Claude)
/api/community/export GET Daten-Export (CSV/JSON)
/api/community/stream GET SSE-Stream für Echtzeit-Updates
/api/community/analytics/* GET Analytics-Daten (6 Endpoints)
/api/auth/meta GET Meta OAuth starten
/api/auth/meta/callback GET Meta OAuth Callback

Sync-Trigger

Trigger Endpoint Plattformen
Cron (alle 15 Min) /api/cron/community-sync Alle aktiven Accounts
Manuell (Inbox-Button) /api/community/sync (POST) Alle (optional filterbar)
YouTube-spezifisch /api/cron/youtube-sync Nur YouTube

CommunityRules (Automatisierung)

Trigger-Typen: keyword, sentiment, question_detected, medical_detected, influencer (>10k Follower), all_new, contains_link, contains_email

Aktionen: set_priority, assign_to, set_flag, suggest_template, send_notification, flag_medical, escalate, mark_spam, set_deadline

Wichtige Dateien

src/lib/integrations/meta/
├── MetaBaseClient.ts          # HTTP-Basis mit Retry + Pagination
├── FacebookClient.ts          # Facebook Graph API Client
├── InstagramClient.ts         # Instagram Graph API Client
├── FacebookSyncService.ts     # Facebook Kommentar-Sync
├── InstagramSyncService.ts    # Instagram Kommentar-Sync
├── oauth.ts                   # Meta OAuth 2.0 Flow
└── index.ts                   # Re-Exports

src/lib/jobs/
├── UnifiedSyncService.ts      # Orchestriert alle Plattform-Syncs
├── syncAllComments.ts         # YouTube-spezifischer Sync (Legacy)
└── JobLogger.ts               # Strukturiertes Logging

src/app/(payload)/api/
├── auth/meta/                 # OAuth Start + Callback
├── community/                 # Community-Endpoints
└── cron/community-sync/       # Cron-Trigger

Timeline Collection

Dedizierte Collection für chronologische Darstellungen.

Typen: history, milestones, releases, career, events, process

Event-Features: Flexible Datumsformate, Kategorien, Wichtigkeitsstufen, Bilder, Links, Rich-Text

Display-Optionen: Layouts (vertikal, alternierend, horizontal, kompakt), Sortierung, Gruppierung nach Jahr

Prozess-spezifische Felder (type=process):

  • stepNumber, duration, responsible, actionRequired, deliverables

API: GET /api/timelines?tenant=1[&type=history][&slug=...][&locale=en]

Workflows Collection

Komplexe Prozess-Darstellungen mit Phasen, Abhängigkeiten und Status-Tracking.

Typen: project, business, approval, onboarding, support, development, marketing, other

Phasen-Struktur:

Workflow → Phasen (Array)
  → name, description, icon, color, estimatedDuration, responsible, deliverables
  → Schritte (Array)
    → name, description, stepType, priority, dependencies, conditions, checklist, resources, outputs

Display: Layouts (vertical, horizontal, flowchart, kanban, gantt), Farbschema (phase, status, priority, brand)

API: GET /api/workflows?tenant=1[&type=project][&complexity=medium][&slug=...][&locale=en]

HeroSliderBlock Features

Slides (1-10): Hintergrundbild (Desktop + Mobil), Headline + Subline (lokalisiert), Text-Ausrichtung, Overlay (Farbe, Deckkraft, Gradient), 2 CTA-Buttons

Animationen: fade, slide, zoom, flip, none (300-1200ms)

Autoplay: Intervall 3-10s, Pause bei Hover/Interaktion

Navigation: Pfeile (verschiedene Stile), Dots (Punkte, Striche, Nummern, Thumbnails, Fortschritt), Touch-Swipe, Tastatur

Layout: Höhe (Vollbild bis kompakt), Mobile-Höhe, Content-Breite

CI/CD Pipeline Details

ci.yml (Main CI Pipeline)

Läuft bei Push/PR auf main und develop:

  • lint: ESLint (flat config, 0 errors)
  • typecheck: TypeScript Compiler (tsc --noEmit, 4GB heap)
  • test: Unit & Integration Tests (Vitest)
  • build: Next.js Production Build
  • e2e: Playwright E2E Tests

security.yml

Gitleaks (Secret Scanning), pnpm audit, CodeQL (SAST), Security Tests

deploy-staging.yml

  • Trigger: Push auf develop oder manual dispatch
  • Ablauf: Pre-checks → SSH → Git Pull → Dependencies → Migrations → Build → PM2 Restart → Health Check
  • Secret: STAGING_SSH_KEY
# Manuelles Staging-Deployment
./scripts/deploy-staging.sh
./scripts/deploy-staging.sh --skip-build
./scripts/deploy-staging.sh --skip-migrations

deploy-production.yml

  • Trigger: Manual dispatch
  • Features: Pre-flight Checks, Database Backup, Health Check, Auto-Rollback
  • Secrets: STAGING_SSH_KEY, PRODUCTION_SSH_KEY
gh workflow run deploy-production.yml              # Via GitHub Actions
./scripts/deploy-production.sh                     # Auf Server
./scripts/deploy-production.sh --rollback          # Rollback
./scripts/deploy-production.sh --dry-run           # Dry-Run

PgBouncer Connection Pooling

Läuft auf dem App-Server (127.0.0.1:6432), pooled Verbindungen zu PostgreSQL (10.10.181.101:5432).

Konfiguration: /etc/pgbouncer/pgbouncer.ini

Parameter Wert
pool_mode transaction
default_pool_size 20
min_pool_size 5
reserve_pool_size 5
max_db_connections 50
max_client_conn 200

TLS: server_tls_sslmode = require (TLS 1.3)

# Statistiken
PGPASSWORD="$DB_PASSWORD" psql -h 127.0.0.1 -p 6432 -U payload -d pgbouncer -c "SHOW POOLS;"

# Direkte Verbindung für Migrationen (umgeht PgBouncer)
./scripts/db-direct.sh migrate
./scripts/db-direct.sh psql

Cron Jobs (Details)

Alle erfordern Authorization: Bearer $CRON_SECRET.

# Community Sync manuell
curl -X POST "https://your-domain/api/cron/community-sync" \
  -H "Authorization: Bearer $CRON_SECRET" \
  -d '{"platforms": ["youtube", "facebook"]}'

# Token Refresh (Dry-Run)
curl "https://your-domain/api/cron/token-refresh?dryRun=true" \
  -H "Authorization: Bearer $CRON_SECRET"

Monitoring:

  • HEAD-Requests: Status-Header (X-Sync-Running, X-Last-Run)
  • Bei laufendem Job: HTTP 423 (Locked)
  • Fehlerhafte Tokens → yt-notifications

YouTube Operations Hub

Umfassendes YouTube-Management-System mit Content-Pipeline, Analytics, Kalender und Task-Management.

Collections (9)

Slug Beschreibung
youtube-channels Multi-Kanal-Verwaltung mit OAuth
youtube-content Videos + Shorts mit Status-Pipeline
yt-series Serien mit Branding (Logo, Farben, Playlist)
yt-notifications Handlungsbedarf-System
yt-tasks Aufgaben mit Zuweisung und Fälligkeitsdatum
yt-batches Produktions-Batches mit Ziel-Tracking
yt-checklist-templates Checklisten-Vorlagen (Upload, Produktion, Review)
yt-monthly-goals Monatsziele (Content, Audience, Engagement, Business)
yt-script-templates Skript-Vorlagen pro Kanal/Serie

Content-Pipeline Status

ideascriptreviewproductioneditingreadypublished

Hooks automatisieren Übergänge und erstellen Tasks bei Statuswechsel.

Custom API Endpoints

Methode Endpoint Beschreibung Auth
GET /api/youtube/auth OAuth-Flow starten (?socialAccountId=) User
GET /api/youtube/callback OAuth-Callback, Token-Speicherung Public (State)
POST /api/youtube/refresh-token Access Token erneuern User + CSRF
GET /api/youtube/dashboard Pipeline-Status, Freigaben, Aufgaben YouTube-Rolle
GET /api/youtube/analytics Multi-Tab Analytics (?tab=&channel=&period=) YouTube-Rolle
GET /api/youtube/calendar Content-Kalender mit Konflikterkennung User
PATCH /api/youtube/calendar Drag-&-Drop-Umplanung User
GET /api/youtube/capacity Team-Kapazität und Auslastung User
GET /api/youtube/my-tasks Eigene offene Tasks YouTube-Rolle
POST /api/youtube/complete-task/[id] Task als erledigt markieren Assignee/Manager
POST/GET /api/youtube/upload Video-Upload via BullMQ-Queue User
POST /api/youtube/thumbnails/bulk Bulk-Thumbnail-Download (?dryRun=true) SuperAdmin

Cron Jobs

Endpoint Schedule Beschreibung
/api/cron/youtube-sync alle 15 Min YouTube-Kommentar-Sync
/api/cron/youtube-channel-sync täglich 04:00 UTC Kanal-Statistiken (Abos, Views, Videos)
/api/cron/youtube-metrics-sync alle 6 Stunden Video-Performance-Metriken

Admin Views

  • YouTube Analytics Dashboard (/admin/views/youtube-analytics) — 7 Tabs: Performance, Pipeline, Goals, Community, Comparison, Trends, ROI
  • Content Calendar (/admin/views/content-calendar) — FullCalendar mit Drag-&-Drop und Konflikterkennung

Services & Utilities

Datei Beschreibung
src/lib/youtube/ConflictDetectionService.ts Erkennt Terminüberschneidungen bei Content-Planung
src/lib/youtube/analytics-helpers.ts Trend-Berechnung, Vergleiche, ROI
src/lib/youtube/capacity-calculator.ts Team-Auslastungsberechnung
src/lib/youtube/youtubeAccess.ts Rollen-basierte Zugriffskontrolle

Hooks (Automatisierung)

  • youtubeChannels/downloadChannelImage — Profilbild automatisch herunterladen
  • youtubeContent/downloadThumbnail — Video-Thumbnails automatisch herunterladen
  • youtubeContent/createTasksOnStatusChange — Tasks bei Statuswechsel erstellen
  • youtubeContent/autoStatusTransitions — Automatische Pipeline-Übergänge
  • ytTasks/notifyOnAssignment — Benachrichtigung bei Task-Zuweisung

Zugriffskontrolle

Funktion Beschreibung
hasYouTubeAccess() Lese-Zugriff (YouTube-Rolle)
isYouTubeManager() Manager-Level (Erstellen, Löschen, Freigaben)
isYouTubeCreatorOrAbove() Creator+ Zugriff
canAccessAssignedContent() Nur zugewiesene Inhalte
canAccessOwnNotifications() Nur eigene Benachrichtigungen