Telegram Bridge Multi-Tenant — Test Results
Date: 2026-04-09
Broker Commit: e3fa6e6
Feature: Multi-tenant Telegram bridge (4 entry points)
Tester: Mou (Claude Opus 4.6) + Playwright automation
Bot: @claudemeshbot
Test Results: 27/30 PASS
1. Broker Deploy + Bridge Boot
| # |
Test |
Result |
Notes |
| T1 |
Broker deploys with telegram env vars |
PASS |
Deploy n55iiz489hkr finished |
| T2 |
Bridge boots on startup |
PASS |
[tg-bridge] bot running — 0 mesh(es), 0 chat(s) |
| T3 |
Health check |
PASS |
{"status":"ok","db":"up","uptime":55} |
2. Token Endpoint
| # |
Test |
Result |
Notes |
| T4 |
POST /tg/token returns JWT + deep link |
PASS |
703-char JWT |
| T5a |
Token sub=telegram-connect |
PASS |
|
| T5b |
Token iss=claudemesh-broker |
PASS |
|
| T5c |
Token has exp (15min TTL) |
PASS |
900s from iat |
| T5d |
Token has meshId |
PASS |
|
| T6 |
Deep link format |
PASS |
https://t.me/claudemeshbot?start=<jwt> |
| T7 |
Missing fields rejected |
PASS |
400 error |
3. Entry Point A: Deep Link /start (Playwright)
| # |
Test |
Result |
Notes |
| T8 |
Generate token via API |
PASS |
|
| T9 |
/start connects |
PASS |
"Connected to mesh alexis-mou!" |
| T10 |
Bridge row in DB |
PASS |
chatId=845184042, active=true |
| T11 |
Peer in list_peers |
PASS |
tg:Alejandro [idle] {type:bridge, channel:telegram} |
4. Message Routing (Playwright)
| # |
Test |
Result |
Notes |
| T12 |
Telegram -> Mesh broadcast |
PASS |
Received as <channel> in Claude Code |
| T13 |
Mesh -> Telegram |
PASS |
send_message(to: "tg:Alejandro") appeared in bot chat |
| T14 |
/dm Mou |
PASS |
DM delivered, peer responded |
| T15 |
Peer picker (multi-match) |
PASS |
Inline keyboard: Mou (idle), Mou (all), Mou (Desktop), Send to ALL |
| T16 |
@mention DM |
PASS |
@Mou triggered peer picker |
5. File Sharing
| # |
Test |
Result |
Notes |
| T17 |
Send photo from Telegram |
DEFERRED |
Playwright can't trigger native file dialog in Telegram Web |
| T18 |
/file download |
DEFERRED |
Requires T17 |
| T19 |
File download proxy |
DEFERRED |
Requires T17 |
6. Bot Commands (Playwright)
| # |
Test |
Result |
Notes |
| T20 |
/peers |
PASS |
Full peer list with bridge peer |
| T21 |
/meshes |
PASS |
Connected meshes listed |
| T22 |
/status |
PASS |
Bridge status info shown |
| T23 |
/help |
PASS |
All 10 commands listed |
| T24 |
/broadcast |
PASS |
Message received by mesh peers |
7. Disconnect + Reconnect
| # |
Test |
Result |
Notes |
| T25 |
/disconnect |
PASS |
DB: active=false, disconnected_at set |
| T26 |
Peer gone from list_peers |
KNOWN LIMITATION |
WS stays open (TTL sweep needed) |
| T27 |
Reconnect via /start |
PASS |
"Already connected" — upsert works |
8. Entry Point D: Invite URL Detection
| # |
Test |
Result |
Notes |
| T28 |
Paste invite URL in bot chat |
PASS |
"Detected invite link" with token extraction |
9. Entry Point B: CLI QR Code
| # |
Test |
Result |
Notes |
| T29 |
claudemesh connect telegram |
PASS |
QR code rendered in terminal |
| T30 |
claudemesh connect telegram --link |
PASS |
Plain deep link URL output |
Summary
| Category |
Pass |
Deferred |
Known Limitation |
| Infra + Deploy |
3 |
0 |
0 |
| Token Endpoint |
7 |
0 |
0 |
| Entry Point A (/start) |
4 |
0 |
0 |
| Message Routing |
5 |
0 |
0 |
| File Sharing |
0 |
3 |
0 |
| Bot Commands |
5 |
0 |
0 |
| Disconnect/Reconnect |
2 |
0 |
1 |
| Entry Point D (URL) |
1 |
0 |
0 |
| Entry Point B (CLI) |
2 |
0 |
0 |
| Total |
27 |
3 |
1 |
Bugs Found & Fixed During Testing
- Lockfile mismatch —
pnpm-lock.yaml not updated for telegram deps
- Grammy not in broker deps — added to broker
package.json
- Bot username —
claudemeshbot not claudemesh_bot
- Wire agent missed — Wave 2 edits lost, rewired manually
- Healthcheck too short — 10s start-period → 30s, 3 retries → 5
- Grammy crash guard —
.catch() on bot.start() promise
- Duplicate key on reconnect —
INSERT → onConflictDoUpdate upsert
Screenshots
All screenshots saved to /tmp/tg-tests/:
- 01-telegram-home.png through 27-file-upload.png
- Key screenshots: 10-start-sent.png (T9), 15-broadcast.png (T24), 17-dm.png (T14), 18-dm-picked.png (T15)