from __future__ import annotations import subprocess from pathlib import Path import pytest from rein_aharness import mailscan class FakeCompleted: def __init__(self, returncode=0, stdout="", stderr=""): self.returncode = returncode self.stdout = stdout self.stderr = stderr def _repo_with_reports(tmp_path: Path, names: list[str]) -> Path: repo = tmp_path / "binky-control" (repo / "mailmeta" / "reports").mkdir(parents=True) for name in names: (repo / "mailmeta" / "reports" / name).write_text("header\nrow1\nrow2\n") return repo def test_mail_scan_approle_lane_and_new_report(tmp_path, monkeypatch) -> None: repo = _repo_with_reports(tmp_path, ["old.csv"]) approle = tmp_path / "approle" approle.mkdir() (approle / "role_id").write_text("rid\n") (approle / "secret_id").write_text("sid\n") monkeypatch.setenv("EXECUTOR_APPROLE_DIR", str(approle)) calls: list[list[str]] = [] def fake_run(cmd, **kwargs): calls.append(cmd) if cmd[0] == "bao" and cmd[1] == "write": assert "auth/approle/login" in cmd return FakeCompleted(stdout="tok123\n") if cmd[0] == "bao" and cmd[1] == "kv": assert kwargs["env"]["BAO_TOKEN"] == "tok123" return FakeCompleted(stdout="value\n") if cmd[1] == "-m": # python3 -m email_connect.cli ... env = kwargs["env"] assert env["IMAP_USERNAME"] == "value" assert env["IMAP_PASSWORD"] == "value" (repo / "mailmeta" / "reports" / "new-report.csv").write_text( "header\na\nb\nc\n" ) return FakeCompleted() raise AssertionError(f"unexpected command: {cmd}") monkeypatch.setattr(subprocess, "run", fake_run) events: list[dict] = [] monkeypatch.setattr( mailscan.hub, "post_progress_event", lambda **kw: events.append(kw) or True, ) result = mailscan.run_mail_scan(repo) assert result.ok is True assert result.auth_lane == "approle" assert result.report_path == "new-report.csv" assert result.new_messages == 3 assert events[0]["event_type"] == "binky_mail_intake" # secret values must never appear in the hub event assert "value" not in str(events[0]["detail"]) def test_mail_scan_failure_does_not_emit_intake_event(tmp_path, monkeypatch) -> None: repo = _repo_with_reports(tmp_path, []) monkeypatch.delenv("EXECUTOR_APPROLE_DIR", raising=False) def fake_run(cmd, **kwargs): if cmd[0] == "bao": return FakeCompleted(stdout="value\n") return FakeCompleted(returncode=3, stderr="imap connect refused") monkeypatch.setattr(subprocess, "run", fake_run) events: list[dict] = [] monkeypatch.setattr( mailscan.hub, "post_progress_event", lambda **kw: events.append(kw) or True, ) result = mailscan.run_mail_scan(repo) assert result.ok is False assert result.auth_lane == "ambient" assert "exited 3" in result.reason assert events[0]["event_type"] == "executor_run" def test_mail_scan_reports_failure_when_bao_unavailable(tmp_path, monkeypatch) -> None: repo = _repo_with_reports(tmp_path, []) monkeypatch.delenv("EXECUTOR_APPROLE_DIR", raising=False) def fake_run(cmd, **kwargs): return FakeCompleted(returncode=2, stderr="permission denied") monkeypatch.setattr(subprocess, "run", fake_run) events: list[dict] = [] monkeypatch.setattr( mailscan.hub, "post_progress_event", lambda **kw: events.append(kw) or True, ) result = mailscan.run_mail_scan(repo) assert result.ok is False assert "bao kv failed" in result.reason assert events[0]["event_type"] == "executor_run"