Skip to content

feat: automatic Telegram bot creation via managed-bot pairing#600

Open
mrubens wants to merge 2 commits into
developfrom
feat/telegram-managed-bot-pairing
Open

feat: automatic Telegram bot creation via managed-bot pairing#600
mrubens wants to merge 2 commits into
developfrom
feat/telegram-managed-bot-pairing

Conversation

@mrubens

@mrubens mrubens commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

What

Adds an automatic path to Telegram setup using Telegram's Managed Bots feature (Bot API 9.6). Instead of walking through BotFather and copy-pasting a token, the setup wizard shows a QR code / deep link; the admin taps Create Bot once in Telegram, and Roomote receives the new bot's token directly, saves it, registers the webhook, and continues to the existing account-link step.

The bot token never passes through the browser: the wizard's server polls the pairing service with a server-side bearer token and feeds the result straight into the existing saveAuthConfig path.

How it works

  1. POST /api/webhooks/telegram-pairing (on a deployment configured with a manager bot) mints a pairing: a high-entropy suggested bot username (roomote_<slug>_bot, the correlation key), a secret poll token (stored hashed), and a t.me/newbot/<manager>/<username> deep link.
  2. The admin confirms creation in Telegram. Telegram sends the manager bot a managed_bot update to /api/webhooks/telegram-manager (secret-token verified); the service fetches the child bot's token via getManagedBotToken and marks the pairing ready.
  3. The admin's deployment polls GET /api/webhooks/telegram-pairing/:id and receives the token exactly once (one-shot retrieval, 15-minute TTL in Redis).

Configuration

  • Client deployments: R_TELEGRAM_PAIRING_URL=<public origin of a deployment running the pairing service> lights up the wizard's automatic path. Unset = manual token entry, unchanged.
  • Pairing-service host: R_TELEGRAM_MANAGER_BOT_TOKEN, R_TELEGRAM_MANAGER_BOT_USERNAME, R_TELEGRAM_MANAGER_WEBHOOK_SECRET (manager bot needs Bot Management Mode enabled in BotFather). All endpoints 404 when unset.

Changes

  • packages/communication: telegram-managed-bot protocol helpers (deep link, username slugs, update parsing, getManagedBotToken, manager webhook registration); mock Telegram server support for getManagedBotToken.
  • apps/api: pairing service handlers + Redis store, route policy entries with rate limits, token-auth bypass for the pairing paths (they authenticate with their own bearer poll token). Mounted under /api/webhooks/ so the web app's existing webhook proxy exposes them.
  • apps/web: comms.startTelegramPairing / comms.checkTelegramPairing commands, telegramPairingAvailable on comms status, wizard UI with QR code (new qrcode.react dep) and a manual-entry escape hatch both ways.
  • apps/docs: Telegram provider page documents both paths.

Testing

  • 9 protocol tests against the mock Telegram server (packages/communication)
  • 7 service tests covering the full create → webhook → poll → one-shot flow plus auth failures (apps/api)
  • 9 client-command tests (apps/web)
  • Existing Telegram step/comms/mock-server/env tests still pass; lint:fast, check-types, and knip clean.

Notes

  • Telegram's public Bot API docs don't spell out getManagedBotToken's response shape; the parser accepts both a bare string and {token}, and the manager webhook returns 500 on fetch failure so Telegram redelivers. Worth watching logs on the first live pairing.
  • The automatic path stays dark until a hosted pairing service exists and R_TELEGRAM_PAIRING_URL points at it; a follow-up can bake in a default URL.

Adds a pairing service (Bot API 9.6 Managed Bots) so the setup wizard can
create a deployment's Telegram bot with one tap in Telegram instead of
manual BotFather token copy-paste. The bot token goes straight from the
pairing service to the deployment server and never touches the browser.
@roomote-roomote

roomote-roomote Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

No new code issues found. See task

  • packages/env/src/index.ts:185 Add the manager bot token and manager webhook secret to INTEGRATION_BOT_SECRET_ENV_VAR_NAMES. They are currently neither reserved from the generic deployment-env editor nor removed from task environments, allowing an agent to read the manager token and export managed child-bot tokens.
  • apps/web/src/trpc/commands/comms/telegram-pairing.ts:154 Do not consume the one-shot service token before configuration persistence succeeds. If saveCommsAuthConfigCommand throws, the service has already deleted the pairing, so every retry reports expired and the newly created bot can no longer be connected.

Reviewed 494338c

- Reserve the manager-bot token and webhook secret (and the manager
  username) as control-plane env vars so they never reach task sandboxes
  or the generic env editor; the manager token can export tokens for
  every managed child bot.
- Stash the one-shot pairing token in Redis before persisting, so a
  failed save no longer strands a freshly created bot; the wizard keeps
  polling and the retry recovers from the stash.
@mrubens

mrubens commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Both review findings addressed in 494338c:

  1. Manager secrets reserved: R_TELEGRAM_MANAGER_BOT_TOKEN and R_TELEGRAM_MANAGER_WEBHOOK_SECRET are now in INTEGRATION_BOT_SECRET_ENV_VAR_NAMES, and R_TELEGRAM_MANAGER_BOT_USERNAME in PROVIDER_IDENTIFIER_ENV_VAR_NAMES, so all three are reserved from the generic env editor and stripped from task sandboxes.

  2. One-shot token no longer lost on save failure: checkTelegramPairingCommand now stashes the retrieved token in Redis (15 min TTL) before calling the save path. If persistence throws, the next poll recovers from the stash without contacting the service, and the wizard keeps polling through transient errors instead of abandoning the pairing. Covered by a new regression test that fails the first save, 404s the service, and verifies the retry still connects the bot.

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