"""Atlas route and Git protocol contracts for the Hermes SCM broker.""" from __future__ import annotations import pytest from testing.tests.test_hermes_scm_broker_support import ( Response, _load, _receive_command, ) @pytest.mark.parametrize( "target", [ "/api/v1/repos/titan/cassandra/pulls/1/merge", "/api/v1/repos/titan/cassandra/pulls/1/reviews", "/api/v1/admin/users", "/git/evil/cassandra.git/info/refs?service=git-upload-pack", "/git/atlas/cassandra.git/hooks", "/git/atlas/cassandra.git/git-receive-pack?force=true", "/git/atlas/cassandra.git/info/refs?service=git-upload-pack\nignored", "/git/atlas/cassandra.git/info/refs?service=git-upload-pack\tignored", "/git/atlas/cassandra.git/info/refs?service=git-upload-pack#fragment", ], ) def test_broker_rejects_privileged_or_non_atlas_routes(target: str): broker = _load("scm_broker") with pytest.raises(broker.PolicyError): broker._git_target(target) def test_broker_metadata_boundary_reuses_explicit_read_allowlist(): api = _load("gitea_api") assert ( api.authorize_request("GET", "/api/v1/repos/titan/cassandra/pulls/1", None) == "pull" ) for path in ( "/api/v1/repos/titan/cassandra/pulls/1/merge", "/api/v1/repos/titan/cassandra/pulls/1/reviews", "/api/v1/repos/titan/cassandra/hooks", "/api/v1/admin/users", ): with pytest.raises(api.PolicyError): api.authorize_request("GET", path, None) def test_receive_pack_allows_only_new_namespaced_feature_branch(): broker = _load("scm_broker") zero = b"0" * 40 commit = b"1" * 40 broker._validate_receive_pack( _receive_command(zero, commit, b"refs/heads/hermes/focused-fix"), "runtime-sentinel", ) for old, new, ref in ( (commit, b"2" * 40, b"refs/heads/hermes/focused-fix"), (commit, zero, b"refs/heads/hermes/focused-fix"), (zero, commit, b"refs/heads/main"), (zero, commit, b"refs/heads/master"), (zero, commit, b"refs/tags/release"), ): with pytest.raises(broker.PolicyError): broker._validate_receive_pack( _receive_command(old, new, ref), "runtime-sentinel" ) def test_git_proxy_uses_fixed_origin_and_never_reflects_credential(): broker = _load("scm_broker") seen = [] def opener(request, timeout): seen.append((request, timeout)) return Response( b"git-result", content_type="application/x-git-upload-pack-result", ) result = broker._upstream_git_request( "/titan/cassandra.git/git-upload-pack", method="POST", body=b"request", content_type="application/x-git-upload-pack-request", expected_type="application/x-git-upload-pack-result", token="runtime-sentinel", opener=opener, ) assert result == b"git-result" request = seen[0][0] assert request.full_url == ( "https://scm.bstein.dev/titan/cassandra.git/git-upload-pack" ) assert b"runtime-sentinel" not in request.data assert "runtime-sentinel" not in request.full_url with pytest.raises(broker.PolicyError, match="credential material"): broker._upstream_git_request( "/titan/cassandra.git/git-upload-pack", method="POST", body=b"request", content_type="application/x-git-upload-pack-request", expected_type="application/x-git-upload-pack-result", token="runtime-sentinel", opener=lambda *_a, **_k: Response( b"runtime-sentinel", content_type="application/x-git-upload-pack-result", ), ) encoded = broker._credential_forms("runtime-sentinel")[1] with pytest.raises(broker.PolicyError, match="credential material"): broker._upstream_git_request( "/titan/cassandra.git/git-upload-pack", method="POST", body=b"request", content_type="application/x-git-upload-pack-request", expected_type="application/x-git-upload-pack-result", token="runtime-sentinel", opener=lambda *_a, **_k: Response( b"Authorization: Basic " + encoded, content_type="application/x-git-upload-pack-result", ), ) @pytest.mark.parametrize("status", [201, 202, 204, 206, 301, 302, 307, 308]) def test_git_proxy_requires_exact_http_200(status: int): broker = _load("scm_broker") with pytest.raises(broker.PolicyError, match="unexpected HTTP status"): broker._upstream_git_request( "/titan/cassandra.git/git-upload-pack", method="POST", body=b"request", content_type="application/x-git-upload-pack-request", expected_type="application/x-git-upload-pack-result", token="runtime-sentinel", opener=lambda *_a, **_k: Response( b"result", status=status, content_type="application/x-git-upload-pack-result", ), )