feat: add channel-relay integration for Slack (#790)

* fix(ci): secrets can't be used in step if conditions [skip-regression-check] (#787)

GitHub Actions step-level `if:` doesn't have access to `secrets` context.
Replace `if: secrets.X != ''` with `continue-on-error: true` and let
the Set token step handle the fallback.

Co-authored-by: Claude Sonnet 4.6 <[email protected]>

* feat: add channel-relay integration for Slack via external relay service

- Add RelayChannel and RelayClient for connecting to channel-relay SSE streams
- Add RelayConfig with env-based configuration (CHANNEL_RELAY_URL, CHANNEL_RELAY_API_KEY)
- Add channel-relay extension lifecycle: install, OAuth auth, activate with hot-add
- Add proxy message sending through channel-relay for Slack chat.postMessage
- Add extension registry entry for Slack relay with OAuth auth hint
- Add relay integration test with mock SSE server
- Wire relay channel into app startup with reconnect on stored credentials
- Add AuthRequired extension error variant for cleaner auth flow detection

[skip-regression-check]

* chore: apply cargo fmt

* fix: remove remaining Telegram test references in relay channel

* fix: address PR #790 review feedback — parser handle leak, CSRF, circuit breaker

- Fix parser handle leak on reconnect by sharing Arc<RwLock> instead of
  creating a local copy in start() (shutdown now aborts the correct task)
- Add CSRF state nonce to OAuth flow: generate in auth_channel_relay,
  validate in slack_relay_oauth_callback_handler, one-time use
- Remove dead proxy_slack method, update integration test to use
  proxy_provider
- Add reconnect circuit breaker (max_consecutive_failures, default 50)
- Fix stale docs (Telegram refs), extract event_types constants

---------

Co-authored-by: Henry Park <[email protected]>
Co-authored-by: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
Pierre LE GUEN
2026-03-10 16:34:54 -07:00
committed by GitHub
co-authored by Henry Park Claude Sonnet 4.6
parent 3a841b30d8
commit b0214fef41
22 changed files with 2707 additions and 89 deletions
+11
View File
@@ -37,6 +37,8 @@ pub enum ExtensionKind {
WasmTool,
/// WASM channel module with hot-activation support.
WasmChannel,
/// External channel via channel-relay service (Slack, etc.).
ChannelRelay,
}
impl std::fmt::Display for ExtensionKind {
@@ -45,6 +47,7 @@ impl std::fmt::Display for ExtensionKind {
ExtensionKind::McpServer => write!(f, "mcp_server"),
ExtensionKind::WasmTool => write!(f, "wasm_tool"),
ExtensionKind::WasmChannel => write!(f, "wasm_channel"),
ExtensionKind::ChannelRelay => write!(f, "channel_relay"),
}
}
}
@@ -99,6 +102,8 @@ pub enum ExtensionSource {
},
/// Discovered online (not yet validated for a specific source type).
Discovered { url: String },
/// External channel via channel-relay service.
ChannelRelay { relay_url: String },
}
/// Hint about what authentication method is needed.
@@ -116,6 +121,8 @@ pub enum AuthHint {
CapabilitiesAuth,
/// No authentication needed.
None,
/// OAuth via channel-relay service.
ChannelRelayOAuth,
}
/// Where a search result came from.
@@ -499,6 +506,9 @@ pub enum ExtensionError {
#[error("Activation failed: {0}")]
ActivationFailed(String),
#[error("Authentication required")]
AuthRequired,
#[error("Installation failed: {0}")]
InstallFailed(String),
@@ -976,6 +986,7 @@ mod tests {
ExtensionError::Config("missing key".into()),
"Config error: missing key",
),
(ExtensionError::AuthRequired, "Authentication required"),
(
ExtensionError::Other("something broke".into()),
"something broke",