Files
2026-09-16 06:26:16 +02:00

6.6 KiB

Erweiterungsplan: mehrere Ein- und Ausgänge

Stand: 2026-09-15 · 0.1.0-alpha.5

Update: Ausbau umgesetzt

SQLite-Outbox, Retry/Deduplizierung, SMTP-Ausgang, IMAP-Eingang, ntfy-/Gotify-Ausgänge, Discord-Slash-Commands, Zustellhistorie, Readiness und Prometheus-Zustandsmetriken sind implementiert. Hinzu kommen bcrypt, CSRF-/Origin-Prüfung, CSP, Login-Limits, Body-Limits und Secret-Referenzen über Umgebungsvariablen. Die API antwortet jetzt nach Speicherung mit HTTP 202. Einrichtung und Grenzen: OPERATIONS.md.

Prüfungen umfassen SQLite-Neustart/Leases/Parallelannahme, selektive Wiederholung, lokale SMTP-/IMAP-Server mit TLS, Discord-Signaturen und einen echten Browser-Test. OAuth2, HTML-Mail-Konvertierung, Aufbewahrungsregeln, Verschlüsselung at rest und CI/Lasttests bleiben Folgearbeiten.

Bewertung des Projekts

Das Go-Projekt besitzt bereits brauchbare Bausteine: authentifizierte ntfy-, Gotify- und Webhook-Eingänge, ein gemeinsames Nachrichtenmodell, Regeln mit Templates, einen Divera247-Client und eine formularbasierte Administration. Der wichtigste architektonische Engpass war die feste Kopplung des Dispatchers an Divera247. Weitere Eingänge allein hätten die möglichen Empfänger nicht erweitert.

Die JSON-Konfiguration bleibt bestehen; SQLite speichert jetzt Zustellaufträge, Checkpoints und Historie. Ein vollständiger Ausbau aller Divera247-Endpunkte hat gegenüber Provider-Auswahl und Zustellzuverlässigkeit zunächst geringere Priorität.

Prioritäten und Abnahmekriterien

Schritt Umfang Abnahme / Status
1: Ausgangsmodell Benannte Ziele, Zuordnung pro Regel, Dry-Run pro Ausgang, Vorschau Umgesetzt; vorhandene Divera247-Regeln behalten ihr Schema
2: HTTP-Ausgänge Discord-Webhooks und generische JSON-Webhooks, Token, Timeout, einzelne Ergebnisse Umgesetzt; lokale HTTP-Tests, keine echten Nachrichten
3: Zuverlässigkeit SQLite-Outbox, Delivery-ID, Idempotenz pro Ziel, Retry/Backoff, Retry-After, Dead-Letter und Audit Neustart verliert keine angenommene Nachricht; bereits erfolgreiche Ziele werden bei Wiederholung nicht erneut versendet
4: Mail-Ausgang SMTP, verpflichtendes TLS/STARTTLS, Secret-Referenzen, Absender und Empfänger, MIME/UTF-8 Tests gegen lokalen SMTP-Server; Header-Injection, TLS-Fehler und Timeouts abgedeckt
5: Mail-Eingang IMAP über TLS, Ordner, UID/UIDVALIDITY-Checkpoint, MIME-Text, Absender-/Empfängerfilter Wiederanlauf ohne Verlust/Doppelverarbeitung; Nachricht erst nach persistenter Annahme quittieren; Limits für MIME/Anhänge
6: Weitere Push-Ausgänge ntfy und Gotify; danach Slack/Teams nach Bedarf Dokumentierte Provider-Payloads, Fehlerfälle und Admin-Vorschau
7: Discord-Eingang Slash-Command/Interaction mit Signaturprüfung; Bot-Gateway nur für benötigtes Kanal-Monitoring Signaturen, Zeitfenster, Channel-/Guild-Allowlist, schnelle Quittierung und Schleifenschutz
8: Betrieb Delivery-Historie mit Wiederholen, Readiness, Metriken, Secret-Referenzen, CSRF/Passwort-Härtung, CI Betriebsfehler diagnostizierbar; keine Secrets in Logs; reproduzierbare automatisierte Prüfungen

Schritt 3 geht Live-Retries und Mail-Polling voraus: Bei mehreren Empfängern darf eine erneute Eingangsanfrage nicht alle schon erfolgreichen Zustellungen wiederholen. Netzwerkzustellung kann trotz Timeout erfolgt sein; „exactly once“ ist ohne Unterstützung des Zielsystems nicht garantiert.

Datenfluss und Erweiterungspunkte

Eingangsadapter → Authentifizierung → InboundMessage → Regeln/Templates → Ausgang → DeliveryResult

  • internal/config/outbound.go: benannte Ausgangskonfiguration und Validierung.
  • internal/gateway: Auswahl der Regeln, providerabhängige Payloads, Vorschau, Weiterleitung an alle passenden Regeln und Sammlung von Fehlern.
  • internal/outbound: HTTP-Transport für Discord und JSON-Webhooks.
  • internal/divera: bestehender spezialisierter Divera247-Client.
  • internal/httpserver: Admin-Formulare, bestehende Eingänge und APIs.

Ein Ausgang ist eine Verbindung, eine Regel bestimmt Inhalt und Ziel. Mehrere Regeln können denselben Eingang an unterschiedliche Ausgänge verteilen. SMTP hat einen eigenen Transport; ein dynamisches Pluginsystem ist für die wenigen eingebauten Adapter derzeit nicht nötig.

Umfang des ersten Implementierungsschritts

  • outbounds[] mit ID, Name, Provider, URL, optionalem Bearer-Token, Timeout und explizitem live-Schalter (Standard: false).
  • target: discord|webhook und outbound_id in Zuordnungen.
  • CRUD-Formulare im Bereich Ausgänge, Zielauswahl und Payload-Vorschau.
  • Discord: wait=true, keine automatischen Mentions, leere oder zu lange Texte werden zurückgewiesen; keine stille Kürzung/Mehrfachnachrichten.
  • HTTP-Webhooks: POST JSON mit gemapptem Titel/Text/Adresse und Metadaten; Raw-Eingaben und Divera247-Extras werden nicht automatisch weitergegeben.
  • URLs, Referenzen, Provider, Timeout und Template-Syntax validieren.
  • HTTP-Redirects blockieren; URLs/Tokens und Remote-Antwortinhalte nicht in Ergebnisse/Fehler der neuen Ausgänge übernehmen.
  • Bei Fehlern weitere passende Regeln versuchen und Einzelergebnisse liefern.
  • Regression: identische Regex in mehreren Bedingungen separat prüfen.

Bewusste Grenzen

Ein Worker verarbeitet die persistente Queue sequenziell. Historie und Deduplizierungsbelege werden noch unbegrenzt aufbewahrt. Ohne expliziten HTTP-Idempotency-Key wird jede Anfrage neu angenommen. Ein unklarer Netzwerkausgang kann trotz stabiler Delivery-ID eine Doppelzustellung beim Ziel verursachen.

IMAP unterstützt Plain-Text-MIME bis 1 MiB; problematische Nachrichten blockieren ihren Checkpoint bis zur Korrektur. Discord-Ingress verarbeitet Slash-Commands, kein allgemeines Channel-Monitoring. Discord-Ausgänge unterstützen Text in normalen Kanälen bzw. bestehende Threads via thread_id in der URL; keine Dateien, Embeds oder automatische Forum-Thread-Erstellung. Webhook-URLs und Tokens liegen wie bisherige Provider-Secrets in der Admin-Konfiguration. Die neuen Transport-Schutzmaßnahmen ersetzen keine projektweite Überarbeitung des bestehenden Divera247-Fehlerhandlings.

Protokollquellen

SMTP nutzt Go net/smtp; IMAP und MIME verwenden die emersion-Bibliotheken. Passwort-/App-Passwort-Anmeldung ist implementiert; OAuth2 bleibt ein eigener Umfang.