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
+9 -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
"""Regression coverage for the remote/repo mismatch guard (#530).
Bare ``remote=prgs`` historically resolved to ``Scaled-Tech-Consulting/Timesheet``
@@ -162,12 +166,12 @@ class TestResolveServerWiring(unittest.TestCase):
self.addCleanup(self.server.REMOTES.__setitem__, "prgs", original)
self.server.REMOTES["prgs"] = {**original, "repo": repo}
def test_resolve_blocks_on_default_repo_mismatch(self):
def test_resolve_prefers_workspace_over_timesheet_default(self):
"""#714: bare remote=prgs must use workspace Gitea-Tools, not REMOTES Timesheet."""
self._set_prgs_default_repo("Timesheet")
with self.assertRaises(RuntimeError) as ctx:
self.server._resolve("prgs", None, None, None)
self.assertIn("Timesheet", str(ctx.exception))
self.assertIn("Gitea-Tools", str(ctx.exception))
host, org, repo = self.server._resolve("prgs", None, None, None)
self.assertEqual(org, "Scaled-Tech-Consulting")
self.assertEqual(repo, "Gitea-Tools")
def test_resolve_allows_explicit_org_and_repo(self):
self._set_prgs_default_repo("Timesheet")