# zeph-gateway
[](https://crates.io/crates/zeph-gateway)
[](https://docs.rs/zeph-gateway)
[](../../LICENSE)
[](https://www.rust-lang.org)
HTTP gateway for webhook ingestion with bearer auth for Zeph.
## Overview
Exposes an axum 0.8 HTTP server that accepts incoming webhooks, validates bearer tokens, and forwards payloads into the agent loop. Includes a `/health` endpoint for liveness probes. Feature-gated behind `gateway`.
## Key Modules
- **server** — `GatewayServer` startup and graceful shutdown
- **handlers** — request handlers for webhook and health routes
- **router** — axum router construction with auth middleware
- **error** — `GatewayError` error types
## Activation
`GatewayServer` starts automatically in daemon mode when the `gateway` feature is enabled and `[gateway]` is configured:
```toml
[gateway]
bind = "0.0.0.0:8090"
auth_token = "your-secret-token" # optional, see authentication below
```
```bash
cargo run --features gateway -- --daemon # starts agent + gateway server
```
The gateway is wired via `src/gateway_spawn.rs` into both `daemon.rs` and `runner.rs`. A background `forward_webhooks` task drains incoming webhook payloads and forwards each one into the agent's input queue as a `ChannelMessage`: a payload recognized as a known slash command is forwarded as-is (subject to the same `CommandHandler::requires_auth` authorization as any other channel); every other payload is sanitized via `ContentSanitizer` (classified `ExternalUntrusted`) before it reaches the agent loop, since a valid bearer token proves only that the sender knows the shared secret, not that the content is safe.
## Authentication
`GatewayServer` supports bearer token authentication via the `with_auth()` builder method. When `auth_token` is `None`, the server emits a `tracing::warn!` at startup indicating that the endpoint is unauthenticated.
```rust
use tokio::sync::{mpsc, watch};
use zeph_gateway::GatewayServer;
let (webhook_tx, _webhook_rx) = mpsc::channel::<String>(64);
let (_shutdown_tx, shutdown_rx) = watch::channel(false);
GatewayServer::new("127.0.0.1", 8080, webhook_tx, shutdown_rx)
.with_auth(Some("secret-token".to_string()))
.with_rate_limit(120) // requests per 60s window per IP; 0 disables
.serve()
.await?;
```
Token comparison uses BLAKE3 + `subtle::ConstantTimeEq` to prevent timing attacks. The rate limiter wraps the auth check (not the reverse), so requests with a missing or invalid bearer token still count against the per-IP limit — a brute-force attempt against the token cannot bypass rate limiting.
## Features
| Feature | Default | Description |
|---------|---------|-------------|
| `prometheus` | — | Exposes a Prometheus metrics endpoint via `prometheus-client` |
## Installation
```bash
cargo add zeph-gateway
```
At the application level the server is activated via the `gateway` feature flag on the root `zeph` crate.
## Documentation
Full documentation: <https://bug-ops.github.io/zeph/>
## License
Licensed under either of [MIT](../../LICENSE) or [Apache License, Version 2.0](../../LICENSE-APACHE) at your option.