- Replace vague 'System Recovered' message with 'Configuration Rolled Back'
and actionable text describing the rollback outcome
- Replace 'Manual Intervention Required' with 'Rollback Unsuccessful' and
specific instructions: check jail.d/{name}.local, fix manually, restart
- Add test_activate_jail_rollback_deletes_file_when_no_prior_local to cover
rollback path when no .local file existed before activation
- Mark all three tasks complete in Tasks.md
4.7 KiB
BanGUI — Task List
This document breaks the entire BanGUI project into development stages, ordered so that each stage builds on the previous one. Every task is described in prose with enough detail for a developer to begin work. References point to the relevant documentation.
✅ Task: Add "Deactivate Jail" Button for Inactive Jails in the Config View
Context:
In frontend/src/components/config/JailsTab.tsx, the "Deactivate Jail" button is currently only rendered when a jail is active. When a jail is inactive but has an existing jail.d/{name}.local file (i.e. it was previously configured and has enabled = false), there is no action button to clean up that override file.
Goal:
Add a "Deactivate Jail" (or "Remove Config") button to the jail config view for inactive jails that have a .local file. Clicking it should delete the jail.d/{name}.local file via the existing deactivate endpoint (POST /api/config/jails/{name}/deactivate) or a dedicated delete-override endpoint, making the UI consistent with the active-jail view. If no .local file exists for the inactive jail, the button should not be shown (there is nothing to clean up).
Acceptance criteria:
- Inactive jails that own a
.localfile show a "Deactivate Jail" button in their config panel. - Calling the button removes or neutralises the
.localfile and refreshes the jail list. - Inactive jails without a
.localfile are unaffected and show no extra button.
✅ Task: Remove the "fail2ban Stopped After Jail Activation" Recovery Banner
Context:
frontend/src/components/common/RecoveryBanner.tsx renders a full-page banner with the heading "fail2ban Stopped After Jail Activation" and the body "fail2ban stopped responding after activating jail {name}. The jail's configuration may be invalid." together with "Disable & Restart" and "View Logs" action buttons. This banner interrupts the UI even when the backend has already handled the rollback automatically.
Goal:
Remove the RecoveryBanner component and all its mount points from the application. Any state that was used exclusively to drive this banner (e.g. a fail2banStopped flag or related context) should also be removed. If the underlying crash-detection logic is still needed for other features, keep that logic but detach it from the banner render path.
Acceptance criteria:
- The full-page banner no longer appears under any circumstances.
- No dead code or orphaned state references remain after the removal.
- All existing tests that reference
RecoveryBannerare updated or removed accordingly.
✅ Task: Fix Activation Failure Rollback — Actually Delete the .local File
Context:
When jail activation fails after the jail.d/{name}.local file has already been written (i.e. fail2ban reloaded but the jail never came up, or fail2ban became unresponsive), _rollback_activation_async() in backend/app/services/config_file_service.py is supposed to restore the pre-activation state. The frontend then displays "Activation Failed — System Recovered" with the message "Activation of jail {name} failed. The server has been automatically recovered."
In practice, recovery does not happen: the .local file remains on disk with enabled = true, leaving fail2ban in a broken state on next restart. The frontend misleadingly reports success.
Goal:
Fix _rollback_activation_async() so that it reliably removes (or reverts) the .local file whenever activation fails:
- If the
.localfile did not exist before activation, deletejail.d/{name}.localoutright. - If it existed before activation (e.g. previously had
enabled = false), restore its original content atomically (temp-file rename pattern already used elsewhere in the service). - After deleting/restoring the file, attempt a
reload_allsocket command so fail2ban picks up the reverted state. - Only set
recovered = truein theJailActivationResponseonce all three steps above have actually succeeded. If any step fails, setrecovered = falseand log the error. - On the frontend side, the "Activation Failed — System Recovered"
MessageBarinActivateJailDialog.tsxshould only be shown when the backend actually returnsrecovered = true. The current misleading message should be replaced with a more actionable one whenrecovered = false.
Acceptance criteria:
- After a failed activation,
jail.d/{name}.localis either absent or contains its pre-activation content. recovered: trueis only returned when the rollback fully succeeded.- The UI message accurately reflects the actual recovery state.
- A test in
backend/tests/test_services/covers the rollback path, asserting the file is absent/reverted and the response flag is correct.