diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..7763238 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,15 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "rutster-signaling-sip" +version = "0.0.0" + +[[package]] +name = "rutster-spend" +version = "0.0.0" + +[[package]] +name = "rutster-tap" +version = "0.0.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..191a497 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,41 @@ +# 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-signaling-sip", + "crates/rutster-tap", + "crates/rutster-spend", +] + +[workspace.package] +license = "GPL-3.0-or-later" +edition = "2021" +repository = "https://github.com/anomalyco/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"] } diff --git a/crates/rutster-signaling-sip/Cargo.toml b/crates/rutster-signaling-sip/Cargo.toml new file mode 100644 index 0000000..e123875 --- /dev/null +++ b/crates/rutster-signaling-sip/Cargo.toml @@ -0,0 +1,8 @@ +# crates/rutster-signaling-sip/Cargo.toml +[package] +name = "rutster-signaling-sip" +version = "0.0.0" +license.workspace = true +edition.workspace = true +repository.workspace = true +description = "Rust-native trunk SIP — stub crate (filled in spearhead step 5)." diff --git a/crates/rutster-signaling-sip/src/lib.rs b/crates/rutster-signaling-sip/src/lib.rs new file mode 100644 index 0000000..2111346 --- /dev/null +++ b/crates/rutster-signaling-sip/src/lib.rs @@ -0,0 +1,23 @@ +//! # rutster-signaling-sip +//! +//! **Status:** stub. Fills in at spearhead step 5 (PSTN trunk). +//! +//! This crate will hold the Rust-native trunk SIP stack: the SIP parser, +//! transaction layer, dialog state, and the carrier trunk integration. See +//! [ADR-0003](../../../docs/adr/0003-sip-rust-native-trunk.md) for the +//! "own the parser from day one" thesis and [PORT_PLAN §1](../../../docs/PORT_PLAN.md) +//! for the surface area (`res_pjsip_session`, `chan_sip`, `_sdp_rtp` rows). +//! +//! Slice 1's WebRTC-only ingress needs no SIP — this stub exists to lock the +//! crate boundary without anticipating code (spec §2.2). It depends on +//! nothing in the workspace in slice 1. Its future dependency direction is +//! `rutster-signaling-sip` → `rutster-call-model` + `rutster-media` (once +//! the SDP help lives here, moved out of `rutster-media`'s WebRTC-ICE-coupled +//! SDP module — see §3.7 of the slice-1 spec for the split rationale). + +#[cfg(test)] +mod tests { + /// Stub crates lock boundaries; the compile-test is the lock. + #[test] + fn crate_compiles() {} +} diff --git a/crates/rutster-spend/Cargo.toml b/crates/rutster-spend/Cargo.toml new file mode 100644 index 0000000..3e834dd --- /dev/null +++ b/crates/rutster-spend/Cargo.toml @@ -0,0 +1,8 @@ +# crates/rutster-spend/Cargo.toml +[package] +name = "rutster-spend" +version = "0.0.0" +license.workspace = true +edition.workspace = true +repository.workspace = true +description = "In-boundary spend / abuse gate — stub crate (filled in spearhead step 6)." diff --git a/crates/rutster-spend/src/lib.rs b/crates/rutster-spend/src/lib.rs new file mode 100644 index 0000000..2ea0d1c --- /dev/null +++ b/crates/rutster-spend/src/lib.rs @@ -0,0 +1,21 @@ +//! # rutster-spend +//! +//! **Status:** stub. Fills in at spearhead step 6 (spend cap / abuse gate). +//! +//! In-boundary spend and abuse control is constitutive of the wedge +//! ([ADR-0002](../../../docs/adr/0002-north-star-and-fused-core.md)): the +//! runaway brain structurally cannot exceed spend or pacing because it +//! doesn't hold the wire — the trunk termination + spend gate do, in one +//! boundary. Pulling spend out into a service re-introduces the 3-vendor +//! structural hole the fused vertical was chosen to eliminate. +//! +//! This crate will hold: spend caps, pacing caps, deny-by-default routing, +//! rate-limits, toll-fraud pattern detection — co-located with trunk +//! termination in `rutster-signaling-sip` (step 5). Depends on nothing in +//! the workspace in slice 1. + +#[cfg(test)] +mod tests { + #[test] + fn crate_compiles() {} +} diff --git a/crates/rutster-tap/Cargo.toml b/crates/rutster-tap/Cargo.toml new file mode 100644 index 0000000..2ccb1d7 --- /dev/null +++ b/crates/rutster-tap/Cargo.toml @@ -0,0 +1,8 @@ +# crates/rutster-tap/Cargo.toml +[package] +name = "rutster-tap" +version = "0.0.0" +license.workspace = true +edition.workspace = true +repository.workspace = true +description = "Agent audio tap — stub crate (filled in spearhead step 2)." diff --git a/crates/rutster-tap/src/lib.rs b/crates/rutster-tap/src/lib.rs new file mode 100644 index 0000000..7843deb --- /dev/null +++ b/crates/rutster-tap/src/lib.rs @@ -0,0 +1,21 @@ +//! # rutster-tap +//! +//! **Status:** stub. Fills in at spearhead step 2 (the tap itself). +//! +//! Slice 1 *pre-paves* the tap by exposing the canonical PCM boundary as +//! the `AudioSource` / `AudioSink` traits in [`rutster_media`](../rutster-media/index.html), +//! and wires an `EchoAudioPipe` between sink and source. Step 2 swaps that +//! pipe for a real WSS tap client (core-as-client, brain-as-server — +//! [ADR-0006](../../../docs/adr/0006-ingress-posture.md)). No code changes to +//! `RtcSession` itself in step 2 — that's the test of the seam. +//! +//! This crate will, when filled in, re-export `PcmFrame` from +//! `rutster-media` (one canonical home — spec §3.1) and ship the WSS +//! tap client + the versioned framing protocol. It depends on nothing in +//! the workspace in slice 1. + +#[cfg(test)] +mod tests { + #[test] + fn crate_compiles() {} +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..84ef13d --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +# rust-toolchain.toml — pins the toolchain for reproducible builds. +[toolchain] +channel = "1.80" +components = ["rustfmt", "clippy"]