feat: add Mattermost channel integration#877
Draft
Aaronontheweb wants to merge 6 commits intodevfrom
Draft
Conversation
…ion tests Implement full Mattermost channel support following the same 3-tier actor hierarchy pattern as Slack and Discord (Gateway → Conversation → Session Binding). Uses Mattermost.NET v4.0.4 for WebSocket event delivery and REST API operations. Production implementation (~3,400 LOC): - MattermostChannel (IChannel + IHostedService lifecycle) - MattermostGatewayActor (4096-entry LRU event dedup) - MattermostConversationActor (ACL, routing policy, session derivation) - MattermostSessionBindingActor (ReceivePersistentActor with cursor tracking) - MattermostNetGatewayClient (WebSocket transport wrapper) - MattermostNetReplyClient + MattermostNetOutboundClient (REST API) - MattermostThreadHistoryFetcher (thread backfill with content scanning) - MattermostApprovalPromptBuilder (letter-based text prompts) - SendMattermostMessageTool + LookupMattermostUserTool (channel tools) - ACL policy, routing policy, reminder target resolver - Config schema, DI wiring, ChannelType enum extension Unit tests (52 tests): - Routing policy, ACL contract, approval prompts, reminder resolution, config defaults, session ID parsing, user allowlist checks Integration tests (11 tests against real Mattermost container): - MattermostFixture with mattermost-preview Docker container - WebSocket event delivery, thread reply routing - Reply client posting, thread replies, message updates - Outbound client DM channel creation, new thread posting - Thread history fetching, root post inclusion, bot post visibility
Remove duplicated approval prompt builder methods from SessionBindingActor (now delegates to MattermostApprovalPromptBuilder). Fix BotUserId being captured too early at DI time by switching to lazy Func<string?> resolution. Fail loud when ServerUrl is absent on the attachment URL trust path. Add missing BotToken to JSON config schema. Replace Task.Delay in integration tests with a polling helper. Cache test user token to avoid re-authenticating per call. Remove TOCTOU File.Exists before File.Delete, redundant BotToken.RequireValid, inline DefaultChannelId duplication, and LINQ allocation in IsMattermostId.
…annel Replace text-only approval prompts with Mattermost interactive message attachments using action buttons. Add HTTP callback endpoint for button clicks and fix several security/correctness issues found in deep review. Interactive buttons: - BuildButtonPrompt produces attachments with styled action buttons - HTTP POST /api/mattermost/actions receives Mattermost button callbacks - Graceful degradation to text-only when CallbackUrl not configured - Buttons cleared on resolution via UpdatePostAsync with colored attachment Security fixes: - Fix URL trust subdomain bypass (StartsWith without trailing slash) - Add Bearer auth to mattermost-files HttpClient (was missing) - Whitelist selectedKey values in callback endpoint - Fix RootPostId routing in button context (was empty, broke actor lookup)
- Add HMAC-SHA256 callback signing for interactive button webhooks with ephemeral per-daemon keys and constant-time signature verification - Add ACL enforcement on callback endpoint and conversation actor for interaction messages - Add message chunking at 16,000 chars with newline-aware splitting to stay under Mattermost's 16,383-char post limit - Fix bot mention stripping to use @username format instead of @userid - Resolve file attachment metadata (name, MIME type, size) via GetFileDetailsAsync instead of using raw file IDs - Remove BotToken from config schema for consistency with other channels - Add comprehensive test coverage: 123 Mattermost tests across conversation actor (22), session binding contracts (26), gateway contracts (3), URL trust (5), chunking (4), approval signing (5), and existing test suites
- Fix wrong ephemeral approval labels in action callback endpoint (used "Approve Once"/"Approve for Session"/"Always Approve" instead of canonical ApprovalOptionKeys labels) - Replace raw string literals in IsValidApprovalKey with ApprovalOptionKeys constants to prevent drift - Extract duplicated attachment-to-payload mapping in MattermostNetReplyClient into shared MapAttachments helper - Add Contains guard before Replace in NormalizeInboundText to avoid unnecessary string allocation on the per-message path - Remove TOCTOU File.Exists check before File.Delete in DownloadFileViaSdkAsync (Delete is a no-op for absent files) - Remove section-divider and narration comments that duplicate what well-named identifiers already communicate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@usernameformat), file attachment metadata resolution viaGetFileDetailsAsync, and URL trust validation for attachment downloadssend_mattermost_messageandlookup_mattermost_userTest plan
dotnet slopwatch analyzeclean (3 pre-existing violations in channel tools, not from this branch)Add-FileHeaders.ps1 -Verify