from __future__ import annotations import unittest from govoplan_core.core.access import PrincipalRef from govoplan_core.core.policy import FunctionAssignmentGovernanceRequest from govoplan_policy.backend.function_assignment_governance import ( FunctionAssignmentGovernancePolicyProvider, ) class FunctionAssignmentGovernancePolicyTests(unittest.TestCase): def setUp(self) -> None: self.provider = FunctionAssignmentGovernancePolicyProvider() self.actor = PrincipalRef( account_id="account-1", membership_id="membership-1", tenant_id="tenant-1", identity_id="identity-1", ) def resolve(self, **overrides): values = { "tenant_id": "tenant-1", "kind": "request", "action": "submit", "function_id": "function-1", "actor": self.actor, "candidate_identity_id": "identity-1", "function_settings": { "assignment_governance": { "request_profile": "holder_with_authority_clearance", "grant_profile": "holder_with_authority_clearance", "authority_function_id": "authority-1", }, }, "context": { "candidate_is_actor": True, "actor_is_holder": False, "actor_is_authority": False, "has_evidence": True, }, } values.update(overrides) return self.provider.resolve_function_assignment_action( request=FunctionAssignmentGovernanceRequest(**values) ) def test_self_request_resolves_holder_and_authority_steps(self) -> None: decision = self.resolve() self.assertTrue(decision.allowed) self.assertEqual(("holder", "authority"), decision.required_steps) self.assertEqual("authority-1", decision.authority_function_id) def test_grant_profiles_recheck_holder_and_authority(self) -> None: holder_grant = self.resolve( kind="grant", context={"actor_is_holder": True, "has_evidence": True}, ) unauthorized = self.resolve( kind="grant", context={"actor_is_holder": False, "has_evidence": True}, ) authority_approval = self.resolve( kind="grant", action="approve_authority", context={"actor_is_authority": True, "has_evidence": True}, ) self.assertTrue(holder_grant.allowed) self.assertIn("recipient", holder_grant.required_steps) self.assertFalse(unauthorized.allowed) self.assertTrue(authority_approval.allowed) def test_missing_authority_and_evidence_fail_closed(self) -> None: decision = self.resolve( function_settings={ "assignment_governance": { "request_profile": "holder_with_authority_clearance", "evidence_required": True, }, }, context={"candidate_is_actor": True, "has_evidence": False}, ) self.assertFalse(decision.allowed) self.assertEqual( ("authority_function", "evidence"), decision.requirements, ) def test_rejection_is_limited_to_the_current_reviewer(self) -> None: holder_reject = self.resolve( action="reject", current_state="awaiting_holder", context={"actor_is_holder": True}, ) authority_cannot_reject_holder_step = self.resolve( action="reject", current_state="awaiting_holder", context={"actor_is_authority": True}, ) recipient_reject = self.resolve( action="reject", current_state="awaiting_recipient", context={"candidate_is_actor": True}, ) self.assertTrue(holder_reject.allowed) self.assertFalse(authority_cannot_reject_holder_step.allowed) self.assertTrue(recipient_reject.allowed) def test_change_request_and_response_follow_current_participants(self) -> None: reviewer = self.resolve( action="request_changes", current_state="awaiting_holder", context={"actor_is_holder": True}, ) responder = self.resolve( action="respond", current_state="changes_requested", context={"actor_is_initiator": True}, ) unrelated = self.resolve( action="respond", current_state="changes_requested", context={}, ) self.assertTrue(reviewer.allowed) self.assertTrue(responder.allowed) self.assertFalse(unrelated.allowed) if __name__ == "__main__": unittest.main()