tests/test_audit.py
2.0 KB · 67 lines · python Raw
1 """Tests for GovernanceAuditLog."""
2
3 from __future__ import annotations
4
5 from pqc_ai_governance import (
6 ConsensusResult,
7 GovernanceAuditLog,
8 GovernanceProposal,
9 ProposalKind,
10 )
11
12
13 def test_log_proposal_created_appends() -> None:
14 log = GovernanceAuditLog()
15 prop = GovernanceProposal.create(
16 kind=ProposalKind.AUTHORIZE_MODEL,
17 subject_id="did:pqaid:model-x",
18 title="x",
19 proposer_did="did:pqaid:alice",
20 )
21 log.log_proposal_created(prop)
22 assert len(log) == 1
23 entries = log.entries()
24 assert entries[0].operation == "proposal_created"
25 assert entries[0].proposal_id == prop.proposal_id
26 assert entries[0].kind == "authorize-model"
27
28
29 def test_log_consensus_reached_captures_decision_and_weights() -> None:
30 log = GovernanceAuditLog()
31 result = ConsensusResult(
32 proposal_id="p1",
33 proposal_hash="h",
34 decision="passed",
35 reason="quorum met",
36 approve_weight=4,
37 reject_weight=1,
38 abstain_weight=0,
39 total_weight=5,
40 included_vote_ids=["v1", "v2", "v3", "v4", "v5"],
41 signer_did="did:pqaid:alice",
42 )
43 log.log_consensus_reached(result)
44 entry = log.entries()[0]
45 assert entry.operation == "consensus_reached"
46 assert entry.decision == "passed"
47 assert entry.details["approve_weight"] == 4
48 assert entry.details["reject_weight"] == 1
49 assert entry.details["vote_count"] == 5
50
51
52 def test_filter_by_operation() -> None:
53 log = GovernanceAuditLog()
54 prop = GovernanceProposal.create(
55 kind=ProposalKind.AUTHORIZE_MODEL,
56 subject_id="x",
57 title="x",
58 proposer_did="did:pqaid:alice",
59 )
60 log.log_proposal_created(prop)
61 log.log_node_added(did="did:pqaid:bob", name="bob", weight=1)
62 log.log_node_added(did="did:pqaid:carol", name="carol", weight=1)
63 assert len(log) == 3
64 adds = log.entries(operation="node_added")
65 assert len(adds) == 2
66 assert all(e.operation == "node_added" for e in adds)
67