diff --git a/routstr/core/logging.py b/routstr/core/logging.py index 563b368d..bc088ed5 100644 --- a/routstr/core/logging.py +++ b/routstr/core/logging.py @@ -183,10 +183,9 @@ class RequestIdFilter(logging.Filter): class ClientAppFilter(logging.Filter): - """Filter to add the requesting client app to all log records.""" + """Attach request-local app attribution to log records.""" def filter(self, record: logging.LogRecord) -> bool: - """Add the client app to the log record if available.""" # Import here to avoid circular imports from .middleware import UNKNOWN_CLIENT_APP, client_app_context diff --git a/routstr/core/middleware.py b/routstr/core/middleware.py index 228cd68a..da073cd5 100644 --- a/routstr/core/middleware.py +++ b/routstr/core/middleware.py @@ -15,13 +15,11 @@ logger = get_logger(__name__) # Context variable to store request ID across async context request_id_context: ContextVar[str | None] = ContextVar("request_id") -# Context variable to store the client app across async context client_app_context: ContextVar[str | None] = ContextVar("client_app") UNKNOWN_CLIENT_APP = "unknown" -# Identity headers in priority order. X-Title and HTTP-Referer are the -# OpenRouter convention; User-Agent covers SDKs and scripts that set neither. +# Prefer OpenRouter app headers, then browser and SDK fallbacks. _CLIENT_APP_HEADERS: tuple[str, ...] = ( "x-title", "http-referer", @@ -29,8 +27,7 @@ _CLIENT_APP_HEADERS: tuple[str, ...] = ( "user-agent", ) -# Header values are attacker-controlled: cap the length so one request can't -# bloat every log line. +# Limit untrusted header data repeated in every log record. _CLIENT_APP_MAX_LENGTH = 120 diff --git a/tests/unit/test_client_app_logging.py b/tests/unit/test_client_app_logging.py index a76d411c..107f8c2c 100644 --- a/tests/unit/test_client_app_logging.py +++ b/tests/unit/test_client_app_logging.py @@ -93,7 +93,6 @@ def test_value_is_truncated_to_120_chars() -> None: def test_control_characters_are_stripped() -> None: - """A crafted header must not be able to forge log records.""" headers = Headers({"user-agent": "evil-app\x1b[0m fake INFO line"}) assert client_app_from_headers(headers) == "evil-app[0m fake INFO line" @@ -178,7 +177,6 @@ def test_filter_defaults_to_unknown_outside_request_context() -> None: def test_handler_logs_carry_client_app(caplog: pytest.LogCaptureFixture) -> None: - """A log line emitted inside a handler still names the app that triggered it.""" app = FastAPI() handler_logger = logging.getLogger("routstr.test.handler")