Files
wfe/wfe-server/Cargo.toml
Sienna Meridian Satterwhite cbbeaf6d67 feat(wfe-server): headless workflow server with gRPC, webhooks, and OIDC auth
Single-binary server exposing the WFE engine over gRPC (13 RPCs) with
HTTP webhook support (GitHub, Gitea, generic events).

Features:
- gRPC API: workflow CRUD, lifecycle event streaming, log streaming,
  log search via OpenSearch
- HTTP webhooks: HMAC-SHA256 verified GitHub/Gitea webhooks with
  configurable triggers that auto-start workflows
- OIDC/JWT auth: discovers JWKS from issuer, validates with asymmetric
  algorithm allowlist to prevent algorithm confusion attacks
- Static bearer token auth with constant-time comparison
- Lifecycle event broadcasting via tokio::broadcast
- Log streaming: real-time stdout/stderr via LogSink trait, history
  replay, follow mode
- Log search: full-text search via OpenSearch with workflow/step/stream
  filters
- Layered config: CLI flags > env vars > TOML file
- Fail-closed on OIDC discovery failure, fail-loud on config parse errors
- 2MB webhook payload size limit
- Blocked sensitive env var injection (PATH, LD_PRELOAD, etc.)
2026-04-01 14:37:25 +01:00

73 lines
1.6 KiB
TOML

[package]
name = "wfe-server"
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
description = "Headless workflow server with gRPC API and HTTP webhooks"
[[bin]]
name = "wfe-server"
path = "src/main.rs"
[dependencies]
# Internal
wfe-core = { workspace = true, features = ["test-support"] }
wfe = { path = "../wfe" }
wfe-yaml = { path = "../wfe-yaml", features = ["rustlang", "buildkit", "containerd"] }
wfe-server-protos = { path = "../wfe-server-protos" }
wfe-sqlite = { workspace = true }
wfe-postgres = { workspace = true }
wfe-valkey = { workspace = true }
wfe-opensearch = { workspace = true }
opensearch = { workspace = true }
# gRPC
tonic = "0.14"
tonic-health = "0.14"
prost-types = "0.14"
# HTTP (webhooks)
axum = { version = "0.8", features = ["json", "macros"] }
hyper = "1"
tower = "0.5"
# Runtime
tokio = { workspace = true }
async-trait = { workspace = true }
# Serialization
serde = { workspace = true }
serde_json = { workspace = true }
toml = "0.8"
# CLI
clap = { version = "4", features = ["derive", "env"] }
# Auth
hmac = "0.12"
sha2 = "0.10"
hex = "0.4"
jsonwebtoken = "9"
subtle = "2"
reqwest = { workspace = true }
# Observability
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
chrono = { workspace = true }
uuid = { workspace = true }
# Utils
tokio-stream = "0.1"
dashmap = "6"
[dev-dependencies]
pretty_assertions = { workspace = true }
tokio = { workspace = true, features = ["test-util"] }
tempfile = { workspace = true }
rsa = { version = "0.9", features = ["pem"] }
rand = "0.8"
base64 = "0.22"