Skip to content

ADR-0068: Telegram als zweiter Messaging-Kanal für Feldkontakte

  • Status: accepted
  • Datum: 2026-10-09
  • Phase: Prozessmanagement
  • Bezug: ADR-0060, ADR-0061

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

  1. 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.
  2. Verbindung als integration_connections mit provider = 'telegram'. Der Bot-Token ist Fernet-verschlüsselt und write-only. config enthält bot_id (aus dem Token-Präfix) und nach dem Test bot_username.
  3. Einrichtung ohne Handarbeit bei Telegram. Speichern führt automatisch Verbindung testen aus: getMe prüft den Token und liefert den @Benutzernamen, setWebhook registriert {Webhook-Basis-URL}/api/v1/webhooks/telegram/{path_token} mit zufälligem secret_token (verschlüsselt in webhook_endpoints.secret_enc) und allowed_updates = message, callback_query. Voraussetzung ist die öffentliche Webhook-Basis-URL (HTTPS), die der Systemadmin unter System → Webhooks setzt.
  4. Routing über messaging_channels(provider = 'telegram', external_id = bot_id) → Mandant. Ein Bot gehört genau einer Organisation (409 sonst). Beim Entfernen der Verbindung wird das Routing freigegeben und deleteWebhook aufgerufen (best effort).
  5. Webhook POST /api/v1/webhooks/telegram/{path_token}: Der Header X-Telegram-Bot-Api-Secret-Token wird gegen das gespeicherte Secret geprüft (401 sonst), Antwort sofort 202, die Verarbeitung übernimmt der Celery-Task linetra.messaging.handle_telegram (Queue sync). Idempotenz über messages.external_id = tg:{chat_id}:{message_id}.
  6. 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 mit SESSION_SECRET und an Organisation und Person gebunden. Tippt die Person in Telegram auf Starten, wird der Chat als contact_identities(channel = 'telegram', external_id = chat_id) verknüpft. Starten gilt als Opt-in (opt_in_at wird gesetzt), der Bot antwortet mit einer Begrüßung.
  7. 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.
  8. Unbekannte Chats bekommen eine Standardantwort mit Hinweis auf den Einladungslink und landen als unbekannter Kontakt in der Inbox; verarbeitet wird nichts.
  9. 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 kind image / audio / document und der Bildunterschrift als body abgelegt; der Medien-Download ist (wie bei WhatsApp) noch nicht angebunden.
  10. 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.
  11. 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.
  12. Versand je Konversation: load_tenant_messengers lä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).
  13. 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/integrations akzeptiert telegram; Telegram-Zeilen tragen webhook_url.
  14. 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/webhooks ist bereits per Traefik auf das Backend geroutet; die öffentliche Webhook-Basis-URL muss unter System → Webhooks gesetzt sein, sonst schlägt Verbindung testen fehl.