Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ async-trait = "0.1"
serenity = { version = "0.12", default-features = false, features = ["client", "gateway", "model", "rustls_backend", "cache"], optional = true }

[features]
# Default: core only (Discord + Slack). Gateway ships as separate binary.
# Default: core only (Discord + Slack). Platform adapters are opt-in.
default = ["discord", "slack", "secrets-aws", "agentcore", "config-s3", "pre-seed"]

# Opt-in: compile all gateway adapters into a single unified binary
unified = ["telegram", "line", "feishu", "googlechat", "wecom", "teams"]
# Opt-in: compile all platform adapters into a single unified binary
unified = ["telegram", "line", "feishu", "googlechat", "wecom", "teams", "vtuber"]

# Core adapters
discord = ["dep:serenity", "openab-core/discord"]
Expand All @@ -40,13 +40,14 @@ agentcore = ["openab-core/agentcore"]
config-s3 = ["openab-core/config-s3"]
pre-seed = ["openab-core/pre-seed"]

# Gateway adapters (each pulls in the gateway crate + axum for embedded server)
# Platform adapters (each pulls in the gateway crate + axum for embedded server)
telegram = ["dep:openab-gateway", "dep:axum", "openab-gateway/telegram"]
line = ["dep:openab-gateway", "dep:axum", "openab-gateway/line"]
feishu = ["dep:openab-gateway", "dep:axum", "openab-gateway/feishu"]
googlechat = ["dep:openab-gateway", "dep:axum", "openab-gateway/googlechat"]
wecom = ["dep:openab-gateway", "dep:axum", "openab-gateway/wecom"]
teams = ["dep:openab-gateway", "dep:axum", "openab-gateway/teams"]
vtuber = ["dep:openab-gateway", "dep:axum", "openab-gateway/vtuber"]

[dev-dependencies]
tempfile = "3.27.0"
3 changes: 2 additions & 1 deletion crates/openab-gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ urlencoding = "2"
wiremock = "0.6"

[features]
default = ["telegram", "line", "feishu", "googlechat", "wecom", "teams"]
default = ["telegram", "line", "feishu", "googlechat", "wecom", "teams", "vtuber"]
telegram = []
line = []
feishu = []
googlechat = []
wecom = []
teams = []
vtuber = []
2 changes: 2 additions & 0 deletions crates/openab-gateway/src/adapters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ pub mod googlechat;
pub mod wecom;
#[cfg(feature = "teams")]
pub mod teams;
#[cfg(feature = "vtuber")]
pub mod vtuber;
16 changes: 12 additions & 4 deletions crates/openab-gateway/src/adapters/teams.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,9 @@ impl TeamsAdapter {
}

// B2: Validate channel endorsements — key must endorse the activity's channelId
let channel_id = activity.channel_id.as_deref()
let channel_id = activity
.channel_id
.as_deref()
.ok_or_else(|| anyhow::anyhow!("activity missing channelId"))?;
if key.endorsements.is_empty() {
anyhow::bail!("JWK has no endorsements — cannot verify channelId={channel_id}");
Expand All @@ -301,9 +303,13 @@ impl TeamsAdapter {
let token_data = decode::<serde_json::Value>(token, &decoding_key, &validation)?;

// B1: Validate serviceUrl claim matches activity's serviceUrl
let activity_service_url = activity.service_url.as_deref()
let activity_service_url = activity
.service_url
.as_deref()
.ok_or_else(|| anyhow::anyhow!("activity missing serviceUrl"))?;
let token_service_url = token_data.claims.get("serviceurl")
let token_service_url = token_data
.claims
.get("serviceurl")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("JWT missing serviceurl claim"))?;
if token_service_url != activity_service_url {
Expand Down Expand Up @@ -799,7 +805,9 @@ mod tests {
async fn jwt_rejects_garbage_token() {
let adapter = TeamsAdapter::new(make_config(vec![]));
let activity = make_activity_with_tenant(Some("t1"));
let result = adapter.validate_jwt("Bearer not.a.valid.jwt", &activity).await;
let result = adapter
.validate_jwt("Bearer not.a.valid.jwt", &activity)
.await;
assert!(result.is_err());
}

Expand Down
Loading
Loading