Discord: fix allowlist gating. Closes #961
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
- Browser: extension mode recovers when only one tab is attached (stale targetId fallback).
|
- Browser: extension mode recovers when only one tab is attached (stale targetId fallback).
|
||||||
- Browser: fix `tab not found` for extension relay snapshots/actions when Playwright blocks `newCDPSession` (use the single available Page).
|
- Browser: fix `tab not found` for extension relay snapshots/actions when Playwright blocks `newCDPSession` (use the single available Page).
|
||||||
- Telegram: add bidirectional reaction support with configurable notifications and agent guidance. (#964) — thanks @bohdanpodvirnyi.
|
- Telegram: add bidirectional reaction support with configurable notifications and agent guidance. (#964) — thanks @bohdanpodvirnyi.
|
||||||
|
- Discord: allow allowlisted guilds without channel lists to receive messages when `groupPolicy="allowlist"`. — thanks @thewilloftheshadow.
|
||||||
|
|
||||||
## 2026.1.14-1
|
## 2026.1.14-1
|
||||||
|
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ Notes:
|
|||||||
- Your config requires mentions and you didn’t mention it, or
|
- Your config requires mentions and you didn’t mention it, or
|
||||||
- Your guild/channel allowlist denies the channel/user.
|
- Your guild/channel allowlist denies the channel/user.
|
||||||
- **`requireMention: false` but still no replies**:
|
- **`requireMention: false` but still no replies**:
|
||||||
- `channels.discord.groupPolicy` defaults to **allowlist**; set it to `"open"` or explicitly list channels under `channels.discord.guilds.<id>.channels`.
|
- `channels.discord.groupPolicy` defaults to **allowlist**; set it to `"open"` or add a guild entry under `channels.discord.guilds` (optionally list channels under `channels.discord.guilds.<id>.channels` to restrict).
|
||||||
- `requireMention` must live under `channels.discord.guilds` (or a specific channel). `channels.discord.requireMention` at the top level is ignored.
|
- `requireMention` must live under `channels.discord.guilds` (or a specific channel). `channels.discord.requireMention` at the top level is ignored.
|
||||||
- **Permission audits** (`channels status --probe`) only check numeric channel IDs. If you use slugs/names as `channels.discord.guilds.*.channels` keys, the audit can’t verify permissions.
|
- **Permission audits** (`channels status --probe`) only check numeric channel IDs. If you use slugs/names as `channels.discord.guilds.*.channels` keys, the audit can’t verify permissions.
|
||||||
- **DMs don’t work**: `channels.discord.dm.enabled=false`, `channels.discord.dm.policy="disabled"`, or you haven’t been approved yet (`channels.discord.dm.policy="pairing"`).
|
- **DMs don’t work**: `channels.discord.dm.enabled=false`, `channels.discord.dm.policy="disabled"`, or you haven’t been approved yet (`channels.discord.dm.policy="pairing"`).
|
||||||
@@ -352,6 +352,7 @@ Allowlist matching notes:
|
|||||||
- Prefixes like `discord:`/`user:` (users) and `channel:` (group DMs) are supported.
|
- Prefixes like `discord:`/`user:` (users) and `channel:` (group DMs) are supported.
|
||||||
- Use `*` to allow any sender/channel.
|
- Use `*` to allow any sender/channel.
|
||||||
- When `guilds.<id>.channels` is present, channels not listed are denied by default.
|
- When `guilds.<id>.channels` is present, channels not listed are denied by default.
|
||||||
|
- When `guilds.<id>.channels` is omitted, all channels in the allowlisted guild are allowed.
|
||||||
|
|
||||||
Native command notes:
|
Native command notes:
|
||||||
- The registered commands mirror Clawdbot’s chat commands.
|
- The registered commands mirror Clawdbot’s chat commands.
|
||||||
|
|||||||
@@ -1542,10 +1542,11 @@ See [Streaming](/concepts/streaming).
|
|||||||
### Discord doesn’t reply in my server even with `requireMention: false`. Why?
|
### Discord doesn’t reply in my server even with `requireMention: false`. Why?
|
||||||
|
|
||||||
`requireMention` only controls mention‑gating **after** the channel passes allowlists.
|
`requireMention` only controls mention‑gating **after** the channel passes allowlists.
|
||||||
By default `channels.discord.groupPolicy` is **allowlist**, so guild channels must be explicitly enabled.
|
By default `channels.discord.groupPolicy` is **allowlist**, so guilds must be explicitly enabled.
|
||||||
|
If you set `channels.discord.guilds.<guildId>.channels`, only the listed channels are allowed; omit it to allow all channels in the guild.
|
||||||
|
|
||||||
Fix checklist:
|
Fix checklist:
|
||||||
1) Set `channels.discord.groupPolicy: "open"` **or** add the guild/channel allowlist.
|
1) Set `channels.discord.groupPolicy: "open"` **or** add a guild allowlist entry (and optionally a channel allowlist).
|
||||||
2) Use **numeric channel IDs** in `channels.discord.guilds.<guildId>.channels`.
|
2) Use **numeric channel IDs** in `channels.discord.guilds.<guildId>.channels`.
|
||||||
3) Put `requireMention: false` **under** `channels.discord.guilds` (global or per‑channel).
|
3) Put `requireMention: false` **under** `channels.discord.guilds` (global or per‑channel).
|
||||||
Top‑level `channels.discord.requireMention` is not a supported key.
|
Top‑level `channels.discord.requireMention` is not a supported key.
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ describe("discord groupPolicy gating", () => {
|
|||||||
expect(
|
expect(
|
||||||
isDiscordGroupAllowedByPolicy({
|
isDiscordGroupAllowedByPolicy({
|
||||||
groupPolicy: "open",
|
groupPolicy: "open",
|
||||||
|
guildAllowlisted: false,
|
||||||
channelAllowlistConfigured: false,
|
channelAllowlistConfigured: false,
|
||||||
channelAllowed: false,
|
channelAllowed: false,
|
||||||
}),
|
}),
|
||||||
@@ -225,26 +226,40 @@ describe("discord groupPolicy gating", () => {
|
|||||||
expect(
|
expect(
|
||||||
isDiscordGroupAllowedByPolicy({
|
isDiscordGroupAllowedByPolicy({
|
||||||
groupPolicy: "disabled",
|
groupPolicy: "disabled",
|
||||||
|
guildAllowlisted: true,
|
||||||
channelAllowlistConfigured: true,
|
channelAllowlistConfigured: true,
|
||||||
channelAllowed: true,
|
channelAllowed: true,
|
||||||
}),
|
}),
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("blocks allowlist when no channel allowlist configured", () => {
|
it("blocks allowlist when guild is not allowlisted", () => {
|
||||||
expect(
|
expect(
|
||||||
isDiscordGroupAllowedByPolicy({
|
isDiscordGroupAllowedByPolicy({
|
||||||
groupPolicy: "allowlist",
|
groupPolicy: "allowlist",
|
||||||
|
guildAllowlisted: false,
|
||||||
channelAllowlistConfigured: false,
|
channelAllowlistConfigured: false,
|
||||||
channelAllowed: true,
|
channelAllowed: true,
|
||||||
}),
|
}),
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("allows allowlist when guild allowlisted but no channel allowlist", () => {
|
||||||
|
expect(
|
||||||
|
isDiscordGroupAllowedByPolicy({
|
||||||
|
groupPolicy: "allowlist",
|
||||||
|
guildAllowlisted: true,
|
||||||
|
channelAllowlistConfigured: false,
|
||||||
|
channelAllowed: true,
|
||||||
|
}),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("allows allowlist when channel is allowed", () => {
|
it("allows allowlist when channel is allowed", () => {
|
||||||
expect(
|
expect(
|
||||||
isDiscordGroupAllowedByPolicy({
|
isDiscordGroupAllowedByPolicy({
|
||||||
groupPolicy: "allowlist",
|
groupPolicy: "allowlist",
|
||||||
|
guildAllowlisted: true,
|
||||||
channelAllowlistConfigured: true,
|
channelAllowlistConfigured: true,
|
||||||
channelAllowed: true,
|
channelAllowed: true,
|
||||||
}),
|
}),
|
||||||
@@ -255,6 +270,7 @@ describe("discord groupPolicy gating", () => {
|
|||||||
expect(
|
expect(
|
||||||
isDiscordGroupAllowedByPolicy({
|
isDiscordGroupAllowedByPolicy({
|
||||||
groupPolicy: "allowlist",
|
groupPolicy: "allowlist",
|
||||||
|
guildAllowlisted: true,
|
||||||
channelAllowlistConfigured: true,
|
channelAllowlistConfigured: true,
|
||||||
channelAllowed: false,
|
channelAllowed: false,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -197,13 +197,15 @@ export function resolveDiscordShouldRequireMention(params: {
|
|||||||
|
|
||||||
export function isDiscordGroupAllowedByPolicy(params: {
|
export function isDiscordGroupAllowedByPolicy(params: {
|
||||||
groupPolicy: "open" | "disabled" | "allowlist";
|
groupPolicy: "open" | "disabled" | "allowlist";
|
||||||
|
guildAllowlisted: boolean;
|
||||||
channelAllowlistConfigured: boolean;
|
channelAllowlistConfigured: boolean;
|
||||||
channelAllowed: boolean;
|
channelAllowed: boolean;
|
||||||
}): boolean {
|
}): boolean {
|
||||||
const { groupPolicy, channelAllowlistConfigured, channelAllowed } = params;
|
const { groupPolicy, guildAllowlisted, channelAllowlistConfigured, channelAllowed } = params;
|
||||||
if (groupPolicy === "disabled") return false;
|
if (groupPolicy === "disabled") return false;
|
||||||
if (groupPolicy === "open") return true;
|
if (groupPolicy === "open") return true;
|
||||||
if (!channelAllowlistConfigured) return false;
|
if (!guildAllowlisted) return false;
|
||||||
|
if (!channelAllowlistConfigured) return true;
|
||||||
return channelAllowed;
|
return channelAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -260,6 +260,7 @@ export async function preflightDiscordMessage(
|
|||||||
isGuildMessage &&
|
isGuildMessage &&
|
||||||
!isDiscordGroupAllowedByPolicy({
|
!isDiscordGroupAllowedByPolicy({
|
||||||
groupPolicy: params.groupPolicy,
|
groupPolicy: params.groupPolicy,
|
||||||
|
guildAllowlisted: Boolean(guildInfo),
|
||||||
channelAllowlistConfigured,
|
channelAllowlistConfigured,
|
||||||
channelAllowed,
|
channelAllowed,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -448,6 +448,7 @@ async function dispatchDiscordCommandInteraction(params: {
|
|||||||
const channelAllowed = channelConfig?.allowed !== false;
|
const channelAllowed = channelConfig?.allowed !== false;
|
||||||
const allowByPolicy = isDiscordGroupAllowedByPolicy({
|
const allowByPolicy = isDiscordGroupAllowedByPolicy({
|
||||||
groupPolicy: discordConfig?.groupPolicy ?? "open",
|
groupPolicy: discordConfig?.groupPolicy ?? "open",
|
||||||
|
guildAllowlisted: Boolean(guildInfo),
|
||||||
channelAllowlistConfigured,
|
channelAllowlistConfigured,
|
||||||
channelAllowed,
|
channelAllowed,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user