Skip to content

Poller: filter out issues assigned by someone other than the operator #79

@oscarvalenzuelab

Description

@oscarvalenzuelab

Problem

Today `IssuePoller` picks up any issue assigned to the configured GitHub user, regardless of who did the assignment. That means a teammate (or any repo admin) can drop an issue on me and the dev pipeline will fire automatically against it. The intended use case is "self-assigned todo list drives the bot" — external assignments become implicit command-and-control over my local compute.

Proposed behavior

Only handle an issue if the most recent `assigned` event targeting the operator was performed by the operator themselves. Any other assigner (including bots) is filtered out — the issue stays visible on GitHub for me to see, but `ctrlrelay` doesn't auto-run on it.

Out of scope: issues where I was auto-assigned via CODEOWNERS, GitHub App, or webhook — those still shouldn't trigger. The filter treats those like any other "not me" assigner.

API notes for the implementer

GitHub's issue payload has `assignees[]` (current state) but no `assigner`. To find who performed the assignment, hit the issue events endpoint:

```
GET /repos/{owner}/{repo}/issues/{issue_number}/events
```

Filter for events where:

  • `event == "assigned"`
  • `assignee.login == config.username`

Take the most recent such event (events are chronological) and compare `actor.login == config.username`. If they match, accept. Otherwise, skip.

The poller already calls `gh issue list --assignee ` once per repo per poll interval. Adding the events check means one extra API call per newly-detected issue (not per poll — only per new issue, which is rare). Acceptable overhead.

Suggested implementation sketch

  • Add `list_assignment_events(repo, issue_number)` to `core/github.py` wrapping `gh api /repos/.../issues/.../events --jq '[.[] | select(.event=="assigned")]'`.
  • In `IssuePoller.poll()`, after an issue is found new-to-us but before it's added to `new_issues`, call the above and apply the self-assignment check. If it fails, log `poll.issue.foreign_assignment` with `repo`, `number`, `assigner_login` and do still mark it seen (otherwise every poll would re-check it and emit duplicate log lines / API calls).
  • Config escape hatch: a per-repo `automation.accept_foreign_assignments: bool = false` flag in `RepoConfig` so specific repos can opt back into the old "any assignment counts" behavior if some team needs it.

Tests

  • Fresh issue self-assigned → poller picks it up.
  • Fresh issue assigned by a different user → poller logs `foreign_assignment`, does NOT add to `new_issues`, DOES mark seen.
  • Issue first self-assigned, later re-assigned (someone else reassigns to me) → the most-recent `assigned` event is by someone else → filtered out.
  • Issue assigned by `github-actions[bot]` → filtered out (same rule — we don't trust bot assignment).
  • Per-repo `accept_foreign_assignments: true` → the check is bypassed.

Not addressed here

Security-wise this is defense-against-annoyance, not hardening — a teammate with write access to a configured repo can still push branches, trigger CI, etc. The filter stops the dev pipeline from spontaneously executing agent-backed work against my machine, which is the specific concern.

Metadata

Metadata

Labels

enhancementNew feature or request

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions