Previously, tenantScopedPublicRead only resolved the tenant from the Host
header, which fails when frontend API clients call cms.c2sgmbh.de (the CMS
hostname doesn't match any tenant domain). Now falls back to extracting the
tenant ID from the where[tenant][equals] query parameter. The returned access
filter still enforces tenant isolation.
Also adds seed script for zweitmeinung (tenant 12) with all content:
site settings, 2 service categories, 6 services, 24 FAQs, navigation,
4 social links, and contact form.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Build was OOM-ing in CI with default Node heap limit. Added
NODE_OPTIONS with 4GB heap. Also ran Prettier on monitoring files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Hardened cron endpoints with coordination and auth improvements
- Added API guards and input validation layer
- Security observability and secrets health checks
- Monitoring types and service improvements
- PDF URL validation and newsletter unsubscribe security
- Unit tests for security-critical paths
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add content-type check in TestEmailButton before parsing response as JSON
- Wrap updateEmailLog in error handler with try-catch to prevent double failures
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SSE stream: detect client disconnect via request.signal to stop
polling loop (prevents wasted DB queries after tab close)
- AlertEvaluator: split shouldFire/recordFired so cooldown is only
recorded after successful dispatch (prevents alert suppression
on dispatch failure)
- SnapshotCollector: cache payload instance (avoid re-importing on
every 60s tick)
- Alert acknowledge: validate alertId type (string|number)
- Logs search: add 300ms debounce to prevent query-per-keystroke
- Replace remaining `any` cast with Record<string, unknown>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The fire-and-forget dynamic import chain (3 awaits) was racing with
test flush timeouts. Caching the resolved payload instance fixes both
the flakiness and eliminates per-call import overhead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Periodic metric collection running in the queue-worker PM2 process.
Collects system metrics every 60s (configurable), stores them in
MonitoringSnapshots, and evaluates alert rules against each snapshot.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fire-and-forget logger that writes to the monitoring-logs collection
with log level filtering via MONITORING_LOG_LEVEL env var. Falls back
to console output when Payload is not yet initialized.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements checkSystemHealth (CPU, memory, disk, load), service checks
(Redis, PostgreSQL, PgBouncer, SMTP, queues, OAuth, cron), and the
collectMetrics aggregator that gathers all metrics in parallel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add monitoring access controls to centralized access module and create
four new system-wide collections for the monitoring dashboard:
- MonitoringSnapshots: historical system metrics for trend charts
- MonitoringLogs: structured logs for business events (WORM)
- MonitoringAlertRules: configurable alert rule definitions
- MonitoringAlertHistory: alert log with acknowledge support
Collections are registered in payload.config.ts but intentionally
excluded from multi-tenant plugin since they are system-wide.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Redis requires authentication but IORedis connections were not passing a
password, causing immediate NOAUTH failures and a PM2 crash-loop (1900+
restarts). Additionally, the PM2 config used `npx` as the script entry
which caused instability.
- Add REDIS_PASSWORD support to queue-service.ts and redis.ts
- Change PM2 script from npx wrapper to direct tsx CLI entry point
- Add explicit exec_mode: 'fork' to prevent cluster mode issues
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes Next.js build failure caused by .js extensions in relative
imports within VideoMetricsSyncService and ChannelMetricsSyncService.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Detect scheduling conflicts in the content calendar including same-day
longform collisions, weekly frequency limit violations, and weekend
scheduling warnings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a capacity calculator utility and API endpoint that computes
workload utilization for team members with YouTube roles.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add analytics helper functions (calculateComparison, calculateTrends,
calculateROI) and extend the analytics API route with three new tabs
for video metric comparison, trend analysis, and ROI calculation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements a service that uploads videos to YouTube via the Data API v3.
Resolves OAuth credentials from social-accounts, reads media files from
disk, and handles scheduled publishes by setting privacyStatus to private
with a publishAt timestamp. Includes 12 unit tests covering successful
uploads, scheduled publishing, credential/media validation, and API errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add YOUTUBE_UPLOAD to QUEUE_NAMES and create the job definition
with enqueue and status functions. Uses 2 retry attempts instead
of the default 3 since uploads are resource-intensive.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add getCommentReplies method to YouTubeClient for fetching reply threads
via the YouTube comments.list API. Modify CommentsSyncService to import
reply threads during sync, storing them as type 'reply' with
parentInteraction relationship in community-interactions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Syncs video performance metrics (views, likes, comments) from YouTube
API to YouTubeContent.performance fields. Supports batch processing
with 50-video API limit, credential validation, and per-batch error
handling.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Syncs channel-level statistics (subscribers, views, video count) from
YouTube Data API to YouTubeChannels.currentMetrics fields for all active
channels. Follows the same credential-loading pattern as existing sync
services.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add batch video statistics retrieval method that fetches view counts,
like counts, and comment counts for up to 50 videos per request.
Includes unit tests covering normal operation, empty input, missing
statistics defaults, null API response, and error propagation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add youtube.upload and yt-analytics.readonly scopes to enable video
uploading and analytics data retrieval in the YouTube Operations Hub.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extend admin component overrides to cover all Payload admin views
(no-html-link-for-pages, no-img-element off for admin panel)
- Rename useGeneratedReply to applyGeneratedReply (not a hook)
- Fix useRealtimeUpdates: resolve circular dependency with connectRef,
wrap ref assignments in useEffect for React 19 compiler compliance
- Fix MetaBaseClient: let -> const for single-assignment variable
ESLint now passes with 0 errors (68 warnings only).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements a unified sync service that orchestrates comment
synchronization across all social media platforms.
UnifiedSyncService:
- Platform-agnostic sync orchestration
- Support for YouTube, Facebook, and Instagram
- Parallel platform detection and account grouping
- Progress tracking with live status updates
- Aggregated results per platform
- Error handling with partial results support
New API Endpoints:
- GET/POST /api/cron/community-sync
- Cron endpoint for scheduled multi-platform sync
- Query params: platforms, accountIds, analyzeWithAI, maxItems
- HEAD for monitoring status
- GET /api/community/sync-status
- Live sync status for dashboard
- Platform overview with account details
- Interaction statistics (total, today, unanswered)
- Last sync result summary
Configuration:
- vercel.json updated to use community-sync cron
- 15-minute sync interval maintained
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements complete Meta Graph API integration for Facebook Pages
and Instagram Business Accounts.
Phase 2.3a - Meta OAuth & Base Infrastructure:
- Meta OAuth service with long-lived token support (60 days)
- MetaBaseClient with error handling and retry logic
- OAuth routes (/api/auth/meta, /api/auth/meta/callback)
- Type definitions for all Meta API responses
Phase 2.3b - Facebook Client:
- FacebookClient extending MetaBaseClient
- Page posts and comments retrieval
- Comment moderation (reply, hide, delete, like)
- Messenger conversations support
- Page insights and analytics
- FacebookSyncService for comment synchronization
Phase 2.3c - Instagram Client:
- InstagramClient for Business Accounts
- Media (posts/reels/carousels) retrieval
- Comment management with replies
- Mentions and Story-Mentions (24h expiry)
- Instagram Direct messaging
- Account and media insights
- InstagramSyncService for comment/mention sync
Additional changes:
- SocialPlatforms collection extended with oauthEndpoint field
- Environment variables documented (META_APP_ID, META_APP_SECRET)
- Module index with all exports
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implementiert automatische YouTube-Kommentar-Synchronisation und
KI-gestützte Antwortvorschläge für das Community Management.
Neue Features:
- Cron-Endpoint für externen Scheduler (/api/cron/youtube-sync)
- ClaudeReplyService für AI-generierte Antworten (3 Tonalitäten)
- Sync Status API mit Live-Polling
- AI Reply Suggestions UI mit Varianten-Auswahl
- Job Logger für strukturiertes Logging von Background Jobs
Änderungen:
- ClaudeAnalysisService: Model-Update auf claude-3-5-haiku-20241022
- CommunityInbox: Sync Status Badge, AI Reply Suggestions Integration
- SCSS: Styles für Sync-Indicator und Suggestion Cards
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 5 new collections: SocialPlatforms, SocialAccounts,
CommunityInteractions, CommunityTemplates, CommunityRules
- Add communityRole field to Users collection
- Add YouTube API client for comment sync
- Add Claude AI service for sentiment analysis
- Add API endpoints: /api/community/sync-comments, /api/community/reply
- Add communityAccess.ts for role-based access control
- Add migrations for all new tables and community_role enum fix
Fix: Make audit hooks non-blocking to prevent user save timeout
Dependencies: @anthropic-ai/sdk, googleapis
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Complete YouTube content management system:
- YouTubeChannels: Channel management with branding and metrics
- YouTubeContent: Video pipeline with workflow, approvals, scheduling
- YtSeries: Dedicated series management per channel (NEW)
- YtBatches: Production batch tracking with targets and progress
- YtTasks: Task management with notifications
- YtNotifications: User notification system
- YtMonthlyGoals: Monthly production goals per channel
- YtScriptTemplates: Reusable script templates
- YtChecklistTemplates: Checklist templates for workflows
Features:
- Role-based access (YouTubeManager, YouTubeCreator, YouTubeViewer)
- Auto-task generation on status changes
- Series relationship with channel-based filtering
- API endpoints for dashboard, tasks, and task completion
- German/English localization support
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update Payload CMS 3.68.4 → 3.69.0 to fix login redirect loop
(formatAdminURL no longer generates absolute URLs for currentRoute)
- Add explicit access control to Users collection for account updates
(multi-tenant plugin was blocking save button)
- Add read/update access controls to SEOSettings global
(settings group was hidden due to missing permissions)
- Regenerate importMap after Payload update
- Remove unused files: custom login page, cache-keys, my-route, migrations_backup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- CSRF: Require CSRF_SECRET in production, throw error on missing secret
- IP Allowlist: TRUST_PROXY must be explicitly set to 'true' for proxy headers
- Rate Limiter: Add proper proxy trust handling for client IP detection
- Login: Add browser form redirect support with safe URL validation
- Add custom admin login page with styled form
- Update CLAUDE.md with TRUST_PROXY documentation
- Update tests for new security behavior
BREAKING: Server will not start in production without CSRF_SECRET or PAYLOAD_SECRET
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix slug-validation.ts: Use proper Where type from Payload
- Fix processFeaturedVideo.ts: Remove TypeWithID constraint, use type casting
- Fix retention-worker.ts: Remove unused import cleanupExpiredConsentLogs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Video Feature Implementation:
- Add Videos and VideoCategories collections with multi-tenant support
- Extend VideoBlock with library/upload/embed sources and playback options
- Add featuredVideo group to Posts collection with processed embed URLs
Hooks & Validation:
- Add processFeaturedVideo hook for URL parsing and privacy mode embedding
- Add createSlugValidationHook for tenant-scoped slug uniqueness
- Add video-utils library (parseVideoUrl, generateEmbedUrl, formatDuration)
Testing:
- Add 84 unit tests for video-utils (URL parsing, duration, embed generation)
- Add 14 integration tests for Videos collection CRUD and slug validation
Database:
- Migration for videos, video_categories tables with locales
- Migration for Posts featuredVideo processed fields
- Update payload internal tables for new collections
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add automatic cleanup for email-logs (90 days default)
- Add automatic cleanup for audit-logs (90 days default)
- Add consent-logs archival based on expiresAt (3 years GDPR)
- Add media orphan cleanup for unreferenced files (30 days min age)
- Add BullMQ-based retention worker with daily scheduler
- Add /api/retention endpoint for manual triggers (super-admin only)
- Update queue worker to include retention worker
- Add comprehensive documentation to CLAUDE.md and TODO.md
New files:
- src/lib/retention/retention-config.ts
- src/lib/retention/cleanup-service.ts
- src/lib/retention/index.ts
- src/lib/queue/jobs/retention-job.ts
- src/lib/queue/workers/retention-worker.ts
- src/app/(payload)/api/retention/route.ts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- CSRF bypass in CI can be disabled with BYPASS_CSRF=false
- Security integration tests set BYPASS_CSRF=false to test CSRF validation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove NODE_ENV check from CSRF bypass (production builds need bypass too)
- Add CI environment stub to CSRF unit tests to ensure normal validation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>