Repository navigation
fix(discord): a role-authorized member's speech, native slash commands and /thread starters reach the agent - #133478
Merged
unsupportedpastels merged 6 commits intoOct 6, 2026
Conversation
…aches the agent With DISCORD_ALLOWED_ROLES and no user allowlist, the voice listen loop admits a role member through the adapter's guild-scoped role check, but _handle_voice_channel_input rebuilds the turn's source from the `/voice join` copy. SessionSource.to_dict() deliberately drops the per-event role_authorized grant, so the gateway's own check saw a principal with no grant and dropped every spoken turn from a role-only member, while the same member's typed messages were answered. The grant is now recomputed for the current speaker against the guild's current member, with the meaning the message path gives it (the adapter has a role allowlist and this user passes its gate). It is never serialized and never inherited from whoever ran `/voice join`: a speaker without the role, or no longer in the guild, is still refused. Reported by andrexibiza (F4, voice half) on NousResearch#128788. (cherry picked from commit 6985ea6)
(cherry picked from commit 7976b4a)
Fixes NousResearch#118958 (cherry picked from commit f5f538e)
Review feedback: the comment read as if the stamped role_authorized value were a per-user role match. It is the same adapter-level verdict the message path stamps: a role allowlist exists and the user passed the slash authorization gate. (cherry picked from commit e4165fc)
… for its own actor only The salvaged NousResearch#125620 commits stamp role_authorized on _build_slash_event and _dispatch_thread_session from bool(_allowed_role_ids), which is only right because today's two callers run _check_slash_authorization first. Neither builder checks its actor itself, so any later caller that builds an event before (or without) the gate would mint a grant for a member the gate refuses. The grant is now re-evaluated from the interaction in both builders (_slash_role_grant): a role allowlist exists AND this actor passes the slash gate, the meaning _discord_message_admission gives the flag. A role-only member still reaches the agent, and an unrelated-role actor's event is refused by the gateway even when built directly. The two salvaged tests fold into one parametrized invariant over both builders with the refusal row. Recomputing the verdict from the actor follows NousResearch#118966 by KoNit-K. Reported by andrexibiza (F4, native half) on NousResearch#128788 and NousResearch#130303. Co-authored-by: KoNit-K <konit.block@protonmail.com> (cherry picked from commit 357e77d)
…apt the thread-starter test _evaluate_slash_authorization moves unchanged into adapter_slash_auth.py beside the new _slash_role_grant, so adapter.py stays within its code-health file cap. The thread-starter test passes a thread, as _dispatch_thread_session now takes one, and the voice role-grant test gains type hints.
unsupportedpastels
force-pushed
the
fix/discord-role-grant-native-voice
branch
from
October 6, 2026 00:18
f765275 to
7ac4ffb
Compare
This was referenced Oct 6, 2026
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
A member admitted only by
DISCORD_ALLOWED_ROLESpasses the Discord adapter's gates but was refused by the gateway on three paths, because the event they produced did not carryrole_authorized:/threadstarter:_build_slash_eventand_dispatch_thread_sessionbuilt the source without the role verdict, so the gateway answered a role-only member with a pairing code ([Bug]: Discord slash commands from role-authorized users are rejected by the gateway (slash event never carries role_authorized) #118958)./voice joincopy, andto_dictdrops the per-event grant, so every role-only speaker was ignored ([Bug]: Discord voice-channel speech from a role-authorized member never reaches the agent (voice source drops role_authorized) #130302).The grant has the message path's meaning (
_discord_message_admission): a role allowlist exists and this actor passes the gate. It is evaluated for each actor, never inherited:/threadevents call_slash_role_grant(interaction), which re-runs_evaluate_slash_authorizationfor that interaction instead of relying on call order.Related Issue
Fixes #130302
Fixes #118958
Salvages #130303 (@jonpol01), which includes @Christopher-Schulze's commits from #125620; all five commits are cherry-picked with authorship kept. #118966 (@KoNit-K) fixes the same slash-role problem and is superseded by this PR. Thanks to @andrexibiza for the review.
Type of Change
Changes Made
plugins/platforms/discord/adapter.py:_build_slash_eventand_dispatch_thread_sessionpassrole_authorized=self._slash_role_grant(interaction).plugins/platforms/discord/adapter_slash_auth.py(new):_evaluate_slash_authorizationmoves here unchanged asDiscordSlashAuthMixin, next to the new_slash_role_grantthat reuses it. The move keepsadapter.pywithin its code-health file cap (7,305 lines, down from 7,368); review withgit diff --color-moved.gateway/run_voice.py:_handle_voice_channel_inputrecomputesrole_authorizedfor the speaker when the adapter has a role allowlist.tests/gateway/test_discord_slash_auth.py: a slash command and a/threadstarter from a role member pass the real gateway check; an actor with an unrelated role does not.tests/gateway/test_discord_voice_role_grant.py(new): a role member's speech is dispatched; a speaker without the role (while the joiner has it) and a speaker who left the guild are not.website/docs/user-guide/features/voice-mode.mdand its zh-Hans copy: voice access followsDISCORD_ALLOWED_ROLEStoo.Conflict resolution against
main: #133463 changed_dispatch_thread_sessionto take the created thread.main's body is kept and only therole_authorizedline is added; the new thread-starter test passes a thread object.How to Test
scripts/run_tests.sh tests/gateway/test_discord_slash_auth.py tests/gateway/test_discord_voice_role_grant.pygives 22 passed. Withmain'sadapter.pyandrun_voice.py, the 3 role-member cases fail; the refusal cases pass on both.Checklist
Code
pytest tests/ -qand all tests pass. Not run in full; the related suites pass.python scripts/checkpasses (11 checks)Documentation & Housekeeping
cli-config.yaml.example: N/ACONTRIBUTING.md/AGENTS.md: N/AInfographic