Files
BanGUI/Docs/Tasks.md
Lukas 0a3f9c6c16 refactor(backend): external logging metrics, required mode, health checks
- Add external_logging_init_failures counter
- Add external_log_required flag, raise if init fails and required
- Health endpoint: add external_logging status check
- Blocklist service: enrich with metadata fields, update import logic
- Health check task: add runtime_state dependency, fix return typing
- Metrics: add Histogram for request latencies
- Frontend: align BlocklistImportLogSection props
- Docs: update deployment guide, remove stale tasks

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-04 03:45:13 +02:00

133 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
### Issue #64: MEDIUM - External Logging Failure Silently Swallowed
**Where found**:
- `backend/app/main.py:192-213`
**Why this is needed**:
When Datadog, Papertrail, or Elasticsearch log handler initialization fails, the error is caught, logged as a warning to stdout, and the application continues. In production this means critical logs may never reach the monitoring system, and operators will not know until an incident occurs.
**Goal**:
External logging failures are surfaced to operators at deployment time.
**What to do**:
1. Promote the warning to an error and expose it via the health endpoint (Issue #57).
2. Add a startup check: if `EXTERNAL_LOG_REQUIRED=true` and initialization fails, abort startup.
3. Emit a metric/alert on initialization failure.
**Possible traps and issues**:
- Making startup fail on logging issues may be too strict for some environments; make `EXTERNAL_LOG_REQUIRED` optional and default to `false`.
**Docs changes needed**:
- `Docs/Deployment.md`: document `EXTERNAL_LOG_REQUIRED` and the health check for logging status.
**Doc references**:
- `backend/app/main.py` logging initialization block
---
### Issue #65: MEDIUM - Abort Selector Inconsistency in useFetchData
**Where found**:
- `frontend/src/hooks/useFetchData.ts:124-131`
**Why this is needed**:
When a request is aborted, `refresh()` returns the raw response without running the `selector()` function. In non-aborted paths the selector runs. Callers of `refresh()` receive different types depending on the abort state, making the return type unreliable and causing subtle state shape mismatches.
**Goal**:
`refresh()` returns a consistent type regardless of abort state.
**What to do**:
1. On abort, return `null` (or a typed sentinel) instead of the raw response, so callers can handle the aborted case explicitly.
2. Update the TypeScript return type of `refresh()` to reflect the nullable result.
**Possible traps and issues**:
- Existing callers that ignore the return value are unaffected; callers that use it need to handle `null`.
**Docs changes needed**:
- `frontend/src/hooks/README.md`: document the `null` return on abort.
**Doc references**:
- `frontend/src/hooks/README.md`
---
### Issue #67: LOW - Default Page Size Inconsistently Applied Across Routers
**Where found**:
- `backend/app/routers/history.py:80-84` uses `DEFAULT_PAGE_SIZE` constant
- Multiple other routers may hardcode page size values
**Why this is needed**:
Endpoints with different default page sizes create an inconsistent API experience and make it hard to reason about server load. A client that does not pass `page_size` gets different result counts from different endpoints.
**Goal**:
All paginated endpoints use the same default page size driven by a single constant.
**What to do**:
1. Audit all `page_size` Query parameters across routers.
2. Replace all hardcoded defaults with `DEFAULT_PAGE_SIZE` from `constants.py`.
3. Add a linting check or unit test that asserts no hardcoded page size defaults exist in routers.
**Possible traps and issues**:
- Some endpoints may intentionally use a different page size for performance reasons; document exceptions explicitly.
**Docs changes needed**:
- API reference: document the default page size and how to override it.
**Doc references**:
- `backend/app/utils/constants.py` `DEFAULT_PAGE_SIZE`
---
### Issue #68: LOW - No Reserved Keyword Validation for Jail Names
**Where found**:
- `backend/app/models/jail.py` jail name validated against alphanumeric regex only
- `backend/app/routers/jail_config.py`
**Why this is needed**:
Fail2ban uses reserved jail names and command keywords (e.g., `all`, `status`, `purge`). A user-created jail with a reserved name could shadow fail2ban built-in commands or produce confusing behavior when management commands are issued.
**Goal**:
Reject jail names that conflict with fail2ban reserved words at model validation time.
**What to do**:
1. Define a `FAIL2BAN_RESERVED_JAIL_NAMES` set in `constants.py`.
2. Add a Pydantic validator on the jail name field that rejects reserved words.
3. Return a 422 with a descriptive error message.
**Possible traps and issues**:
- The reserved word list may change across fail2ban versions; source it from fail2ban documentation and version-gate if necessary.
**Docs changes needed**:
- API reference: document the list of reserved jail names.
**Doc references**:
- Fail2ban documentation on reserved jail identifiers
---
### Issue #69: LOW - Jail Names Echoed in Error Messages Without Sanitization
**Where found**:
- `backend/app/exceptions.py:138,351` jail names interpolated directly into error strings
**Why this is needed**:
Although Python's `repr()` provides basic escaping, user-supplied jail names are reflected back in error messages. If these messages are ever rendered in an HTML context (e.g., a future admin UI or email notification), they become XSS vectors. They also act as confirmation oracles when combined with timing attacks.
**Goal**:
Error messages referencing user input are sanitized before inclusion.
**What to do**:
1. Pass user-supplied values through a dedicated `sanitize_for_display()` helper before interpolation.
2. Ensure the helper strips or escapes HTML special characters.
3. For API responses, always return the original (validated) field name rather than the raw user input.
**Possible traps and issues**:
- Over-escaping in JSON responses is not needed (JSON is not HTML); apply sanitization only at HTML render boundaries.
**Docs changes needed**:
- `CONTRIBUTING.md`: document the rule that user input must not be echoed raw in messages.
**Doc references**:
- `backend/app/exceptions.py`