Files
rutster/Cargo.toml
Aaron D. Lee a7203ab51b feat(trunk): TwilioCallControlClient (live REST impl behind twilio-live) + env parser (slice-5 T6)
The live Twilio call-control client. Originates outbound calls via Twilio's
Calls.json API (TwiML <Connect><Stream> instructs Twilio to fork audio back
to our /twilio/media-stream WSS endpoint); hangs up via Status=completed.
HTTP basic auth over HTTPS; auth_token is NEVER logged (ADR-0009 -- provider
credentials never reach the brain) -- tracing fields expose only caller-
controlled values (to, from) + the CallSid's last 4 chars.

Feature-gated behind `twilio-live` so the routine CI gate stays feature-
default-off: MockCallControlClient is the per-PR test surface; the maintainer
runs cargo test --features=twilio-live when validating a release. reqwest +
tracing + serde_json are optional deps (dep:foo syntax) -- pulled in only
when the feature is on, keeping the default resolve lean.

The env parser (config::twilio_credentials) follows slice-5/seams' pure-
function pattern: takes Option<String> inputs (testable without env mutation),
returns Ok(None) when all four RUTSTER_TWILIO_* vars are unset (WebRTC-only
mode), Ok(Some) when all four present + parse, Err on partial config (fail-
fast at startup) or malformed values. TwilioCredentials is imported by the
binary but never re-exported through the workspace (ADR-0009).

T6 of slice-5. Depends on T2 (TwilioCredentials + CallControlClient trait).

Signed-off-by: Aaron D. Lee <himself@adlee.work>
2026-07-05 03:04:22 -04:00

69 lines
2.9 KiB
TOML

# Cargo.toml — rutster workspace root.
# Spec ref: slice-1 §2. The workspace pins shared dep versions here so
# member crates can't drift (§2.1). Each member references with
# `dep.workspace = true`.
[workspace]
resolver = "2"
members = [
"crates/rutster",
"crates/rutster-call-model",
"crates/rutster-media",
"crates/rutster-trunk",
"crates/rutster-tap",
"crates/rutster-tap-echo",
"crates/rutster-brain-realtime",
"crates/rutster-spend",
]
[workspace.package]
license = "GPL-3.0-or-later"
edition = "2024"
repository = "https://git.adlee.work/alee/rutster"
# Pinned versions for all member crates. References are `foo.workspace = true`
# in the member manifest. Keeps the dep tree unified (§2.1).
[workspace.dependencies]
# str0m 0.21: sans-IO WebRTC. Frame API (Event::MediaData + Writer::write).
str0m = "0.21"
# opus 0.3.1: libopus FFI (system libopus required — see README).
opus = "0.3"
# axum 0.7: HTTP signaling surface.
axum = { version = "0.7", features = ["macros"] }
# tokio 1: runtime driving the str0m poll loop (slice-1 deviation per §3.4).
tokio = { version = "1", features = ["full"] }
# dashmap 6: in-process session store.
dashmap = "6"
# uuid 1: ChannelId newtype backing.
uuid = { version = "1", features = ["v4"] }
thiserror = "1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# tower: used by the binary crate's integration tests (ServiceExt::oneshot
# on the axum Router). Axum re-exports parts of tower but the integration test
# uses `tower::ServiceExt` directly, so it needs to be a workspace dep.
tower = { version = "0.5", features = ["util"] }
# tokio-tungstenite 0.24: WS client + server (slice-2 tap transport).
tokio-tungstenite = { version = "0.24", features = ["connect"] }
# futures-util 0.3: Sink/Stream traits for WebSocketStream.
futures-util = "0.3"
# url 2: tap URL parsing + host validation (spec §4.4).
url = "2"
# base64 0.22: PCM <-> base64 codec for the v1 wire format (spec §3).
base64 = "0.22"
# async-trait 0.1: async fns in trait objects (Tool trait, slice-3 spec §6.1).
async-trait = "0.1"
# http 1: Request/Response builders for the OpenAI WS handshake (slice-3
# spec §5.3). Task 9's main.rs builds the http::Request<...> the tungstenite
# client sends before WS upgrade; `openai_client::openai_headers` produces
# the header pairs the caller stuffs into it.
http = "1"
# reqwest 0.12: HTTP client for the green-zone Twilio REST call-control
# client (slice-5 T6, feature-gated behind `twilio-live`). `rustls-tls`
# (not native-tls/OpenSSL) keeps the TLS stack pure-Rust + consistent with
# str0m's existing aws-lc-rs crypto provider (ADR-0001 "memory-safe by
# construction"). `default-features = false` drops the default
# native-tls/OpenSSL backend. `json` for the Calls.json response parsing.
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }