fix: preflight member records before rules

This commit is contained in:
Marcel Peterkau
2026-06-21 17:54:09 +02:00
parent 55bc3b666e
commit 7596e47981
10 changed files with 163 additions and 44 deletions
+13
View File
@@ -108,6 +108,19 @@ def test_repository_reports_empty_contributions_file(tmp_path) -> None:
assert any("contributions.json" in error for error in repository.validate())
def test_repository_rejects_structurally_invalid_member_json(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
member = repository.create_member(first_name="Invalid", last_name="Structure")
path = repository.members_root / member.member_id / "member.json"
raw = json.loads(path.read_text(encoding="utf-8"))
raw["person"] = []
path.write_text(json.dumps(raw), encoding="utf-8")
with pytest.raises(RepositoryError, match="person muss ein JSON-Objekt sein"):
repository.preflight_member_record(member.member_id)
def test_member_path_rejects_traversal(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
+56 -2
View File
@@ -122,7 +122,61 @@ def test_broken_contributions_file_creates_task_without_overwriting_file(tmp_pat
findings = Housekeeper(repository).run(today=date(2026, 6, 21))
assert path.read_bytes() == b""
assert [finding.code for finding in findings] == ["invalid_contributions_file"]
assert [finding.code for finding in findings] == ["invalid_member_record"]
state = json.loads((repository.root / "hausmeister.json").read_text(encoding="utf-8"))
task = next(item for item in state["items"] if item["code"] == "invalid_contributions_file")
task = next(item for item in state["items"] if item["code"] == "invalid_member_record")
assert task["status"] == "open"
def test_preflight_skips_all_rules_for_broken_member_file(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
member = repository.create_member(first_name="Broken", last_name="Member")
member_path = repository.members_root / member.member_id / "member.json"
contributions_path = repository.members_root / member.member_id / "contributions.json"
contributions_before = contributions_path.read_bytes()
member_path.write_text("{", encoding="utf-8")
findings = Housekeeper(repository).run(today=date(2026, 6, 21))
state = json.loads((repository.root / "hausmeister.json").read_text(encoding="utf-8"))
assert [finding.code for finding in findings] == ["invalid_member_record"]
assert len(state["items"]) == 1
assert contributions_path.read_bytes() == contributions_before
def test_preflight_blocks_rules_for_broken_event_log(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
member = repository.create_member(first_name="Broken", last_name="Events", birth_date="1990-01-01")
member.status = "active"
member.accepted_at = "2026-01-01"
member.membership_started_at = "2026-01-01"
repository.save_member(member)
events_path = repository.members_root / member.member_id / "events.jsonl"
with events_path.open("a", encoding="utf-8") as handle:
handle.write("not-json\n")
findings = Housekeeper(repository).run(today=date(2026, 6, 21))
assert [finding.code for finding in findings] == ["invalid_member_record"]
assert repository.get_contributions(member.member_id).claims == []
def test_preflight_task_resolves_after_record_is_repaired(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
member = repository.create_member(first_name="Repair", last_name="Record", birth_date="1990-01-01")
contributions_path = repository.members_root / member.member_id / "contributions.json"
original = contributions_path.read_bytes()
contributions_path.write_bytes(b"")
housekeeper = Housekeeper(repository)
housekeeper.run(today=date(2026, 6, 21))
contributions_path.write_bytes(original)
housekeeper.run(today=date(2026, 6, 21))
state = json.loads((repository.root / "hausmeister.json").read_text(encoding="utf-8"))
task = next(item for item in state["items"] if item["code"] == "invalid_member_record")
assert task["status"] == "resolved"
assert task["resolved_run"] == "2026-06-21:000002"