fix(mcp): enforce role capability invariants (Closes #723)
This commit is contained in:
@@ -19,7 +19,12 @@ import unittest
|
||||
|
||||
import gitea_config
|
||||
from role_session_router import MERGER_TASKS, REVIEWER_TASKS
|
||||
from task_capability_map import required_permission, required_role
|
||||
from task_capability_map import (
|
||||
ROLE_EXCLUSIVE_TASKS,
|
||||
TASK_CAPABILITY_MAP,
|
||||
required_permission,
|
||||
required_role,
|
||||
)
|
||||
|
||||
# Canonical role-profile permission shape. Mirrors the configured
|
||||
# author/reviewer/merger/reconciler profiles (profiles.json v2 role split):
|
||||
@@ -112,6 +117,42 @@ FORMAL_REVIEW_TASKS = (
|
||||
"pr-queue-cleanup",
|
||||
)
|
||||
|
||||
# Complete resolver role-exclusive set on master when #723 was reconstructed.
|
||||
# The shared constant must replace this exact inline authority without dropping
|
||||
# later lease and PR-sync aliases added after the preserved source commits.
|
||||
EXPECTED_ROLE_EXCLUSIVE_TASKS = frozenset(
|
||||
{
|
||||
"acquire_reviewer_pr_lease",
|
||||
"gitea_acquire_reviewer_pr_lease",
|
||||
"review_pr",
|
||||
"approve_pr",
|
||||
"request_changes_pr",
|
||||
"blind_pr_queue_review",
|
||||
"pr_queue_cleanup",
|
||||
"pr-queue-cleanup",
|
||||
"merge_pr",
|
||||
"acquire_merger_pr_lease",
|
||||
"gitea_acquire_merger_pr_lease",
|
||||
"adopt_merger_pr_lease",
|
||||
"gitea_adopt_merger_pr_lease",
|
||||
"release_merger_pr_lease",
|
||||
"gitea_release_merger_pr_lease",
|
||||
"create_branch",
|
||||
"push_branch",
|
||||
"create_pr",
|
||||
"commit_files",
|
||||
"gitea_commit_files",
|
||||
"address_pr_change_requests",
|
||||
"update_pr_branch_by_merge",
|
||||
"gitea_update_pr_branch_by_merge",
|
||||
"delete_branch",
|
||||
"cleanup_merged_pr_branch",
|
||||
"reconciliation_cleanup",
|
||||
"work_issue",
|
||||
"work-issue",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def _profile_satisfies(role_name, task):
|
||||
"""True when the canonical *role_name* profile can perform *task*."""
|
||||
@@ -201,5 +242,30 @@ class TestMergerBoundary(unittest.TestCase):
|
||||
)
|
||||
|
||||
|
||||
class TestRoleExclusiveSetIntegrity(unittest.TestCase):
|
||||
"""#723: the shared set is complete, mapped, and role-satisfiable."""
|
||||
|
||||
def test_complete_current_role_exclusive_set(self):
|
||||
self.assertEqual(ROLE_EXCLUSIVE_TASKS, EXPECTED_ROLE_EXCLUSIVE_TASKS)
|
||||
|
||||
def test_every_role_exclusive_task_exists_in_capability_map(self):
|
||||
for task in sorted(ROLE_EXCLUSIVE_TASKS):
|
||||
with self.subTest(task=task):
|
||||
self.assertIn(task, TASK_CAPABILITY_MAP)
|
||||
|
||||
def test_formal_review_tasks_are_role_exclusive(self):
|
||||
self.assertTrue(set(FORMAL_REVIEW_TASKS) <= ROLE_EXCLUSIVE_TASKS)
|
||||
|
||||
def test_every_role_exclusive_task_has_a_satisfying_profile(self):
|
||||
for task in sorted(ROLE_EXCLUSIVE_TASKS):
|
||||
with self.subTest(task=task):
|
||||
role = required_role(task)
|
||||
self.assertIn(role, CANONICAL_ROLE_PROFILES)
|
||||
self.assertTrue(
|
||||
_profile_satisfies(role, task),
|
||||
f"canonical {role!r} profile cannot satisfy {task!r}",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user