Complete Postbox access transition matrix
This commit is contained in:
@@ -38,6 +38,11 @@ def decide(
|
||||
assignments=(),
|
||||
selected_assignment_id: str | None = None,
|
||||
acting_for_account_id: str | None = None,
|
||||
classification: str = "internal",
|
||||
authorized_classifications: frozenset[str] = frozenset(
|
||||
{"public", "internal"}
|
||||
),
|
||||
binding_status: str | None = None,
|
||||
):
|
||||
return evaluate_postbox_access(
|
||||
postbox_id="postbox-1",
|
||||
@@ -49,12 +54,15 @@ def decide(
|
||||
selected_assignment_id=selected_assignment_id,
|
||||
acting_for_account_id=acting_for_account_id,
|
||||
authorized_actions=authorized_actions, # type: ignore[arg-type]
|
||||
authorized_classifications=authorized_classifications, # type: ignore[arg-type]
|
||||
),
|
||||
organization_unit_id="unit-1" if binding_available else None,
|
||||
function_id="function-1" if binding_available else None,
|
||||
holder_count=len(assignments),
|
||||
binding_available=binding_available,
|
||||
binding_assignments=assignments,
|
||||
binding_status=binding_status, # type: ignore[arg-type]
|
||||
classification=classification,
|
||||
)
|
||||
|
||||
|
||||
@@ -66,6 +74,7 @@ class PostboxAccessDecisionTableTests(unittest.TestCase):
|
||||
"inactive_postbox",
|
||||
"generic_permission",
|
||||
"administrator",
|
||||
"classification_clearance",
|
||||
"active_function_binding",
|
||||
],
|
||||
)
|
||||
@@ -102,6 +111,65 @@ class PostboxAccessDecisionTableTests(unittest.TestCase):
|
||||
self.assertTrue(decision.allowed)
|
||||
self.assertEqual(decision.reason_code, "generic_administrator")
|
||||
|
||||
def test_reply_is_a_distinct_permission_decision(self) -> None:
|
||||
missing = decide(
|
||||
action="reply",
|
||||
authorized_actions=frozenset({"send"}),
|
||||
assignments=(assignment(),),
|
||||
)
|
||||
allowed = decide(
|
||||
action="reply",
|
||||
authorized_actions=frozenset({"reply"}),
|
||||
assignments=(assignment(),),
|
||||
)
|
||||
|
||||
self.assertEqual(missing.reason_code, "generic_permission_missing")
|
||||
self.assertTrue(allowed.allowed)
|
||||
|
||||
def test_classification_is_fail_closed_and_explained(self) -> None:
|
||||
missing_clearance = decide(
|
||||
classification="confidential",
|
||||
assignments=(assignment(),),
|
||||
)
|
||||
allowed = decide(
|
||||
classification="confidential",
|
||||
authorized_classifications=frozenset(
|
||||
{"public", "internal", "confidential"}
|
||||
),
|
||||
assignments=(assignment(),),
|
||||
)
|
||||
unsupported = decide(
|
||||
classification="secret",
|
||||
authorized_classifications=frozenset(
|
||||
{"public", "internal", "confidential", "restricted"}
|
||||
),
|
||||
assignments=(assignment(),),
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
missing_clearance.reason_code,
|
||||
"classification_clearance_missing",
|
||||
)
|
||||
self.assertFalse(missing_clearance.classification_allowed)
|
||||
self.assertTrue(allowed.allowed)
|
||||
self.assertEqual(unsupported.reason_code, "classification_unsupported")
|
||||
|
||||
def test_binding_failures_have_stable_transition_reasons(self) -> None:
|
||||
expected = {
|
||||
"unit_inactive": "organization_unit_inactive",
|
||||
"function_inactive": "organization_function_inactive",
|
||||
"function_reassigned": "organization_function_reassigned",
|
||||
"directory_unavailable": "organization_directory_unavailable",
|
||||
}
|
||||
for binding_status, reason_code in expected.items():
|
||||
with self.subTest(binding_status=binding_status):
|
||||
decision = decide(
|
||||
assignments=(assignment(),),
|
||||
binding_status=binding_status,
|
||||
)
|
||||
self.assertFalse(decision.allowed)
|
||||
self.assertEqual(decision.reason_code, reason_code)
|
||||
|
||||
def test_direct_delegated_directory_governance_and_system_sources_are_allowed(self) -> None:
|
||||
for source in (
|
||||
"direct",
|
||||
|
||||
Reference in New Issue
Block a user