Integration with XMPP for notifications (SZ-77)
Artur Hefczyc opened 3 months ago

This could/should probably be more general to send notifications. And we could support different channels through plugins or modules, like XMPP, email, text messages (Twillio API), etc...

  • rk@tigase.net commented 3 months ago

    I assume I should use Togase XMPP server. Please point me to any documentation on how to integrate Sztab with Tigase XMPP

  • Artur Hefczyc commented 3 months ago

    Yes, I would like to do this integration with Tigase. Tigase offers some REST APIs that we could/should use.

  • rk@tigase.net referenced from other issue 2 months ago
  • rk@tigase.net referenced from other issue 2 months ago
  • rk@tigase.net referenced from other issue 2 months ago
  • rk@tigase.net referenced from other issue 1 month ago
  • rk@tigase.net commented 1 week ago

    XMPP Integration in Sztab - Architecture Outline and Initial Scope

    1. XMPP's Place in Sztab

    1.1 Sztab => User Notifications

    The primary and most immediate use of XMPP. Sztab publishes human-readable messages to individual users via Tigase's REST API. The user receives them in any XMPP client (Conversations, Gajim, etc.). Sztab has no knowledge of XMPP protocol internals — it only speaks to Tigase over HTTP.

    Event types in scope long-term:

    • Issue assigned, reassigned, or overdue
    • Comment posted on a watched issue or PR
    • @mention in any comment
    • PR review requested or completed
    • Branch push linked to an issue (via SZ-122 auto-linking)
    • PAT approaching expiry
    • Scheduled reminders (standup prompts, overdue digests) — later phase

    1.2 Intra-Sztab Component Communication

    XMPP pub/sub (XEP-0060) as an internal async event bus between Sztab's own components, specifically where HTTP callbacks are today synchronous and fragile.

    The primary candidate is the Sztabina => Spring Boot post-receive hook. Today this is a synchronous HTTP callback that fails silently if Spring Boot is temporarily unavailable. Replacing it with an XMPP pub/sub node makes delivery async and decoupled - Sztabina publishes a git.push event, Spring Boot consumes it when ready.

    Candidate internal pub/sub topics:

    TopicPublisherSubscriber
    sztab.git.pushSztabinaSpring Boot (issue auto-linking, PR update)
    sztab.git.pr.openedSztabinaSpring Boot (PR lifecycle)
    sztab.import.progressImport worker (SZ-130)Spring Boot (status updates)
    sztab.ai.query.resultAI backend (future)Spring Boot (Copilot responses)

    This pattern also future-proofs Sztab for additional services without introducing a separate message broker (Kafka, RabbitMQ) into the stack. Tigase is already in the infrastructure - it earns its place as a lightweight internal bus at no additional operational cost.

    Important constraint: Tigase must not become a hard dependency for synchronous, latency-sensitive operations. Intra-process Spring application events remain the right tool inside the Spring Boot backend itself. XMPP pub/sub is for cross-process, cross-language async delivery only.

    1.3 Sztab Service Status Announcements

    XMPP has a well-established presence and availability model (RFC 6121) that maps naturally onto service status. Sztab can maintain a bot JID (e.g. sztab@tigase.example.com) whose XMPP presence reflects the health of the Sztab service.

    Two mechanisms are relevant here:

    Presence (RFC 6121) The Sztab bot JID publishes presence stanzas reflecting service state:

    • available - Sztab is fully operational
    • away - degraded (e.g. Sztabina unreachable, background jobs stalled)
    • unavailable - Sztab is down or in maintenance

    Any XMPP user who has subscribed to the bot JID sees this in their client's contact list as a live status indicator - no polling, no dashboard required.

    Service announcements via MUC or pub/sub (XEP-0045 / XEP-0060) For broadcast announcements (planned maintenance, release deployments, incident notifications), Sztab can publish to a dedicated XMPP channel or pub/sub node:

    • sztab-announce@conference.tigase.example.com (MUC room)
    • or sztab.status pub/sub node

    Stakeholders subscribe once and receive all future announcements passively. This is particularly useful for Artur and Andrzej - operational awareness without checking a separate status page.


    2. What Is Not XMPP's Job in Sztab

    To keep the architecture honest:

    • Intra-Spring Boot communication - Spring application events
    • Synchronous service-to-service calls - HTTP/REST as today
    • Database-backed state - PostgreSQL as today
    • Authentication - Sztab's own session/PAT mechanism

    XMPP handles async human-facing delivery and async cross-process eventing. Nothing else.


    3. Initial Scope: First Cut

    3.1 Objectives

    Deliver two things only:

    1. Sztab => User notifications for a defined initial event set
    2. Sztab service status announcements via bot presence and a status pub/sub node

    No inbound message handling. No bot commands. No pub/sub for internal component communication. Those are follow-on phases.

    3.2 Core Abstraction

    A NotificationEvent domain object:

    public record NotificationEvent(
        String recipientJid,   // resolved from user profile
        NotificationEventType type,
        Map<String, String> payload  // issueId, title, actor, link, etc.
    ) {}
    

    NotificationEventType enum — initial values:

    • ISSUE_ASSIGNED
    • COMMENT_POSTED
    • MENTION
    • PR_REVIEW_REQUESTED
    • PR_REVIEW_COMPLETED

    3.3 Components to Build

    User JID field Optional per-user profile field. If absent, XMPP delivery is silently skipped for that user. User-supplied — no JID resolution or directory lookup in this phase.

    Notification dispatch service Thin orchestration layer. Receives NotificationEvent via Spring application events. Fans out to registered NotificationChannelAdapter implementations. Only the XMPP adapter is registered in this phase.

    public interface NotificationChannelAdapter {
        void deliver(NotificationEvent event);
    }
    

    Tigase REST adapter Implements NotificationChannelAdapter. POSTs to Tigase's HTTP API to deliver a message to the recipient JID. This is the only component in Sztab that knows XMPP exists. Configured via application.yml:

    sztab:
      notifications:
        xmpp:
          enabled: true
          tigase-rest-url: https://tigase.example.com
          bot-jid: sztab@tigase.example.com
          credentials:
            username: sztab-bot
            password: ${SZTAB_XMPP_BOT_PASSWORD}
    

    Message templates Plain text only. One template per event type. Short and actionable:

    [Sztab] SZ-00132: "Bug in login flow" assigned to you by artur.
    View: https://sztab.local/issues/SZ-00132
    

    Sztab bot presence publisher A Spring @Component that connects to Tigase on startup and publishes presence on behalf of the bot JID. Presence is updated by a health check scheduler:

    • Healthy => available
    • Degraded (Sztabina unreachable, job queue stalled) => away
    • Shutdown hook => unavailable

    Status announcement publisher On significant events (startup, shutdown, deployment, detected degradation), Sztab publishes a plain-text message to the sztab.status pub/sub node on Tigase. Administrators subscribe to this node once to receive all future announcements.

    3.4 Explicit Out of Scope for This Cut

    • Inbound XMPP message handling
    • Bot commands (/status, /create, etc.)
    • Email, SMS, or any other notification channel
    • Per-user notification preferences
    • Digest or batching of notifications
    • MUC room management
    • Intra-component pub/sub (Sztabina → Spring Boot)
    • GenAI / RAG
    • Admin UI for XMPP config: application.yml only

    3.5 Issues to File

    IssueDescription
    SZ-77 (update)Umbrella: pluggable NotificationChannelAdapter architecture
    NewUser JID field - profile settings and persistence
    NewTigase REST adapter - NotificationChannelAdapter implementation
    NewInitial five NotificationEventType values wired to dispatch
    NewSztab bot presence publisher - health-driven presence updates
    NewStatus announcement publisher - startup, shutdown, degradation events

    4. Natural Follow-On Phases

    For reference: not in scope now, but the architecture above accommodates all of these without structural change:

    • Phase 2 - Intra-component pub/sub: Sztabina => Spring Boot via sztab.git.push node replacing synchronous HTTP hook
    • Phase 3 - Bot command handling: inbound message parsing, /status, /create issue, structured query responses
    • Phase 4 - Per-user notification preferences: which event types to receive, per channel
    • Phase 5 - Executive NL query interface via XMPP bot backed by Sztab Copilot / RAG
issue 1 of 1
Type
New Feature
Priority
Normal
Assignee
Version
none
Sprints
n/a
Customer
n/a
Issue Votes (0)
Watchers (2)
Reference
SZ-77
Please wait...
Page is in error, reload to recover