Skip to content

fix: update set_content ordering in refresh_external_sources#232

Open
rdmcd wants to merge 3 commits intoOpenBuilders:devfrom
rdmcd:fix/refresh-external-sources-kick-bug
Open

fix: update set_content ordering in refresh_external_sources#232
rdmcd wants to merge 3 commits intoOpenBuilders:devfrom
rdmcd:fix/refresh-external-sources-kick-bug

Conversation

@rdmcd
Copy link

@rdmcd rdmcd commented Mar 13, 2026

Description

Fixes a bug in refresh_external_sources where users removed from an external API whitelist are never kicked.

set_content was called after kick_ineligible_chat_members. The eligibility check inside the kick path reads rule.content from the DB, which still contains the old list (including the removed user). So is_whitelisted returns True, the user appears eligible, and kick_chat_member is never called. After that, set_content updates the DB — and the next cycle sees no diff, so the user is never kicked.

Checklist

  • I have read the contributing guidelines.
  • I ran all tests and they passed successfully.
  • I reviewed my own code and followed the project's code style.
  • I included relevant details in the PR description or commit messages.

Changes

  • Move set_content before kick block: Content is updated before the eligibility check runs, so is_whitelisted reads the current list instead of the stale one. If a kick fails mid-way, the periodic compliance check (check_chat_members_compliance) will catch the user on the next run.
  • Add 2 unit tests: Covering the fixed behavior — removed user is kicked, and no diff means no kicks.

How Has This Been Tested?

Unit tests added in tests/unit/community_manager/actions/test_refresh_external_sources.py:

MODE=test ./docker.sh run --rm -it test pytest tests/unit/community_manager/actions/test_refresh_external_sources.py -v

Additional Notes

Existing users who should have been kicked but weren't can be cleaned up by running check-target-chat-members for each chat with external source rules — the updated rule.content already excludes them, so the compliance check will correctly identify them as ineligible.

rdmcd added 2 commits March 13, 2026 19:43
1. Moved set_content before kick_ineligible_chat_members so that
   is_whitelisted reads the updated rule.content during eligibility check.
   Previously, the stale content caused removed users to appear eligible,
   preventing them from ever being kicked.

2. Added chat_ids filter to get_all query so that only memberships
   in the target chat are evaluated, not memberships in unrelated chats.
Move set_content before kick_ineligible_chat_members so that
is_whitelisted reads the updated rule.content during the eligibility
check. Previously, the stale content caused removed users to appear
eligible, preventing them from ever being kicked.
Copilot AI review requested due to automatic review settings March 13, 2026 16:48
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a correctness issue in refresh_external_sources where members removed from an external whitelist were not being kicked because the DB-backed content used during eligibility evaluation was updated too late.

Changes:

  • Update external-source content before running the kick/eligibility path so eligibility checks use the latest list.
  • Add unit coverage for “removed user is kicked” and “no diff means no kicks”.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
backend/community_manager/actions/chat.py Reorders external source content persistence ahead of eligibility/kick evaluation.
backend/tests/unit/community_manager/actions/test_refresh_external_sources.py Adds async unit tests verifying kicks happen for removed users and do not happen when nothing changes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 1005 to 1007
if diff.removed:
logger.info(
f"Found {len(diff.removed)} removed members from the source {source.chat_id!r}"
) as mock_kick:
await action.refresh_external_sources()

assert mock_kick.call_count == 0
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@rdmcd
Copy link
Author

rdmcd commented Mar 13, 2026

Initial PR was coauthored by Claude.

So it can be labelled vibecoded

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.

3 participants