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:
+37
-1
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user