### 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`