Fix HIGH priority issues: unbounded queries, rate limiting, health checks

Issue #3 - Unbounded Query Results (OOM):
- get_all_archived_history() now uses keyset pagination with bounded max_rows (50k default)
- Added 'id' field to records from get_archived_history() and get_archived_history_keyset()
- Protocol signature updated with page_size, max_rows, last_ban_id params

Issue #7 - Docker Health Check Fails:
- Added curl to Dockerfile.backend runtime image
- HEALTHCHECK now uses 'curl -f http://localhost:8000/api/health'
- compose.prod.yml: increased start_period to 40s, timeout to 10s
- Frontend healthcheck proxies to backend /api/health

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-05-01 21:47:36 +02:00
parent 1830da496d
commit 0d5882b32f
39 changed files with 2067 additions and 339 deletions

View File

@@ -16,7 +16,7 @@ from typing import TypeVar, cast
import structlog
from app import __version__
from app.models.config import ServiceStatusResponse
from app.models.config_domain import DomainServiceStatus
from app.models.server import ServerStatus
from app.utils.constants import FAIL2BAN_SOCKET_TIMEOUT_FAST
from app.utils.fail2ban_client import (
@@ -69,7 +69,7 @@ async def _safe_get_typed(
async def get_service_status(
socket_path: str,
probe_fn: Callable[[str], Awaitable[ServerStatus]] | None = None,
) -> ServiceStatusResponse:
) -> DomainServiceStatus:
"""Return fail2ban service health status with log configuration.
Delegates to an injectable *probe_fn* (defaults to
@@ -80,7 +80,7 @@ async def get_service_status(
probe_fn: Optional probe function.
Returns:
:class:`~app.models.config.ServiceStatusResponse`.
:class:`~app.models.config_domain.DomainServiceStatus`.
"""
if probe_fn is None:
raise ValueError(
@@ -110,7 +110,7 @@ async def get_service_status(
jail_count=server_status.active_jails,
)
return ServiceStatusResponse(
return DomainServiceStatus(
online=server_status.online,
version=__version__,
jail_count=server_status.active_jails,