Skip to content

feat(doctor): nudge when Slack has no channel allowlist - #86

Merged
github-actions[bot] merged 1 commit into
mainfrom
claude/open-linear-items-iem7gq
Jul 17, 2026
Merged

feat(doctor): nudge when Slack has no channel allowlist#86
github-actions[bot] merged 1 commit into
mainfrom
claude/open-linear-items-iem7gq

Conversation

@dizhaky

@dizhaky dizhaky commented Jul 12, 2026

Copy link
Copy Markdown
Owner

What does this PR do?

Adds a "Slack Configuration" section to hermes doctor that fires only when SLACK_BOT_TOKEN is set, warning if slack.allowed_channels (config.yaml or SLACK_ALLOWED_CHANNELS) is empty — since an empty allowlist is the documented, backward-compatible default where the bot responds in every channel it's a member of, including any privileged ones it's since been invited to.

This is informational only. It does not set, infer, or recommend a specific channel list — that decision (which channels are privileged, which should stay open) is the deployment owner's call, not doctor's.

Related Issue

Linear DAN-2043 ("Scope Hermes allowed_channels to an explicit allowlist") raises the concern that an empty allowlist means the bot responds in every channel it's a member of, including privileged ones (#accounting, #legal, #security in the reporter's workspace), and explicitly says the actual channel-list decision "NEEDS USER SIGN-OFF." This PR only adds the visibility half of that ticket — a hermes doctor nudge — not the channel-list decision itself.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • hermes_cli/doctor.py: new _check_slack_channel_exposure() helper, wired into run_doctor() right after the gateway-service-linger check. Silent when Slack isn't configured (no SLACK_BOT_TOKEN); otherwise reports check_ok with the channel count or check_warn + an actionable issue when the allowlist is empty.
  • tests/hermes_cli/test_doctor.py: new TestSlackChannelExposureCheck covering silent-when-unconfigured, warn-when-empty, and ok-when-set (both config.yaml and env var paths).

How to Test

  1. uv run pytest tests/hermes_cli/test_doctor.py -q — 67 passed.
  2. Smoke-ran run_doctor() with SLACK_BOT_TOKEN set and no allowlist — shows the new ◆ Slack Configuration section with the warning and fix hint.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits
  • My PR contains only changes related to this fix/feature
  • I've run pytest tests/hermes_cli/test_doctor.py -q and all tests pass
  • I've added tests for my changes

Documentation & Housekeeping

  • N/A — no config keys added (reads existing slack.allowed_channels/SLACK_ALLOWED_CHANNELS), no docs/tool-schema changes

Generated by Claude Code

hermes doctor now warns when SLACK_BOT_TOKEN is set but
slack.allowed_channels is empty, since the bot will respond in every
channel it's a member of (including any privileged ones it's since been
invited to). Informational only — it never sets or infers a channel
list; that decision stays with the user.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P96ZSh1Dc9mX3vCd29dieZ
@github-actions

Copy link
Copy Markdown

🔎 Lint report: claude/open-linear-items-iem7gq vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 8615 on HEAD, 8615 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 4587 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@dizhaky
dizhaky marked this pull request as ready for review July 17, 2026 10:37
@github-actions
github-actions Bot merged commit 1ec3535 into main Jul 17, 2026
32 of 47 checks passed
@github-actions
github-actions Bot deleted the claude/open-linear-items-iem7gq branch July 17, 2026 10:37

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2aba64abce

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hermes_cli/doctor.py
Comment on lines +293 to +295
raw = (cfg.get("slack") or {}).get("allowed_channels")
if raw is None:
raw = os.environ.get("SLACK_ALLOWED_CHANNELS", "")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor the environment allowlist before merged defaults

load_config_readonly() deep-merges DEFAULT_CONFIG, where slack.allowed_channels is always present as "", so an env-only deployment with SLACK_ALLOWED_CHANNELS=C123 never reaches this raw is None fallback and is incorrectly reported as unrestricted. This contradicts the documented env configuration and the gateway's env-precedence behavior; check the environment value first or read the raw YAML rather than the default-merged config.

Useful? React with 👍 / 👎.

Comment thread hermes_cli/doctor.py
Comment on lines +288 to +289
if not get_env_value("SLACK_BOT_TOKEN"):
return # Slack isn't configured; nothing to warn about.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip the exposure warning when Slack is disabled

A retained SLACK_BOT_TOKEN does not mean the Slack gateway is active: slack.enabled: false and platforms.slack.enabled: false are explicitly supported so the token can remain available to outbound skills without activating the adapter. In that configuration this check still claims the bot responds in every joined channel and adds an issue, so it should inspect the effective enabled setting before warning.

Useful? React with 👍 / 👎.

Comment thread hermes_cli/doctor.py

_section("Slack Configuration")
cfg = load_config_readonly()
raw = (cfg.get("slack") or {}).get("allowed_channels")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle malformed Slack sections without crashing doctor

If a syntactically valid but malformed config contains a truthy non-mapping Slack section, such as slack: disabled, this expression calls .get() on a string and aborts the entire doctor run whenever a Slack token exists. Since the existing structure validator does not validate the Slack section and doctor is the recovery path for bad configuration, guard the section type or use the repository's safe cfg_get() helper.

Useful? React with 👍 / 👎.

Comment thread hermes_cli/doctor.py
Comment on lines +292 to +295
cfg = load_config_readonly()
raw = (cfg.get("slack") or {}).get("allowed_channels")
if raw is None:
raw = os.environ.get("SLACK_ALLOWED_CHANNELS", "")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Inspect the effective gateway allowlist configuration

Slack's adapter also accepts allowed_channels through platforms.slack.extra and the legacy gateway.json platform configuration, but this check reads only the top-level slack section. Deployments using either supported gateway configuration path therefore receive an unrestricted-channel warning even though SlackAdapter._slack_allowed_channels() enforces their allowlist; derive this diagnostic from the effective gateway configuration or check those sources too.

Useful? React with 👍 / 👎.

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.

2 participants