Skip to content

feat(telegram): auto-approve groups via HSM when admin adds the bot#120

Open
juniperbevensee wants to merge 2 commits into
mainfrom
dev/juniperbevensee/tg-group-autoapprove
Open

feat(telegram): auto-approve groups via HSM when admin adds the bot#120
juniperbevensee wants to merge 2 commits into
mainfrom
dev/juniperbevensee/tg-group-autoapprove

Conversation

@juniperbevensee

Copy link
Copy Markdown
Collaborator

What

When someone adds the Hermes bot to a Telegram group, the adapter now (optionally) asks Hermes Swarm Map to auto-approve the group: HSM checks whether the adder is a platform admin and, if so, adds the group to the allowlist. Approved → the bot greets the group and stays. Denied → the bot posts one polite decline ("this group isn't approved for me yet — ask my admin") and leaves.

Previously these my_chat_member updates were requested (allowed_updates=Update.ALL_TYPES) but silently dropped — no handler existed. Mirrors the existing Mattermost _handle_channel_join gate.

HSM contract consumed

Pairs with hermes-swarm-map PR #181:

POST {HSM_URL}/api/harnesses/{HERMES_AGENT_NAME}/surfaces/telegram/groups/{groupId}
Body: { "addedByUserId": "<numeric telegram user id>" }
  • { "approved": true, "restarted": bool } → approved (allowlist updated; restarted:false = env written but recreate failed — still approved)
  • { "approved": true, "already_allowed": true } → approved (wildcard or already listed)
  • { "approved": false, "reason": "..." } → decline + leave
  • 400 { "error": "..." }, network error, non-200, or missing/non-bool approved → decline + leave (fail-closed)

No auth header (HSM is network-local), 5s timeout — same conventions as the existing is_group_allowed / is_platform_admin helpers in plugins/swarm_map_policy.

Feature flag & safe-deploy story

Enforcement is gated behind TELEGRAM_GROUP_AUTOAPPROVE (true/1/yes/on; default off):

  • Flag unset (default): bot-added events are logged at INFO and nothing else happens — byte-for-byte the current behavior. Fleet containers can pick up this image before the HSM endpoint ships without bots declining and leaving groups admins add them to.
  • Flag set: full enforcement, fail-closed. Enable per-agent once the paired HSM deploy is live.

Handler only fires on transitions INTO a group/supergroup (left/kicked/none → member/administrator); promotions/demotions, the bot leaving, and private/channel chats are no-ops, so approval can't double-fire.

Also documents the previously-undocumented TELEGRAM_ALLOW_BOTS in .env.example.

Tests

  • tests/plugins/test_swarm_map_policy.py — 10 new tests: approve_group_add response matrix (approved / already_allowed / restarted:false / not approved / 400 / network error / missing field / non-bool approved / unconfigured HSM / exact URL+body)
  • tests/gateway/test_telegram_group_autoapprove.py — 9 new tests: approved greets+stays, denied declines+leaves, flag-off no-op, promotion no-op, bot-leaving no-op, private-chat no-op, plain group enforced, approval exception fails closed, decline-send failure still leaves

Results:

  • tests/gateway/test_telegram_group_autoapprove.py + tests/plugins/test_swarm_map_policy.py: 41 passed
  • Full tests/gateway -k telegram sweep: 1226 passed, 8 failed — the same 8 order-dependent failures reproduce on clean origin/main (escaping/model-picker/network-classifier tests; all pass in isolation on both trees). Pre-existing pollution, not introduced here.
  • ruff check on all touched files: clean.

🤖 Generated with Claude Code

juniperbevensee and others added 2 commits July 24, 2026 18:08
POST /api/harnesses/{harness}/surfaces/{platform}/groups/{groupId} with
{addedByUserId} — HSM verifies the adder is a platform admin and updates
the group allowlist. Fail-closed like the existing helpers: returns True
only on HTTP 200 with approved:true; network errors, non-200, and
missing/non-bool fields all deny. 5s timeout, no auth (HSM is
network-local), consistent with is_group_allowed/is_platform_admin.

Pairs with the HSM endpoint added in hermes-swarm-map PR #181.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Register a ChatMemberHandler (MY_CHAT_MEMBER scope) so the adapter
finally sees its own membership changes — allowed_updates=ALL_TYPES
already requested them, but they were silently dropped with no handler.

New _handle_my_chat_member acts only on transitions INTO a
group/supergroup (left/kicked/none -> member/administrator); promotions,
demotions, the bot leaving, and private/channel chats are ignored.

Behavior is feature-flagged behind TELEGRAM_GROUP_AUTOAPPROVE:
- unset/false (default): log the add at INFO and do nothing — identical
  to today's behavior, safe to deploy before the HSM endpoint is live
- true: call swarm_map_policy.approve_group_add (HSM checks the adder is
  a platform admin and updates the allowlist). Approved -> greet the
  group; denied/error -> one polite decline, then leave_chat
  (fail-closed, mirroring the Mattermost _handle_channel_join gate)

Document TELEGRAM_GROUP_AUTOAPPROVE and the previously-undocumented
TELEGRAM_ALLOW_BOTS in .env.example.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant