Add server wipe detection#53
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new “server wipe detection” feature to RustPlusBot that detects wipe signals on reconnect, announces the wipe in the per-server #events channel (optionally pinging @everyone), and purges paired smart-device state so stale entities/notifications don’t survive a wipe.
Changes:
- Introduces
RustPlusBot.Features.Wipes(detector + hosted service + announcer + embed renderer + Discord poster) and theServerWipedEventabstraction event. - Persists a per-server wipe baseline (
LastWipeTimeUtc,LastMapSeed,LastMapSize) and adds a guild toggle (PingEveryoneOnWipe) with a new #settings UI button. - Adds wipe purge handlers for Alarms, Switches, and StorageMonitors (DB rows removed first, then best-effort Discord message deletes), plus extensive test coverage.
Reviewed changes
Copilot reviewed 64 out of 66 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/RustPlusBot.Persistence.Tests/Workspace/WorkspaceStoreWipePingTests.cs | Verifies PingEveryoneOnWipe default + upsert/round-trip behavior in WorkspaceStore. |
| tests/RustPlusBot.Persistence.Tests/Wipes/WipeBaselineStoreTests.cs | Unit tests for reading/writing wipe baseline via IWipeBaselineStore. |
| tests/RustPlusBot.Persistence.Tests/Servers/RustServerWipeColumnsTests.cs | Migration/schema round-trip test for wipe baseline columns + guild ping default. |
| tests/RustPlusBot.Localization.Tests/StringsResourceParityTests.cs | Updates expected localization key count for added wipe/settings strings. |
| tests/RustPlusBot.Features.Workspace.Tests/Messages/SettingsMessageRendererWipePingTests.cs | Validates the settings message wipe-ping toggle button rendering. |
| tests/RustPlusBot.Features.Workspace.Tests/Messages/RendererTests.cs | Adjusts renderer wiring to provide an IWorkspaceStore to settings renderer. |
| tests/RustPlusBot.Features.Workspace.Tests/Fakes/FakeWorkspaceStore.cs | Extends fake workspace store with wipe-ping flag storage. |
| tests/RustPlusBot.Features.Wipes.Tests/WipeRegistrationTests.cs | Ensures AddWipes() registers and resolves required services. |
| tests/RustPlusBot.Features.Wipes.Tests/WipeEmbedRendererTests.cs | Verifies wipe announcement embed structure and localization. |
| tests/RustPlusBot.Features.Wipes.Tests/WipeDetectorTests.cs | Covers wipe detection diff rules, tolerance, and backfill/noop behavior. |
| tests/RustPlusBot.Features.Wipes.Tests/WipeAnnouncerTests.cs | Tests posting behavior including optional @everyone and culture selection. |
| tests/RustPlusBot.Features.Wipes.Tests/RustPlusBot.Features.Wipes.Tests.csproj | Adds a dedicated test project for the new wipes feature. |
| tests/RustPlusBot.Features.Wipes.Tests/Hosting/WipesHostedServiceTests.cs | Validates hosted service routes bus events to detector/announcer. |
| tests/RustPlusBot.Features.Switches.Tests/SwitchWipePurgerTests.cs | Tests switch purge handler: remove rows + best-effort message deletes. |
| tests/RustPlusBot.Features.Switches.Tests/Hosting/SwitchesHostedServiceTests.cs | Updates Switches hosted service tests for injected wipe purger. |
| tests/RustPlusBot.Features.StorageMonitors.Tests/StorageMonitorWipePurgerTests.cs | Tests storage monitor purge handler behavior. |
| tests/RustPlusBot.Features.StorageMonitors.Tests/Hosting/StorageMonitorsHostedServiceTests.cs | Updates StorageMonitors hosted service tests for injected wipe purger. |
| tests/RustPlusBot.Features.Alarms.Tests/Hosting/AlarmsHostedServiceTests.cs | Updates Alarms hosted service tests for injected wipe purger. |
| tests/RustPlusBot.Features.Alarms.Tests/AlarmWipePurgerTests.cs | Tests alarm purge handler behavior. |
| src/RustPlusBot.Persistence/Workspace/WorkspaceStore.cs | Adds persistence accessors/mutator for GuildSettings.PingEveryoneOnWipe. |
| src/RustPlusBot.Persistence/Workspace/IWorkspaceStore.cs | Extends workspace store contract with wipe-ping flag operations. |
| src/RustPlusBot.Persistence/Wipes/WipeBaselineStore.cs | Implements baseline store over RustServer wipe baseline columns. |
| src/RustPlusBot.Persistence/Wipes/WipeBaseline.cs | Defines WipeBaseline record (wipe time, seed, size). |
| src/RustPlusBot.Persistence/Wipes/IWipeBaselineStore.cs | Adds interface for reading/writing wipe baseline. |
| src/RustPlusBot.Persistence/PersistenceServiceCollectionExtensions.cs | Registers IWipeBaselineStore in persistence DI. |
| src/RustPlusBot.Persistence/Migrations/BotDbContextModelSnapshot.cs | Updates EF snapshot with new guild/server wipe-related columns. |
| src/RustPlusBot.Persistence/Migrations/20260715195556_WipeDetection.Designer.cs | EF migration designer for wipe detection schema changes. |
| src/RustPlusBot.Persistence/Migrations/20260715195556_WipeDetection.cs | Migration adding wipe baseline columns + PingEveryoneOnWipe default false. |
| src/RustPlusBot.Persistence/Configurations/RustServerConfiguration.cs | Configures conversions for new uint? seed/size columns to SQLite-friendly types. |
| src/RustPlusBot.Localization/Strings.resx | Adds English strings for wipe embed + settings wipe-ping toggle labels. |
| src/RustPlusBot.Localization/Strings.fr.resx | Adds French strings for wipe embed + settings wipe-ping toggle labels. |
| src/RustPlusBot.Host/RustPlusBot.Host.csproj | References the new wipes feature project from the host. |
| src/RustPlusBot.Host/Program.cs | Registers wipes feature via builder.Services.AddWipes(). |
| src/RustPlusBot.Features.Workspace/Modules/SettingsComponentModule.cs | Adds interaction handler to toggle wipe-ping flag and re-render settings. |
| src/RustPlusBot.Features.Workspace/Messages/SettingsMessageRenderer.cs | Renders wipe-ping toggle button in global settings message. |
| src/RustPlusBot.Features.Wipes/WipeServiceCollectionExtensions.cs | Adds DI setup for wipes feature components and hosted service. |
| src/RustPlusBot.Features.Wipes/RustPlusBot.Features.Wipes.csproj | New wipes feature project definition and references. |
| src/RustPlusBot.Features.Wipes/Rendering/WipeEmbedRenderer.cs | Renders localized wipe announcement embed. |
| src/RustPlusBot.Features.Wipes/Posting/IWipeChannelPoster.cs | Defines posting abstraction for wipe announcements. |
| src/RustPlusBot.Features.Wipes/Posting/DiscordWipeChannelPoster.cs | Posts wipe announcements to Discord via gateway client. |
| src/RustPlusBot.Features.Wipes/Hosting/WipesHostedService.cs | Subscribes to connection-status and wipe events to trigger detection/announce. |
| src/RustPlusBot.Features.Wipes/Detection/WipeDetector.cs | Implements diff rules against persisted baseline and publishes ServerWipedEvent. |
| src/RustPlusBot.Features.Wipes/Detection/IWipeDetector.cs | Defines wipe detector contract. |
| src/RustPlusBot.Features.Wipes/Announcing/WipeAnnouncer.cs | Locates #events, resolves culture + ping flag, and posts wipe embed. |
| src/RustPlusBot.Features.Wipes/Announcing/IWipeAnnouncer.cs | Defines wipe announcer contract. |
| src/RustPlusBot.Features.Switches/SwitchServiceCollectionExtensions.cs | Registers switch wipe purger for event-driven purge. |
| src/RustPlusBot.Features.Switches/Relaying/SwitchWipePurger.cs | Purges switches (DB first, then message deletes) on ServerWipedEvent. |
| src/RustPlusBot.Features.Switches/Posting/ISwitchChannelPoster.cs | Extends poster contract to support message deletion. |
| src/RustPlusBot.Features.Switches/Posting/DiscordSwitchChannelPoster.cs | Implements best-effort raw message deletes via gateway client. |
| src/RustPlusBot.Features.Switches/Hosting/SwitchesHostedService.cs | Adds ServerWipedEvent subscription loop to invoke switch purge. |
| src/RustPlusBot.Features.StorageMonitors/StorageMonitorServiceCollectionExtensions.cs | Registers storage monitor wipe purger. |
| src/RustPlusBot.Features.StorageMonitors/Relaying/StorageMonitorWipePurger.cs | Purges storage monitors on wipe event. |
| src/RustPlusBot.Features.StorageMonitors/Posting/IStorageMonitorChannelPoster.cs | Extends poster contract to support message deletion. |
| src/RustPlusBot.Features.StorageMonitors/Posting/DiscordStorageMonitorChannelPoster.cs | Implements storage monitor message deletes via gateway client. |
| src/RustPlusBot.Features.StorageMonitors/Hosting/StorageMonitorsHostedService.cs | Adds wipe-purge event loop for storage monitors. |
| src/RustPlusBot.Features.Alarms/Relaying/AlarmWipePurger.cs | Purges alarms on wipe event. |
| src/RustPlusBot.Features.Alarms/Posting/IAlarmChannelPoster.cs | Extends alarm poster contract to support message deletion. |
| src/RustPlusBot.Features.Alarms/Posting/DiscordAlarmChannelPoster.cs | Adds alarm message deletion implementation. |
| src/RustPlusBot.Features.Alarms/Hosting/AlarmsHostedService.cs | Adds wipe-purge loop subscription for alarms. |
| src/RustPlusBot.Features.Alarms/AlarmServiceCollectionExtensions.cs | Registers alarm wipe purger in DI. |
| src/RustPlusBot.Domain/Servers/RustServer.cs | Adds persisted wipe baseline properties to the server entity. |
| src/RustPlusBot.Domain/Guilds/GuildSettings.cs | Adds PingEveryoneOnWipe flag to guild settings. |
| src/RustPlusBot.Abstractions/Events/ServerWipedEvent.cs | Introduces cross-feature wipe event contract. |
| RustPlusBot.slnx | Adds wipes feature and test projects to the solution. |
| docs/superpowers/specs/2026-07-15-wipe-detection-design.md | Adds the design spec documenting wipe detection approach and decisions. |
Files not reviewed (1)
- src/RustPlusBot.Persistence/Migrations/20260715195556_WipeDetection.Designer.cs: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| await channel.SendMessageAsync( | ||
| content, | ||
| embed: embed, | ||
| options: options, | ||
| allowedMentions: AllowedMentions.All) | ||
| .ConfigureAwait(false); |
There was a problem hiding this comment.
Good catch — fixed in 249beb1. PostAsync now passes AllowedMentions.None for embed-only posts (content is null) and keeps AllowedMentions.All only when explicit ping content is present, so incidental mention-like text in the localized embed can never ping. Ping behavior on the @everyone path is unchanged.
Only pass AllowedMentions.All when ping content is present; use AllowedMentions.None for embed-only posts so incidental mention-like text in the localized embed cannot ping users or roles. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Adds server wipe detection to RustPlusBot. When the Rust server wipes, the bot now detects it on reconnect, announces it in the per-server #events channel, and purges all paired smart devices so no stale devices or dead alarm notifications survive the wipe.
Design spec:
docs/superpowers/specs/2026-07-15-wipe-detection-design.mdWhat it does
RustPlusBot.Features.Wipesproject checks each reconnect transition (ConnectionStatusChangedEventwithIsConnected && !WasConnected), diffing live wipe time / map seed / map size against a baseline persisted on theRustServerrow (newWipeDetectionmigration addsLastWipeTimeUtc,LastMapSeed,LastMapSize). A wipe fires when the wipe time advances beyond a 60s jitter tolerance, or the seed/size changes — so wipes that happen while the bot is offline are still caught on the next connect. The first observation after deploy backfills the baseline silently (no false announcement on upgrade).PingEveryoneOnWipe, default off).ServerWipedEventand delete their DB rows first (the stale-notification guarantee — a late trigger for a dead entity finds no row and is dropped), then best-effort delete their Discord embeds. Idempotent; missing channel/message tolerated.(size, seed), so the new seed regenerates it automatically.Testing
-warnaserror).jb cleanupcodegate clean.Notes
ConnectionSupervisoris untouched.PairedEntitypurge was dropped — nothing in production writes that table.dotnet efin this repo must use--startup-project src/RustPlusBot.Persistence(Host fails on a pre-existing packaging quirk).🤖 Generated with Claude Code