"""Secret masking and logging handler setup.""" from __future__ import annotations import logging from sebrief.config import Settings from sebrief.logging_setup import ( LOG_FILE_NAME, mask_secrets, register_secret_values, setup_logging, ) def teardown_function(): register_secret_values() # clear the registry between tests def test_mask_sk_keys_and_url_params(): assert mask_secrets("key sk-abcdef123456 leaked") == "key *** leaked" assert mask_secrets("GET https://x/api?api_key=deadbeef&x=1") == "GET https://x/api?api_key=***&x=1" assert mask_secrets("token=verysecretvalue123") == "token=verysecretvalue123" # no ?/& prefix def test_registered_values_masked_verbatim(): register_secret_values("my-odd-shaped-secret") assert mask_secrets("value my-odd-shaped-secret here") == "value *** here" register_secret_values() # cleared assert "my-odd-shaped-secret" in mask_secrets("value my-odd-shaped-secret here") def test_short_values_not_registered(): register_secret_values("short") assert mask_secrets("short") == "short" def test_setup_logging_masks_in_file_and_is_idempotent(tmp_path): settings = Settings( _env_file=None, MINIMAX_API_KEY="sk-verysecretkey12345", SEBRIEF_LOG_DIR=str(tmp_path / "logs"), ) setup_logging(settings) setup_logging(settings) # handlers replaced, not duplicated root = logging.getLogger() ours = [h for h in root.handlers if getattr(h, "_sebrief_handler", False)] assert len(ours) == 2 # console + file logging.getLogger("sebrief.test").info("key=%s", "sk-verysecretkey12345") for handler in ours: handler.flush() text = (tmp_path / "logs" / LOG_FILE_NAME).read_text(encoding="utf-8") assert "sk-verysecretkey12345" not in text assert "***" in text for handler in ours: # clean up for other tests root.removeHandler(handler) handler.close() def test_setup_logging_survives_unwritable_log_dir(tmp_path): blocker = tmp_path / "logs" blocker.write_text("file, not a dir") settings = Settings(_env_file=None, SEBRIEF_LOG_DIR=str(blocker)) setup_logging(settings) # must not raise root = logging.getLogger() ours = [h for h in root.handlers if getattr(h, "_sebrief_handler", False)] assert len(ours) == 1 # console only for handler in ours: root.removeHandler(handler) handler.close()