# 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=` | | 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 `` 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 1. **Lockfile mismatch** — `pnpm-lock.yaml` not updated for telegram deps 2. **Grammy not in broker deps** — added to broker `package.json` 3. **Bot username** — `claudemeshbot` not `claudemesh_bot` 4. **Wire agent missed** — Wave 2 edits lost, rewired manually 5. **Healthcheck too short** — 10s start-period → 30s, 3 retries → 5 6. **Grammy crash guard** — `.catch()` on `bot.start()` promise 7. **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)