import copy from types import SimpleNamespace import pytest import yaml from secrets_engine.catalog import validate_entry from secrets_engine.config import Config from secrets_engine.errors import DecisionError, PolicyGuardError from secrets_engine.lane_state import ( load_lane_state, require_delivery_state, require_provision_state, save_lane_state, ) from tests.test_catalog import VALID def _cfg(tmp_path): return Config( catalog_dir=tmp_path, policy_dir=tmp_path, evidence_dir=tmp_path / "evidence", hub_url="", bao_addr="http://127.0.0.1:8200", topic_id="test-topic", ) def test_missing_state_is_active(tmp_path): record = load_lane_state(tmp_path / "evidence", "test-lane") assert record.state == "active" assert record.last_operation == "" def test_compromise_blocks_delivery_and_provision(tmp_path): evidence = tmp_path / "evidence" save_lane_state(evidence, "test-lane", "compromised", operation="compromise") with pytest.raises(DecisionError, match="compromised"): require_delivery_state(evidence, "test-lane", "exec") with pytest.raises(DecisionError, match="rotate"): require_provision_state(evidence, "test-lane") path = evidence / "lane-state" / "test-lane.yaml" dumped = path.read_text(encoding="utf-8") assert yaml.safe_load(dumped)["state"] == "compromised" assert "npm_" not in dumped def test_reason_rejects_secret_like_material(tmp_path): with pytest.raises(PolicyGuardError, match="secret-like"): save_lane_state( tmp_path / "evidence", "test-lane", "compromised", operation="compromise", reason="npm_abcdefghijklmnop", ) def test_exec_refuses_compromised_lane(tmp_path, monkeypatch): from secrets_engine import cli entry = validate_entry(copy.deepcopy(VALID)) save_lane_state(tmp_path / "evidence", entry.id, "compromised", operation="compromise") monkeypatch.setattr(cli, "get_entry", lambda *_args: entry) monkeypatch.setattr(cli, "_require_lane_approval", lambda *_args, **_kwargs: None) monkeypatch.setattr( cli.OpenBaoClient, "resolve", lambda *_args, **_kwargs: pytest.fail("backend must not be reached"), ) args = SimpleNamespace( catalog=entry.id, field="api_token", mode="exec-env", command=["true"], bootstrap_token_file=None, auth="auto", ) with pytest.raises(DecisionError, match="compromised"): cli.cmd_exec(_cfg(tmp_path), args) def test_state_show_defaults_active(tmp_path, monkeypatch): from secrets_engine import cli entry = validate_entry(copy.deepcopy(VALID)) monkeypatch.setattr(cli, "get_entry", lambda *_args: entry) args = SimpleNamespace(catalog_id=entry.id, json=True) rc = cli.cmd_state_show(_cfg(tmp_path), args) assert rc == 0