#11611: feat: separate group-level allowlist from sender-level command authorization
docs
channel: telegram
channel: whatsapp-web
gateway
size: M
## Problem
Currently `groupPolicy: "allowlist"` + `groupAllowFrom` gates **all** group interaction (both chat and commands) by sender phone number. There is no way to:
1. Allowlist specific groups by JID while letting anyone in those groups chat
2. Restrict slash commands (`/new`, `/reset`, etc.) to the owner only
3. Prevent the bot from being pulled into spam groups while keeping approved groups open to all participants
## Solution
When `groupPolicy: "allowlist"` is set **and** a `groups` config is present (mapping group JIDs), the access control layer now uses the `groups` config as the group-level gate instead of filtering by sender via `groupAllowFrom`.
This means:
- **Group-level filtering:** Only groups listed in `groups` config are accepted (spam groups blocked)
- **Open chat in approved groups:** Anyone in an approved group can chat (mention or always-on)
- **Command authorization unchanged:** `groupAllowFrom` continues to gate slash command access, so only the owner (or specified senders) can run `/new`, `/reset`, etc.
### Example config
```yaml
channels:
whatsapp:
groupPolicy: allowlist
groupAllowFrom: ["+1234567890"] # only owner can run slash commands
groups:
"my-group-123@g.us":
requireMention: true
"another-group@g.us": {}
```
### Backward compatibility
When no `groups` config is present, the existing sender-based `groupAllowFrom` filtering is preserved exactly as before.
## Changes
- **`src/web/inbound/access-control.ts`** — Integrate `resolveChannelGroupPolicy` to check group JID allowlist when `groups` config is present
- **`src/config/types.whatsapp.ts`** — Updated JSDoc for `groupPolicy` to document the new behavior
- **`src/web/inbound/access-control.group-allowlist.test.ts`** — 4 new tests covering the group allowlist behavior
## Dependencies
- Depends on #3326 — this PR incorporates their fix (only enable group allowlist when `groupPolicy` is explicitly `"allowlist"`, preventing implicit allowlist when `groups` config coexists with `groupPolicy: "open"`)
## Manual Testing
1. Set `groupPolicy: "allowlist"` with specific `groups` entries and `groupAllowFrom` with just your number
2. Send a message from a **non-allowlisted sender** in an approved group → ✅ should be received
3. Send `/new` from a **non-allowlisted sender** → ✅ should be silently ignored (only `groupAllowFrom` numbers can run slash commands)
4. Send a message from any **group not in `groups` config** → ❌ should be blocked
5. Remove `groups` entries → falls back to old sender-based filtering via `groupAllowFrom` (backward compat)
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR changes WhatsApp `groupPolicy: "allowlist"` handling so that when a `channels.whatsapp.groups` mapping is present, inbound group access is gated by group JID membership in that mapping (via `resolveChannelGroupPolicy`), rather than by sender phone number. When no `groups` config is present, the prior sender-based behavior (using `groupAllowFrom`/`allowFrom`) remains.
It also updates the WhatsApp config type docs to describe the new behavior and adds a dedicated Vitest suite covering: (1) allowing messages from an approved group JID, (2) blocking unapproved group JIDs, (3) legacy sender-based fallback when no `groups` config exists, and (4) confirming that approved groups allow any sender to chat while command authorization remains separate.
<h3>Confidence Score: 4/5</h3>
- This PR appears safe to merge, with one small documentation inconsistency to fix.
- Core logic change is localized to `checkInboundAccessControl` and delegates group-JID gating to `resolveChannelGroupPolicy`, preserving the legacy sender-based path when no groups mapping exists. Added tests cover the new branches. Only issue found is an outdated inline comment that no longer matches behavior; runtime logic impact is unlikely beyond intended policy change.
- src/web/inbound/access-control.ts (update the stale allowlist comment)
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#5665: fix: match group JIDs in groupAllowFrom allowlist
by koala73 · 2026-01-31
90.5%
#4390: fix(whatsapp): allow media from allowlisted groups without groupAllow…
by Sarang19114 · 2026-01-30
89.5%
#6567: fix: include paired users in WhatsApp group sender allowlist
by giannisanni · 2026-02-01
88.4%
#23288: feat(whatsapp): group command gating via commands.allowFrom + sende...
by rodrigoscoelho · 2026-02-22
87.2%
#4402: fix: store group messages from non-allowlisted senders as pending c...
by adam91holt · 2026-01-30
86.8%
#2703: docs(groups): clarify groupAllowFrom vs groups config
by RichardFellows · 2026-01-27
86.3%
#4337: fix(signal): add group-level allowlist support via groups config
by derekross · 2026-01-30
81.5%
#22106: fix(whatsapp): honor selfChatMode override for group mentions
by sportclaw · 2026-02-20
81.1%
#14789: fix: per-account dmPolicy ignored in checkInboundAccessControl
by croll83 · 2026-02-12
80.4%
#11166: fix(whatsapp): detect LID @mentions in self-chat mode
by mcaxtr · 2026-02-07
79.9%