Remove command permission lookup

This commit is contained in:
2026-07-19 18:38:38 +02:00
parent 276b5590b5
commit f68d7cbc32
4 changed files with 6 additions and 48 deletions
+3 -4
View File
@@ -15,9 +15,9 @@ one persistent Docker Compose service on the same Docker network as Gitea.
| PR | `/agent iterate [message]` | Resume an agent implementation and its reviewer once. | | PR | `/agent iterate [message]` | Resume an agent implementation and its reviewer once. |
| PR | `/agent fix [message]` | Start a fresh one-shot fix session and push one commit. | | PR | `/agent fix [message]` | Start a fresh one-shot fix session and push one commit. |
Only repository writers and administrators can enqueue commands. Each command Anyone who can comment on an issue or pull request can enqueue commands. Each
gets separate queued and started comments. Final plans, PR results, failures, command gets separate queued and started comments. Final plans, PR results,
and remaining review findings are posted separately. failures, and remaining review findings are posted separately.
## Deploy ## Deploy
@@ -83,4 +83,3 @@ uv run pytest
The tests fail if any tracked Python file exceeds 250 lines. Prompts and JSON The tests fail if any tracked Python file exceeds 250 lines. Prompts and JSON
schemas live outside Python so orchestration modules remain small and readable. schemas live outside Python so orchestration modules remain small and readable.
-7
View File
@@ -34,13 +34,6 @@ class GiteaClient:
async def close(self) -> None: async def close(self) -> None:
await self.client.aclose() await self.client.aclose()
async def has_write_permission(self, owner: str, repo: str, username: str) -> bool:
response = await self._request(
"GET", f"/repos/{owner}/{repo}/collaborators/{username}/permission"
)
permission = str(response.json().get("permission", "")).lower()
return permission in {"write", "admin", "owner"}
async def repository(self, owner: str, repo: str) -> RepositoryInfo: async def repository(self, owner: str, repo: str) -> RepositoryInfo:
data = (await self._request("GET", f"/repos/{owner}/{repo}")).json() data = (await self._request("GET", f"/repos/{owner}/{repo}")).json()
return RepositoryInfo( return RepositoryInfo(
-13
View File
@@ -70,19 +70,6 @@ async def _handle_command(container: Any, event: CommandEvent) -> Response:
if not event.body.strip().startswith("/agent"): if not event.body.strip().startswith("/agent"):
return Response(status_code=status.HTTP_204_NO_CONTENT) return Response(status_code=status.HTTP_204_NO_CONTENT)
log.info("agent command received", extra=extra) log.info("agent command received", extra=extra)
permitted = await container.gitea.has_write_permission(
event.repo_owner, event.repo_name, event.requester
)
if not permitted:
log.warning("agent command rejected: insufficient permission", extra=extra)
if await container.storage.record_delivery(event.delivery_id, event.comment_id):
await container.gitea.create_comment(
event.repo_owner,
event.repo_name,
event.issue_number,
"Agent command rejected: repository write permission is required.",
)
return Response(status_code=status.HTTP_202_ACCEPTED)
try: try:
command = parse_command(event.body) command = parse_command(event.body)
except CommandError as exc: except CommandError as exc:
+3 -24
View File
@@ -29,13 +29,9 @@ class FakeStorage:
class FakeGitea: class FakeGitea:
def __init__(self, permitted: bool = True) -> None: def __init__(self) -> None:
self.permitted = permitted
self.comments: list[str] = [] self.comments: list[str] = []
async def has_write_permission(self, *_args):
return self.permitted
async def create_comment(self, _owner, _repo, _number, body): async def create_comment(self, _owner, _repo, _number, body):
self.comments.append(body) self.comments.append(body)
return len(self.comments) return len(self.comments)
@@ -76,25 +72,8 @@ async def test_authorized_command_is_queued() -> None:
assert "queued" in gitea.comments[0] assert "queued" in gitea.comments[0]
async def test_unauthorized_command_is_rejected_and_deduplicated() -> None: async def test_non_command_is_ignored() -> None:
storage = FakeStorage() container = SimpleNamespace(storage=FakeStorage(), gitea=FakeGitea())
gitea = FakeGitea(permitted=False)
container = SimpleNamespace(storage=storage, gitea=gitea)
event = _event_from_payload("delivery", payload("/agent implement"))
assert event is not None
await _handle_command(container, event)
await _handle_command(container, event)
assert storage.jobs == []
assert len(gitea.comments) == 1
assert "write permission" in gitea.comments[0]
async def test_non_command_does_not_query_permission() -> None:
class ExplodingGitea(FakeGitea):
async def has_write_permission(self, *_args):
raise AssertionError("permission lookup should not run")
container = SimpleNamespace(storage=FakeStorage(), gitea=ExplodingGitea())
event = _event_from_payload("delivery", payload("ordinary discussion")) event = _event_from_payload("delivery", payload("ordinary discussion"))
assert event is not None assert event is not None
response = await _handle_command(container, event) response = await _handle_command(container, event)