import pytest from types import SimpleNamespace from secrets_engine.catalog import validate_entry from secrets_engine.cli import _require_lane_approval from secrets_engine.decisions import Decision, require_approved, resolve_decision from secrets_engine.errors import DecisionError from tests.test_catalog import VALID def _approved(model="decision"): d = dict(VALID, approval={"model": model, "decision_ref": "x"}) return validate_entry(d) def test_bootstrap_only_needs_no_decision(): e = validate_entry(dict(VALID, approval={"model": "bootstrap-only"})) require_approved(e, None) # must not raise def test_unapproved_decision_refused(): e = _approved() d = Decision(id="d", title="t", status="pending", superseded_by=None, source="hub") with pytest.raises(DecisionError): require_approved(e, d) def test_superseded_decision_refused(): e = _approved() d = Decision(id="d", title="t", status="resolved", superseded_by="d2", source="hub") with pytest.raises(DecisionError): require_approved(e, d) def test_approved_decision_passes(): e = _approved() d = Decision(id="d", title="t", status="resolved", superseded_by=None, source="hub") require_approved(e, d) # must not raise def test_local_fixture_resolves(tmp_path): (tmp_path / ".decisions").mkdir() (tmp_path / ".decisions" / "myref.yaml").write_text( "id: myref\ntitle: t\nstatus: resolved\nsuperseded_by: null\n" ) d = resolve_decision(hub_url="http://127.0.0.1:1", repo_root=tmp_path, decision_ref="myref") assert d.source == "local-fixture" assert d.is_approved() def test_missing_decision_raises(tmp_path): with pytest.raises(DecisionError): resolve_decision(hub_url="http://127.0.0.1:1", repo_root=tmp_path, decision_ref="nope") def test_privileged_lane_helper_fails_closed_without_decision(tmp_path, monkeypatch): import secrets_engine.cli as cli monkeypatch.setattr(cli, "repo_root", lambda: tmp_path) with pytest.raises(DecisionError): _require_lane_approval(SimpleNamespace(hub_url=""), _approved()) def test_privileged_lane_helper_accepts_local_approval(tmp_path, monkeypatch): import secrets_engine.cli as cli (tmp_path / ".decisions").mkdir() (tmp_path / ".decisions" / "x.yaml").write_text( "id: x\ntitle: approved\nstatus: resolved\nsuperseded_by: null\n" ) monkeypatch.setattr(cli, "repo_root", lambda: tmp_path) decision = _require_lane_approval(SimpleNamespace(hub_url=""), _approved()) assert decision.id == "x" def test_production_action_fails_closed_before_legacy_decision(monkeypatch): import secrets_engine.cli as cli entry = validate_entry(dict(VALID, stage="prod", approval={"model": "bootstrap-only"})) cfg = SimpleNamespace(hub_url="http://127.0.0.1:8000", bao_addr="http://127.0.0.1:8200") monkeypatch.delenv("SECRETS_ENGINE_UNSAFE_DEMO", raising=False) with pytest.raises(DecisionError, match="production action 'apply'"): _require_lane_approval(cfg, entry, "apply") def test_production_demo_requires_all_three_safety_conditions(tmp_path, monkeypatch): import secrets_engine.cli as cli (tmp_path / ".decisions").mkdir() (tmp_path / ".decisions" / "x.yaml").write_text( "id: x\ntitle: approved\nstatus: resolved\nsuperseded_by: null\n" ) entry = validate_entry( dict(VALID, stage="prod", approval={"model": "decision", "decision_ref": "x"}) ) monkeypatch.setattr(cli, "repo_root", lambda: tmp_path) monkeypatch.setenv("SECRETS_ENGINE_UNSAFE_DEMO", "1") allowed = SimpleNamespace(hub_url="", bao_addr="http://127.0.0.1:8200") assert _require_lane_approval(allowed, entry, "apply").id == "x" for cfg in ( SimpleNamespace(hub_url="http://127.0.0.1:8000", bao_addr="http://127.0.0.1:8200"), SimpleNamespace(hub_url="", bao_addr="https://bao.example.test"), ): with pytest.raises(DecisionError, match="live production remains disabled"): _require_lane_approval(cfg, entry, "apply")