Skip to content

Open cowork groups never build a roster: members are allowed but never recorded #840

Description

@adolfousier

Problem

A user added to an open cowork group can talk immediately but is never written to that group's allowed_users. The roster stays empty, so there is no record of who actually used the bot there.

Mechanism, confirmed

user_allowed short-circuits on the open flag (config/types.rs:464):

.is_some_and(|g| g.open || Self::id_in(&g.allowed_users, uid))

g.open is true, so the allow-list is never consulted.

Lazy registration then never fires, because it is gated on the ACL having FAILED (handler.rs:781):

if !acl_passed && !is_dm && is_cowork_group(...) {
    auto_register_to_group(...)
}

In an open group acl_passed is already true, so the branch is skipped. Registration survives only on three narrow paths: a non-bot new_chat_members event, /start, or an ACL rejection — and open groups defeat the third.

The code's own comment says the roster is meant to exist (handler.rs:644):

open=true already allows every member; the allowlist entry just keeps a visible roster of who's in.

It just has no path that populates it in the case it describes.

Why it matters

  • No audit trail. There is no record of who used the bot in that group.
  • open is not reversible. Turning it off locks out every existing member, because none were ever written to the list. What looks like tightening a setting is a silent mass revocation.

Fix

Register on first message regardless of whether the ACL already passed: record the user if absent, then continue. Membership becomes a consequence of participating rather than of being rejected first.

Care

  • Must not widen access. Registration is a record of someone already permitted; it must never be what grants permission. A user the ACL rejects in a NON-open group must still be rejected.
  • Bots stay excluded, matching the existing join path.
  • Idempotent and quiet. It runs on every message, so an already-registered user must be a cheap no-op with no repeated config writes and no log spam.

Not included

The stuck "Add to Group" sheet reported alongside this is a separate surface. The button is a URL button opening Telegram's native ?startgroup= picker, so there is no callback to answer and no API to dismiss it — the bot cannot close that sheet. Whether the inline &admin= rights request (#709) makes the picker wait on an extra confirmation is untested, and testing it needs a client, not a code change.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions