"""WP-090 contract and adversarial tests.""" from __future__ import annotations import asyncio import copy import hashlib import json import os import tempfile import unittest from datetime import UTC, datetime from pathlib import Path from unittest.mock import patch from uuid import UUID, uuid4 import httpx from dulwich import porcelain from connectors.gitea import FakeGiteaServer, GiteaConnector from connectors.gitea.changesets import ( DulwichChangesetWorkspace, apply_unified_patch, validate_operations, ) from connectors.gitea.managed_validation import MANAGED_VALIDATION_WORKFLOW from connectors.gitea.server import _managed_validation_profile, _select_validation_workflow from connectors.knowledge import KnowledgeConnector from packages.connector_kit import ( ConnectorContext, GiteaClient, GiteaError, GiteaRepositoryRegistry, GiteaSettings, InMemoryKnowledgeIndex, PageRequest, RegisteredRepository, StaticTokenProvider, ) from packages.hub_core.domain import Connector, Project from services.control_api.gitea.registry import registration_from_project PROJECT_ID = UUID("11111111-1111-1111-1111-111111111111") OTHER_PROJECT_ID = UUID("22222222-2222-2222-2222-222222222222") ROOT = Path(__file__).resolve().parents[1] PROJECTBRAIN_VALIDATION_WORKFLOW = ( ROOT / "tests" / "fixtures" / "projectbrain-managed-validation.yml" ).read_text(encoding="utf-8") def projectbrain_connector( server: FakeGiteaServer | None = None, ) -> tuple[GiteaConnector, FakeGiteaServer]: fixture = server or FakeGiteaServer() fixture._repos["Jens/projectbrain"] = { "owner": {"login": "Jens"}, "name": "projectbrain", "full_name": "Jens/projectbrain", "description": "ProjectBrain", "private": True, "default_branch": "main", } fixture._managed_workflows["Jens/projectbrain"] = PROJECTBRAIN_VALIDATION_WORKFLOW protection = copy.deepcopy(fixture._branch_protections["acme/hub"][0]) protection["status_check_contexts"] = ["Pull request / quality (pull_request)"] protection["required_approvals"] = 2 fixture._branch_protections["Jens/projectbrain"] = [protection] settings = GiteaSettings( base_url="http://gitea.test", token_reference="docker-secret://gitea_mcp_token", # noqa: S106 allow_insecure_http_for_tests=True, ) client = GiteaClient( settings, StaticTokenProvider("fixture-token-must-not-leak"), transport=fixture.transport() ) registry = GiteaRepositoryRegistry( ( RegisteredRepository( repository_ref="projectbrain-repository", project_id=PROJECT_ID, owner="Jens", name="projectbrain", source_uri="itworx-git://projectbrain/projectbrain-repository", private=True, ), ) ) return GiteaConnector(client, registry, write_client=client), fixture def context(project_id: UUID = PROJECT_ID, slug: str = "hub") -> ConnectorContext: return ConnectorContext( workspace_id=uuid4(), project_id=project_id, project_slug=slug, environment="test" ) def connector( server: FakeGiteaServer | None = None, *, project_id: UUID = PROJECT_ID ) -> tuple[GiteaConnector, FakeGiteaServer]: fixture = server or FakeGiteaServer() settings = GiteaSettings( base_url="http://gitea.test", token_reference="docker-secret://gitea_mcp_token", # noqa: S106 allow_insecure_http_for_tests=True, ) client = GiteaClient( settings, StaticTokenProvider("fixture-token-must-not-leak"), transport=fixture.transport() ) registry = GiteaRepositoryRegistry( ( RegisteredRepository( repository_ref="hub-repository", project_id=project_id, owner="acme", name="hub", source_uri="itworx-git://hub/hub-repository", private=True, ), ) ) return GiteaConnector( client, registry, write_client=client, changeset_workspace=FakeChangesetWorkspace() ), fixture class FakeChangesetWorkspace: def apply( self, repository: RegisteredRepository, branch: str, message: str, operations: object, ) -> dict[str, object]: return { "commitSha": "6" * 40, "branch": branch, "operationCount": len(operations), # type: ignore[arg-type] "atomic": True, } class GiteaConnectorTests(unittest.TestCase): def test_registry_resolves_an_exact_qualified_name_within_project_scope(self) -> None: instance, _ = connector() resolved = instance.registry.resolve(PROJECT_ID, "Acme/Hub") self.assertEqual(resolved.repository_ref, "hub-repository") with self.assertRaisesRegex(GiteaError, "repository is not registered"): instance.registry.resolve(OTHER_PROJECT_ID, "acme/hub") with self.assertRaisesRegex(GiteaError, "repository is not registered"): instance.registry.resolve(PROJECT_ID, "hub") def test_managed_validation_is_preferred_over_legacy_workflow_order(self) -> None: legacy = {"id": "legacy", "path": ".gitea/workflows/chatgpt-validation.yml"} managed = {"id": "managed", "path": ".gitea/workflows/managed-validation.yml"} self.assertIs(_select_validation_workflow([legacy, managed]), managed) self.assertIs(_select_validation_workflow([managed, legacy]), managed) def test_projectbrain_managed_validation_profile_is_pinned_and_repository_scoped(self) -> None: self.assertEqual( _managed_validation_profile("Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW), "projectbrain", ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace("pnpm test:e2e:real", ""), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( "pnpm test:e2e:real", "# pnpm test:e2e:real" ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( "pnpm test:e2e:real", 'echo "pnpm test:e2e:real"' ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( 'export TEST_DATABASE_URL="${DATABASE_URL}"', '# export TEST_DATABASE_URL="${DATABASE_URL}"', ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " image: postgres:16", " image: postgres:15" ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace(" pull_request:\n", ""), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " pull_request:\n", ' pull_request:\n paths: ["backend/**"]\n' ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " pull_request:\n", " pull_request:\n types: [edited]\n" ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace("branches: [main]", "branches: [master]"), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( "branches: [main]", "branches: [main, '!main']" ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " pull_request:\n", " pull_request:\n branches: [main, '!main']\n", ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " name: full\n", " name: full\n if: false\n" ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " name: full\n", " name: full\n needs: [conditional-setup]\n" ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " - name: Validate repository with a bounded profile\n", " - name: Validate repository with a bounded profile\n if: false\n", ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " name: full\n", " name: full\n continue-on-error: true\n" ), ) ) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " - name: Validate repository with a bounded profile\n", " - name: Validate repository with a bounded profile\n" " continue-on-error: true\n", ), ) ) bypass_mutations = ( PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " pnpm test:e2e:real\n", " cat <<'EOF'\n pnpm test:e2e:real\n EOF\n", ), PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " pnpm --dir backend test:database\n", " exit 0\n pnpm --dir backend test:database\n", ), PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " pnpm test:e2e:real\n", " if false; then\n" " pnpm test:e2e:real\n" " fi\n", ), PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " pnpm test:e2e:real\n", " export PATH=/tmp/untrusted:$PATH\n" " pnpm test:e2e:real\n", ), PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 " "# v4.2.2\n", " - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 " "# v4.2.2\n" " - run: echo injected-action\n", ), PROJECTBRAIN_VALIDATION_WORKFLOW.replace( "run-name: \"Managed validation / ${{ inputs.profile || 'full' }}\"", 'run-name: "Managed validation / full"', ), PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " default: full\n", " default: test\n" ), PROJECTBRAIN_VALIDATION_WORKFLOW.replace( "permissions:\n", "env:\n PATH: /tmp/untrusted\n\npermissions:\n" ), PROJECTBRAIN_VALIDATION_WORKFLOW.replace( "permissions:\n", "defaults:\n run:\n shell: sh\n\npermissions:\n" ), PROJECTBRAIN_VALIDATION_WORKFLOW.replace( "jobs:\n", "jobs:\n extra:\n runs-on: linux-validation\n steps: []\n" ), ) for modified_workflow in bypass_mutations: with self.subTest(modified_workflow=modified_workflow[-160:]): self.assertIsNone( _managed_validation_profile("Jens/projectbrain", modified_workflow) ) alias_chain = ["level0: &level0 [marker]"] for level in range(1, 23): alias_chain.append( f"level{level}: &level{level} [*level{level - 1}, *level{level - 1}]" ) alias_bomb = PROJECTBRAIN_VALIDATION_WORKFLOW.replace( "jobs:\n", "\n".join(alias_chain) + "\njobs:\n" ) self.assertIsNone(_managed_validation_profile("Jens/projectbrain", alias_bomb)) self.assertIsNone( _managed_validation_profile( "Jens/projectbrain", PROJECTBRAIN_VALIDATION_WORKFLOW + "\njobs: {}\n" ) ) self.assertIsNone(_managed_validation_profile("Acme/hub", PROJECTBRAIN_VALIDATION_WORKFLOW)) self.assertEqual( _managed_validation_profile("Acme/hub", MANAGED_VALIDATION_WORKFLOW), "canonical", ) self.assertIsNone( _managed_validation_profile( "Acme/hub", MANAGED_VALIDATION_WORKFLOW + "\n# custom project workflow\n" ) ) def test_projectbrain_profile_pins_coverage_audits_security_and_doc_checks(self) -> None: required_commands = ( ("root coverage gate", "pnpm run test:coverage", "pnpm --if-present test"), ( "backend coverage gate", "pnpm --filter projectbrain-api run test:coverage", "pnpm --filter projectbrain-api run test", ), ("security audit", "pnpm run audit:security", "pnpm --if-present audit:security"), ("OpenAPI audit", "pnpm run audit:openapi", "echo skipped-openapi-audit"), ( "architecture audit", "pnpm run audit:architecture", "echo skipped-architecture-audit", ), ("documentation audit", "pnpm run audit:docs", "echo skipped-docs-audit"), ("v1 freeze audit", "pnpm run audit:v1-freeze", "echo skipped-v1-freeze-audit"), ( "Unraid template audit", "pnpm run audit:unraid-template", "echo skipped-unraid-template-audit", ), ( "documentation fast-path check", "node scripts/check-doc-links.mjs", "echo skipped-doc-link-check", ), ( "Unraid documentation fast-path check", "node scripts/check-unraid-template-readiness.mjs", "echo skipped-unraid-readiness-check", ), ) for label, command, replacement in required_commands: with self.subTest(gate=label): self.assertIn(command, PROJECTBRAIN_VALIDATION_WORKFLOW) modified_workflow = PROJECTBRAIN_VALIDATION_WORKFLOW.replace( command, replacement, 1 ) self.assertIsNone( _managed_validation_profile("Jens/projectbrain", modified_workflow) ) def test_native_skills_are_complete_digest_verified_and_bounded(self) -> None: from services.runtime.mcp_skills import SkillGetParams, SkillListParams, StaticSkills extension = StaticSkills(ROOT / "plugins/itworx-gitea/skills") self.assertEqual( {item["frontmatter"]["name"] for item in extension.catalog}, { "repository-engineer", "portfolio-engineer", "projectbrain-operator", "projectbrain-feature-delivery", "projectbrain-portfolio-curator", }, ) resources = { str(binding.resource.uri): binding.resource for binding in extension.resources() } for skill in extension.catalog: self.assertEqual(skill["uri"], skill["resources"][0]["uri"]) for descriptor in skill["resources"]: resource = resources[descriptor["uri"]] self.assertEqual( descriptor["digest"], f"sha256:{hashlib.sha256(resource.text.encode('utf-8')).hexdigest()}", ) listed = asyncio.run(extension._list(None, SkillListParams())) self.assertEqual(listed["skills"], list(extension.catalog)) selected = extension.catalog[0] fetched = asyncio.run(extension._get(None, SkillGetParams(uri=selected["uri"]))) self.assertEqual(fetched, {"skill": selected}) with self.assertRaisesRegex(ValueError, "not registered"): asyncio.run( extension._get( None, SkillGetParams(uri="skill://itworx-gitea/missing/SKILL.md"), ) ) def test_registered_read_paths_and_source_metadata(self) -> None: connector_instance, fixture = connector() try: current = context() self.assertEqual( connector_instance.repository_get(current, "hub-repository")["data"]["fullName"], "acme/hub", ) self.assertEqual( len(connector_instance.branch_list(current, "hub-repository")["data"]["items"]), 3 ) self.assertEqual( connector_instance.commit_list(current, "hub-repository")["data"]["items"][0][ "authorName" ], "Ada", ) self.assertEqual( connector_instance.release_list(current, "hub-repository")["data"]["items"][0][ "tag" ], "v1.0.0", ) self.assertEqual( connector_instance.issue_list(current, "hub-repository")["data"]["items"][0][ "number" ], 1, ) self.assertEqual( connector_instance.pull_request_list(current, "hub-repository")["data"]["items"][0][ "number" ], 7, ) pull = connector_instance.pull_request_get(current, "hub-repository", 7)["data"] self.assertEqual(pull["baseRef"], "main") self.assertEqual(pull["changedFiles"][0]["path"], "services/runtime/mcp_server.py") statuses = connector_instance.commit_status_list(current, "hub-repository", "main")[ "data" ]["items"] self.assertEqual(statuses[0]["state"], "success") file_result = connector_instance.file_read( current, "itworx-git://hub/hub-repository/README.md" ) self.assertIn("ITWorx MCP Hub", file_result["data"]["content"]) self.assertEqual(file_result["meta"]["source"], "gitea:hub-repository") self.assertTrue(all(method == "GET" for method in fixture.recorded_methods)) self.assertTrue(all(path.startswith("/api/v1/") for path in fixture.recorded_paths)) finally: connector_instance.client.close() def test_repository_list_ref_is_reusable_across_read_contract(self) -> None: connector_instance, fixture = connector() try: current = context() listed = connector_instance.repository_list(current)["data"]["items"][0] repository_ref = listed["repositoryRef"] default_branch = listed["defaultBranch"] self.assertEqual(default_branch, "main") self.assertEqual( connector_instance.repository_get(current, repository_ref)["data"]["repositoryRef"], repository_ref, ) self.assertTrue( connector_instance.branch_list(current, repository_ref)["data"]["items"] ) self.assertTrue( connector_instance.commit_list(current, repository_ref)["data"]["items"] ) self.assertTrue( connector_instance.commit_status_list(current, repository_ref, default_branch)[ "data" ]["items"] ) self.assertTrue( connector_instance.release_list(current, repository_ref)["data"]["items"] ) self.assertTrue(connector_instance.issue_list(current, repository_ref)["data"]["items"]) portfolio_issues = connector_instance.issue_search( current, state="open", exclude_repository_names=[] )["data"] self.assertEqual(portfolio_issues["items"][0]["repositoryRef"], repository_ref) self.assertEqual(portfolio_issues["items"][0]["number"], 1) self.assertEqual( connector_instance.issue_search( current, state="open", exclude_repository_names=["hub"] )["data"]["items"], [], ) pulls = connector_instance.pull_request_list(current, repository_ref)["data"]["items"] self.assertTrue(pulls) self.assertEqual( connector_instance.pull_request_get(current, repository_ref, pulls[0]["number"])[ "data" ]["number"], pulls[0]["number"], ) file_uri = f"{listed['sourceUri']}/README.md" self.assertIn( "ITWorx MCP Hub", connector_instance.file_read(current, file_uri)["data"]["content"], ) search = connector_instance.code_search(current, repository_ref, "ITWorx") self.assertEqual(search["data"]["items"][0]["fileUri"], file_uri) self.assertTrue(all(path.startswith("/api/v1/") for path in fixture.recorded_paths)) finally: connector_instance.client.close() def test_repository_agent_context_search_feedback_validation_and_resume(self) -> None: connector_instance, fixture = connector() try: current = context() fixture._branches.append( { "name": "codex/workflows", "commit": {"id": "e" * 40}, "protected": False, } ) context_result = connector_instance.repository_context(current, "hub-repository") context_pack = context_result["data"] self.assertFalse(context_result["meta"]["cacheHit"]) self.assertEqual(context_pack["stacks"], []) self.assertEqual(context_pack["documents"][0]["path"], "README.md") search_result = connector_instance.code_search( current, "hub-repository", "safe fixture" ) self.assertTrue(search_result["meta"]["cacheHit"]) results = search_result["data"] self.assertEqual(results["items"][0]["matches"][0]["line"], 3) fixture._reviews = [ {"id": 11, "state": "REQUEST_CHANGES", "user": {"login": "reviewer"}} ] feedback = connector_instance.pull_request_feedback(current, "hub-repository", 7)[ "data" ] self.assertEqual(feedback["reviews"][0]["comments"][0]["path"], "README.md") dispatched = connector_instance.validation_run( current, "hub-repository", "codex/workflows", "full" )["data"] self.assertEqual(dispatched["id"], 42) self.assertTrue(dispatched["dispatched"]) reused_runs = [ connector_instance.validation_run( current, "hub-repository", "codex/workflows", "full" )["data"] for _ in range(4) ] self.assertTrue(all(item["id"] == 42 for item in reused_runs)) self.assertTrue(all(item["dispatched"] is False for item in reused_runs)) self.assertTrue(all(item["reused"] is True for item in reused_runs)) self.assertTrue(all(item["deduplicatedRunId"] == 42 for item in reused_runs)) self.assertEqual( sum(path.endswith("/dispatches") for path in fixture.recorded_paths), 1 ) validation = connector_instance.validation_get( current, "hub-repository", 42, include_logs=True )["data"] self.assertEqual(validation["run"]["conclusion"], "success") self.assertEqual(validation["run"]["jobs"][0]["conclusion"], "success") self.assertIn("checks passed", validation["run"]["jobs"][0]["logs"]) self.assertTrue(validation["run"]["terminal"]) self.assertEqual(validation["run"]["pollAfterMs"], 0) connector_instance.branch_create(current, "hub-repository", "codex/workflows", "main") status = connector_instance.change_status(current, "hub-repository", "codex/workflows")[ "data" ] self.assertEqual(status["pullRequest"]["number"], 7) self.assertEqual(status["validationRuns"][0]["id"], 42) self.assertEqual(status["validationState"], "succeeded") self.assertTrue(status["terminal"]) finally: connector_instance.client.close() def test_repository_context_stays_below_connector_response_budget(self) -> None: connector_instance, fixture = connector() fixture._file = "R" * 100_000 large_tree = [ { "path": f"src/generated-{index:03d}.cs", "type": "blob", "sha": f"{index:040x}", "size": 100, } for index in range(200) ] large_tree.append({"path": "README.md", "type": "blob", "sha": "d" * 40, "size": 100_000}) try: with patch.object( connector_instance.client, "git_tree", return_value={"sha": "a" * 40, "tree": large_tree, "truncated": False}, ): result = connector_instance.repository_context(context(), "hub-repository") data = result["data"] self.assertEqual(len(data["tree"]), 64) self.assertTrue(data["treeTruncated"]) self.assertTrue(data["documentsTruncated"]) self.assertTrue(result["meta"]["truncated"]) self.assertLessEqual(len(data["documents"]), 4) self.assertLessEqual( sum(len(item["content"].encode("utf-8")) for item in data["documents"]), 8_192, ) self.assertLess(len(json.dumps(result).encode("utf-8")), 32_768) finally: connector_instance.client.close() def test_failed_cached_validation_is_dispatched_again(self) -> None: connector_instance, fixture = connector() try: fixture._branches.append( {"name": "codex/workflows", "commit": {"id": "e" * 40}, "protected": False} ) first = connector_instance.validation_run( context(), "hub-repository", "codex/workflows", "full" )["data"] self.assertTrue(first["dispatched"]) fixture._action_run.update({"status": "completed", "conclusion": "failure"}) retried = connector_instance.validation_run( context(), "hub-repository", "codex/workflows", "full" )["data"] self.assertTrue(retried["dispatched"]) self.assertFalse(retried["reused"]) self.assertEqual( sum(path.endswith("/dispatches") for path in fixture.recorded_paths), 2 ) finally: connector_instance.client.close() def test_changeset_preview_and_atomic_apply_support_patch_move_and_delete(self) -> None: connector_instance, _ = connector() try: operations = [ { "kind": "patch", "path": "README.md", "expectedSha": "d" * 40, "patch": ( "--- a/README.md\n+++ b/README.md\n" "@@ -1,3 +1,3 @@\n # ITWorx MCP Hub\n \n-This is a safe fixture.\n" "+This is an improved fixture.\n" ), } ] preview = connector_instance.changeset_preview( context(), "hub-repository", "codex/workflows", operations )["data"] self.assertTrue(preview["valid"]) self.assertIn("improved fixture", preview["operations"][0]["diff"]) applied = connector_instance.changeset_apply( context(), "hub-repository", "codex/workflows", "Improve fixture", operations, )["data"] self.assertTrue(applied["atomic"]) self.assertEqual(applied["commitSha"], "6" * 40) finally: connector_instance.client.close() def test_unified_patch_rejects_stale_context_and_operation_budgets(self) -> None: original = "one\ntwo\n" patch_text = "@@ -1,2 +1,2 @@\n one\n-two\n+three\n" self.assertEqual(apply_unified_patch(original, patch_text), "one\nthree\n") with self.assertRaisesRegex(GiteaError, "context does not match"): apply_unified_patch("zero\ntwo\n", patch_text) with self.assertRaisesRegex(GiteaError, "operation count"): validate_operations([]) def test_dulwich_workspace_pushes_one_atomic_multi_file_commit(self) -> None: with tempfile.TemporaryDirectory() as directory: root = Path(directory) remote = root / "acme" / "hub.git" remote.parent.mkdir(parents=True) bare = porcelain.init(remote, bare=True) bare.close() seed = root / "seed" repo = porcelain.init(seed) (seed / "README.md").write_text("one\ntwo\n", encoding="utf-8") porcelain.add(repo, ["README.md"]) porcelain.commit( repo, message=b"seed", author=b"Test ", committer=b"Test ", ) porcelain.branch_create(repo, "codex/atomic") porcelain.push( repo, str(remote), refspecs=[ "refs/heads/master:refs/heads/master", "refs/heads/codex/atomic:refs/heads/codex/atomic", ], ) sha = repo.open_index()[b"README.md"].sha.decode("ascii") workspace = DulwichChangesetWorkspace( str(root), StaticTokenProvider("unused-local-token"), "docker-secret://test" ) previous_identity = {name: os.environ.get(name) for name in ("USER", "EMAIL")} observed_identity: list[tuple[str | None, str | None]] = [] def require_explicit_identity() -> tuple[str, str]: identity = (os.environ.get("USER"), os.environ.get("EMAIL")) observed_identity.append(identity) self.assertEqual(identity, ("mcp-agent", "mcp-agent@example.com")) return identity[0] or "", identity[1] or "" with patch( "dulwich.repo._get_default_identity", side_effect=require_explicit_identity, ): result = workspace.apply( RegisteredRepository( repository_ref="hub", project_id=PROJECT_ID, owner="acme", name="hub", source_uri="itworx-git://hub/hub", private=True, ), "codex/atomic", "Atomic update", [ { "kind": "patch", "path": "README.md", "expectedSha": sha, "patch": "@@ -1,2 +1,2 @@\n one\n-two\n+three\n", }, {"kind": "create", "path": "new.txt", "content": "created\n"}, ], ) self.assertTrue(observed_identity) self.assertEqual( {name: os.environ.get(name) for name in ("USER", "EMAIL")}, previous_identity, ) self.assertTrue(result["atomic"]) repo.close() checkout = root / "checkout" checkout_repo = porcelain.clone(str(remote), checkout, branch="codex/atomic") self.assertEqual((checkout / "README.md").read_text(encoding="utf-8"), "one\nthree\n") self.assertEqual((checkout / "new.txt").read_text(encoding="utf-8"), "created\n") checkout_repo.close() def test_repository_list_rejects_nonempty_repository_without_default_branch(self) -> None: fixture = FakeGiteaServer() fixture._repos["acme/hub"]["default_branch"] = None connector_instance, _ = connector(fixture) try: with self.assertRaisesRegex(GiteaError, "without a default branch"): connector_instance.repository_list(context()) finally: connector_instance.client.close() def test_project_and_repository_allowlist_isolation(self) -> None: connector_instance, _ = connector() try: with self.assertRaisesRegex(GiteaError, "not registered"): connector_instance.repository_get( context(OTHER_PROJECT_ID, "other"), "hub-repository" ) with self.assertRaisesRegex(GiteaError, "not registered"): connector_instance.repository_get(context(), "acme-hub") finally: connector_instance.client.close() def test_file_uri_path_escape_is_denied(self) -> None: connector_instance, _ = connector() try: for file_uri in ( "itworx-git://hub/hub-repository/../secret", "itworx-git://hub/hub-repository/%2e%2e/secret", "itworx-git://hub/hub-repository//absolute", "itworx-git://other/hub-repository/README.md", ): with self.subTest(file_uri=file_uri), self.assertRaises(GiteaError): connector_instance.file_read(context(), file_uri) finally: connector_instance.client.close() def test_cursor_pagination_is_opaque_and_bounded(self) -> None: connector_instance, _ = connector(FakeGiteaServer()) try: current = context() first = connector_instance.branch_list( current, "hub-repository", page=PageRequest(limit=2) ) self.assertEqual(len(first["data"]["items"]), 2) self.assertTrue(first["data"]["nextCursor"]) second = connector_instance.branch_list( current, "hub-repository", page=PageRequest(limit=2, cursor=first["data"]["nextCursor"]), ) self.assertEqual(len(second["data"]["items"]), 1) with self.assertRaises(ValueError): connector_instance.branch_list( current, "hub-repository", page=PageRequest(limit=101) ) finally: connector_instance.client.close() def test_token_and_response_headers_are_not_exposed(self) -> None: connector_instance, fixture = connector() try: output = repr(connector_instance.repository_get(context(), "hub-repository")) self.assertNotIn("fixture-token-must-not-leak", output) self.assertEqual( fixture.recorded_authorizations[0], "token fixture-token-must-not-leak" ) self.assertNotIn("authorization", output.lower()) finally: connector_instance.client.close() def test_redirect_to_other_origin_is_denied(self) -> None: connector_instance, fixture = connector( FakeGiteaServer(redirect_to="http://169.254.169.254/latest/meta-data") ) try: with self.assertRaisesRegex(GiteaError, "leaves the configured origin"): connector_instance.repository_get(context(), "hub-repository") self.assertEqual(len(fixture.recorded_methods), 1) finally: connector_instance.client.close() def test_unsupported_optional_api_is_degraded(self) -> None: connector_instance, _ = connector(FakeGiteaServer(unsupported_search=True)) try: with self.assertRaisesRegex(GiteaError, "unsupported"): connector_instance.code_search(context(), "hub-repository", "bounded") finally: connector_instance.client.close() def test_control_plane_registration_projects_allowlist_and_camel_case_settings(self) -> None: now = datetime.now(UTC) project = Project( workspace_id=uuid4(), slug="hub", name="Hub", repository_provider="gitea", repository_owner="acme", repository_name="hub", created_at=now, updated_at=now, ) connector_model = Connector( project_id=project.id, workspace_id=project.workspace_id, type="gitea", slug="gitea-default", endpoint="https://gitea.example", credential_reference="docker-secret://gitea_mcp_token", # noqa: S106 configuration={"requestTimeoutSeconds": 9, "maxPageSize": 50}, enabled=True, created_at=now, updated_at=now, ) registration = registration_from_project(project, connector_model) self.assertEqual(registration.settings.timeout_seconds, 9) self.assertEqual(registration.settings.max_page_size, 50) self.assertEqual(registration.repositories[0].qualified_name, "acme/hub") self.assertNotIn("fixture-token-must-not-leak", repr(registration.settings)) def test_publication_separates_read_and_pr_first_write_tools(self) -> None: connector_instance, _ = connector() try: tools = connector_instance.tools() names = {tool.canonical_name for tool in tools} self.assertEqual(len(names), 37) self.assertIn("gitea.research.search", names) self.assertIn("gitea.research.fetch", names) self.assertTrue(all(tool.read_only for tool in tools)) write_tools = list(connector_instance.write_tools()) self.assertEqual(len(write_tools), 21) self.assertEqual({tool.risk_class for tool in write_tools}, {"R2", "R3"}) self.assertTrue( all(tool.required_scopes == ("project:{project}:write",) for tool in write_tools) ) schemas = {tool.canonical_name: tool.input_schema for tool in write_tools} repository_create = next( tool for tool in write_tools if tool.canonical_name == "gitea.repository.create" ) self.assertEqual(repository_create.version, "1.8.0") self.assertEqual( schemas["gitea.repository.create"]["required"], ["name", "description", "private", "autoInit", "defaultBranch"], ) self.assertIs( schemas["gitea.repository.create"]["properties"]["autoInit"]["const"], True ) self.assertEqual( schemas["gitea.repository.create"]["properties"]["defaultBranch"]["const"], "main", ) self.assertIn("expectedPlanHash", schemas["gitea.branchprotection.ensure"]["required"]) self.assertEqual( schemas["gitea.branchprotection.ensure"]["properties"]["applyScope"]["enum"], ["all", "protection_only"], ) portfolio_plan_properties = schemas["gitea.portfolio.governance.apply"]["properties"][ "plans" ]["items"]["properties"] self.assertEqual( portfolio_plan_properties["applyScope"]["enum"], ["all", "protection_only"] ) self.assertEqual( schemas["gitea.portfolio.governance.apply"]["properties"]["plans"]["maxItems"], 5, ) self.assertIn("expectedSha", schemas["gitea.file.update"]["required"]) self.assertIn("expectedSha", schemas["gitea.file.delete"]["required"]) self.assertIn("head", schemas["gitea.pullrequest.create"]["required"]) self.assertEqual( schemas["gitea.pullrequest.close"]["required"], ["repositoryRef", "number", "expectedHeadSha"], ) self.assertIn("number", schemas["gitea.issue.comment.create"]["required"]) self.assertIn("number", schemas["gitea.issue.update"]["required"]) self.assertIn("operations", schemas["gitea.changeset.apply"]["required"]) self.assertIn("profile", schemas["gitea.validation.run"]["required"]) self.assertIn("expectedHeadSha", schemas["gitea.pullrequest.merge"]["required"]) self.assertEqual( schemas["gitea.pullrequest.sync"]["required"], [ "repositoryRef", "number", "expectedHeadSha", "expectedBaseSha", "strategy", "dryRun", ], ) self.assertIn("expectedHeadSha", schemas["gitea.branch.delete"]["required"]) self.assertIn("profile", schemas["gitea.workspace.run"]["required"]) self.assertIn( "expectedOrchestrationId", schemas["gitea.orchestration.start"]["required"], ) self.assertNotIn("gitea.pullrequest.merge", names) self.assertNotIn("gitea.branch.delete", names) self.assertEqual( connector_instance.resources()[0].uri_template, "itworx-git://{project}/{repositoryRef}/{path}", ) tree = connector_instance.tree_list(context(), "hub-repository")["data"]["items"] self.assertEqual(tree[0]["path"], "README.md") finally: connector_instance.client.close() def test_runtime_hides_write_tools_until_feature_flag_is_enabled(self) -> None: connector_instance, _ = connector() try: with ( patch.dict(os.environ, {"GITEA_ENABLE_PR_WRITES": ""}), patch( "services.runtime.connector_gitea.build_connector", return_value=(connector_instance, {"hub"}), ), patch( "services.runtime.connector_gitea.load_connector_identity_key", return_value=b"x" * 32, ), ): from services.runtime.connector_gitea import build_server server = build_server() tools = asyncio.run(server.list_tools()) names = {tool.name for tool in tools} self.assertIn("gitea.repository.list", names) self.assertIn("gitea.tree.list", names) self.assertNotIn("gitea.file.create", names) self.assertNotIn("gitea.file.delete", names) self.assertNotIn("gitea.file.update", names) self.assertNotIn("gitea.repository.create", names) self.assertNotIn("gitea.issue.create", names) self.assertNotIn("gitea.issue.update", names) self.assertNotIn("gitea.pullrequest.create", names) self.assertNotIn("gitea.changeset.apply", names) self.assertNotIn("gitea.validation.run", names) finally: connector_instance.client.close() def test_runtime_registers_only_bounded_write_tools_when_enabled(self) -> None: connector_instance, _ = connector() try: with ( patch.dict(os.environ, {"GITEA_ENABLE_PR_WRITES": "true"}), patch( "services.runtime.connector_gitea.build_connector", return_value=(connector_instance, {"hub"}), ), patch( "services.runtime.connector_gitea.load_connector_identity_key", return_value=b"x" * 32, ), ): from services.runtime.connector_gitea import build_server server = build_server() tools = asyncio.run(server.list_tools()) resources = asyncio.run(server.list_resources()) prompts = asyncio.run(server.list_prompts()) self.assertEqual(server.version, "1.14.0") self.assertIn("plan-locked governance tools", server.instructions) names = {tool.name for tool in tools} ensure_tool = next( tool for tool in tools if tool.name == "gitea.branchprotection.ensure" ) portfolio_apply_tool = next( tool for tool in tools if tool.name == "gitea.portfolio.governance.apply" ) self.assertEqual( ensure_tool.input_schema["properties"]["applyScope"]["enum"], ["all", "protection_only"], ) portfolio_schema = portfolio_apply_tool.input_schema plan_ref = portfolio_schema["properties"]["plans"]["items"]["$ref"] plan_schema_name = plan_ref.rsplit("/", maxsplit=1)[-1] plan_schema = portfolio_schema["$defs"][plan_schema_name] self.assertEqual( plan_schema["properties"]["applyScope"]["enum"], ["all", "protection_only"] ) self.assertEqual(portfolio_schema["properties"]["plans"]["maxItems"], 5) self.assertTrue( { "gitea.repository.create", "gitea.branchprotection.ensure", "gitea.portfolio.governance.apply", "gitea.branch.create", "gitea.issue.create", "gitea.issue.update", "gitea.issue.comment.create", "gitea.file.create", "gitea.file.update", "gitea.file.delete", "gitea.pullrequest.create", "gitea.pullrequest.update", "gitea.pullrequest.close", "gitea.pullrequest.sync", "gitea.changeset.apply", "gitea.validation.run", "gitea.validation.failure.get", "gitea.change.reconcile", "gitea.pullrequest.merge", "gitea.branch.delete", }.issubset(names) ) self.assertEqual(len(names), 58) self.assertIn("gitea.selftest.run", names) repository_create_tool = next( tool for tool in tools if tool.name == "gitea.repository.create" ) self.assertEqual( repository_create_tool.input_schema["required"], ["name", "description", "private", "autoInit", "defaultBranch"], ) self.assertIn("search", names) self.assertIn("fetch", names) search_tool = next(tool for tool in tools if tool.name == "search") fetch_tool = next(tool for tool in tools if tool.name == "fetch") self.assertEqual(search_tool.input_schema["required"], ["query"]) self.assertEqual(fetch_tool.input_schema["required"], ["id"]) self.assertIn("results", search_tool.output_schema["properties"]) self.assertIn("text", fetch_tool.output_schema["properties"]) self.assertIn("io.modelcontextprotocol/skills", server._lowlevel_server.extensions) self.assertNotIn("io.modelcontextprotocol/ui", server._lowlevel_server.extensions) self.assertIn("repository-engineer", {prompt.name for prompt in prompts}) self.assertIn("portfolio-engineer", {prompt.name for prompt in prompts}) self.assertFalse( any(str(resource.uri).startswith("ui://itworx-gitea/") for resource in resources) ) app_tool_names = { tool.name for tool in tools if tool.meta and tool.meta.get("openai/outputTemplate") } self.assertEqual(app_tool_names, set()) finally: connector_instance.client.close() def test_runtime_requires_a_distinct_write_token_secret(self) -> None: base_environment = { "GITEA_ENABLE_PR_WRITES": "true", "GITEA_ENDPOINT": "https://gitea.test", "GITEA_REPOSITORIES_JSON": ('[{"project":"hub","owner":"acme","name":"hub"}]'), "GITEA_TOKEN_FILE": "/run/secrets/gitea_read_token", } from services.runtime.connector_gitea import build_connector with ( patch.dict(os.environ, base_environment, clear=True), self.assertRaisesRegex(ValueError, "GITEA_WRITE_TOKEN_FILE is required"), ): build_connector() with ( patch.dict( os.environ, {**base_environment, "GITEA_WRITE_TOKEN_FILE": "/run/secrets/gitea_read_token"}, clear=True, ), self.assertRaisesRegex(ValueError, "separate secret files"), ): build_connector() def test_runtime_derives_fixed_write_owner_and_admits_focused_profiles(self) -> None: environment = { "GITEA_ENABLE_PR_WRITES": "true", "GITEA_ENDPOINT": "https://gitea.test", "GITEA_REPOSITORIES_JSON": ('[{"project":"gitea-all","owner":"acme","name":"hub"}]'), "GITEA_ADDITIONAL_PROJECTS": "gitea-loop", "GITEA_TOKEN_FILE": "/run/secrets/gitea_read_token", "GITEA_WRITE_TOKEN_FILE": "/run/secrets/gitea_write_token", } from services.runtime.common import deterministic_id from services.runtime.connector_gitea import build_connector with patch.dict(os.environ, environment, clear=True): connector_instance, projects = build_connector() try: self.assertEqual(connector_instance.write_owner, "acme") self.assertEqual(projects, {"gitea-all", "gitea-loop"}) assert connector_instance.repository_create_project is not None self.assertEqual(connector_instance.repository_create_project[1], "gitea-all") focused = connector_instance.registry.list(deterministic_id("project", "gitea-loop")) self.assertEqual([item.qualified_name for item in focused], ["acme/hub"]) resolved = connector_instance.registry.resolve( deterministic_id("project", "gitea-loop"), "hub" ) self.assertEqual(resolved.qualified_name, "acme/hub") with self.assertRaisesRegex(GiteaError, "not registered"): connector_instance.registry.resolve(uuid4(), "hub") finally: connector_instance.client.close() assert connector_instance.write_client is not None connector_instance.write_client.close() def test_runtime_requires_explicit_write_owner_for_multiple_namespaces(self) -> None: environment = { "GITEA_ENABLE_PR_WRITES": "true", "GITEA_ENDPOINT": "https://gitea.test", "GITEA_REPOSITORIES_JSON": ( '[{"project":"gitea-all","owner":"acme","name":"hub"},' '{"project":"gitea-all","owner":"other","name":"service"}]' ), "GITEA_TOKEN_FILE": "/run/secrets/gitea_read_token", "GITEA_WRITE_TOKEN_FILE": "/run/secrets/gitea_write_token", } from services.runtime.connector_gitea import build_connector with ( patch.dict(os.environ, environment, clear=True), self.assertRaisesRegex(ValueError, "GITEA_WRITE_OWNER is required"), ): build_connector() def test_safe_write_workflow_is_branch_scoped_and_pr_first(self) -> None: connector_instance, fixture = connector() try: current = context() branch = connector_instance.branch_create( current, "hub-repository", "chatgpt/readme-update", "main" )["data"] self.assertTrue(branch["created"]) issue = connector_instance.issue_create( current, "hub-repository", "Document safe write mode", "Track the rollout." )["data"] self.assertEqual(issue["number"], 2) changed_issue = connector_instance.issue_update( current, "hub-repository", 2, "Document governed write mode", "Tracked and completed.", "closed", )["data"] self.assertTrue(changed_issue["updated"]) self.assertEqual(changed_issue["state"], "closed") comment = connector_instance.issue_comment_create( current, "hub-repository", 2, "Implementation is ready for review." )["data"] self.assertEqual(comment["commentId"], 99) created = connector_instance.file_create( current, "hub-repository", "README.md", "chatgpt/readme-update", "# Updated\n", "docs: update README", )["data"] self.assertEqual(created["operation"], "created") updated = connector_instance.file_update( current, "hub-repository", "README.md", "chatgpt/readme-update", "# Updated again\n", "docs: refine README", "9" * 40, )["data"] self.assertEqual(updated["operation"], "updated") pull = connector_instance.pull_request_create( current, "hub-repository", "chatgpt/readme-update", "main", "Update README", "Please review this bounded change.", )["data"] self.assertTrue(pull["created"]) self.assertEqual(pull["headRef"], "chatgpt/readme-update") self.assertEqual( fixture.recorded_methods, [ "GET", "POST", "POST", "GET", "PATCH", "POST", "GET", "POST", "GET", "PUT", "POST", ], ) self.assertEqual(fixture.recorded_bodies[0]["old_ref_name"], "main") self.assertNotIn("fixture-token-must-not-leak", repr(fixture.recorded_bodies)) finally: connector_instance.client.close() def test_repository_create_is_idempotent_and_immediately_registered(self) -> None: connector_instance, fixture = connector() try: created = connector_instance.repository_create( context(), "projectbrain-created", "Created through the governed MCP tool.", True, True, "main", )["data"] self.assertTrue(created["created"]) self.assertTrue(created["availableImmediately"]) self.assertTrue(created["initialized"]) self.assertTrue(created["branchReady"]) self.assertTrue(created["governanceReady"]) self.assertTrue(created["managedValidationReady"]) self.assertTrue(created["defaultBranchProtected"]) self.assertFalse(created["repairedEmptyRepository"]) self.assertEqual(created["headSha"], "a" * 40) self.assertEqual(created["repositoryRef"], "all-projectbrain-created") self.assertEqual( connector_instance.repository_get(context(), created["repositoryRef"])["data"][ "fullName" ], "acme/projectbrain-created", ) reused = connector_instance.repository_create( context(), "projectbrain-created", private=True )["data"] self.assertFalse(reused["created"]) self.assertEqual(reused["repositoryRef"], created["repositoryRef"]) self.assertEqual(fixture.recorded_methods.count("POST"), 3) with self.assertRaisesRegex(GiteaError, "outside the safe policy"): connector_instance.repository_create(context(), "../unsafe") with self.assertRaisesRegex(GiteaError, "requires an initialized default branch"): connector_instance.repository_create( context(), "projectbrain-empty-request", auto_init=False ) with self.assertRaisesRegex(GiteaError, "canonical main branch"): connector_instance.repository_create( context(), "projectbrain-master-request", default_branch="master" ) with self.assertRaisesRegex(GiteaError, "different visibility"): connector_instance.repository_create( context(), "projectbrain-created", private=False ) public_repository = connector_instance.repository_create( context(), "projectbrain-public", private=False )["data"] self.assertNotIn("/api/v1/user", fixture.recorded_paths) restarted, _ = connector(fixture) try: restarted.discovery_projects = {PROJECT_ID: "hub"} refs = { item["repositoryRef"] for item in restarted.repository_list(context(), page=PageRequest(limit=100))[ "data" ]["items"] } self.assertIn(public_repository["repositoryRef"], refs) self.assertIn("/api/v1/user/repos", fixture.recorded_paths) finally: restarted.client.close() finally: connector_instance.client.close() def test_governance_preview_ensure_verify_is_plan_locked_and_idempotent(self) -> None: connector_instance, fixture = connector() fixture._managed_workflows.pop("acme/hub") fixture._branch_protections["acme/hub"] = [] try: current = context() preview = connector_instance.branch_protection_preview(current, "hub-repository")[ "data" ] self.assertEqual(preview["workflow"]["action"], "create") self.assertEqual(preview["branchProtection"]["action"], "create") self.assertFalse(preview["compliant"]) with self.assertRaisesRegex(GiteaError, "preview the repository again"): connector_instance.branch_protection_ensure(current, "hub-repository", "0" * 64) applied = connector_instance.branch_protection_ensure( current, "hub-repository", preview["planHash"] )["data"] self.assertTrue(applied["changed"]) self.assertTrue(applied["verified"]) verified = connector_instance.portfolio_governance_verify(current, ["hub-repository"])[ "data" ] self.assertEqual(verified["summary"], {"total": 1, "compliant": 1, "attention": 0}) replay = connector_instance.branch_protection_ensure( current, "hub-repository", applied["planHash"] )["data"] self.assertFalse(replay["changed"]) self.assertTrue(replay["verified"]) finally: connector_instance.client.close() def test_projectbrain_custom_workflow_is_preserved_while_full_and_quality_are_added( self, ) -> None: connector_instance, fixture = projectbrain_connector() original_workflow = fixture._managed_workflows["Jens/projectbrain"] fixture._branch_protections["Jens/projectbrain"][0]["status_check_contexts"] = [ "Pull request / quality (pull_request)" ] original_protection = copy.deepcopy(fixture._branch_protections["Jens/projectbrain"][0]) try: current = context() preview = connector_instance.branch_protection_preview( current, "projectbrain-repository" )["data"] self.assertEqual(preview["workflow"]["profile"], "projectbrain") self.assertEqual(preview["workflow"]["action"], "none") self.assertNotEqual( preview["workflow"]["currentDigest"], hashlib.sha256(MANAGED_VALIDATION_WORKFLOW.encode()).hexdigest(), ) self.assertEqual( preview["branchProtection"]["desired"]["status_check_contexts"], [ "Managed validation / full (pull_request)", "Pull request / quality (pull_request)", ], ) self.assertEqual(preview["branchProtection"]["action"], "update") applied = connector_instance.branch_protection_ensure( current, "projectbrain-repository", preview["planHash"] )["data"] self.assertTrue(applied["changed"]) self.assertTrue(applied["verified"]) self.assertTrue(applied["compliant"]) self.assertEqual(fixture._managed_workflows["Jens/projectbrain"], original_workflow) self.assertEqual( fixture._branch_protections["Jens/projectbrain"][0]["status_check_contexts"], [ "Managed validation / full (pull_request)", "Pull request / quality (pull_request)", ], ) self.assertEqual( fixture._branch_protections["Jens/projectbrain"][0]["required_approvals"], original_protection["required_approvals"], ) workflow_writes = [ (method, path) for method, path in zip( fixture.recorded_methods, fixture.recorded_paths, strict=True ) if path.endswith("/.gitea/workflows/managed-validation.yml") and method in {"POST", "PUT", "DELETE"} ] self.assertEqual(workflow_writes, []) finally: connector_instance.client.close() def test_projectbrain_all_scope_fails_if_gitea_drops_an_extra_required_context(self) -> None: connector_instance, fixture = projectbrain_connector() fixture._branch_protections["Jens/projectbrain"][0]["status_check_contexts"] = [ "Pull request / quality (pull_request)", "Additional required check", ] original_read = connector_instance.client.branch_protections read_count = 0 def drop_extra_context(repository: RegisteredRepository) -> list[dict[str, object]]: nonlocal read_count read_count += 1 if read_count == 3: fixture._branch_protections["Jens/projectbrain"][0]["status_check_contexts"].remove( "Additional required check" ) return original_read(repository) try: current = context() with patch.object( connector_instance.client, "branch_protections", side_effect=drop_extra_context, ): preview = connector_instance.branch_protection_preview( current, "projectbrain-repository" )["data"] self.assertIn( "Additional required check", preview["branchProtection"]["desired"]["status_check_contexts"], ) with self.assertRaisesRegex(GiteaError, "did not retain"): connector_instance.branch_protection_ensure( current, "projectbrain-repository", preview["planHash"] ) self.assertNotIn( "Additional required check", fixture._branch_protections["Jens/projectbrain"][0]["status_check_contexts"], ) finally: connector_instance.client.close() def test_projectbrain_all_scope_rejects_an_accepted_workflow_digest_change(self) -> None: connector_instance, fixture = projectbrain_connector() fixture._branch_protections["Jens/projectbrain"][0]["status_check_contexts"] = [ "Pull request / quality (pull_request)" ] modified_workflow = PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " pull_request:\n", " pull_request:\n branches: [main]\n" ) original_update = connector_instance.client.update_branch_protection def update_protection_then_change_workflow( repository: RegisteredRepository, branch: str, payload: dict[str, object], ) -> object: response = original_update(repository, branch, payload) fixture._managed_workflows["Jens/projectbrain"] = modified_workflow return response try: current = context() preview = connector_instance.branch_protection_preview( current, "projectbrain-repository" )["data"] self.assertEqual(preview["workflow"]["profile"], "projectbrain") with patch.object( connector_instance.client, "update_branch_protection", side_effect=update_protection_then_change_workflow, ): with self.assertRaisesRegex(GiteaError, "did not retain"): connector_instance.branch_protection_ensure( current, "projectbrain-repository", preview["planHash"] ) self.assertEqual( _managed_validation_profile("Jens/projectbrain", modified_workflow), "projectbrain", ) self.assertEqual(fixture._managed_workflows["Jens/projectbrain"], modified_workflow) finally: connector_instance.client.close() def test_projectbrain_custom_profile_blocks_unsafe_existing_protection(self) -> None: connector_instance, fixture = projectbrain_connector() protection = fixture._branch_protections["Jens/projectbrain"][0] protection["enable_push"] = True protection["block_admin_merge_override"] = False original_protection = copy.deepcopy(protection) try: current = context() preview = connector_instance.branch_protection_preview( current, "projectbrain-repository" )["data"] self.assertEqual(preview["workflow"]["profile"], "projectbrain") self.assertIn( "managed-validation-projectbrain-protection-safety-locks-invalid", preview["blockers"], ) with self.assertRaisesRegex(GiteaError, "unresolved blockers"): connector_instance.branch_protection_ensure( current, "projectbrain-repository", preview["planHash"] ) self.assertEqual( fixture._branch_protections["Jens/projectbrain"][0], original_protection ) finally: connector_instance.client.close() def test_projectbrain_all_scope_creates_safe_protection_without_rewriting_profile(self) -> None: connector_instance, fixture = projectbrain_connector() original_workflow = fixture._managed_workflows["Jens/projectbrain"] fixture._branch_protections["Jens/projectbrain"] = [] try: current = context() preview = connector_instance.branch_protection_preview( current, "projectbrain-repository" )["data"] self.assertEqual(preview["workflow"]["profile"], "projectbrain") self.assertEqual(preview["branchProtection"]["action"], "create") applied = connector_instance.branch_protection_ensure( current, "projectbrain-repository", preview["planHash"] )["data"] self.assertTrue(applied["compliant"]) self.assertTrue(applied["verified"]) self.assertEqual(fixture._managed_workflows["Jens/projectbrain"], original_workflow) created_protection = fixture._branch_protections["Jens/projectbrain"][0] self.assertEqual( created_protection["status_check_contexts"], [ "Managed validation / full (pull_request)", "Pull request / quality (pull_request)", ], ) self.assertTrue(created_protection["block_admin_merge_override"]) finally: connector_instance.client.close() def test_projectbrain_protection_only_is_hash_bound_and_preserves_workflow( self, ) -> None: connector_instance, fixture = projectbrain_connector() invalid_workflow = PROJECTBRAIN_VALIDATION_WORKFLOW.replace(" pull_request:\n", "") fixture._managed_workflows["Jens/projectbrain"] = invalid_workflow protection = fixture._branch_protections["Jens/projectbrain"][0] protection["status_check_contexts"] = [ "Pull request / quality (pull_request)", "Additional required check", ] protection["required_approvals"] = 2 protection["require_signed_commits"] = True original_protection = copy.deepcopy(protection) try: current = context() preview = connector_instance.branch_protection_preview( current, "projectbrain-repository" )["data"] self.assertEqual(preview["workflow"]["profile"], "projectbrain-required") self.assertEqual(preview["workflow"]["action"], "none") self.assertIn("managed-validation-projectbrain-profile-invalid", preview["blockers"]) self.assertFalse(preview["compliant"]) self.assertTrue(preview["protectionOnlyAvailable"]) self.assertNotEqual(preview["planHash"], preview["protectionOnlyPlanHash"]) with self.assertRaisesRegex(GiteaError, "unresolved blockers"): connector_instance.branch_protection_ensure( current, "projectbrain-repository", preview["planHash"] ) with self.assertRaisesRegex(GiteaError, "preview the repository again"): connector_instance.branch_protection_ensure( current, "projectbrain-repository", preview["planHash"], apply_scope="protection_only", ) self.assertEqual(fixture._managed_workflows["Jens/projectbrain"], invalid_workflow) self.assertEqual( fixture._branch_protections["Jens/projectbrain"][0], original_protection ) portfolio_result = connector_instance.portfolio_governance_apply( current, [ { "repositoryRef": "projectbrain-repository", "planHash": preview["protectionOnlyPlanHash"], "applyScope": "protection_only", } ], )["data"] self.assertEqual(portfolio_result["summary"], {"total": 1, "applied": 1, "failed": 0}) self.assertEqual(portfolio_result["items"][0]["applyScope"], "protection_only") updated_protection = fixture._branch_protections["Jens/projectbrain"][0] self.assertEqual( updated_protection["status_check_contexts"], [ "Additional required check", "Managed validation / full (pull_request)", "Pull request / quality (pull_request)", ], ) self.assertEqual(updated_protection["required_approvals"], 2) self.assertTrue(updated_protection["require_signed_commits"]) self.assertEqual(fixture._managed_workflows["Jens/projectbrain"], invalid_workflow) self.assertEqual( fixture.recorded_bodies[-1], { "status_check_contexts": [ "Additional required check", "Managed validation / full (pull_request)", "Pull request / quality (pull_request)", ] }, ) finally: connector_instance.client.close() def test_projectbrain_protection_only_requires_an_existing_enabled_rule(self) -> None: connector_instance, fixture = projectbrain_connector() fixture._managed_workflows["Jens/projectbrain"] = PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " pull_request:\n", "" ) fixture._branch_protections["Jens/projectbrain"] = [] try: preview = connector_instance.branch_protection_preview( context(), "projectbrain-repository" )["data"] self.assertFalse(preview["protectionOnlyAvailable"]) self.assertIsNone(preview["protectionOnlyPlanHash"]) self.assertEqual(preview["branchProtection"]["action"], "create") finally: connector_instance.client.close() def test_projectbrain_protection_only_fails_if_gitea_drops_an_extra_context(self) -> None: connector_instance, fixture = projectbrain_connector() fixture._managed_workflows["Jens/projectbrain"] = PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " pull_request:\n", "" ) fixture._branch_protections["Jens/projectbrain"][0]["status_check_contexts"] = [ "Pull request / quality (pull_request)", "Additional required check", ] original_read = connector_instance.client.branch_protections read_count = 0 def drop_extra_context(repository: RegisteredRepository) -> list[dict[str, object]]: nonlocal read_count read_count += 1 if read_count == 3: fixture._branch_protections["Jens/projectbrain"][0]["status_check_contexts"].remove( "Additional required check" ) return original_read(repository) try: current = context() with patch.object( connector_instance.client, "branch_protections", side_effect=drop_extra_context, ): preview = connector_instance.branch_protection_preview( current, "projectbrain-repository" )["data"] self.assertTrue(preview["protectionOnlyAvailable"]) with self.assertRaisesRegex(GiteaError, "did not retain"): connector_instance.branch_protection_ensure( current, "projectbrain-repository", preview["protectionOnlyPlanHash"], apply_scope="protection_only", ) self.assertNotIn( "Additional required check", fixture._branch_protections["Jens/projectbrain"][0]["status_check_contexts"], ) finally: connector_instance.client.close() def test_projectbrain_protection_only_rejects_other_protection_changes(self) -> None: connector_instance, fixture = projectbrain_connector() fixture._managed_workflows["Jens/projectbrain"] = PROJECTBRAIN_VALIDATION_WORKFLOW.replace( " pull_request:\n", "" ) original_read = connector_instance.client.branch_protections read_count = 0 def changed_protection_response( repository: RegisteredRepository, ) -> list[dict[str, object]]: nonlocal read_count protections = original_read(repository) read_count += 1 if read_count == 3: protections[0]["required_approvals"] = 0 protections[0]["block_admin_merge_override"] = False return protections try: current = context() with patch.object( connector_instance.client, "branch_protections", side_effect=changed_protection_response, ): preview = connector_instance.branch_protection_preview( current, "projectbrain-repository" )["data"] with self.assertRaisesRegex(GiteaError, "did not retain"): connector_instance.branch_protection_ensure( current, "projectbrain-repository", preview["protectionOnlyPlanHash"], apply_scope="protection_only", ) self.assertEqual( fixture._managed_workflows["Jens/projectbrain"], PROJECTBRAIN_VALIDATION_WORKFLOW.replace(" pull_request:\n", ""), ) finally: connector_instance.client.close() def test_governance_update_never_relaxes_protected_main_push( self, ) -> None: fixture = FakeGiteaServer(deny_protected_workflow_writes=True) fixture._managed_workflows["acme/hub"] = "name: stale managed validation\n" original_protection = copy.deepcopy(fixture._branch_protections["acme/hub"][0]) connector_instance, _ = connector(fixture) try: current = context() preview = connector_instance.branch_protection_preview(current, "hub-repository")[ "data" ] self.assertEqual(preview["workflow"]["action"], "update") with self.assertRaisesRegex(GiteaError, "validated pull request"): connector_instance.branch_protection_ensure( current, "hub-repository", preview["planHash"] ) self.assertEqual( fixture._managed_workflows["acme/hub"], "name: stale managed validation\n" ) self.assertEqual(fixture._branch_protections["acme/hub"][0], original_protection) protection_writes = [body for body in fixture.recorded_bodies if "enable_push" in body] self.assertFalse(protection_writes) finally: connector_instance.client.close() def test_repository_create_retains_repository_when_governance_fails(self) -> None: connector_instance, fixture = connector() try: with patch.object( connector_instance, "branch_protection_ensure", side_effect=GiteaError( "GITEA_ACCESS_DENIED", "fixture denial", upstream_status=403 ), ): with self.assertRaises(GiteaError) as raised: connector_instance.repository_create(context(), "recover-created") self.assertEqual(raised.exception.code, "GITEA_REPOSITORY_GOVERNANCE_PENDING") self.assertEqual(raised.exception.upstream_status, 403) self.assertNotIn("DELETE", fixture.recorded_methods) self.assertEqual( connector_instance.repository_get(context(), "all-recover-created")["data"][ "fullName" ], "acme/recover-created", ) repaired = connector_instance.repository_create(context(), "recover-created")["data"] self.assertFalse(repaired["created"]) self.assertTrue(repaired["governanceReady"]) self.assertEqual(fixture.recorded_paths.count("/api/v1/user/repos"), 1) finally: connector_instance.client.close() def test_repository_create_repairs_an_existing_empty_repository(self) -> None: connector_instance, fixture = connector() fixture._repos["acme/projectbrain-empty"] = { "owner": {"login": "acme"}, "name": "projectbrain-empty", "full_name": "acme/projectbrain-empty", "description": "", "private": True, "empty": True, "default_branch": "", "html_url": "https://gitea.example/acme/projectbrain-empty", } try: result = connector_instance.repository_create( context(), "projectbrain-empty", "Initialized after an interrupted bootstrap.", True, True, "main", )["data"] self.assertFalse(result["created"]) self.assertTrue(result["repairedEmptyRepository"]) self.assertTrue(result["branchReady"]) self.assertEqual(result["defaultBranch"], "main") self.assertIn( "/api/v1/repos/acme/projectbrain-empty/contents/README.md", fixture.recorded_paths ) finally: connector_instance.client.close() def test_focused_repository_create_registers_in_primary_gitea_project(self) -> None: connector_instance, fixture = connector() connector_instance.repository_create_project = (PROJECT_ID, "hub") try: created = connector_instance.repository_create( context(OTHER_PROJECT_ID, "gitea-loop"), "focused-created" )["data"] self.assertTrue(created["created"]) self.assertEqual(created["repositoryRef"], "all-focused-created") self.assertEqual( connector_instance.repository_get(context(), created["repositoryRef"])["data"][ "fullName" ], "acme/focused-created", ) with self.assertRaisesRegex(GiteaError, "not registered"): connector_instance.repository_get( context(OTHER_PROJECT_ID, "gitea-loop"), created["repositoryRef"] ) self.assertNotIn("/api/v1/user", fixture.recorded_paths) finally: connector_instance.client.close() def test_file_delete_is_change_branch_scoped_and_sha_locked(self) -> None: connector_instance, fixture = connector() try: deleted = connector_instance.file_delete( context(), "hub-repository", "README.md", "chatgpt/remove-readme", "docs: remove obsolete readme", "d" * 40, )["data"] self.assertEqual(deleted["operation"], "deleted") self.assertEqual(fixture.recorded_methods, ["GET", "DELETE"]) with self.assertRaises(GiteaError): connector_instance.file_delete( context(), "hub-repository", "README.md", "main", "delete", "d" * 40 ) with self.assertRaises(GiteaError): connector_instance.file_delete( context(), "hub-repository", "README.md", "chatgpt/remove-readme", "delete", "stale", ) finally: connector_instance.client.close() def test_extended_read_and_review_surface_is_bounded(self) -> None: connector_instance, fixture = connector() try: current = context() fixture._branches.append( { "name": "codex/workflows", "commit": {"id": "e" * 40}, "protected": False, } ) commit = connector_instance.commit_get(current, "hub-repository", "main")["data"] self.assertTrue(commit["verified"]) self.assertEqual(commit["files"][0]["path"], "README.md") comparison = connector_instance.ref_compare( current, "hub-repository", "main", "codex/workflows" )["data"] self.assertEqual(comparison["totalCommits"], 1) health = connector_instance.repository_health(current, "hub-repository")["data"] self.assertTrue(health["defaultBranchProtected"]) self.assertTrue(health["validationWorkflowAvailable"]) runs = connector_instance.validation_list( current, "hub-repository", "codex/workflows", page=PageRequest(limit=10), )["data"]["items"] self.assertEqual(runs[0]["conclusion"], "success") review = connector_instance.change_review(current, "hub-repository", "codex/workflows")[ "data" ] self.assertTrue(review["readyToMerge"]) self.assertEqual(review["comparison"]["files"][0]["path"], "README.md") finally: connector_instance.client.close() def test_capability_connection_and_portfolio_surfaces_are_bounded(self) -> None: connector_instance, fixture = connector() try: current = context() capabilities = connector_instance.capabilities_get(current)["data"] self.assertEqual(fixture.recorded_paths, []) self.assertEqual(capabilities["version"], "1.14.0") self.assertEqual(capabilities["changeBranchPrefixes"], []) self.assertEqual(capabilities["workBranchPolicy"], "any-valid-non-default-branch") self.assertEqual(capabilities["toolCount"], 58) self.assertEqual(capabilities["registeredHandlerCount"], 58) self.assertEqual(capabilities["missingHandlers"], []) self.assertEqual(capabilities["extraHandlers"], []) self.assertEqual(capabilities["subsystems"]["runtime"], "READY") self.assertEqual(capabilities["subsystems"]["write"], "READY") self.assertIn("buildSha", capabilities) self.assertEqual(capabilities["riskCounts"], {"R1": 37, "R2": 18, "R3": 3}) self.assertEqual(len(capabilities["capabilityFingerprint"]), 64) self.assertFalse(capabilities["arbitraryExecution"]) connection = connector_instance.connection_check(current)["data"] self.assertTrue(connection["connected"]) self.assertEqual(connection["toolCount"], 58) self.assertEqual(connection["credentialMode"], "mounted-secret") selftest = connector_instance.selftest_run(current)["data"] self.assertEqual(selftest["status"], "PASS") self.assertTrue(selftest["probeOnly"]) self.assertEqual(selftest["mutationsAttempted"], 0) self.assertEqual( {item["name"] for item in selftest["checks"]}, {"handler-parity", "gitea-connection", "write-runtime", "managed-actions"}, ) repository_health = connector_instance.repository_health(current, "hub-repository")[ "data" ] portfolio = connector_instance.portfolio_health(current, ["hub-repository"])["data"] self.assertEqual(portfolio["summary"]["total"], 1) self.assertTrue(portfolio["items"][0]["healthy"]) self.assertEqual( portfolio["items"][0]["openPullRequestCount"], len(repository_health["openPullRequests"]), ) self.assertEqual( portfolio["items"][0]["safeBranchCount"], len(repository_health["changeBranches"]), ) self.assertEqual(portfolio["items"][0]["snapshotId"], repository_health["snapshotId"]) self.assertEqual( portfolio["items"][0]["sourceRevision"], repository_health["sourceRevision"] ) with self.assertRaisesRegex(GiteaError, "1-25 unique"): connector_instance.portfolio_health(current, ["hub-repository", "hub-repository"]) finally: connector_instance.client.close() def test_company_knowledge_search_and_fetch_are_citable_and_scope_bound(self) -> None: connector_instance, _ = connector() try: current = context() search = connector_instance.research_search(current, "ITWorx Hub") self.assertGreaterEqual(len(search["results"]), 1) result = search["results"][0] self.assertTrue(result["id"].startswith("gitea:")) self.assertIn("/src/commit/", result["url"]) fetched = connector_instance.research_fetch(current, result["id"]) self.assertEqual(fetched["id"], result["id"]) self.assertIn("ITWorx MCP Hub", fetched["text"]) self.assertEqual(fetched["metadata"]["repositoryRef"], "hub-repository") with self.assertRaisesRegex(GiteaError, "document ID"): connector_instance.research_fetch(current, "gitea:not-valid-base64") finally: connector_instance.client.close() def test_readiness_proves_upstream_access_and_caches_the_probe(self) -> None: connector_instance, fixture = connector() try: first = connector_instance.readiness() second = connector_instance.readiness() self.assertEqual(first, second) self.assertEqual(first["upstream"], "reachable") self.assertEqual(first["toolCount"], 58) self.assertEqual(len(first["capabilityFingerprint"]), 64) self.assertEqual(fixture.recorded_paths.count("/api/v1/repos/search"), 1) finally: connector_instance.client.close() unavailable, _ = connector(FakeGiteaServer(unsupported_search=True)) try: with self.assertRaises(GiteaError): unavailable.readiness() finally: unavailable.client.close() def test_workspace_is_durable_and_runs_only_fixed_profiles(self) -> None: connector_instance, fixture = connector() fixture._branches.append( {"name": "codex/workflows", "commit": {"id": "e" * 40}, "protected": False} ) try: current = context() first = connector_instance.workspace_status( current, "hub-repository", "codex/workflows" )["data"] second = connector_instance.workspace_status( current, "hub-repository", "codex/workflows" )["data"] self.assertEqual(first["workspaceId"], second["workspaceId"]) self.assertEqual(first["stateVersion"], second["stateVersion"]) self.assertEqual(first["execution"]["mode"], "managed-actions") self.assertFalse(first["execution"]["arbitraryCommands"]) self.assertEqual(first["pollAfterMs"], 0) self.assertTrue(first["terminal"]) self.assertRegex(first["validationStateVersion"], r"^[0-9a-f]{24}$") run = connector_instance.workspace_run( current, "hub-repository", "codex/workflows", "test" )["data"] self.assertEqual(run["workspaceId"], first["workspaceId"]) self.assertEqual(run["executionMode"], "managed-actions") self.assertIn(run["validationState"], {"queued", "running", "succeeded"}) with self.assertRaisesRegex(GiteaError, "not allowlisted"): connector_instance.workspace_run( current, "hub-repository", "codex/workflows", "shell" ) finally: connector_instance.client.close() def test_cross_repository_orchestration_is_previewed_locked_and_resumable(self) -> None: connector_instance, _ = connector() try: current = context() plan = connector_instance.orchestration_plan( current, ["hub-repository"], "dependency-refresh" )["data"] self.assertEqual(plan["items"][0]["branch"], "codex/dependency-refresh") with self.assertRaisesRegex(GiteaError, "plan changed"): connector_instance.orchestration_start( current, ["hub-repository"], "dependency-refresh", "0" * 24, ) started = connector_instance.orchestration_start( current, ["hub-repository"], "dependency-refresh", plan["orchestrationId"], )["data"] self.assertEqual(started["items"][0]["state"], "created") resumed = connector_instance.orchestration_start( current, ["hub-repository"], "dependency-refresh", plan["orchestrationId"], )["data"] self.assertEqual(resumed["items"][0]["state"], "resumed") with self.assertRaisesRegex(GiteaError, "branchSuffix"): connector_instance.orchestration_plan(current, ["hub-repository"], "../unsafe") finally: connector_instance.client.close() def test_reviewed_lifecycle_requires_sha_validation_merge_and_cleanup(self) -> None: connector_instance, fixture = connector() try: current = context() updated = connector_instance.pull_request_update( current, "hub-repository", 7, "e" * 40, title="Reviewed repository workflow", body="Validated and ready.", )["data"] self.assertTrue(updated["updated"]) with self.assertRaisesRegex(GiteaError, "head changed"): connector_instance.pull_request_merge( current, "hub-repository", 7, "d" * 40, "squash" ) merged = connector_instance.pull_request_merge( current, "hub-repository", 7, "e" * 40, "squash" )["data"] self.assertTrue(merged["merged"]) fixture._branches.append( { "name": "codex/workflows", "commit": {"id": "e" * 40}, "protected": False, } ) deleted = connector_instance.branch_delete( current, "hub-repository", "codex/workflows", "e" * 40 )["data"] self.assertTrue(deleted["deleted"]) self.assertNotIn("codex/workflows", {item["name"] for item in fixture._branches}) merge_body = next( body for body in fixture.recorded_bodies if body.get("do") == "squash" ) self.assertNotIn("Do", merge_body) self.assertFalse(merge_body["force_merge"]) self.assertFalse(merge_body["delete_branch_after_merge"]) finally: connector_instance.client.close() def test_pull_request_close_is_sha_locked_and_closes_only_an_open_pull_request(self) -> None: connector_instance, fixture = connector() try: current = context() with self.assertRaisesRegex(GiteaError, "repository is not registered"): connector_instance.pull_request_close( context(OTHER_PROJECT_ID, "other"), "hub-repository", 7, "e" * 40 ) with self.assertRaisesRegex(GiteaError, "head changed"): connector_instance.pull_request_close(current, "hub-repository", 7, "d" * 40) closed = connector_instance.pull_request_close(current, "hub-repository", 7, "e" * 40)[ "data" ] self.assertTrue(closed["closed"]) self.assertEqual(closed["state"], "closed") self.assertEqual(closed["headSha"], "e" * 40) self.assertIn({"state": "closed"}, fixture.recorded_bodies) with self.assertRaisesRegex(GiteaError, "only an open pull request"): connector_instance.pull_request_close(current, "hub-repository", 7, "e" * 40) finally: connector_instance.client.close() def test_closed_unmerged_pull_request_branch_can_be_deleted_with_exact_sha(self) -> None: connector_instance, fixture = connector() try: fixture._branches.append( {"name": "codex/workflows", "commit": {"id": "e" * 40}, "protected": False} ) connector_instance.pull_request_close(context(), "hub-repository", 7, "e" * 40) deleted = connector_instance.branch_delete( context(), "hub-repository", "codex/workflows", "e" * 40 )["data"] self.assertTrue(deleted["deleted"]) self.assertEqual(deleted["cleanupDisposition"], "closed-unmerged") self.assertEqual(deleted["closedPullRequest"], 7) self.assertEqual(deleted["preconditionMode"], "optimistic-double-read") finally: connector_instance.client.close() def test_branch_delete_rejects_open_pr_and_unrelated_same_sha(self) -> None: connector_instance, fixture = connector() try: fixture._branches.extend( [ {"name": "codex/workflows", "commit": {"id": "e" * 40}, "protected": False}, {"name": "codex/unrelated", "commit": {"id": "e" * 40}, "protected": False}, ] ) with self.assertRaisesRegex(GiteaError, "open pull request"): connector_instance.branch_delete( context(), "hub-repository", "codex/workflows", "e" * 40 ) connector_instance.pull_request_close(context(), "hub-repository", 7, "e" * 40) with self.assertRaisesRegex(GiteaError, "merged or closed pull request"): connector_instance.branch_delete( context(), "hub-repository", "codex/unrelated", "e" * 40 ) finally: connector_instance.client.close() def test_gitea_125_merge_uses_legacy_strategy_field_without_forcing(self) -> None: fixture = FakeGiteaServer(gitea_version="1.25.5") connector_instance, _ = connector(fixture) try: merged = connector_instance.pull_request_merge( context(), "hub-repository", 7, "e" * 40, "squash" )["data"] self.assertTrue(merged["merged"]) merge_body = next( body for body in fixture.recorded_bodies if body.get("Do") == "squash" ) self.assertNotIn("do", merge_body) self.assertFalse(merge_body["force_merge"]) self.assertFalse(merge_body["merge_when_checks_succeed"]) self.assertFalse(merge_body["delete_branch_after_merge"]) self.assertEqual(fixture.recorded_paths.count("/api/v1/version"), 1) finally: connector_instance.client.close() def test_unknown_gitea_version_fails_closed_before_merge_write(self) -> None: fixture = FakeGiteaServer(gitea_version="1.28.0") connector_instance, _ = connector(fixture) try: with self.assertRaisesRegex( GiteaError, "requires an identified 1.14, 1.25, 1.26, 1.27, or 28.x", ) as raised: connector_instance.pull_request_merge( context(), "hub-repository", 7, "e" * 40, "squash" ) self.assertEqual(raised.exception.code, "GITEA_VERSION_UNSUPPORTED") self.assertNotIn("/api/v1/repos/acme/hub/pulls/7/merge", fixture.recorded_paths) finally: connector_instance.client.close() def test_unrelated_merge_405_fails_closed_without_a_schema_retry(self) -> None: fixture = FakeGiteaServer(deny_merge_transition=True) connector_instance, _ = connector(fixture) try: with self.assertRaises(GiteaError) as raised: connector_instance.pull_request_merge( context(), "hub-repository", 7, "e" * 40, "squash" ) self.assertEqual(raised.exception.code, "GITEA_UPSTREAM_MERGE_REJECTED") self.assertEqual( fixture.recorded_paths.count("/api/v1/repos/acme/hub/pulls/7/merge"), 1 ) merge_body = next(body for body in fixture.recorded_bodies if "do" in body) self.assertNotIn("Do", merge_body) finally: connector_instance.client.close() def test_account_discovery_adds_future_repositories_without_changing_existing_refs( self, ) -> None: fixture = FakeGiteaServer() fixture._repos["acme/future"] = { "owner": {"login": "acme"}, "name": "future", "full_name": "acme/future", "description": "Future project", "private": True, "default_branch": "main", "updated_at": "2026-08-25T10:00:00Z", } connector_instance, _ = connector(fixture) connector_instance.discovery_projects = {PROJECT_ID: "hub"} try: items = connector_instance.repository_list(context(), page=PageRequest(limit=100))[ "data" ]["items"] refs = {item["repositoryRef"] for item in items} self.assertIn("hub-repository", refs) self.assertIn("all-future", refs) self.assertIn("/api/v1/repos/search", fixture.recorded_paths) self.assertIn("/api/v1/user/repos", fixture.recorded_paths) finally: connector_instance.client.close() def test_account_discovery_keeps_private_results_when_user_repo_list_is_denied(self) -> None: fixture = FakeGiteaServer(deny_user_repositories=True) connector_instance, _ = connector(fixture) connector_instance.discovery_projects = {PROJECT_ID: "hub"} try: items = connector_instance.repository_list(context(), page=PageRequest(limit=100))[ "data" ]["items"] self.assertIn("hub-repository", {item["repositoryRef"] for item in items}) self.assertIn("/api/v1/repos/search", fixture.recorded_paths) self.assertIn("/api/v1/user/repos", fixture.recorded_paths) finally: connector_instance.client.close() def test_discovery_refs_are_deterministic_for_same_named_future_repositories(self) -> None: repositories = [ {"owner": {"login": "zeta"}, "name": "shared", "private": True}, {"owner": {"login": "alpha"}, "name": "shared", "private": True}, ] first = GiteaRepositoryRegistry() second = GiteaRepositoryRegistry() first.add_discovered(PROJECT_ID, "hub", repositories) second.add_discovered(PROJECT_ID, "hub", list(reversed(repositories))) first_refs = {item.qualified_name: item.repository_ref for item in first.list(PROJECT_ID)} second_refs = {item.qualified_name: item.repository_ref for item in second.list(PROJECT_ID)} self.assertEqual(first_refs, second_refs) self.assertEqual(first_refs["alpha/shared"], "all-alpha-shared") self.assertEqual(first_refs["zeta/shared"], "all-zeta-shared") def test_write_policy_accepts_any_non_default_branch_and_rejects_unsafe_targets(self) -> None: connector_instance, fixture = connector() try: current = context() created = connector_instance.branch_create( current, "hub-repository", "m15-backup-restore-dr", "main" )["data"] self.assertEqual(created["name"], "m15-backup-restore-dr") pull = connector_instance.pull_request_create( current, "hub-repository", "m15-backup-restore-dr", "main", "M15 backup and restore", )["data"] self.assertEqual(pull["headRef"], "m15-backup-restore-dr") for branch in ("main", "feature/../main", "feature/x.lock"): with self.subTest(branch=branch), self.assertRaises(GiteaError): connector_instance.branch_create(current, "hub-repository", branch, "main") with self.assertRaises(GiteaError): connector_instance.file_update( current, "hub-repository", "README.md", "chatgpt/safe", "content", "message", "not-a-sha", ) with self.assertRaises(GiteaError): connector_instance.file_create( current, "hub-repository", "../secret", "chatgpt/safe", "content", "message", ) self.assertEqual(fixture.recorded_methods, ["GET", "POST", "POST", "GET"]) finally: connector_instance.client.close() def test_write_redirect_is_never_followed(self) -> None: connector_instance, fixture = connector( FakeGiteaServer(redirect_to="https://gitea.test/login") ) try: with self.assertRaisesRegex(GiteaError, "write redirects are not followed"): connector_instance.issue_create(context(), "hub-repository", "Title") self.assertEqual(fixture.recorded_methods, ["POST"]) finally: connector_instance.client.close() def test_write_methods_fail_closed_without_a_separate_write_client(self) -> None: connector_instance, fixture = connector() connector_instance.write_client = None try: with self.assertRaisesRegex(GiteaError, "not enabled"): connector_instance.issue_create(context(), "hub-repository", "Title") self.assertEqual(fixture.recorded_methods, []) self.assertTrue(connector_instance.health()["readOnly"]) self.assertEqual(connector_instance.readiness()["writeMode"], "disabled") finally: connector_instance.client.close() def test_gitea_failure_does_not_replace_knowledge_surface(self) -> None: connector_instance, _ = connector(FakeGiteaServer(redirect_to="http://169.254.169.254/")) try: knowledge = KnowledgeConnector(index=InMemoryKnowledgeIndex()) self.assertEqual(knowledge.readiness()["status"], "ready") with self.assertRaises(GiteaError): connector_instance.repository_get(context(), "hub-repository") self.assertEqual(knowledge.health()["status"], "healthy") finally: connector_instance.client.close() def test_secret_reference_and_transport_policy_are_strict(self) -> None: with self.assertRaises(ValueError): GiteaSettings(base_url="http://gitea.test", token_reference="raw-token") # noqa: S106 with self.assertRaises(ValueError): GiteaSettings( base_url="https://user:pass@gitea.test", token_reference="docker-secret://gitea", # noqa: S106 ) def test_validation_workflows_use_an_isolated_python_environment(self) -> None: local = (ROOT / ".gitea/workflows/chatgpt-validation.yml").read_text(encoding="utf-8") scoped = (ROOT / ".gitea/scoped_workflows/chatgpt-validation.yml").read_text( encoding="utf-8" ) self.assertEqual(local, scoped) self.assertIn('python -m venv "${RUNNER_TEMP}/chatgpt-uv"', local) self.assertIn('UV_PROJECT_ENVIRONMENT="${RUNNER_TEMP}/chatgpt-project-venv"', local) self.assertNotIn("--break-system-packages", local) def test_managed_validation_is_pull_request_only_and_bounds_python_discovery(self) -> None: self.assertIn(" pull_request:", MANAGED_VALIDATION_WORKFLOW) self.assertIn(" workflow_dispatch:", MANAGED_VALIDATION_WORKFLOW) self.assertNotIn(" push:", MANAGED_VALIDATION_WORKFLOW) self.assertIn("git ls-files -z '*.py'", MANAGED_VALIDATION_WORKFLOW) self.assertLess( MANAGED_VALIDATION_WORKFLOW.index( 'export PATH="${RUNNER_TEMP}/managed-python/bin:${PATH}"' ), MANAGED_VALIDATION_WORKFLOW.index("if [[ -f package.json ]]"), ) self.assertIn("'^(<<<<<<< |=======$|>>>>>>> )'", MANAGED_VALIDATION_WORKFLOW) self.assertNotIn("'^(<<<<<<<|=======|>>>>>>>)'", MANAGED_VALIDATION_WORKFLOW) self.assertNotIn("python -m compileall", MANAGED_VALIDATION_WORKFLOW) self.assertNotIn("--all-extras", MANAGED_VALIDATION_WORKFLOW) self.assertIn("if: ${{ hashFiles('*.sln') != '' }}", MANAGED_VALIDATION_WORKFLOW) self.assertIn( "uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4", MANAGED_VALIDATION_WORKFLOW, ) self.assertIn("python_tests_ran=1", MANAGED_VALIDATION_WORKFLOW) self.assertIn("run_node_test=0", MANAGED_VALIDATION_WORKFLOW) self.assertIn("(?:pytest|unittest)", MANAGED_VALIDATION_WORKFLOW) def test_governance_file_commit_skips_unrelated_push_workflows(self) -> None: connector_instance, fixture = connector() fixture._managed_workflows.clear() try: preview = connector_instance.branch_protection_preview(context(), "hub-repository")[ "data" ] connector_instance.branch_protection_ensure( context(), "hub-repository", preview["planHash"] ) workflow_commits = [ str(body.get("message", "")) for body in fixture.recorded_bodies if body.get("content") ] self.assertTrue(workflow_commits) self.assertTrue(all("[skip ci]" in message for message in workflow_commits)) finally: connector_instance.client.close() def test_repository_engineer_eval_contract_references_published_safe_tools(self) -> None: connector_instance, _ = connector() try: published = { tool.canonical_name for tool in connector_instance.tools() + connector_instance.write_tools() } payload = json.loads( (ROOT / "evals/gitea-repository-engineer.json").read_text(encoding="utf-8") ) self.assertGreaterEqual(len(payload["cases"]), 8) for case in payload["cases"]: for tool in case.get("expectedTools", []): self.assertIn(tool, published) self.assertTrue( all(isinstance(tool, str) for tool in case.get("forbiddenTools", [])) ) self.assertNotIn("shell.execute", published) self.assertNotIn("gitea.repository.delete", published) destructive = {"gitea.branch.delete"} confirmation_cases = { tool for case in payload["cases"] if case.get("requiresConfirmation") for tool in case.get("expectedTools", []) } self.assertTrue(destructive.issubset(confirmation_cases)) finally: connector_instance.client.close() def test_validation_failure_extraction_is_bounded_and_sanitized(self) -> None: connector_instance, fixture = connector() fixture._action_run.update({"status": "completed", "conclusion": "failure"}) fixture._action_job.update( { "status": "completed", "conclusion": "failure", "steps": [ {"name": "Unit tests", "conclusion": "failure"}, ], } ) fixture._action_job_logs = ( "prepare\nRun python -m pytest\ncollecting\nERROR test_example failed\n" "process exited with code 2\nafter\n" ) try: result = connector_instance.validation_failure_get(context(), "hub-repository", 42) data = result["data"] self.assertEqual(data["failureCount"], 1) self.assertFalse(data["fullLogsIncluded"]) failure = data["failures"][0] self.assertEqual(failure["step"], "Unit tests") self.assertEqual(failure["exitCode"], 2) self.assertEqual(failure["command"], "Run python -m pytest") self.assertLessEqual(len(failure["relevantLogs"]), 100) self.assertNotIn("fixture-token", json.dumps(result)) finally: connector_instance.client.close() def test_validation_failure_extraction_enforces_aggregate_budget_and_inline_redaction( self, ) -> None: connector_instance, fixture = connector() fixture._action_run.update({"status": "completed", "conclusion": "failure"}) jobs = [ { "id": index + 1, "name": f"failure-{index}", "status": "completed", "conclusion": "failure", "steps": [{"name": "test", "conclusion": "failure"}], } for index in range(30) ] logs = "\n".join( f"ERROR failure line {index} GITEA_TOKEN=opaquecredentialvalue{index}" for index in range(150) ) try: with ( patch.object(connector_instance.client, "action_run_jobs", return_value=jobs), patch.object( connector_instance.client, "action_job_logs", return_value=(logs, False), ), ): result = connector_instance.validation_failure_get(context(), "hub-repository", 42) data = result["data"] self.assertLessEqual(data["failureCount"], 20) self.assertLessEqual(sum(len(item["relevantLogs"]) for item in data["failures"]), 100) rendered = json.dumps(result) self.assertNotIn("opaquecredentialvalue", rendered) self.assertIn("", rendered) self.assertTrue(result["meta"]["truncated"]) self.assertLess(len(rendered.encode()), 262_144) finally: connector_instance.client.close() def test_change_reconcile_and_sha_locked_pull_request_sync(self) -> None: connector_instance, fixture = connector() fixture._branches.append( {"name": "codex/workflows", "commit": {"id": "e" * 40}, "protected": False} ) try: reconciled = connector_instance.change_reconcile( context(), "hub-repository", "codex/workflows" )["data"] self.assertEqual(reconciled["recommendedNextAction"], "review-and-merge") self.assertFalse(reconciled["mutationPerformed"]) preview = connector_instance.pull_request_sync( context(), "hub-repository", 7, "e" * 40, "a" * 40, "rebase", True, )["data"] self.assertFalse(preview["synced"]) self.assertEqual(preview["conflictFiles"], []) self.assertFalse(preview["conflictDetailsAvailable"]) synced = connector_instance.pull_request_sync( context(), "hub-repository", 7, "e" * 40, "a" * 40, "rebase", False, )["data"] self.assertTrue(synced["synced"]) self.assertTrue(synced["validationRequired"]) self.assertEqual(synced["newHeadSha"], "d" * 40) self.assertEqual(synced["preconditionMode"], "optimistic-double-read") self.assertTrue( any(path.endswith("/pulls/7/update") for path in fixture.recorded_paths) ) with self.assertRaises(GiteaError) as raised: connector_instance.pull_request_sync( context(), "hub-repository", 7, "e" * 40, "a" * 40, "merge", False, ) self.assertEqual(raised.exception.code, "GITEA_CONFLICT") self.assertEqual(raised.exception.actual_state, "d" * 40) finally: connector_instance.client.close() def test_change_reconcile_detects_outdated_branch_on_gitea_127(self) -> None: connector_instance, fixture = connector() fixture._branches.append( {"name": "codex/workflows", "commit": {"id": "e" * 40}, "protected": False} ) fixture._reverse_compare_commits = [ {"sha": "d" * 40, "commit": {"message": "Advance default branch"}} ] try: reconciled = connector_instance.change_reconcile( context(), "hub-repository", "codex/workflows" )["data"] self.assertEqual(reconciled["branchBehindBy"], 1) self.assertEqual(reconciled["recommendedNextAction"], "sync-or-resolve-conflicts") self.assertTrue(reconciled["validationRequired"]) finally: connector_instance.client.close() def test_pull_request_sync_fails_closed_when_state_moves_during_preparation(self) -> None: connector_instance, fixture = connector() current = copy.deepcopy(fixture._pulls[0]) moved = copy.deepcopy(current) moved["head"]["sha"] = "f" * 40 update_path = "/api/v1/repos/acme/hub/pulls/7/update" try: with patch.object( connector_instance.client, "pull_request", side_effect=[current, moved], ): with self.assertRaises(GiteaError) as raised: connector_instance.pull_request_sync( context(), "hub-repository", 7, "e" * 40, "a" * 40, "merge", False, ) self.assertEqual(raised.exception.code, "GITEA_CONCURRENT_MODIFICATION") self.assertTrue(raised.exception.safe_to_retry) self.assertFalse(any(path.startswith(update_path) for path in fixture.recorded_paths)) finally: connector_instance.client.close() def test_change_review_soak_stays_bounded_and_runtime_remains_usable(self) -> None: connector_instance, fixture = connector() fixture._branches.append( {"name": "codex/workflows", "commit": {"id": "e" * 40}, "protected": False} ) fixture._compare_commits = [ { "sha": f"{index:040x}", "commit": {"message": "bounded review " + ("x" * 5000)}, } for index in range(60) ] try: for _ in range(100): review = connector_instance.change_review( context(), "hub-repository", "codex/workflows" ) self.assertTrue(review["data"]["comparison"]["truncated"]) self.assertLess(len(json.dumps(review).encode()), 524_288) capabilities = connector_instance.capabilities_get(context())["data"] self.assertEqual(capabilities["toolCount"], 58) self.assertEqual(capabilities["subsystems"]["session"], "RESUMABLE") finally: connector_instance.client.close() def test_change_review_concurrent_drift_is_recoverable(self) -> None: connector_instance, fixture = connector() fixture._branches.append( {"name": "codex/workflows", "commit": {"id": "e" * 40}, "protected": False} ) moved = copy.deepcopy(fixture._pulls[0]) moved["head"]["sha"] = "f" * 40 try: with patch.object(connector_instance.client, "pull_request", return_value=moved): with self.assertRaises(GiteaError) as raised: connector_instance.change_review(context(), "hub-repository", "codex/workflows") error = raised.exception self.assertEqual(error.code, "GITEA_CONCURRENT_MODIFICATION") self.assertTrue(error.retryable) self.assertTrue(error.safe_to_retry) self.assertEqual(error.expected_state, "e" * 40) self.assertEqual(error.actual_state, "f" * 40) finally: connector_instance.client.close() def test_resilient_mcp_server_preserves_structured_gitea_error(self) -> None: from mcp.shared.exceptions import MCPError from services.runtime.mcp_server import ResilientMCPServer server = ResilientMCPServer("resilience-test") @server.tool(name="gitea.test.error") async def failing_tool() -> dict[str, object]: raise GiteaError( "GITEA_UPSTREAM_UNAVAILABLE", "Gitea is temporarily unavailable", retryable=True, safe_to_retry=True, upstream_status=503, ) with self.assertRaises(MCPError) as raised: asyncio.run(server.call_tool("gitea.test.error", {})) self.assertEqual(raised.exception.code, -32050) self.assertEqual(raised.exception.data["operation"], "gitea.test.error") self.assertEqual(raised.exception.data["upstreamStatus"], 503) self.assertTrue(raised.exception.data["safeToRetry"]) def test_runtime_supervisor_recovers_after_a_following_successful_request(self) -> None: from packages.hub_runtime.supervisor import RuntimeSupervisor supervisor = RuntimeSupervisor() supervisor.started() supervisor.failed("UnexpectedFailure", fatal=True) self.assertEqual(supervisor.snapshot()["circuitState"], "DEGRADED") supervisor.started() supervisor.completed() recovered = supervisor.snapshot() self.assertEqual(recovered["circuitState"], "CLOSED") self.assertEqual(recovered["recoveryCount"], 1) self.assertEqual(recovered["lastFatalErrorCode"], "UnexpectedFailure") def test_gitea_get_retries_transient_failures_but_write_does_not(self) -> None: calls: list[str] = [] def handle(request: httpx.Request) -> httpx.Response: calls.append(request.method) if request.method == "GET" and calls.count("GET") < 3: return httpx.Response(503, json={"message": "temporary"}, request=request) if request.method == "POST": return httpx.Response(503, json={"message": "temporary"}, request=request) return httpx.Response( 200, json={"name": "hub", "private": True, "default_branch": "main"}, request=request, ) settings = GiteaSettings( base_url="http://gitea.test", token_reference="docker-secret://gitea_mcp_token", # noqa: S106 allow_insecure_http_for_tests=True, ) client = GiteaClient( settings, StaticTokenProvider("fixture-token"), transport=httpx.MockTransport(handle), ) repository = RegisteredRepository( repository_ref="hub-repository", project_id=PROJECT_ID, owner="acme", name="hub", source_uri="itworx-git://hub/hub-repository", private=True, ) try: with patch("packages.connector_kit.gitea.time.sleep"): self.assertEqual(client.repository(repository)["name"], "hub") with self.assertRaises(GiteaError) as raised: client.create_issue(repository, "title", "body") self.assertEqual(calls, ["GET", "GET", "GET", "POST"]) self.assertTrue(raised.exception.retryable) self.assertFalse(raised.exception.safe_to_retry) envelope = raised.exception.envelope(operation="gitea.issue.create") self.assertEqual(envelope["subsystem"], "upstream_gitea") self.assertFalse(envelope["safeToRetry"]) finally: client.close() def test_gitea_same_origin_redirect_get_keeps_structured_retry_semantics(self) -> None: calls = 0 def handle(request: httpx.Request) -> httpx.Response: nonlocal calls calls += 1 if calls == 1: return httpx.Response( 307, headers={"location": str(request.url)}, request=request, ) if calls < 4: raise httpx.ConnectError("temporary", request=request) return httpx.Response( 200, json={"name": "hub", "private": True, "default_branch": "main"}, request=request, ) client = GiteaClient( GiteaSettings( base_url="http://gitea.test", token_reference="docker-secret://gitea_mcp_token", # noqa: S106 allow_insecure_http_for_tests=True, ), StaticTokenProvider("fixture-token"), transport=httpx.MockTransport(handle), ) repository = RegisteredRepository( repository_ref="hub-repository", project_id=PROJECT_ID, owner="acme", name="hub", source_uri="itworx-git://hub/hub-repository", private=True, ) try: with patch("packages.connector_kit.gitea.time.sleep"): self.assertEqual(client.repository(repository)["name"], "hub") self.assertEqual(calls, 4) finally: client.close() @unittest.skipUnless( os.getenv("GITEA_LIVE_TESTS") == "1", "requires explicitly enabled configured Gitea" ) def test_live_configured_gitea(self) -> None: self.skipTest("Live acceptance is environment-owned and requires external credentials") if __name__ == "__main__": unittest.main()