Skip to content

feat: chatops_repo restriction — keep slash commands off public repos#32

Merged
avrabe merged 1 commit into
mainfrom
feat/chatops-private-repo
Apr 29, 2026
Merged

feat: chatops_repo restriction — keep slash commands off public repos#32
avrabe merged 1 commit into
mainfrom
feat/chatops-private-repo

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented Apr 28, 2026

Why

ChatOps commands are currently honoured from any installed repo. Even with `allowed_command_users` restricting who can trigger, the bot's "Working on it…" + result replies are public — landing in whichever public repo the maintainer commented in. For an org-wide sweep (`/sync-all-repos` migrating every repo to Repository Rulesets + applying config via PR), trigger + response trail should stay in a private admin repo.

What

Opt-in `chatops_repo:` section. When `enabled: true`, the `issue_comment.created` handler silently ignores any comment starting with `/` UNLESS posted in `repo`. Check fires before command extraction → no log, no comment, no public footprint.

Non-command comments (no leading `/`) unaffected. Commands in the designated repo work exactly as before.

Operational pattern unlocked

  1. Create `pulseengine/temper-ops` (private)
  2. Install Temper on it
  3. `chatops_repo.enabled: true` + `repo: pulseengine/temper-ops` in `config.local.yml`
  4. Trigger from there. Bot replies stay private. Bot's PRs against public repos stay public — intentional asymmetry: trigger private, application public.

Test plan

  • 792 tests pass (+4: honoured-from-admin, silently-ignored-from-public, non-command-comments-unaffected, legacy-default-honours-every-repo)
  • eslint clean
  • After deploy + enable: comment `/configure-repo` on any public pulseengine repo → complete no-op. Comment in temper-ops → works.

Risk & rollout

  • Risk: low. Opt-in. Default unchanged.
  • Rollout: self-update on merge.

🤖 Generated with Claude Code

## Why
ChatOps commands (/configure-repo, /sync-all-repos, /review-pr, etc.) are
currently honoured from any repo where Temper is installed. Even with
allowed_command_users restricting *who* can trigger them, the bot's "Working
on it…" replies and any error responses are public — sitting in whichever
public repo the maintainer happened to comment in.

For an org running an org-wide config sweep (especially the upcoming
/sync-all-repos that migrates every repo to Repository Rulesets + applies
config changes via PR), the user wants the trigger and the bot's response
trail to stay in a private admin repo.

## What
Opt-in `chatops_repo:` config section:

  chatops_repo:
    enabled: false
    repo: pulseengine/temper-ops

When `enabled: true`, the issue_comment.created handler silently ignores
any comment starting with `/` UNLESS it's posted in `repo`. The check fires
*before* command extraction, so:
  - no log line emitted
  - no comment posted back
  - no public footprint at all

Non-command comments (no leading `/`) are unaffected — handler proceeds
through the existing no-op path. Commands posted in the designated repo
work exactly as before.

## Operational pattern this unlocks
1. Create `pulseengine/temper-ops` as a **private** repo
2. Install Temper on it
3. Set `chatops_repo.enabled: true` and `repo: pulseengine/temper-ops` in
   `config.local.yml`
4. Trigger /sync-all-repos, /configure-repo, etc. from there
5. The bot's "Working on it…" + result replies all land in the private
   repo. Configuration PRs the bot opens against public repos are still
   public — that's the intentional asymmetry: trigger private, application
   public, audit trail intact.

## Test plan
- [x] All 792 tests pass (was 788; +4 covering: command honoured from admin
      repo, command silently ignored from public repo, non-command comments
      unaffected, legacy default still honours every repo)
- [x] eslint clean
- [ ] After deploy: enable chatops_repo, comment /configure-repo on any
      public pulseengine repo — should be a complete no-op (no working
      comment, no error). Comment from temper-ops — should work normally.

## Risk & rollout
- Risk: low. Opt-in via config; default behaviour unchanged.
- Rollout: self-update on merge.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@avrabe avrabe merged commit 2754f38 into main Apr 29, 2026
5 checks passed
@avrabe avrabe deleted the feat/chatops-private-repo branch April 29, 2026 04:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant