fix(session): require config-backed mutation authority and workspace-bound targets (#714)

Close the #714 remediation gap left at 943d402 where env-only mutation
profiles, REMOTES Timesheet defaults treated as explicit caller input, and
machine-dependent Git remotes produced false greens.

- Fail closed when mutations lack a config-backed profile with non-empty
  allowed_repositories; env ops cannot invent mutation authority.
- Preserve omitted-vs-explicit org/repo provenance through the mutation
  gate; omitted targets bind to the verified workspace repository.
- Prefer workspace-aligned Git remotes over historical Timesheet defaults
  in MCP _resolve and CLI resolve_remote.
- Centralize deterministic config-backed mutation fixtures; migrate
  mutation tests off env-only authority without weakening security
  assertions.

Full suite: 2744 passed, 6 skipped.
This commit is contained in:
2026-07-15 21:13:21 -04:00
parent 943d40270e
commit dc899d23c8
36 changed files with 1343 additions and 227 deletions
+24 -5
View File
@@ -1,3 +1,7 @@
import sys as _sys
from pathlib import Path as _Path
_sys.path.insert(0, str(_Path(__file__).resolve().parent))
from mutation_profile_fixture import shared_mutation_env # noqa: E402
"""Tests for early duplicate-work detection (#400)."""
import os
import sys
@@ -144,10 +148,12 @@ class TestInjectableDuplicateFetcher(unittest.TestCase):
},
):
with tempfile.TemporaryDirectory() as lock_dir:
with patch.dict(os.environ, {
"GITEA_ALLOWED_OPERATIONS": "gitea.issue.comment",
"GITEA_ISSUE_LOCK_DIR": lock_dir,
}, clear=True):
env = shared_mutation_env(
"test-author-prgs",
include_example_repo=True,
GITEA_ISSUE_LOCK_DIR=lock_dir,
)
with patch.dict(os.environ, env, clear=True):
mcp_server.gitea_lock_issue(
issue_number=400,
branch_name="feat/issue-400-duplicate-work-preflight",
@@ -161,7 +167,11 @@ class TestMcpDuplicateRecheck(unittest.TestCase):
self._dir = tempfile.TemporaryDirectory()
self._env_patch = patch.dict(
os.environ,
{"GITEA_ISSUE_LOCK_DIR": self._dir.name},
shared_mutation_env(
"test-author-prgs",
include_example_repo=True,
GITEA_ISSUE_LOCK_DIR=self._dir.name,
),
clear=False,
)
self._env_patch.start()
@@ -171,6 +181,11 @@ class TestMcpDuplicateRecheck(unittest.TestCase):
})
self._remotes.start()
mcp_server._IDENTITY_CACHE.clear()
try:
import session_context_binding as _sc
_sc._reset_session_context_for_testing()
except Exception:
pass
def tearDown(self):
patch.stopall()
@@ -205,6 +220,8 @@ class TestMcpDuplicateRecheck(unittest.TestCase):
"allowed_operations": ["gitea.read", "gitea.repo.commit"],
"forbidden_operations": [],
"audit_label": "test-author",
"allowed_repositories": ["Example-Org/Example-Repo"],
"base_url": "https://gitea.example.com",
})
@patch("mcp_server.get_auth_header", return_value="token x")
def test_commit_files_blocked_on_recheck(self, _auth, _profile, mock_gate):
@@ -239,6 +256,8 @@ class TestMcpDuplicateRecheck(unittest.TestCase):
"allowed_operations": ["gitea.read", "gitea.pr.create"],
"forbidden_operations": [],
"audit_label": "test-author",
"allowed_repositories": ["Example-Org/Example-Repo"],
"base_url": "https://gitea.example.com",
})
@patch("mcp_server.get_auth_header", return_value="token x")
def test_create_pr_returns_handoff_on_duplicate(self, _auth, _profile, mock_gate):