Eliminate remaining PROJECT_ROOT coupling in cross-repository MCP operations #741

Open
opened 2026-07-18 02:50:03 -05:00 by jcwalker3 · 0 comments
Owner

Context

PR #740 (issue #739) fixes three canonical-root consumption defects:

  • first-call effective-remote binding in gitea_get_runtime_context;
  • reconciler delete-branch repository identity;
  • separate, labelled target-repository parity evidence.

During that work, additional repository-sensitive paths were found still passing or deriving state from the Gitea-Tools installation PROJECT_ROOT (gitea_mcp_server.py:158, os.path.dirname(os.path.abspath(__file__))). The common root is _local_git_remote_url (gitea_mcp_server.py:8484-8498), which runs git remote get-url with cwd=PROJECT_ROOT and therefore always reports the Gitea-Tools checkout, plus roughly twenty git-operation call sites that pass PROJECT_ROOT directly as their working repository.

Cross-repository namespaces cannot be commissioned for unattended operation until every mutation-critical consumer either uses the immutable session canonical_repository_root or is proven intentionally installation-scoped.

This issue is deliberately scoped to the paths #740 did not touch. #740 covers only the three defects above and explicitly lists these as out of scope.

Required investigation

Inventory every production use of PROJECT_ROOT, _workspace_repository_slug, _local_git_remote_url, and equivalent installation-root helpers.

Classify every call site as exactly one of:

  1. MCP server implementation / install scope — must remain anchored to Gitea-Tools;
  2. Canonical target-repository scope — must use the immutable session canonical_repository_root;
  3. Ambiguous — must fail closed until explicitly classified.

At minimum, investigate:

  • _resolve paths (gitea_mcp_server.py:2366-2407) — explicit org/repo currently win over workspace inference and are validated only against the install checkout's remote;
  • _enforce_remote_repo_guard (#530) — compares against _local_git_remote_url, and is bypassed under pytest unless GITEA_FORCE_REMOTE_REPO_CHECK is set;
  • anti-stomp org/repo filling (gitea_mcp_server.py:906-960, 1008-1018) — workspace-filled sides are marked explicit, which relaxes the #530 check for those sides;
  • branch creation and pushing;
  • repository commit operations;
  • PR creation;
  • reviewer lease and review operations;
  • merger lease, merge preflight, and merge operations;
  • reconciler closure and cleanup;
  • branch cleanup/deletion beyond the binding guard fixed in #740;
  • any git subprocess or remote-URL lookup used by a mutation guard.

Record the classification for every site, including the ones that stay installation-scoped, so the audit is complete rather than partial.

Acceptance criteria

  1. Every mutation-critical local repository operation derives target identity from the immutable session canonical_repository_root.
  2. Gitea-Tools server implementation/version checks remain anchored to the installation checkout and are clearly labelled as such.
  3. Explicit org/repo coordinates may confirm an already-correct canonical binding but can never override or authorize an incorrect binding.
  4. A namespace rooted at mcp-control-plane can perform its role's sanctioned operations against only Scaled-Tech-Consulting/mcp-control-plane.
  5. The same namespace fails closed against Gitea-Tools or any other repository.
  6. A Gitea-Tools-rooted namespace remains unable to mutate mcp-control-plane.
  7. Author, reviewer, merger, and reconciler workflows each have cross-repository integration coverage.
  8. Merge and cleanup paths are explicitly tested; configuration installation must remain blocked until these paths pass.
  9. Repository identity must not depend on request ordering or a preliminary whoami call.
  10. No request-supplied workspace, remote, owner, repository, or worktree can replace the immutable canonical root.
  11. Existing same-repository Gitea-Tools behaviour remains unchanged.
  12. Tests cover positive, negative, mismatch, missing-root, stale-target, and explicit-coordinate cases.
  13. Any v1 or v2-environments configuration path that accepts canonical_repository_root validates it equivalently to the v2-contexts loader, or rejects unsupported usage explicitly. (Today _validate_canonical_repository_root is called only from _load_v2_contexts at gitea_config.py:604; the v1 path and the v2-environments path read the field via gitea_auth.py:808 without validating it.)
  14. Documentation describes the difference between the server installation root and the canonical target repository root.

Commissioning dependency

The four mcp-control-plane namespace profiles and their client launcher entries must not be installed for mutation work until all of the following hold:

  • PR #740 is independently reviewed and merged;
  • this issue's critical mutation paths are fixed and merged;
  • the Gitea-Tools MCP daemons are restarted on the resulting master (the running processes execute their startup commit, so merged fixes are not live until restart);
  • repository-correct commissioning passes for author, reviewer, merger, and reconciler.

Reference

## Context PR #740 (issue #739) fixes three canonical-root consumption defects: * first-call effective-remote binding in `gitea_get_runtime_context`; * reconciler delete-branch repository identity; * separate, labelled target-repository parity evidence. During that work, additional repository-sensitive paths were found still passing or deriving state from the Gitea-Tools installation `PROJECT_ROOT` (`gitea_mcp_server.py:158`, `os.path.dirname(os.path.abspath(__file__))`). The common root is `_local_git_remote_url` (`gitea_mcp_server.py:8484-8498`), which runs `git remote get-url` with `cwd=PROJECT_ROOT` and therefore always reports the Gitea-Tools checkout, plus roughly twenty git-operation call sites that pass `PROJECT_ROOT` directly as their working repository. Cross-repository namespaces cannot be commissioned for unattended operation until every mutation-critical consumer either uses the immutable session `canonical_repository_root` or is proven intentionally installation-scoped. This issue is deliberately scoped to the paths #740 did not touch. #740 covers only the three defects above and explicitly lists these as out of scope. ## Required investigation Inventory every production use of `PROJECT_ROOT`, `_workspace_repository_slug`, `_local_git_remote_url`, and equivalent installation-root helpers. Classify every call site as exactly one of: 1. **MCP server implementation / install scope** — must remain anchored to Gitea-Tools; 2. **Canonical target-repository scope** — must use the immutable session `canonical_repository_root`; 3. **Ambiguous** — must fail closed until explicitly classified. At minimum, investigate: * `_resolve` paths (`gitea_mcp_server.py:2366-2407`) — explicit `org`/`repo` currently win over workspace inference and are validated only against the install checkout's remote; * `_enforce_remote_repo_guard` (#530) — compares against `_local_git_remote_url`, and is bypassed under pytest unless `GITEA_FORCE_REMOTE_REPO_CHECK` is set; * anti-stomp org/repo filling (`gitea_mcp_server.py:906-960`, `1008-1018`) — workspace-filled sides are marked explicit, which relaxes the #530 check for those sides; * branch creation and pushing; * repository commit operations; * PR creation; * reviewer lease and review operations; * merger lease, merge preflight, and merge operations; * reconciler closure and cleanup; * branch cleanup/deletion beyond the binding guard fixed in #740; * any git subprocess or remote-URL lookup used by a mutation guard. Record the classification for every site, including the ones that stay installation-scoped, so the audit is complete rather than partial. ## Acceptance criteria 1. Every mutation-critical local repository operation derives target identity from the immutable session `canonical_repository_root`. 2. Gitea-Tools server implementation/version checks remain anchored to the installation checkout and are clearly labelled as such. 3. Explicit `org`/`repo` coordinates may confirm an already-correct canonical binding but can never override or authorize an incorrect binding. 4. A namespace rooted at `mcp-control-plane` can perform its role's sanctioned operations against only `Scaled-Tech-Consulting/mcp-control-plane`. 5. The same namespace fails closed against Gitea-Tools or any other repository. 6. A Gitea-Tools-rooted namespace remains unable to mutate `mcp-control-plane`. 7. Author, reviewer, merger, and reconciler workflows each have cross-repository integration coverage. 8. Merge and cleanup paths are explicitly tested; configuration installation must remain blocked until these paths pass. 9. Repository identity must not depend on request ordering or a preliminary `whoami` call. 10. No request-supplied workspace, remote, owner, repository, or worktree can replace the immutable canonical root. 11. Existing same-repository Gitea-Tools behaviour remains unchanged. 12. Tests cover positive, negative, mismatch, missing-root, stale-target, and explicit-coordinate cases. 13. Any v1 or v2-environments configuration path that accepts `canonical_repository_root` validates it equivalently to the v2-contexts loader, or rejects unsupported usage explicitly. (Today `_validate_canonical_repository_root` is called only from `_load_v2_contexts` at `gitea_config.py:604`; the v1 path and the v2-`environments` path read the field via `gitea_auth.py:808` without validating it.) 14. Documentation describes the difference between the server installation root and the canonical target repository root. ## Commissioning dependency The four `mcp-control-plane` namespace profiles and their client launcher entries must not be installed for mutation work until all of the following hold: * PR #740 is independently reviewed and merged; * this issue's critical mutation paths are fixed and merged; * the Gitea-Tools MCP daemons are restarted on the resulting master (the running processes execute their startup commit, so merged fixes are not live until restart); * repository-correct commissioning passes for author, reviewer, merger, and reconciler. ## Reference * Issue #739 * PR #740 * PR #736 / issue #706
jcwalker3 added the status:readytype:bug labels 2026-07-18 02:50:03 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#741