feat(slack): Slack integration fixes, Teams support, and Athena→Sparks rebrand completion#84
Merged
feat(slack): Slack integration fixes, Teams support, and Athena→Sparks rebrand completion#84
Conversation
Detailed plan covering architecture, config, module structure, security considerations, and open questions for adding Slack as a new messaging platform frontend alongside Telegram. https://claude.ai/code/session_01A6hKTjyT5yywNUDEfWP6Ly
Add complete Slack bot frontend mirroring the existing Telegram integration: - Socket Mode (default) and Events API support - Thread-based replies with Block Kit interactive UI - SlackConfirmer for approve/deny buttons via oneshot channels - All slash commands via /athena (help, status, plan, implement, ghosts, memories, dispatch, model, models, review, explain, watch, search, alerts) - Planning interview state machine with Block Kit buttons - Streaming response via chat.update with 800ms throttle - File download/upload support - Pulse delivery to Slack channels - Per-channel rate limiting and authorization Also broadens feature gates from telegram-only to any(telegram, slack) in core.rs, session_review.rs, pulse.rs, and llm.rs. https://claude.ai/code/session_01A6hKTjyT5yywNUDEfWP6Ly
Port 7 remaining commands from Telegram: - /knobs: display all runtime knobs - /mood: detailed mood state with energy bar - /jobs: list scheduled cron jobs - /session: current session info (turns, tokens, context) - /cli: switch CLI tool with interactive Block Kit buttons - /set: modify runtime knobs - /cli_model: show/switch CLI model override Add interactive Block Kit buttons for planning interview: - Constraints step: timeline, scope, no-constraints, skip buttons - Output step: checklist, spec, draft buttons - Summary step: confirm, edit, cancel buttons - Post-generation: implement, refine, done buttons Also broadens mood.rs energy()/modifier() feature gates to any(telegram, slack). https://claude.ai/code/session_01A6hKTjyT5yywNUDEfWP6Ly
Covers Slack app creation, OAuth scopes, Socket Mode and Events API configuration, channel access control, all 21 slash commands, features overview, and troubleshooting tips. https://claude.ai/code/session_01A6hKTjyT5yywNUDEfWP6Ly
Fixes from security review: CRITICAL: - Add is_authorized check to handle_slash_command (was missing, allowing any channel to execute admin commands) - Add is_authorized check to handle_interaction_event (was missing, allowing unauthorized channels to approve/deny confirmations) HIGH: - Add rate limiting to handle_app_mention (was unprotected) - Add rate limiting to handle_slash_command (was unprotected) MEDIUM: - Harden escape_mrkdwn to neutralize *_~` formatting chars, preventing mrkdwn injection in reflected user content - Replace all user-facing error messages with generic text, log full errors server-side via tracing::error to prevent leaking internal paths/details - Fix potential panics from &id[..8] slicing on short IDs, use get(..8).unwrap_or() instead - Cap stream_buffer at 100KB to prevent OOM from unbounded LLM streaming responses https://claude.ai/code/session_01A6hKTjyT5yywNUDEfWP6Ly
- Merge conflict: Cargo.lock regenerated with slack-morphism added, ort pinned to rc.11 - Fix AthenaError→SparksError and AthenaCore→SparksCore renames from main - Critical: run_events_api now returns an error (was silently non-functional) - Fix: rate limiting keyed per user+channel instead of per channel - Remove unused ImplementContext struct and implementing HashMap - Fix: planning_value_label used consistently in handle_planning_quick_select - Fix: tracing::info! instead of eprintln! for Slack startup message - Add: Serialize derive to SlackConfig - Add: CI jobs for cargo check/test --features slack - Add: is_authorized precedence comment for allow_all vs allowed_channels All 417 tests pass (391 base + 26 Slack-feature tests). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tegration Slack fixes (from second review pass): - SparksError::Denied distinct from Cancelled (deny vs timeout) - render_review_mrkdwn / render_search_results_mrkdwn / render_alert_rules_mrkdwn in session_review.rs — Teams/Slack get native format instead of fragile HTML→mrkdwn conversion - dispatch_to_core_with_followup unified (dispatch_to_core now forwards to it) - Makefile: add slack/teams build targets Teams integration (--features teams, Bot Framework REST API): - JWT RS256 signature verification via Microsoft JWKS endpoint (jsonwebtoken crate) - serviceUrl validation against known Bot Framework domains before outbound calls - Tenant authorization (allowed_tenants / allow_all_tenants, same precedence as Slack) - Rate limiting per user+conversation (not per conversation alone) - Adaptive Cards for confirmations and planning interview (5-step flow) - All commands: help, status, run, plan, memory, review, explain, search, alerts, health - PlanningStep state machine enforced in handle_planning_invoke - LazyLock regex for @mention stripping (not compiled per-message) - Tenant auth applied to both message and invoke (Adaptive Card action) paths - Bearer token cache with 60s pre-expiry window - Cleanup task for stale confirmations and planning sessions - 16 unit tests, 435 tests total passing (includes slack + telegram) - CI: cargo check/test --features teams in maintainability.yml - docs/teams-setup.md: Azure Bot registration, ngrok tunneling, all config fields - config.example.toml: [teams] section with all defaults documented Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…gistry Root causes found and fixed: 1. TLS connection broken (root cause of "app did not respond" error): slack-morphism's hyper feature enables tokio-tungstenite/rustls-native-certs but NOT rustls-tls-native-roots which activates the __rustls-tls backend. Fix: add tokio-tungstenite optional dep + tokio-tungstenite/rustls-tls-native-roots to the slack feature flags in Cargo.toml. 2. Stale /athena branding in all help text, usage strings, and docs: All /athena command references replaced with /sparks. "Athena" header/footer in help message replaced with "Sparks". docs/slack-setup.md updated (binary name, command references, setup guide). 3. Slack tokens missing from secrets registry: slack.bot_token, slack.app_token, slack.signing_secret added to KNOWN_SECRETS so `sparks secrets set slack.*` works and keyring loading picks them up. 4. apply_env_overrides missing Slack support: ATHENA_SLACK_BOT_TOKEN, ATHENA_SLACK_APP_TOKEN, ATHENA_SLACK_SIGNING_SECRET now populate config.slack.* on startup, consistent with other integrations. 5. collect_inline_secret_labels missing Slack: Inline Slack tokens in config.toml now trigger the security warning. Verified working in real Slack workspace: - /sparks help ✓ (all commands listed with /sparks prefix) - /sparks status ✓ (system status, model, uptime, ghosts, mood) - /sparks ghosts ✓ (coder and scout listed with tools) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- secrets.rs: verify slack.bot_token, app_token, signing_secret are in KNOWN_SECRETS with correct ATHENA_SLACK_* env var mappings - config.rs: verify apply_env_overrides loads Slack tokens from env vars; verify collect_inline_secret_labels flags/skips inline secrets per env state - slack.rs: verify no /athena command references remain (rename regression) Use a static Mutex in config tests to serialize env-var-mutating tests and prevent parallel race conditions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename ATHENA_SLACK_* env vars → SPARKS_SLACK_* (secrets.rs, config.rs, slack.rs, config.example.toml, docs/slack-setup.md) - Update [athena_cli_contract] → [sparks_cli_contract] in docs (matches actual tag emitted by src/tools.rs) - Replace `athena` binary refs with `sparks` across all docs and scripts - Replace ~/.athena/ paths with ~/.sparks/ throughout - Update RUST_LOG=athena → RUST_LOG=sparks, log file names, pgrep patterns - Update model names "athena"/"athena/coder" → "sparks"/"sparks/coder" - Update ATHENA_DISABLE_HOME_PROFILES → SPARKS_DISABLE_HOME_PROFILES - Fix broken README anchor (#what-athena-does-not-do-yet) - Update LICENSE copyright to Emberloom contributors - 27 files changed; all 419 tests still pass Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
slack-morphism's prelude is designed to be used as a glob import; annotate with `// hygiene: allow` to satisfy the hygiene check. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
Url(TlsFeatureNotEnabled)by addingtokio-tungstenite/rustls-tls-native-rootsto theslackfeature flag; fixednot_in_channelby documenting bot channel membership requirement/athena→/sparks: All slash command strings, help text, and error messages updatedSPARKS_SLACK_BOT_TOKEN,SPARKS_SLACK_APP_TOKEN,SPARKS_SLACK_SIGNING_SECRETadded toKNOWN_SECRETSandapply_env_overrides~/.athena/→~/.sparks/), CLI contract tag, model names, docsTest plan
cargo test --features slack— all 419 tests pass/sparks help,/sparks status,/sparks ghostsrespond in Slack (verified live in Luminary workspace)Athena/athenareferences outside CHANGELOG.md and PLAN.md🤖 Generated with Claude Code