examples/model_authorization.py
4.3 KB · 113 lines · python Raw
1 """End-to-end example: five governance nodes vote to authorize a medical AI model.
2
3 Alice proposes `AUTHORIZE_MODEL` for `did:pqaid:medical-ai-v2`. Alice, Bob,
4 Carol and Dave approve. Eve abstains. The round finalises, the ML-DSA
5 signature on the result verifies, and an ``AuthorizationChain`` is populated
6 with the passed grant.
7 """
8
9 from __future__ import annotations
10
11 from quantumshield.identity.agent import AgentIdentity
12
13 from pqc_ai_governance import (
14 AuthorizationChain,
15 AuthorizationGrant,
16 ConsensusRound,
17 GovernanceAuditLog,
18 GovernanceNode,
19 GovernanceProposal,
20 NodeRegistry,
21 ProposalKind,
22 QuorumPolicy,
23 VoteDecision,
24 )
25
26
27 def main() -> None:
28 print("== PQC AI Governance: Model Authorization ==\n")
29
30 # 1. Five governance nodes with varied weights.
31 alice = GovernanceNode(identity=AgentIdentity.create("alice"), name="alice", weight=1)
32 bob = GovernanceNode(identity=AgentIdentity.create("bob"), name="bob", weight=1)
33 carol = GovernanceNode(identity=AgentIdentity.create("carol"), name="carol", weight=1)
34 dave = GovernanceNode(identity=AgentIdentity.create("dave"), name="dave", weight=2)
35 eve = GovernanceNode(identity=AgentIdentity.create("eve"), name="eve", weight=1)
36
37 registry = NodeRegistry()
38 for node in (alice, bob, carol, dave, eve):
39 registry.register(node)
40 print(f"Registered {len(registry)} nodes, total voting weight = {registry.total_weight()}")
41
42 audit = GovernanceAuditLog()
43
44 # 2. Alice proposes authorizing the medical AI model.
45 proposal = GovernanceProposal.create(
46 kind=ProposalKind.AUTHORIZE_MODEL,
47 subject_id="did:pqaid:medical-ai-v2",
48 title="Authorize medical-ai-v2 for production",
49 description="Radiology triage model; HIPAA envelope in place.",
50 proposer_did=alice.did,
51 parameters={"environment": "prod", "max_rate_qps": 50, "region": "us-east-1"},
52 )
53 alice.sign_proposal(proposal)
54 audit.log_proposal_created(proposal)
55 assert GovernanceNode.verify_proposal(proposal), "proposer signature invalid"
56 print(f"\nProposal {proposal.proposal_id}")
57 print(f" kind : {proposal.kind.value}")
58 print(f" subject: {proposal.subject_id}")
59 print(f" hash : {proposal.proposal_hash()[:16]}...")
60
61 # 3. Cast votes: 4 approve, 1 abstain.
62 rnd = ConsensusRound(proposal=proposal, registry=registry, policy=QuorumPolicy())
63 votes = [
64 (alice, VoteDecision.APPROVE, "clinical team approved"),
65 (bob, VoteDecision.APPROVE, "security review clean"),
66 (carol, VoteDecision.APPROVE, "compliance signed off"),
67 (dave, VoteDecision.APPROVE, "infra capacity available"),
68 (eve, VoteDecision.ABSTAIN, "not in my domain"),
69 ]
70 for voter, decision, rationale in votes:
71 signed = voter.cast_vote(proposal, decision, rationale=rationale)
72 rnd.cast(signed)
73 audit.log_vote_cast(signed)
74 print(f" {voter.name:5s} -> {decision.value:<8s} ({rationale})")
75
76 # 4. Finalize and sign the consensus result.
77 result = rnd.finalize(coordinator=alice)
78 audit.log_consensus_reached(result)
79 print("\nConsensus:")
80 print(f" decision : {result.decision}")
81 print(f" reason : {result.reason}")
82 print(f" approve : {result.approve_weight}/{result.total_weight}")
83 print(f" reject : {result.reject_weight}")
84 print(f" abstain : {result.abstain_weight}")
85 print(f" signed by: {result.signer_did[:22]}... ({result.algorithm})")
86
87 # 5. Verify the signed result, then bind it into an authorization chain.
88 assert ConsensusRound.verify_result(result), "result signature failed to verify"
89 print(" signature: OK (ML-DSA verified)")
90
91 chain = AuthorizationChain(subject_id=proposal.subject_id)
92 chain.add(
93 AuthorizationGrant(
94 subject_id=proposal.subject_id,
95 kind=proposal.kind,
96 result=result,
97 scope=dict(proposal.parameters),
98 )
99 )
100 audit.log_authorization_granted(
101 subject_id=proposal.subject_id,
102 kind=proposal.kind,
103 proposal_id=proposal.proposal_id,
104 )
105
106 authorized = chain.is_authorized(ProposalKind.AUTHORIZE_MODEL)
107 print(f"\nAuthorizationChain: is_authorized(AUTHORIZE_MODEL) = {authorized}")
108 print(f"Audit entries: {len(audit)}")
109
110
111 if __name__ == "__main__":
112 main()
113