Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions charts/openab/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ metadata:
data:
config.toml: |
{{- if ($cfg.discord).enabled }}
{{- if not $cfg.discord.allowedChannels }}
{{- fail (printf "agents.%s.discord.allowedChannels is required — empty means the bot will not respond to any messages. Add at least one channel ID." $name) }}
{{- end }}
[discord]
bot_token = "${DISCORD_BOT_TOKEN}"
{{- range $cfg.discord.allowedChannels }}
Expand Down Expand Up @@ -52,6 +55,9 @@ data:
{{- end }}

{{- if and ($cfg.slack).enabled }}
{{- if not (($cfg.slack).allowedChannels) }}
{{- fail (printf "agents.%s.slack.allowedChannels is required — empty means the bot will not respond to any messages. Add at least one channel ID." $name) }}
{{- end }}
[slack]
bot_token = "${SLACK_BOT_TOKEN}"
app_token = "${SLACK_APP_TOKEN}"
Expand Down
6 changes: 6 additions & 0 deletions charts/openab/tests/adapter-enablement_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ tests:
- it: renders [slack] when enabled=true
set:
agents.kiro.slack.enabled: true
agents.kiro.slack.allowedChannels:
- "C0123456789"
asserts:
- matchRegex:
path: data["config.toml"]
Expand All @@ -49,6 +51,8 @@ tests:
- it: renders [slack] with placeholder tokens when enabled=true
set:
agents.kiro.slack.enabled: true
agents.kiro.slack.allowedChannels:
- "C0123456789"
asserts:
- matchRegex:
path: data["config.toml"]
Expand All @@ -61,6 +65,8 @@ tests:
set:
agents.kiro.discord.enabled: true
agents.kiro.slack.enabled: true
agents.kiro.slack.allowedChannels:
- "C0123456789"
asserts:
- matchRegex:
path: data["config.toml"]
Expand Down
19 changes: 19 additions & 0 deletions charts/openab/tests/configmap_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,27 @@ tests:
- it: renders slack allow_user_messages = "multibot-mentions"
set:
agents.kiro.slack.enabled: true
agents.kiro.slack.allowedChannels:
- "C0123456789"
agents.kiro.slack.allowUserMessages: multibot-mentions
asserts:
- matchRegex:
path: data["config.toml"]
pattern: 'allow_user_messages = "multibot-mentions"'

- it: rejects empty discord allowedChannels
set:
agents.kiro.discord.enabled: true
agents.kiro.discord.allowedChannels: []
asserts:
- failedTemplate:
errorPattern: "discord.allowedChannels is required"

- it: rejects empty slack allowedChannels
set:
agents.kiro.discord.enabled: false
agents.kiro.slack.enabled: true
agents.kiro.slack.allowedChannels: []
asserts:
- failedTemplate:
errorPattern: "slack.allowedChannels is required"
2 changes: 1 addition & 1 deletion charts/openab/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ agents:
enabled: false
botToken: "" # Bot User OAuth Token (xoxb-...)
appToken: "" # App-Level Token (xapp-...) for Socket Mode
allowedChannels: [] # empty = allow all channels
allowedChannels: [] # required — empty = deny all channels (secure by default)
allowedUsers: [] # empty = allow all users
# allowBotMessages: "off" (default) | "mentions" | "all"
allowBotMessages: "off"
Expand Down
4 changes: 2 additions & 2 deletions config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[discord]
bot_token = "${DISCORD_BOT_TOKEN}"
allowed_channels = ["1234567890"] # empty or omitted = allow all channels
allowed_channels = ["1234567890"] # required — empty or omitted = deny all channels (secure by default)
# allowed_users = ["<YOUR_DISCORD_USER_ID>"] # empty or omitted = allow all users
# allow_bot_messages = "off" # "off" (default) | "mentions" | "all"
# "mentions" is recommended for multi-agent collaboration
Expand All @@ -14,7 +14,7 @@ allowed_channels = ["1234567890"] # empty or omitted = allow all channels
# [slack]
# bot_token = "${SLACK_BOT_TOKEN}" # Bot User OAuth Token (xoxb-...)
# app_token = "${SLACK_APP_TOKEN}" # App-Level Token (xapp-...) for Socket Mode
# allowed_channels = ["C0123456789"] # empty or omitted = allow all channels
# allowed_channels = ["C0123456789"] # required — empty or omitted = deny all channels (secure by default)
# allowed_users = ["U0123456789"] # empty or omitted = allow all users
# allow_bot_messages = "off" # "off" (default) | "mentions" | "all"
# trusted_bot_ids = [] # empty = any bot (mode permitting); set to restrict
Expand Down
7 changes: 4 additions & 3 deletions docs/discord.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Complete guide to setting up, configuring, and running OpenAB with Discord.
```toml
[discord]
bot_token = "${DISCORD_BOT_TOKEN}"
allowed_channels = ["123456789"] # channel ID allowlist (empty = all)
allowed_channels = ["123456789"] # channel ID allowlist (empty = deny all)
allowed_users = ["987654321"] # user ID allowlist (empty = all)
allow_bot_messages = "off" # off | mentions | all
allow_user_messages = "involved" # involved | mentions
Expand All @@ -75,11 +75,12 @@ trusted_bot_ids = [] # bot user IDs allowed through (empty = an

| `allowed_channels` | `allowed_users` | Result |
|---|---|---|
| empty | empty | All users, all channels (default) |
| empty | empty | **No channels, no users — bot ignores all messages** |
| set | empty | Only these channels, all users |
| empty | set | All channels, only these users |
| empty | set | **Bot ignores all messages** (channels must be configured first) |
| set | set | **AND** — must be in allowed channel AND allowed user |

- Empty `allowed_channels` = bot will not respond anywhere (secure by default)
- Empty `allowed_users` (default) = no user filtering
- Denied users get a 🚫 reaction and no reply

Expand Down
14 changes: 13 additions & 1 deletion docs/slack-bot-howto.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,22 @@ Add the `[slack]` section to your `config.toml`:
[slack]
bot_token = "${SLACK_BOT_TOKEN}"
app_token = "${SLACK_APP_TOKEN}"
allowed_channels = [] # empty = allow all channels
allowed_channels = ["C0123456789"] # required — empty = deny all channels (secure by default)
# allowed_users = ["U0123456789"] # empty = allow all users
```

### Access control behavior

| `allowed_channels` | `allowed_users` | Result |
|---|---|---|
| empty | empty | **No channels, no users — bot ignores all messages** |
| set | empty | Only these channels, all users |
| empty | set | **Bot ignores all messages** (channels must be configured first) |
| set | set | **AND** — must be in allowed channel AND allowed user |

- Empty `allowed_channels` = bot will not respond anywhere (secure by default)
- Empty `allowed_users` (default) = no user filtering

Set the environment variables:

```bash
Expand Down
7 changes: 5 additions & 2 deletions src/discord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,11 @@ impl EventHandler for Handler {
}).clone();

let channel_id = msg.channel_id.get();
let in_allowed_channel =
self.allowed_channels.is_empty() || self.allowed_channels.contains(&channel_id);
if self.allowed_channels.is_empty() {
debug!("allowed_channels is empty — ignoring message in channel {}", channel_id);
return;
}
let in_allowed_channel = self.allowed_channels.contains(&channel_id);

let is_mentioned = msg.mentions_user_id(bot_id)
|| msg.content.contains(&format!("<@{}>", bot_id));
Expand Down
8 changes: 7 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use serenity::prelude::*;
use std::collections::HashSet;
use std::path::PathBuf;
use std::sync::Arc;
use tracing::{error, info};
use tracing::{error, info, warn};

#[derive(Parser)]
#[command(name = "openab")]
Expand Down Expand Up @@ -111,6 +111,9 @@ async fn main() -> anyhow::Result<()> {

// Spawn Slack adapter (background task)
let slack_handle = if let Some(slack_cfg) = cfg.slack {
if slack_cfg.allowed_channels.is_empty() {
warn!("no allowed_channels configured for Slack — bot will not respond to any messages. Add at least one channel ID to [slack] allowed_channels.");
}
info!(
channels = slack_cfg.allowed_channels.len(),
users = slack_cfg.allowed_users.len(),
Expand Down Expand Up @@ -148,6 +151,9 @@ async fn main() -> anyhow::Result<()> {
if let Some(discord_cfg) = cfg.discord {
let allowed_channels =
parse_id_set(&discord_cfg.allowed_channels, "discord.allowed_channels")?;
if allowed_channels.is_empty() {
warn!("no allowed_channels configured for Discord — bot will not respond to any messages. Add at least one channel ID to [discord] allowed_channels.");
}
let allowed_users = parse_id_set(&discord_cfg.allowed_users, "discord.allowed_users")?;
let trusted_bot_ids = parse_id_set(&discord_cfg.trusted_bot_ids, "discord.trusted_bot_ids")?;
info!(
Expand Down
8 changes: 6 additions & 2 deletions src/slack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -803,8 +803,12 @@ async fn handle_message(
};
let thread_ts = event["thread_ts"].as_str().map(|s| s.to_string());

// Check allowed channels (empty = allow all)
if !allowed_channels.is_empty() && !allowed_channels.contains(&channel_id) {
// Check allowed channels (empty = deny all)
if allowed_channels.is_empty() {
tracing::debug!("allowed_channels is empty — ignoring message in channel {}", channel_id);
return;
}
if !allowed_channels.contains(&channel_id) {
return;
}

Expand Down
Loading