Example #1
0
def send_welcome_email_to_participant(
    participant_email: str, incident: Incident, db_session: SessionLocal
):
    """Sends a welcome email to the participant."""
    # we load the incident instance
    plugin = plugin_service.get_active_instance(
        db_session=db_session, project_id=incident.project.id, plugin_type="email"
    )
    if not plugin:
        log.warning("Participant welcome email not sent, not email plugin configured.")
        return

    message_kwargs = {
        "name": incident.name,
        "title": incident.title,
        "description": incident.description,
        "status": incident.status,
        "type": incident.incident_type.name,
        "type_description": incident.incident_type.description,
        "priority": incident.incident_priority.name,
        "priority_description": incident.incident_priority.description,
        "commander_fullname": incident.commander.individual.name,
        "commander_team": incident.commander.team,
        "commander_weblink": incident.commander.individual.weblink,
        "reporter_fullname": incident.reporter.individual.name,
        "reporter_team": incident.reporter.team,
        "reporter_weblink": incident.reporter.individual.weblink,
        "document_weblink": resolve_attr(incident, "incident_document.weblink"),
        "storage_weblink": resolve_attr(incident, "storage.weblink"),
        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
        "conference_weblink": resolve_attr(incident, "conference.weblink"),
        "conference_challenge": resolve_attr(incident, "conference.conference_challenge"),
        "contact_fullname": incident.commander.individual.name,
        "contact_weblink": incident.commander.individual.weblink,
    }

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        message_kwargs.update({"faq_weblink": faq_doc.weblink})

    conversation_reference = document_service.get_conversation_reference_document(
        db_session=db_session
    )
    if conversation_reference:
        message_kwargs.update(
            {"conversation_commands_reference_document_weblink": conversation_reference.weblink}
        )

    notification_text = "Incident Notification"
    plugin.instance.send(
        participant_email,
        notification_text,
        INCIDENT_PARTICIPANT_WELCOME_MESSAGE,
        MessageType.incident_participant_welcome,
        **message_kwargs,
    )

    log.debug(f"Welcome email sent to {participant_email}.")
Example #2
0
def send_incident_resources_ephemeral_message_to_participant(
    user_id: str, incident: Incident, db_session: SessionLocal
):
    """Sends the list of incident resources to the participant via an ephemeral message."""
    plugin = plugin_service.get_active_instance(
        db_session=db_session, project_id=incident.project.id, plugin_type="conversation"
    )
    if not plugin:
        log.warning("Incident resource message not sent, no conversation plugin enabled.")
        return

    message_kwargs = {
        "title": incident.title,
        "description": incident.description,
        "commander_fullname": incident.commander.individual.name,
        "commander_team": incident.commander.team,
        "commander_weblink": incident.commander.individual.weblink,
        "reporter_fullname": incident.reporter.individual.name,
        "reporter_team": incident.reporter.team,
        "reporter_weblink": incident.reporter.individual.weblink,
        "document_weblink": resolve_attr(incident, "incident_document.weblink"),
        "storage_weblink": resolve_attr(incident, "storage.weblink"),
        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
        "conference_weblink": resolve_attr(incident, "conference.weblink"),
        "conference_challenge": resolve_attr(incident, "conference.conference_challenge"),
    }

    if incident.incident_review_document:
        message_kwargs.update(
            {"review_document_weblink": incident.incident_review_document.weblink}
        )

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        message_kwargs.update({"faq_weblink": faq_doc.weblink})

    conversation_reference = document_service.get_conversation_reference_document(
        db_session=db_session
    )
    if conversation_reference:
        message_kwargs.update(
            {"conversation_commands_reference_document_weblink": conversation_reference.weblink}
        )

    # we send the ephemeral message
    plugin.instance.send_ephemeral(
        incident.conversation.channel_id,
        user_id,
        "Incident Resources Message",
        INCIDENT_RESOURCES_MESSAGE,
        MessageType.incident_resources_message,
        **message_kwargs,
    )

    log.debug(f"List of incident resources sent to {user_id} via ephemeral message.")
Example #3
0
def send_incident_created_notifications(incident: Incident, db_session: SessionLocal):
    """Sends incident created notifications."""
    notification_template = INCIDENT_NOTIFICATION.copy()

    if incident.status != IncidentStatus.closed:
        notification_template.insert(0, INCIDENT_NAME_WITH_ENGAGEMENT)
    else:
        notification_template.insert(0, INCIDENT_NAME)

    notification_kwargs = {
        "name": incident.name,
        "title": incident.title,
        "description": incident.description,
        "status": incident.status,
        "type": incident.incident_type.name,
        "type_description": incident.incident_type.description,
        "priority": incident.incident_priority.name,
        "priority_description": incident.incident_priority.description,
        "reporter_fullname": incident.reporter.individual.name,
        "reporter_team": incident.reporter.team,
        "reporter_weblink": incident.reporter.individual.weblink,
        "commander_fullname": incident.commander.individual.name,
        "commander_team": incident.commander.team,
        "commander_weblink": incident.commander.individual.weblink,
        "document_weblink": resolve_attr(incident, "incident_document.weblink"),
        "storage_weblink": resolve_attr(incident, "storage.weblink"),
        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
        "conference_weblink": resolve_attr(incident, "conference.weblink"),
        "conference_challenge": resolve_attr(incident, "conference.conference_challenge"),
        "contact_fullname": incident.commander.individual.name,
        "contact_weblink": incident.commander.individual.weblink,
        "incident_id": incident.id,
    }

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        notification_kwargs.update({"faq_weblink": faq_doc.weblink})

    notification_params = {
        "text": "Incident Notification",
        "type": MessageType.incident_notification,
        "template": notification_template,
        "kwargs": notification_kwargs,
    }

    notification_service.filter_and_send(
        db_session=db_session,
        incident=incident,
        class_instance=incident,
        notification_params=notification_params,
    )

    log.debug("Incident created notifications sent.")
Example #4
0
def list_incidents(incident_id: int, command: dict = None, db_session=None):
    """Returns the list of current active and stable incidents,
    and closed incidents in the last 24 hours."""
    incidents = []

    # We fetch active incidents
    incidents = incident_service.get_all_by_status(
        db_session=db_session, status=IncidentStatus.active.value)
    # We fetch stable incidents
    incidents.extend(
        incident_service.get_all_by_status(db_session=db_session,
                                           status=IncidentStatus.stable.value))
    # We fetch closed incidents in the last 24 hours
    incidents.extend(
        incident_service.get_all_last_x_hours_by_status(
            db_session=db_session,
            status=IncidentStatus.closed.value,
            hours=24))

    blocks = []
    blocks.append({
        "type": "header",
        "text": {
            "type": "plain_text",
            "text": "List of Incidents"
        }
    })

    if incidents:
        for incident in incidents:
            if incident.visibility == Visibility.open:
                ticket_weblink = resolve_attr(incident, "ticket.weblink")
                try:
                    blocks.append({
                        "type": "section",
                        "text": {
                            "type":
                            "mrkdwn",
                            "text":
                            (f"*<{ticket_weblink}|{incident.name}>*\n"
                             f"*Title*: {incident.title}\n"
                             f"*Type*: {incident.incident_type.name}\n"
                             f"*Priority*: {incident.incident_priority.name}\n"
                             f"*Status*: {incident.status}\n"
                             f"*Incident Commander*: <{incident.commander.individual.weblink}|{incident.commander.individual.name}>"
                             ),
                        },
                    })
                except Exception as e:
                    log.exception(e)

    dispatch_slack_service.send_ephemeral_message(
        slack_client,
        command["channel_id"],
        command["user_id"],
        "Incident List",
        blocks=blocks,
    )
Example #5
0
def run_monitors(db_session,
                 project,
                 monitor_plugin,
                 incidents,
                 notify: bool = False):
    """Performs monitor run."""
    for incident in incidents:
        for monitor in incident.monitors:
            # once an instance is complete we don't update it any more
            if not monitor.enabled:
                continue

            log.debug(f"Processing monitor. Monitor: {monitor.weblink}")
            monitor_status = monitor_plugin.instance.get_match_status(
                weblink=monitor.weblink,
                last_modified=monitor.updated_at,
            )

            log.debug(f"Retrieved data from plugin. Data: {monitor_status}")
            if not monitor_status:
                continue

            monitor_status_old = monitor.status
            if monitor_status["state"] == monitor.status["state"]:
                continue

            monitor_service.update(
                db_session=db_session,
                monitor=monitor,
                monitor_in=MonitorUpdate(
                    id=monitor.id,
                    weblink=monitor.weblink,
                    enabled=monitor.enabled,
                    status=monitor_status,
                ),
            )

            if notify:
                send_monitor_notification(
                    project.id,
                    incident.conversation.channel_id,
                    INCIDENT_MONITOR_UPDATE_NOTIFICATION,
                    db_session,
                    monitor_state_old=monitor_status_old["state"],
                    monitor_state_new=monitor.status["state"],
                    weblink=monitor.weblink,
                    monitor_creator_name=resolve_attr(
                        monitor, "creator.individual.name"),
                )
Example #6
0
def send_incident_report_reminder(incident: Incident, report_type: ReportTypes,
                                  db_session: SessionLocal):
    """Sends a direct message to the incident commander indicating that they should complete a report."""
    message_text = f"Incident {report_type} Reminder"
    message_template = INCIDENT_REPORT_REMINDER
    command_name, message_type = get_report_reminder_settings(report_type)

    # check to see if there wasn't a recent report
    now = datetime.utcnow()
    if incident.last_tactical_report:
        last_reported_at = incident.last_tactical_report.created_at
        if now - last_reported_at < timedelta(hours=1):
            return

    plugin = plugin_service.get_active_instance(db_session=db_session,
                                                project_id=incident.project.id,
                                                plugin_type="conversation")
    if not plugin:
        log.warning(
            "Incident report reminder not sent, no conversation plugin enabled."
        )
        return

    report_command = plugin.instance.get_command_name(command_name)
    ticket_weblink = resolve_attr(incident, "ticket.weblink")

    items = [{
        "command": report_command,
        "name": incident.name,
        "report_type": report_type,
        "ticket_weblink": ticket_weblink,
        "title": incident.title,
    }]

    plugin.instance.send_direct(
        incident.commander.individual.email,
        message_text,
        message_template,
        message_type,
        items=items,
    )

    log.debug(
        f"Incident report reminder sent to {incident.commander.individual.email}."
    )
Example #7
0
def send_incident_update_notifications(incident: Incident,
                                       previous_incident: IncidentRead,
                                       db_session: SessionLocal):
    """Sends notifications about incident changes."""
    notification_text = "Incident Notification"
    notification_type = MessageType.incident_notification
    notification_template = INCIDENT_NOTIFICATION_COMMON.copy()

    change = False
    if previous_incident.status != incident.status:
        change = True
        notification_template.append(INCIDENT_STATUS_CHANGE)

    if previous_incident.incident_type.name != incident.incident_type.name:
        change = True
        notification_template.append(INCIDENT_TYPE_CHANGE)

    if previous_incident.incident_priority.name != incident.incident_priority.name:
        change = True
        notification_template.append(INCIDENT_PRIORITY_CHANGE)

    if not change:
        # we don't need to notify
        log.debug("Incident updated notifications not sent.")
        return

    notification_template.append(INCIDENT_COMMANDER)

    # we send an update to the incident conversation if the incident is active or stable
    if incident.status != IncidentStatus.closed:
        incident_conversation_notification_template = notification_template.copy(
        )
        incident_conversation_notification_template.insert(0, INCIDENT_NAME)

        convo_plugin = plugin_service.get_active_instance(
            db_session=db_session,
            project_id=incident.project.id,
            plugin_type="conversation")
        if convo_plugin:
            convo_plugin.instance.send(
                incident.conversation.channel_id,
                notification_text,
                incident_conversation_notification_template,
                notification_type,
                commander_fullname=incident.commander.individual.name,
                commander_team=incident.commander.team,
                commander_weblink=incident.commander.individual.weblink,
                incident_priority_new=incident.incident_priority.name,
                incident_priority_old=previous_incident.incident_priority.name,
                incident_status_new=incident.status,
                incident_status_old=previous_incident.status,
                incident_type_new=incident.incident_type.name,
                incident_type_old=previous_incident.incident_type.name,
                name=incident.name,
                ticket_weblink=incident.ticket.weblink,
                title=incident.title,
            )
        else:
            log.debug(
                "Incident updated notification not sent to incident conversation. No conversation plugin enabled."
            )

    # we send a notification to the notification conversations and emails
    fyi_notification_template = notification_template.copy()
    if incident.status != IncidentStatus.closed:
        fyi_notification_template.insert(0, INCIDENT_NAME_WITH_ENGAGEMENT)
    else:
        fyi_notification_template.insert(0, INCIDENT_NAME)

    notification_kwargs = {
        "commander_fullname": incident.commander.individual.name,
        "commander_team": incident.commander.team,
        "commander_weblink": incident.commander.individual.weblink,
        "contact_fullname": incident.commander.individual.name,
        "contact_weblink": incident.commander.individual.weblink,
        "incident_id": incident.id,
        "incident_priority_new": incident.incident_priority.name,
        "incident_priority_old": previous_incident.incident_priority.name,
        "incident_status_new": incident.status,
        "incident_status_old": previous_incident.status,
        "incident_type_new": incident.incident_type.name,
        "incident_type_old": previous_incident.incident_type.name,
        "organization_slug": incident.project.organization.slug,
        "name": incident.name,
        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
        "title": incident.title,
    }

    notification_params = {
        "text": notification_text,
        "type": notification_type,
        "template": fyi_notification_template,
        "kwargs": notification_kwargs,
    }

    notification_service.filter_and_send(
        db_session=db_session,
        incident=incident,
        class_instance=incident,
        notification_params=notification_params,
    )

    log.debug("Incident updated notifications sent.")
Example #8
0
def list_incidents(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    config: SlackConversationConfiguration = None,
    command: dict = None,
    db_session=None,
    slack_client=None,
):
    """Returns the list of current active and stable incidents,
    and closed incidents in the last 24 hours."""
    projects = []
    incidents = []
    args = command["text"].split(" ")

    # scopes reply to the current incident's project
    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

    if incident:
        # command was run in an incident conversation
        projects.append(incident.project)
    else:
        # command was run in a non-incident conversation
        if len(args) == 2:
            project = project_service.get_by_name(db_session=db_session, name=args[1])

            if project:
                projects.append()
            else:
                raise ValidationError(
                    [
                        ErrorWrapper(
                            NotFoundError(
                                msg=f"Project name '{args[1]}' in organization '{args[0]}' not found. Check your spelling."
                            ),
                            loc="project",
                        )
                    ],
                    model=BaseModel,
                )

        else:
            projects = project_service.get_all(db_session=db_session)

    for project in projects:
        # we fetch active incidents
        incidents.extend(
            incident_service.get_all_by_status(
                db_session=db_session, project_id=project.id, status=IncidentStatus.active
            )
        )
        # We fetch stable incidents
        incidents.extend(
            incident_service.get_all_by_status(
                db_session=db_session,
                project_id=project.id,
                status=IncidentStatus.stable,
            )
        )
        # We fetch closed incidents in the last 24 hours
        incidents.extend(
            incident_service.get_all_last_x_hours_by_status(
                db_session=db_session,
                project_id=project.id,
                status=IncidentStatus.closed,
                hours=24,
            )
        )

    blocks = []
    blocks.append({"type": "header", "text": {"type": "plain_text", "text": "List of Incidents"}})

    if incidents:
        for incident in incidents:
            if incident.visibility == Visibility.open:
                ticket_weblink = resolve_attr(incident, "ticket.weblink")
                try:
                    blocks.append(
                        {
                            "type": "section",
                            "text": {
                                "type": "mrkdwn",
                                "text": (
                                    f"*<{ticket_weblink}|{incident.name}>*\n"
                                    f"*Title*: {incident.title}\n"
                                    f"*Type*: {incident.incident_type.name}\n"
                                    f"*Priority*: {incident.incident_priority.name}\n"
                                    f"*Status*: {incident.status}\n"
                                    f"*Incident Commander*: <{incident.commander.individual.weblink}|{incident.commander.individual.name}>\n"
                                    f"*Project*: {incident.project.name}"
                                ),
                            },
                        }
                    )
                except Exception as e:
                    log.exception(e)

    dispatch_slack_service.send_ephemeral_message(
        slack_client,
        channel_id,
        user_id,
        "Incident List",
        blocks=blocks,
    )
Example #9
0
def list_incidents(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    command: dict = None,
    db_session=None,
    slack_client=None,
):
    """Returns the list of current active and stable incidents,
    and closed incidents in the last 24 hours."""
    projects = []
    incidents = []

    # scopes reply to the current incident's project
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    if incident:
        # command was run in an incident conversation
        projects.append(incident.project)
    else:
        # command was run in a non-incident conversation
        projects = project_service.get_all(db_session=db_session)

    for project in projects:
        # we fetch active incidents
        incidents.extend(
            incident_service.get_all_by_status(db_session=db_session,
                                               project_id=project.id,
                                               status=IncidentStatus.active))
        # We fetch stable incidents
        incidents.extend(
            incident_service.get_all_by_status(
                db_session=db_session,
                project_id=project.id,
                status=IncidentStatus.stable,
            ))
        # We fetch closed incidents in the last 24 hours
        incidents.extend(
            incident_service.get_all_last_x_hours_by_status(
                db_session=db_session,
                project_id=project.id,
                status=IncidentStatus.closed,
                hours=24,
            ))

    blocks = []
    blocks.append({
        "type": "header",
        "text": {
            "type": "plain_text",
            "text": "List of Incidents"
        }
    })

    if incidents:
        for incident in incidents:
            if incident.visibility == Visibility.open:
                ticket_weblink = resolve_attr(incident, "ticket.weblink")
                try:
                    blocks.append({
                        "type": "section",
                        "text": {
                            "type":
                            "mrkdwn",
                            "text":
                            (f"*<{ticket_weblink}|{incident.name}>*\n"
                             f"*Title*: {incident.title}\n"
                             f"*Type*: {incident.incident_type.name}\n"
                             f"*Priority*: {incident.incident_priority.name}\n"
                             f"*Status*: {incident.status}\n"
                             f"*Incident Commander*: <{incident.commander.individual.weblink}|{incident.commander.individual.name}>\n"
                             f"*Project*: {incident.project.name}"),
                        },
                    })
                except Exception as e:
                    log.exception(e)

    dispatch_slack_service.send_ephemeral_message(
        slack_client,
        channel_id,
        user_id,
        "Incident List",
        blocks=blocks,
    )
Example #10
0
def daily_report(db_session=None):
    """
    Creates and sends incident daily reports based on notifications.
    """
    for project in project_service.get_all(db_session=db_session):
        # we fetch all active, stable and closed incidents
        active_incidents = get_all_by_status(
            db_session=db_session,
            project_id=project.id,
            status=IncidentStatus.active.value)
        stable_incidents = get_all_last_x_hours_by_status(
            db_session=db_session,
            project_id=project.id,
            status=IncidentStatus.stable.value,
            hours=24,
        )
        closed_incidents = get_all_last_x_hours_by_status(
            db_session=db_session,
            project_id=project.id,
            status=IncidentStatus.closed.value,
            hours=24,
        )
        incidents = active_incidents + stable_incidents + closed_incidents

        # we map incidents to notification filters
        incidents_notification_filters_mapping = defaultdict(
            lambda: defaultdict(lambda: []))
        notifications = notification_service.get_all_enabled(
            db_session=db_session, project_id=project.id)
        for incident in incidents:
            for notification in notifications:
                for search_filter in notification.filters:
                    match = search_filter_service.match(
                        db_session=db_session,
                        filter_spec=search_filter.expression,
                        class_instance=incident,
                    )
                    if match:
                        incidents_notification_filters_mapping[
                            notification.id][search_filter.id].append(incident)

                if not notification.filters:
                    incidents_notification_filters_mapping[
                        notification.id][0].append(incident)

        # we create and send an incidents daily report for each notification filter
        for notification_id, search_filter_dict in incidents_notification_filters_mapping.items(
        ):
            for search_filter_id, incidents in search_filter_dict.items():
                items_grouped = []
                items_grouped_template = INCIDENT

                for idx, incident in enumerate(incidents):
                    try:
                        item = {
                            "commander_fullname":
                            incident.commander.individual.name,
                            "commander_team":
                            incident.commander.team,
                            "commander_weblink":
                            incident.commander.individual.weblink,
                            "incident_id":
                            incident.id,
                            "name":
                            incident.name,
                            "priority":
                            incident.incident_priority.name,
                            "priority_description":
                            incident.incident_priority.description,
                            "status":
                            incident.status,
                            "ticket_weblink":
                            resolve_attr(incident, "ticket.weblink"),
                            "title":
                            incident.title,
                            "type":
                            incident.incident_type.name,
                            "type_description":
                            incident.incident_type.description,
                        }

                        if incident.status != IncidentStatus.closed.value:
                            item.update({
                                "button_text":
                                "Join Incident",
                                "button_value":
                                str(incident.id),
                                "button_action":
                                f"{ConversationButtonActions.invite_user.value}-{incident.status}-{idx}",
                            })

                        items_grouped.append(item)
                    except Exception as e:
                        log.exception(e)

                notification_kwargs = {
                    "contact_fullname": DISPATCH_HELP_EMAIL,
                    "contact_weblink": DISPATCH_HELP_EMAIL,
                    "items_grouped": items_grouped,
                    "items_grouped_template": items_grouped_template,
                }

                notification_params = {
                    "text": INCIDENT_DAILY_REPORT_TITLE,
                    "type": MessageType.incident_daily_report,
                    "template": INCIDENT_DAILY_REPORT,
                    "kwargs": notification_kwargs,
                }

                notification = notification_service.get(
                    db_session=db_session, notification_id=notification_id)

                notification_service.send(
                    db_session=db_session,
                    project_id=notification.project.id,
                    notification=notification,
                    notification_params=notification_params,
                )
Example #11
0
def send_welcome_ephemeral_message_to_participant(participant_email: str,
                                                  incident_id: int,
                                                  db_session: SessionLocal):
    """Sends an ephemeral message to the participant."""
    # we load the incident instance
    plugin = plugin_service.get_active(db_session=db_session,
                                       plugin_type="conversation")
    if not plugin:
        log.warning(
            "Incident welcome message not sent, not conversation plugin enabled."
        )
        return

    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    # we send the ephemeral message
    message_kwargs = {
        "name":
        incident.name,
        "title":
        incident.title,
        "description":
        incident.description,
        "status":
        incident.status,
        "type":
        incident.incident_type.name,
        "type_description":
        incident.incident_type.description,
        "priority":
        incident.incident_priority.name,
        "priority_description":
        incident.incident_priority.description,
        "commander_fullname":
        incident.commander.individual.name,
        "commander_team":
        incident.commander.team,
        "commander_weblink":
        incident.commander.individual.weblink,
        "reporter_fullname":
        incident.reporter.individual.name,
        "reporter_team":
        incident.reporter.team,
        "reporter_weblink":
        incident.reporter.individual.weblink,
        "document_weblink":
        resolve_attr(incident, "incident_document.weblink"),
        "storage_weblink":
        resolve_attr(incident, "storage.weblink"),
        "ticket_weblink":
        resolve_attr(incident, "ticket.weblink"),
        "conference_weblink":
        resolve_attr(incident, "conference.weblink"),
        "conference_challenge":
        resolve_attr(incident, "conference.conference_challenge"),
    }

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        message_kwargs.update({"faq_weblink": faq_doc.weblink})

    conversation_reference = document_service.get_conversation_reference_document(
        db_session=db_session)
    if conversation_reference:
        message_kwargs.update({
            "conversation_commands_reference_document_weblink":
            conversation_reference.weblink
        })

    plugin.instance.send_ephemeral(
        incident.conversation.channel_id,
        participant_email,
        "Incident Welcome Message",
        INCIDENT_PARTICIPANT_WELCOME_MESSAGE,
        MessageType.incident_participant_welcome,
        **message_kwargs,
    )

    log.debug(f"Welcome ephemeral message sent to {participant_email}.")