# 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 `.local` file show a "Deactivate Jail" button in their config panel. - Calling the button removes or neutralises the `.local` file and refreshes the jail list. - Inactive jails without a `.local` file 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 `RecoveryBanner` are 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: 1. If the `.local` file did not exist before activation, **delete** `jail.d/{name}.local` outright. 2. 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). 3. After deleting/restoring the file, attempt a `reload_all` socket command so fail2ban picks up the reverted state. 4. Only set `recovered = true` in the `JailActivationResponse` once all three steps above have actually succeeded. If any step fails, set `recovered = false` and log the error. 5. On the frontend side, the *"Activation Failed — System Recovered"* `MessageBar` in `ActivateJailDialog.tsx` should only be shown when the backend actually returns `recovered = true`. The current misleading message should be replaced with a more actionable one when `recovered = false`. **Acceptance criteria:** - After a failed activation, `jail.d/{name}.local` is either absent or contains its pre-activation content. - `recovered: true` is 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.