From 6116ec4e5a1c08a0fc19e6d216ffe10700a3e09e Mon Sep 17 00:00:00 2001 From: Erik Simon Date: Sun, 23 Aug 2026 08:18:11 +0200 Subject: [PATCH] gitea: name the hermes hook and send only PR comments Names the webhook "PR comments Hermes" (gitea's CreateHookOption/EditHookOption both carry an optional `name`, so it survives the create and the update path) and narrows it from all 26 event types to pull_request_comment alone. Gitea sends pull_request_comment distinctly from issue_comment, so the hook now covers comments on pull requests and nothing else. Hermes would have dropped the rest anyway -- its route filters on X-GitHub-Event before any LLM call -- so this is defence in depth rather than the only gate, but it keeps traffic that can never be acted on from crossing the wire and reaching the agent's process at all. The tradeoff is that event selection now lives on both sides: a second Hermes route needs its event adding here as well as being subscribed. That is the right way round for a single-purpose hook, and the comment says so. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01S94o42aQ8VkBmEWvDem5xa --- services/dev/gitea.nix | 43 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/services/dev/gitea.nix b/services/dev/gitea.nix index 0b5c51b..c2fdc84 100644 --- a/services/dev/gitea.nix +++ b/services/dev/gitea.nix @@ -21,38 +21,20 @@ let # nothing she does lands without darman clicking merge. lunaRepos = [ "darman/homelab" ]; - # Send every Gitea event to Hermes on mars. Hermes owns the decision about - # which events matter and what to do with them: its route filters on - # X-GitHub-Event and drops the rest before any LLM call, so narrowing this - # list would only move that policy to the wrong side of the wire. + # Only the event Hermes's gitea-pr-comments route actually handles. Gitea + # sends pull_request_comment distinctly from issue_comment, so this covers + # comments on PRs and nothing else — no issue comments, no pushes. + # + # Hermes would drop the rest anyway (its route filters on X-GitHub-Event + # before any LLM call), so this is defence in depth rather than the only + # gate: it keeps traffic that can never be acted on from crossing the wire + # and reaching the agent's process at all. Adding a second Hermes route + # means adding its event here as well as subscribing it. giteaWebhookEvents = [ - "create" - "delete" - "fork" - "push" - "issues" - "issue_assign" - "issue_label" - "issue_milestone" - "issue_comment" - "pull_request" - "pull_request_assign" - "pull_request_label" - "pull_request_milestone" "pull_request_comment" - "pull_request_review_approved" - "pull_request_review_rejected" - "pull_request_review_comment" - "pull_request_sync" - "pull_request_review_request" - "wiki" - "repository" - "release" - "package" - "status" - "workflow_run" - "workflow_job" ]; + + giteaWebhookName = "PR comments Hermes"; in { services.gitea = { @@ -396,8 +378,9 @@ in # runs as the gitea user on a multi-user box, and a request body passed # with -d is world-readable in /proc//cmdline for its lifetime. body="$(jq -n --arg url "$target" --arg secret "$secret" \ + --arg name ${lib.escapeShellArg giteaWebhookName} \ --argjson events '${builtins.toJSON giteaWebhookEvents}' \ - '{type: "gitea", config: {content_type: "json", url: $url, secret: $secret}, events: $events, active: true}')" + '{type: "gitea", name: $name, config: {content_type: "json", url: $url, secret: $secret}, events: $events, active: true}')" hook_id="$(curl -fsS "''${auth[@]}" "$api/repos/darman/homelab/hooks" \ | jq -r --arg url "$target" 'first(.[] | select(.type == "gitea" and .config.url == $url)) | .id // empty')"