- schedules/: Add schedule executor in SchedulesService — polls every 60s for
tasks where next_run <= now, dispatches NATS commands per task_type
(restart, announcement, command, plugin_reload). Calculates next_run from
cron expression on create/update/toggle. Bootstraps missing next_run values
on startup. Wire NatsService into SchedulesModule.
- alerts/: Add alert evaluator in AlertsService — polls every 90s, loads all
alert_config rows, queries latest server_stats per license, evaluates FPS
degradation and population drop thresholds. Fires alert_history records on
breach. Enforces 10-minute in-memory cooldown per alert type per license to
prevent flooding. Wire ServerStats repo into AlertsModule.
- wipes/: Replace hardcoded dry-run mock with profile-aware simulation.
Resolves actual WipeProfile by ID (cross-tenant protected), builds
would_delete/would_preserve lists from wipe_type, factors pre_wipe_config
(backup, countdown warnings) and post_wipe_config (health checks, retry
attempts) into estimated_duration_seconds. Returns profile_name and notes.
- store/: Fix installModule stub — creates a real module_installations record
with status='installed' and installed_at timestamp. Idempotent on retry,
resets failed installations. Wire ModuleInstallation repo into StoreModule.
getMyModules now returns real installation data instead of filtered purchases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause of all remaining 500s: TypeORM entities were scaffolded with
"ideal" column names that don't match the Postgres columns created by
the Rust migrations. Every query generated SQL referencing non-existent
columns.
Entity fixes:
- notifications_config: email_enabled→email_alerts_enabled, removed
6 phantom columns (email_address, notify_on_start, notify_on_stop,
notify_on_player_threshold, player_threshold), renamed 4 notify
columns to match DB (notify_server_crash, notify_wipe_start, etc),
added 3 missing columns (notify_server_offline, notify_store_purchase,
notify_player_report)
- team_members: joined_at→accepted_at (nullable, matches DB)
- roles: removed description column (doesn't exist in DB)
- scheduled_tasks: is_enabled→is_active, removed phantom last_run
- wipe_profiles: pre/post_wipe_config nullable→NOT NULL with default
Service/DTO fixes:
- Updated all property references across notifications, team, schedules
services and DTOs to match corrected entity names
- Added is_active to UpdateTaskDto (frontend sends it, was being
rejected by forbidNonWhitelisted validation)
- Removed description from CreateRoleDto
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>