Add structured data (icon, features[], detailSections[]) to all 6 services
so the frontend can render benefits grids and checklists from CMS data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
- 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>
- 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>
- Remove redundant NODE_OPTIONS override (heap limit now in package.json)
- Add CRON_SECRET placeholder for pre-test build step
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Next.js builds run in NODE_ENV=production which triggers env
validation requiring CRON_SECRET (added by security hardening).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The codebase grew past the 2GB heap limit with security/monitoring
additions. cross-env in build script overrides CI NODE_OPTIONS, so
the limit must be set in package.json itself.
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>
Monitors porwoll.de and blogwoman.de for stale builds caused by
Plesk Git's silent deploy failures (code pulled but build never ran).
- Compares source file timestamps vs .next/BUILD_ID mtime
- HTTP health checks via public URLs
- --alert flag for CMS monitoring API integration
- Runs as cron job every 30 minutes on sv-payload
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>
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>
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>
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>
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>
Deploys frontend sites on sv-frontend via SSH.
Supports: blogwoman, porwoll, or all sites at once.
Usage: ./scripts/deploy-frontend.sh <blogwoman|porwoll|all>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
- 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>
- Mark Monitoring & Alerting Dashboard as completed in roadmap
- Add monitoring subsystem to CLAUDE.md subsystems table
- Add 4 monitoring collections to collections list (55+ → 59+)
- Add monitoring dashboard URL
- Add changelog entry for 15.02.2026
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>
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>
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>
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>
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>
Event-driven architecture with SSE real-time updates, 5-tab dashboard
(System Health, Services, Performance, Alerts, Logs), 4 new collections,
and integration with existing alert-service.ts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add comprehensive YouTube feature documentation covering 9 collections,
12 custom API endpoints, 3 cron jobs, admin views, services, hooks,
and access control across CLAUDE.md, CLAUDE_REFERENCE.md, and
API_ANLEITUNG.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Script extracts types from payload-types.ts, updates the
payload-contracts repo, builds to verify, and optionally pushes.
Usage: ./scripts/update-contracts.sh [--push]
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>