From e568f208716d0fdb285fc6cba67dc20d667aed4b Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Sun, 5 Apr 2026 11:46:21 -0400 Subject: [PATCH] feat(config): deprecation warning for [system] arm_pin_hash If a config still has the legacy [system] arm_pin_hash set but no [security] pin_hash, load_config logs a WARNING telling the operator to re-run 'vigilar config set-pin'. The legacy field is still parsed (so old configs don't fail validation) but ignored at runtime. Part of issue #2 PIN hashing unification. --- tests/unit/test_config.py | 19 +++++++++++++++++++ vigilar/config.py | 14 +++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index e3e29bd..233a2c2 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -138,3 +138,22 @@ class TestCameraConfigLocation: from vigilar.config import CameraConfig cfg = CameraConfig(id="test", display_name="Test", rtsp_url="rtsp://x", location="EXTERIOR") assert cfg.location == "EXTERIOR" + + +def test_deprecation_warning_for_arm_pin_hash(tmp_path, caplog): + """Loading a config that still uses the legacy [system] arm_pin_hash + must log a clear warning pointing the user at `vigilar config set-pin`.""" + import logging + cfg_path = tmp_path / "legacy.toml" + cfg_path.write_text( + '[system]\n' + 'arm_pin_hash = "pbkdf2_sha256$abc$def"\n' + ) + with caplog.at_level(logging.WARNING): + from vigilar.config import load_config + load_config(str(cfg_path)) + + messages = [r.message for r in caplog.records if r.levelno >= logging.WARNING] + assert any("arm_pin_hash" in m and "deprecated" in m.lower() for m in messages), ( + f"expected deprecation warning mentioning arm_pin_hash, got: {messages}" + ) diff --git a/vigilar/config.py b/vigilar/config.py index 1caf730..13d75d8 100644 --- a/vigilar/config.py +++ b/vigilar/config.py @@ -1,7 +1,10 @@ """Configuration loading and validation via TOML + Pydantic.""" +import logging import sys import tomllib + +log = logging.getLogger(__name__) from pathlib import Path from typing import Self @@ -435,4 +438,13 @@ def load_config(path: str | Path | None = None) -> VigilarConfig: raw["sensors.gpio"] = gpio_config # The [[sensors]] array items remain as 'sensors' key from TOML parsing - return VigilarConfig(**raw) + cfg = VigilarConfig(**raw) + + if cfg.system.arm_pin_hash and not cfg.security.pin_hash: + log.warning( + "DEPRECATED: [system] arm_pin_hash is ignored; the arm/disarm " + "PIN lives under [security] pin_hash. Run `vigilar config " + "set-pin` and paste the output into [security]." + ) + + return cfg