Files
Gitea-Tools/tests/test_cross_project_mutation_boundary.py
T

95 lines
4.1 KiB
Python

import os
import sys
import unittest
from unittest import mock
import remote_repo_guard
import gitea_mcp_server as server
from session_context_binding import _reset_session_context_for_testing, bind_session_context
LOCAL_GITEA_TOOLS_URL = "https://gitea.prgs.cc/Scaled-Tech-Consulting/Gitea-Tools.git"
class TestCrossProjectMutationBoundary(unittest.TestCase):
def setUp(self):
os.environ["PYTEST_CURRENT_TEST"] = "test"
_reset_session_context_for_testing()
def tearDown(self):
_reset_session_context_for_testing()
os.environ.pop("PYTEST_CURRENT_TEST", None)
def test_cross_project_codebase_mutation_blocked(self):
"""Codebase mutations targeting another project must fail closed (#707)."""
assessment = remote_repo_guard.assess_remote_repo_match(
remote="prgs",
resolved_org="Other-Org",
resolved_repo="Other-Repo",
local_remote_url=LOCAL_GITEA_TOOLS_URL,
org_explicit=True,
repo_explicit=True,
for_mutation=True,
)
self.assertTrue(assessment["block"])
self.assertTrue(assessment.get("cross_project_mutation_block"))
self.assertEqual(assessment["primary_org"], "Scaled-Tech-Consulting")
self.assertEqual(assessment["primary_repo"], "Gitea-Tools")
err_msg = remote_repo_guard.format_remote_repo_guard_error(assessment)
self.assertIn("Cross-project mutation guard (#707)", err_msg)
self.assertIn("Attempted codebase mutation targeting 'Other-Org/Other-Repo'", err_msg)
self.assertIn("outside of primary authorized project context 'Scaled-Tech-Consulting/Gitea-Tools'", err_msg)
self.assertIn("create an issue in the target repository ('Other-Org/Other-Repo') instead", err_msg)
def test_same_project_codebase_mutation_allowed(self):
"""Codebase mutations targeting the primary project context are allowed."""
assessment = remote_repo_guard.assess_remote_repo_match(
remote="prgs",
resolved_org="Scaled-Tech-Consulting",
resolved_repo="Gitea-Tools",
local_remote_url=LOCAL_GITEA_TOOLS_URL,
org_explicit=True,
repo_explicit=True,
for_mutation=True,
)
self.assertFalse(assessment["block"])
self.assertFalse(assessment.get("cross_project_mutation_block", False))
def test_cross_project_metadata_operation_allowed(self):
"""Metadata operations (issue creation, comments) across project boundaries are allowed."""
assessment = remote_repo_guard.assess_remote_repo_match(
remote="prgs",
resolved_org="Other-Org",
resolved_repo="Other-Repo",
local_remote_url=LOCAL_GITEA_TOOLS_URL,
org_explicit=True,
repo_explicit=True,
for_mutation=False,
)
self.assertTrue(assessment["proven"])
self.assertFalse(assessment["block"])
@mock.patch.dict(os.environ, {"GITEA_FORCE_REMOTE_REPO_CHECK": "1"})
@mock.patch("gitea_mcp_server._local_git_remote_url", return_value=LOCAL_GITEA_TOOLS_URL)
def test_mcp_server_resolve_cross_project_mutation_fails_closed(self, mock_remote):
"""_resolve with for_mutation=True blocks cross-project targets."""
with self.assertRaises(RuntimeError) as ctx:
server._resolve("prgs", None, "Other-Org", "Other-Repo", for_mutation=True)
err = str(ctx.exception)
self.assertIn("Cross-project mutation guard (#707)", err)
self.assertIn("create an issue in the target repository", err)
@mock.patch.dict(os.environ, {"GITEA_FORCE_REMOTE_REPO_CHECK": "1"})
@mock.patch("gitea_mcp_server._local_git_remote_url", return_value=LOCAL_GITEA_TOOLS_URL)
def test_mcp_server_resolve_cross_project_metadata_succeeds(self, mock_remote):
"""_resolve with for_mutation=False allows explicit cross-project target."""
host, org, repo = server._resolve("prgs", None, "Other-Org", "Other-Repo", for_mutation=False)
self.assertEqual(org, "Other-Org")
self.assertEqual(repo, "Other-Repo")
if __name__ == "__main__":
unittest.main()