feat: wire up unified webhook runtime (Phase 2)#1171
Merged
Conversation
added 10 commits
June 21, 2026 20:18
Replaces TODO stub with architecture doc comment. Implementation in progress.
Step 1 of Phase 2: Extract the gateway event processing logic (filtering, allowlists, attachments, slash commands, dispatch) into a standalone public function that can be called from both: - The existing WebSocket handler (unchanged) - The new unified mode's embedded axum server (Phase 2) New public API: - GatewayEventContext: config/deps needed for event processing - process_gateway_event(): processes JSON event, returns dispatched/filtered
- Start axum on GATEWAY_LISTEN (default :8080) when any gateway platform env vars are detected at runtime - Only compiled in when gateway features are enabled - Creates dedicated Dispatcher for unified events - Adds /health endpoint - Adapter webhook routes to be wired in Step 3 Dependencies: axum added as optional dep, enabled per gateway feature.
Complete unified mode wiring:
- Reuse gateway crate's AppState + all adapter webhook handlers as-is
- Mount platform-specific routes (telegram, line, feishu, wecom, teams)
- Bridge: event_tx → process_gateway_event() → Dispatcher
- Each adapter uses #[cfg(feature)] gating
- Same signature verification as standalone gateway
Architecture:
Webhook → adapter handler → event_tx.send(json)
→ bridge task → process_gateway_event()
→ Dispatcher.submit() → ACP Agent
… gating - Fix send_text -> send_message compile error in process_gateway_event - Implement UnifiedGatewayAdapter that routes ChatAdapter calls through in-process gateway platform adapters (telegram, line, feishu, etc.) based on ChannelRef.platform field - Replace hardcoded allow_all=true with env-var based config: GATEWAY_ALLOW_ALL_CHANNELS, GATEWAY_ALLOWED_CHANNELS, GATEWAY_ALLOW_ALL_USERS, GATEWAY_ALLOWED_USERS, GATEWAY_BOT_USERNAME Addresses: F1 (outbound reply path missing), F2 (security gating bypass) from architecture review.
- Replace uuid::Uuid::new_v4() with std::time nanos (uuid not in root deps) - Add reqwest to root Cargo.toml (needed for AppState.client construction) - Fix Dispatcher::new → Dispatcher::with_idle_timeout (correct API)
In openab-core/Cargo.toml: serenity is now optional = true, gated by discord = ["dep:serenity"]. In root Cargo.toml: same pattern. Modules that use serenity (discord.rs, remind.rs) are already behind #[cfg(feature = "discord")]. Added cfg gates to ctl.rs ShardSlot and agent.status handler. This reduces compile time for non-Discord builds (gateway-only, etc).
Move all server setup logic (adapter initialization, axum router, background tasks, WebSocket handler) from main.rs into a pub async fn serve(ServeConfig) in lib.rs. The gateway binary is now a thin 15-line wrapper that calls openab_gateway::serve(ServeConfig::default()). This makes the gateway server embeddable and testable as a library.
Add Dockerfile.builder as the single source of truth for the cargo cache-build pattern repeated across all 13+ Dockerfiles. Add docker-bake.hcl for local development — enables BuildKit to share a single cached builder layer across all image variants, dramatically speeding up multi-image rebuilds. CI continues to use plain 'docker build -f Dockerfile.X .' which remains self-contained. The bake file is opt-in for local iteration.
Collaborator
Author
|
Addresses review finding from 擺渡法師 (F3).
Collaborator
Author
|
Collaborator
Author
Final Group Review — All LGTM ✅HEAD: Review Result4 independent reviewers approved from different angles (Security/CI, Architecture, Code Quality, Correctness). No 🔴 Critical findings. Findings Resolved in This PR
Follow-up Items (non-blocking, tracked in PR description)
Praise Highlights
Ready to merge. All reviewers approved, CI green, no 🔴 blockers. |
7 tasks
thepagent
approved these changes
Jun 22, 2026
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
Implements all 4 tasks from tracking issue #1170 (workspace restructure follow-up):
BUILD_MODE=unifiednow starts an axum webhook server at runtime, routing events directly to Dispatcher (no WebSocket hop).serenityis nowoptional = truein bothopenab-coreand rootCargo.toml, gated bydiscord = ["dep:serenity"]. Non-Discord builds skip compiling serenity entirely.Dockerfile.builderas single source of truth for the cargo cache-build pattern +docker-bake.hclfor shared BuildKit layer caching across all 13+ image variants.serve()in gateway lib — All server logic moved topub async fn serve(ServeConfig)inlib.rs. Binary is now a 15-line thin wrapper.Architecture
Before (standalone gateway + WebSocket)
After (unified binary, direct dispatch)
Conditional Compilation (serenity)
Related
Follow-up Items (non-blocking)
From group review — tracked in #1172:
GATEWAY_ALLOW_BOT_MESSAGES/GATEWAY_TRUSTED_BOT_IDSenv for multi-agentgoogle_chat: NoneTODO)process_gateway_event()/run_gateway_adapter()shared logicAppState::from_env()factory to avoid unified/standalone divergencecreate_threadfails