fix(mcp): seed cross-repo session identity from configured canonical root (#706 F1)

Addresses REQUEST_CHANGES review 457 on PR #736.

Root cause: _trusted_session_repository derived the session org/repository
solely from _workspace_repository_slug -> _local_git_remote_url, which runs
`git remote get-url` in PROJECT_ROOT (the Gitea-Tools install checkout). A
cross-repository namespace with a configured canonical_repository_root then
pinned the Gitea-Tools identity while #274 filesystem membership bound the
external target, so _enforce_canonical_repository_root failed closed on a
self-inflicted identity mismatch and the mcp-control-plane / eagenda
namespaces stayed blocked end-to-end.

Fix: when a canonical_repository_root is configured (env over profile) and
passes existence / git-toplevel / resolvable-remote-identity validation, the
session repository slug is derived from repository_identity_slug(configured
root) instead of the install remote. The derived identity is still authorized
by the profile allowed_repositories allowlist (never self-authorizing); the
canonical filesystem root and org/repo identity remain immutable for the
session; invalid / non-git / unresolvable / unallowlisted / forged / drift
cases fail closed; unconfigured single-repo Gitea-Tools namespaces keep the
install-derived slug unchanged.

Tests: new tests/test_issue_706_f1_seed_identity_integration.py drives the
real _seed_session_context -> _enforce_canonical_repository_root path with two
real temporary git repositories (install=Gitea-Tools, configured target=
mcp-control-plane): env + profile config, reviewer + merger role kinds, and
fail-closed cases (nonexistent / non-git / unallowlisted / forged identity
drift). Reproduces the F1 block before the fix; green after.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
2026-07-18 01:27:26 -04:00
co-authored by Claude Opus 4.8
parent 6a0d7bbef4
commit 61c0d73cd1
2 changed files with 258 additions and 1 deletions
+37 -1
View File
@@ -1675,7 +1675,43 @@ def _trusted_session_repository(
"repository": None,
"reasons": [str(exc)],
}
slug = _workspace_repository_slug(remote)
# #706 F1: when a cross-repository canonical root is configured, the session
# repository identity must be derived from that validated *target* repository,
# not from the install-checkout git remote. ``_workspace_repository_slug``
# reads ``_local_git_remote_url`` in ``PROJECT_ROOT`` (always Gitea-Tools), so
# without this a cross-repo namespace pinned Gitea-Tools while #274 filesystem
# membership bound the external root, and ``_enforce_canonical_repository_root``
# then failed closed on a self-inflicted identity mismatch. The derived
# identity is still authorized by the profile allowlist below (never
# self-authorizing). Env-over-profile precedence and fail-closed validation
# (existence, git toplevel, resolvable remote identity) are handled by
# ``crr``; unconfigured single-repo namespaces keep the install-derived slug.
configured_value, configured_source = crr.configured_canonical_root(
profile, os.environ
)
if configured_value:
assessment = crr.assess_canonical_repository_root(
configured_value=configured_value,
source=configured_source,
expected_slug=None,
process_project_root=PROJECT_ROOT,
remote=remote,
require_binding=True,
)
slug = assessment.get("resolved_slug")
if assessment.get("block") or not slug:
return {
"org": None,
"repository": None,
"reasons": assessment.get("reasons")
or [
"configured canonical repository root has no resolvable "
"repository identity; session repository cannot be "
"authorized (fail closed)"
],
}
else:
slug = _workspace_repository_slug(remote)
scope = session_ctx.assess_repository_scope(
workspace_slug=slug,
allowed=allowed,