ADR-0068: Telegram als zweiter Messaging-Kanal für Feldkontakte
Kontext
Der WhatsApp-Kanal (ADR-0060) ist für kleine Kunden schwer zu erreichen: Meta Business-Verifizierung, Template-Freigabe und Token-Pflege (ablaufende Zugriffstoken, Systemnutzer) kosten Tage bis Wochen und Know-how, das dort selten vorhanden ist. Ein Telegram-Bot braucht dagegen nur einen Token von @BotFather, den der Org-Admin in wenigen Minuten erzeugt. Die MessagingBackend-Abstraktion aus ADR-0060 war dafür vorgesehen.
Entscheidung
- Telegram Bot API als zweiter Adapter neben WhatsApp. Ein Bot pro Organisation, nur private 1:1-Chats. Gruppen, Kanäle und bearbeitete Nachrichten werden ignoriert.
- Verbindung als
integration_connectionsmitprovider = 'telegram'. Der Bot-Token ist Fernet-verschlüsselt und write-only.configenthältbot_id(aus dem Token-Präfix) und nach dem Testbot_username. - Einrichtung ohne Handarbeit bei Telegram. Speichern führt automatisch Verbindung testen aus:
getMeprüft den Token und liefert den @Benutzernamen,setWebhookregistriert{Webhook-Basis-URL}/api/v1/webhooks/telegram/{path_token}mit zufälligemsecret_token(verschlüsselt inwebhook_endpoints.secret_enc) undallowed_updates = message, callback_query. Voraussetzung ist die öffentliche Webhook-Basis-URL (HTTPS), die der Systemadmin unter System → Webhooks setzt. - Routing über
messaging_channels(provider = 'telegram', external_id = bot_id)→ Mandant. Ein Bot gehört genau einer Organisation (409sonst). Beim Entfernen der Verbindung wird das Routing freigegeben unddeleteWebhookaufgerufen (best effort). - Webhook
POST /api/v1/webhooks/telegram/{path_token}: Der HeaderX-Telegram-Bot-Api-Secret-Tokenwird gegen das gespeicherte Secret geprüft (401sonst), Antwort sofort202, die Verarbeitung übernimmt der Celery-Tasklinetra.messaging.handle_telegram(Queuesync). Idempotenz übermessages.external_id = tg:{chat_id}:{message_id}. - Identität per Einladungslink statt Telefonnummer. Ein Bot sieht keine Nummern. Das Büro erzeugt je Person einen Link
https://t.me/<bot>?start=<token>(7 Tage gültig). Der Token ist zustandslos, HMAC-SHA256-signiert mitSESSION_SECRETund an Organisation und Person gebunden. Tippt die Person in Telegram auf Starten, wird der Chat alscontact_identities(channel = 'telegram', external_id = chat_id)verknüpft. Starten gilt als Opt-in (opt_in_atwird gesetzt), der Bot antwortet mit einer Begrüßung. - Kein Übernehmen. Ein Link kann weder eine Person übernehmen, die schon mit einem anderen Chat verknüpft ist, noch einen Chat, der zu einer anderen Person gehört. Abgelaufene oder gefälschte Links bekommen eine höfliche Antwort. Der Einladungs-Token wird nie in Nachrichten gespeichert (der gespeicherte Text ist nur
/start). Trennen widerruft die Identität; der Chat ist danach wieder unbekannt, der Verlauf bleibt zugeordnet. - Unbekannte Chats bekommen eine Standardantwort mit Hinweis auf den Einladungslink und landen als unbekannter Kontakt in der Inbox; verarbeitet wird nichts.
- Eingang von verknüpften Kontakten läuft durch dieselbe Assistant-Pipeline wie bei WhatsApp (ADR-0061): Vorschläge, Backoffice-Freigabe, keine direkten Schreibrechte. Fotos, Sprachnachrichten und Dokumente werden mit
kindimage/audio/documentund der Bildunterschrift alsbodyabgelegt; der Medien-Download ist (wie bei WhatsApp) noch nicht angebunden. - Ausgehend: Es gibt weder Templates noch ein 24-Stunden-Fenster. Lange Texte werden bei 4096 Zeichen geteilt. Der Bot kann nicht als Erster schreiben, bevor der Kontakt Starten gedrückt hat.
- Briefings: Hat eine Person einen verknüpften Telegram-Chat, gewinnt er gegenüber der aus der Telefonnummer abgeleiteten WhatsApp-Identität; sonst WhatsApp wie bisher.
- Versand je Konversation:
load_tenant_messengerslädt pro Mandant die aktiven Backends (WhatsApp und Telegram). Jede Unterhaltung wird über ihren eigenen Kanal gesendet; ein Kanal ohne Verbindung wird simuliert (die Nachricht steht trotzdem in der Inbox). - API: Verknüpft wird pro Mitarbeiter der Organisation (Kontomenü → Organisation → Mitarbeiter), nicht in den Stammdaten.
POST /api/v1/users/{user_id}/telegram-invite→{url, expires_at}(Mitarbeiter verwalten;400, wenn kein getesteter Bot existiert),DELETE /api/v1/users/{user_id}/telegram(204),ManagedUserOut.telegram_linked./api/v1/integrationsakzeptierttelegram; Telegram-Zeilen tragenwebhook_url. - Keine Migration. Bestehende Tabellen (
integration_connections,webhook_endpoints,messaging_channels,contact_identities,conversations,messages) werden wiederverwendet.
Begründung
Der Engpass bei kleinen Kunden ist nicht die Technik, sondern die Plattform-Hürde. Telegram senkt sie auf einen Token. Weil der Bot keine Nummern sieht, muss die Identität anders entstehen: Der signierte, ablaufende Einladungslink bindet einen Chat bewusst an eine Person und ersetzt die von Meta verifizierte Nummer. Das Risiko (Link weitergegeben) ist durch Einmal-Verknüpfung, Ablauf und die Bestätigungsschleife der Pipeline (ADR-0061) begrenzt. Das secret_token-Verfahren von Telegram ersetzt die Signaturprüfung von Meta.
Verworfene Alternativen
| Alternative | Warum verworfen |
|---|---|
| Telegram-Benutzerkonto statt Bot („Userbot“) | Verstößt gegen die Telegram-Nutzungsbedingungen, Sperrrisiko; hängt an einer privaten Nummer |
| Gruppen-Bot pro Projekt | Datentrennung je Kontakt und Projekt gilt wie bei WhatsApp; Gruppen bleiben außerhalb des Scopes |
| Webhook manuell bei Telegram eintragen | Fehleranfällig; setWebhook per API macht den Schritt überflüssig |
| WhatsApp ersetzen | Viele Feldmitarbeiter haben WhatsApp bereits; beide Kanäle laufen nebeneinander |
Folgen
- Einrichtung in Minuten statt Wochen: kein Meta-Konto, keine Template-Freigabe, kein ablaufender Token.
- Keine Fensterlogik und keine Templates; Briefings und Rückfragen kommen jederzeit an.
- Feldmitarbeiter müssen Telegram installieren und den Einladungslink einmal öffnen.
- Der Bot kann nicht zuerst schreiben; vor Starten ist keine Zustellung möglich.
- Die Telefonnummer des Kontakts ist nicht sichtbar. Die Zuordnung hängt allein am Einladungslink, der vertraulich zu übermitteln ist.
- Ein Bot gehört genau einer Organisation; ein Wechsel erfordert Entfernen der Verbindung.
- Datenschutz: Telegram ist ein weiterer Drittanbieter; Opt-in (Starten) und Löschfrist (Default 180 Tage) gelten wie bei WhatsApp. Die datenschutzrechtliche Bewertung ist offen.
- Medien-Download (Fotos, Sprache, Dokumente) ist noch nicht angebunden.
- Der Webhook-Pfad
/api/v1/webhooksist bereits per Traefik auf das Backend geroutet; die öffentliche Webhook-Basis-URL muss unter System → Webhooks gesetzt sein, sonst schlägt Verbindung testen fehl.