Commit graph

149 commits

Author SHA1 Message Date
5cd3f8a1b7 feat: add HtmlEmbedBlock and convert zweitmeinu.ng static pages to CMS
Add html-embed-block for raw HTML/iframe embedding in Pages layout.
Update seed script with hero blocks for impressum/datenschutz and
alfright.eu iframe via html-embed-block for privacy policy page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 15:44:13 +00:00
9e791648e9 fix: support slug and where[] query params in custom posts route
The custom /api/posts route intercepted all post queries but only
supported listing parameters (category, type, page). Frontend detail
pages sending where[slug][equals]=X got all posts back, always
showing the latest post regardless of which article was clicked.

Now parses slug from both ?slug=X and ?where[slug][equals]=X format.
Replaced getPostsByCategory with direct payload.find using properly
typed Where conditions. Detail queries (with slug) include content
and readingTime in the response.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 15:58:32 +00:00
8cb04fd130 fix: enforce mandatory tenant parameter on frontend API routes
Custom API routes at /api/posts, /api/search, and /api/search/suggestions
used payload.find() with overrideAccess:true (default) and optional tenant
filtering. Without a ?tenant= parameter, ALL data from ALL tenants was
returned — causing cross-tenant data leaks (e.g. sensualmoment.de Journal
showing blogwoman articles).

Now all three routes require a tenant parameter (400 error without it).
Also accepts where[tenant][equals] format for compatibility with
payload-contracts API clients. Removed debug logging from tenantAccess.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 15:22:48 +00:00
eb31df112b feat: add seed script and implementation plan for sensualmoment.de (tenant 13)
- Seed script creates: site-settings, 2 social-links, 3 testimonials, 12 FAQs,
  navigation, contact form, 10 pages with block layouts
- Implementation plan for full-stack frontend setup
- StatsBlock: add iconAlignment field to style group (schema synced)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 12:58:20 +00:00
a77c2b747d fix: make SEO global read public to prevent 403 during admin SSR
The SEO Settings global had `read: ({ req: { user } }) => Boolean(user)`
which requires authentication. During admin panel server-side rendering
(after saves), the user context is not propagated to global reads,
causing a Forbidden error that crashes the entire page render.

SEO data is not sensitive, so public read access is appropriate.
Also removes temporary debug logging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 13:32:00 +00:00
36823b2d9f debug: fix types for 403 interceptors 2026-02-25 13:13:10 +00:00
26ceccbfb9 debug: add 403 interceptors to find which operation fails 2026-02-25 13:11:55 +00:00
06999b2bd7 fix: add allowedOrigins for Next.js server actions behind reverse proxy
Next.js has its own CSRF protection for server actions, separate from
Payload's csrf config. Without allowedOrigins, server actions from the
admin panel behind a reverse proxy are rejected because the Origin header
(cms.c2sgmbh.de) doesn't match the Host header (localhost:3001).

Also removes temporary debug logging from multiTenant access check.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 13:02:03 +00:00
35bab1935a debug: add temporary logging to userHasAccessToAllTenants 2026-02-25 12:55:58 +00:00
47c6500679 fix: add cms.c2sgmbh.de to CORS/CSRF and save isSuperAdmin to JWT
- Add pl.c2sgmbh.de and cms.c2sgmbh.de to cors and csrf arrays
  to fix Forbidden error on PATCH requests from these domains
- Add saveToJWT: true to isSuperAdmin field so multiTenantPlugin
  correctly grants super admins access to all tenants

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 12:32:51 +00:00
ab4ee4bb70 fix(access): allow tenant resolution from query parameter in tenantScopedPublicRead
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>
2026-02-21 00:44:42 +00:00
290c2af40f fix(cors): add sv-frontend IP to CORS and CSRF whitelist
Add http://10.10.181.104:3000 (sv-frontend staging) to allow cross-origin
form submissions from the staging frontend to the CMS API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:23:35 +00:00
d90657c2cf fix: form submission hooks — tenant propagation + email notification
- FormSubmissionsOverrides: fields must be a function (not array) for
  the form-builder plugin to merge them with defaultFields
- setSubmissionTenant: add overrideAccess for unauthenticated submissions
- sendFormNotification: handle populated form object (extract ID),
  add overrideAccess for tenant SMTP lookup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:58:40 +00:00
5e223cd7fb feat: multi-tenant contact form refactoring
- Add forms + form-submissions to multiTenantPlugin with tenant scoping
- Inject tenant field into forms via formOverrides
- Reorder plugins: formBuilderPlugin before multiTenantPlugin (fixes warning)
- Refactor ContactFormBlock: form relationship replaces hardcoded recipientEmail
- Add setSubmissionTenant hook to auto-copy tenant from form to submission
- Add tenant field (read-only) to FormSubmissionsOverrides
- Migration: tenant_id on forms/form_submissions, form_id on contact block

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:22:58 +00:00
037835d1de fix(ci): increase build heap size and format monitoring files
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>
2026-02-17 11:58:08 +00:00
884d33c0ae fix: remove .js extensions from monitoring module imports
Next.js webpack build cannot resolve .js extensions for .ts files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 11:51:25 +00:00
bb02128b28 fix: stabilize guard responses and validation typing 2026-02-17 11:47:55 +00:00
e3987e50dc feat: security hardening, monitoring improvements, and API guards
- 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>
2026-02-17 11:42:56 +00:00
063dae411c security: harden payload endpoints and access controls 2026-02-17 10:41:51 +00:00
5f45cc820d fix: unblock tenant SMTP saves in admin 2026-02-17 08:58:21 +00:00
4386ac5d8d fix: resolve global typecheck errors 2026-02-17 08:57:32 +00:00
6b4dae8eeb fix: handle non-JSON responses in test email and prevent cascading failures
- 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>
2026-02-16 16:32:32 +00:00
0c222b9aa9 fix(tenants): make SMTP password field visible in admin panel
neverReadable blocked the field everywhere including the admin UI.
Changed to allow read for authenticated users only, so the field
shows in admin but stays hidden in unauthenticated API responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:19:09 +00:00
9bb041bd7c fix(blocks): add database migration for CardGridBlock icon fields
Adds missing columns (media_type, icon, icon_position) to
pages_blocks_card_grid_block_cards table. Without this migration,
pages API returns 500 on production.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 14:30:04 +00:00
85c76a1eb4 feat(blocks): add icon support to CardGridBlock
Cards can now display a Lucide icon as alternative to an image,
with configurable position (top/left). Fields show conditionally
based on mediaType selection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 14:07:51 +00:00
8abf3a346e refactor(pages): remove fixed hero group from Pages collection
Hero content is now handled via HeroBlock/HeroSliderBlock in the
flexible layout blocks system, giving editors full control.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:17:11 +00:00
153e4a2d5f fix(monitoring): regenerate importMap with monitoring components
The importMap was missing MonitoringNavLinks and MonitoringDashboardView
entries, causing the /admin/monitoring page to render blank.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 01:24:51 +00:00
086dd269fa fix(monitoring): address code review findings
- 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>
2026-02-15 01:02:50 +00:00
151b96d641 fix(monitoring): cache payload instance in logger to prevent flaky tests
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>
2026-02-15 00:52:17 +00:00
dd73162035 feat(monitoring): add monitoring dashboard UI with 5 tabs, SSE connection, and shared components
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:45:41 +00:00
5f38136b95 feat(monitoring): add REST API endpoints for monitoring dashboard
Add 7 API route handlers for the monitoring system:
- GET /api/monitoring/health - system health overview
- GET /api/monitoring/services - individual service status checks
- GET /api/monitoring/performance - performance metrics with period filter
- GET /api/monitoring/alerts - paginated alert history with severity filter
- POST /api/monitoring/alerts/acknowledge - acknowledge alerts
- GET /api/monitoring/logs - paginated logs with level/source/date filters
- GET /api/monitoring/snapshots - time-series data for charts

All endpoints require super-admin authentication.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:37:01 +00:00
0615b22188 feat(monitoring): add snapshot collector to queue worker
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>
2026-02-15 00:34:28 +00:00
d252ed321a feat(monitoring): add retention policies for monitoring collections
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:33:43 +00:00
0ff8b5c9d8 feat(monitoring): add structured monitoring logger
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>
2026-02-15 00:32:09 +00:00
97c8f32967 feat(monitoring): add alert evaluator with cooldown and multi-channel dispatch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:30:21 +00:00
dc14c5dbc7 feat(monitoring): add performance tracker with ring buffer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:29:58 +00:00
4907371715 feat(monitoring): add monitoring service with system health and service checks
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>
2026-02-15 00:26:28 +00:00
ee981c32bc feat(monitoring): add database migration for 4 monitoring collections
Creates tables, enums, and indexes for monitoring_snapshots,
monitoring_logs, monitoring_alert_rules, and monitoring_alert_history.
Includes hasMany select tables and the critical
payload_locked_documents_rels columns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:19:35 +00:00
34becc8f49 feat(monitoring): add 4 monitoring collections (Snapshots, Logs, AlertRules, AlertHistory)
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>
2026-02-15 00:14:53 +00:00
214e2ddde8 feat(monitoring): add shared types for monitoring system
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:11:33 +00:00
e904f0949b fix(queue): resolve queue-worker crash-loop via Redis auth and PM2 config
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>
2026-02-14 17:46:54 +00:00
ed07e15670 fix: remove .js extensions from TypeScript imports
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>
2026-02-14 17:24:43 +00:00
692498871c feat(youtube): register content calendar as admin view
Adds the Content Calendar view at /admin/content-calendar and
integrates it into the YouTube Dashboards nav group.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 17:18:12 +00:00
5394f628e4 feat(youtube): add FullCalendar content calendar component
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 13:53:30 +00:00
95079ec652 feat(youtube): add content calendar API with conflict detection
GET endpoint returns FullCalendar-compatible events with schedule
conflict detection. PATCH endpoint supports drag & drop rescheduling
with published-video protection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 13:52:17 +00:00
2466745e7f feat(youtube): add conflict detection service
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>
2026-02-14 13:50:24 +00:00
d8118528db feat(youtube): add team capacity planning API
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>
2026-02-14 13:49:55 +00:00
8ae5841cc1 feat(youtube): add auto status transition hook
Automatically transitions YouTube content status when conditions are met
(e.g., upload_scheduled -> published when videoId is present) and sends
notifications to assigned users.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 13:42:25 +00:00
9e7b433cd0 feat(youtube): add comparison, trends, ROI analytics
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>
2026-02-14 13:37:51 +00:00
e4fea9db4c feat(youtube): add ROI cost fields to YouTubeContent
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 13:35:57 +00:00