Record the SIP edge decision and align the docs: - docs/adr/0001-sip-strategy.md: layered strategy (own Rust parser, rent the interop tail via a Kamailio + rtpengine SBC, grow native core behind the shield); pjproject FFI explicitly rejected for breaking the memory-safety thesis at the most exposed seam. - PORT_PLAN §1 + open decisions: SIP row updated to the decided strategy. - ARCHITECTURE: "biggest technical risk" now points at ADR-0001. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C2bfD7MkqEdfnMXxXBu456
57 lines
2.8 KiB
Markdown
57 lines
2.8 KiB
Markdown
# Rutster Architecture
|
|
|
|
## The reframe
|
|
|
|
Asterisk's power was: *one process, load any `.so`, wire anything to anything in the
|
|
dialplan.* That composability is the thing to match — but it does **not** require a
|
|
1.2M-LOC monolith. Rutster delivers the same "build anything" through a different
|
|
substrate:
|
|
|
|
- a **small hardened core** (media + signaling glue + call model),
|
|
- a **WASM plugin runtime** for safe, third-party-extensible logic,
|
|
- **declarative routing** as data for the common path,
|
|
- a **programmable API** (REST/gRPC + event stream) modeled on Asterisk's ARI.
|
|
|
|
More extensible than Asterisk, because extensions are safe to run from people you
|
|
don't fully trust.
|
|
|
|
## Three planes
|
|
|
|
### Control plane (stateless-ish, horizontally scalable)
|
|
The ARI-style resource API (channels / bridges / endpoints / recordings / playbacks)
|
|
over REST + gRPC + a WebSocket/SSE event stream. Registrar, routing, auth. This is
|
|
where "the dialplan" disappears — replaced by declarative routing + external services
|
|
reacting to call events (the Twilio / ARI-Stasis model). Asterisk's
|
|
`rest-api/api-docs/*.json` is a reusable spec for the resource model.
|
|
|
|
### Media plane (stateful, latency-pinned, scaled separately)
|
|
RTP/SRTP termination, mixing/bridging (softmix), transcoding, record/playback. A
|
|
controllable media node driven over gRPC by the control plane. Built on the Rust
|
|
WebRTC media ecosystem (`str0m` sans-IO design, `webrtc-rs`). **The media datapath
|
|
stays tight** — do not over-decompose it across service hops; latency and failure
|
|
modes compound.
|
|
|
|
### App plane (your services + plugins, outside the core)
|
|
IVR, queues, voicemail, dialers, custom routing — driven via the API, deployed
|
|
independently. WASM plugins for in-call logic that needs to run close to the core;
|
|
microservices for stateful/business/billing logic.
|
|
|
|
## Cross-cutting
|
|
|
|
- **Event bus** (NATS / Redis Streams / Kafka) replaces Asterisk's internal Stasis bus
|
|
for cross-service events; a lightweight in-core dispatcher handles intra-core.
|
|
- **State store** replaces `astdb` + realtime/sorcery.
|
|
- **Security is load-bearing, not a row:** memory-safe fuzzed parsers, TLS/SRTP
|
|
mandatory, deny-by-default routing + toll-fraud engine, mTLS gRPC admin (no AMI),
|
|
WASM tenant isolation, SBOM + KMS/Vault for secrets.
|
|
- **Observability:** OpenTelemetry traces that follow a single call across
|
|
signaling → media → app services.
|
|
|
|
## Biggest technical risk
|
|
|
|
The **SIP stack** — **decided in [ADR-0001](adr/0001-sip-strategy.md)**: own the Rust
|
|
parser from day one (the security thesis depends on it), front the public edge with a
|
|
proven **Kamailio + rtpengine** SBC to absorb the interop tail, and grow the native Rust
|
|
transaction/dialog core behind that shield. No pjproject FFI. Everything else builds on
|
|
the existing Rust media ecosystem.
|