# Rutster — Vision Revision: the self-hosted AI-era contact-center engine - **Status:** Ratified 2026-06-26 — folded into `README.md`, `docs/ARCHITECTURE.md`, `docs/PORT_PLAN.md`, and ADRs 0002–0006. Kept as the design record of the pressure-test. - **Date:** 2026-06-26 - **Origin:** A pressure-test of the four founding docs (README, ARCHITECTURE, PORT_PLAN, ADR-0001). This document records the decisions that pressure-test produced. - **Amends:** `README.md`, `docs/ARCHITECTURE.md`, `docs/PORT_PLAN.md` - **Reverses:** `docs/adr/0001-sip-strategy.md` (to be formalized as a new ADR-0003) --- ## TL;DR > **rutster** — the open-source engine for self-hosting an AI-first contact center on commodity trunking: high-containment AI self-serve, seamless human takeover when it breaks down, and a closed ML loop that learns from every escalation — all on infrastructure and data **you** own. "Spiritual successor to Asterisk" means successor to its **place in the world** — *the self-hostable engine a technical builder uses to stand up a call center* — not successor to its protocols or its architecture. Asterisk's subsystem map (the PORT_PLAN) is a capability **checklist**, not a template. --- ## What changed, and why (the pressure-test in brief) The founding docs were architecturally rich but anchored to "memory-safe successor to Asterisk." Six load-bearing premises were stressed; the vision that survived is sharper and, in several places, reversed: 1. **North star moved** — from "Asterisk successor" (a consolidating PBX category, and a 1.18M-LOC feature-parity death-march) to **"the engine for the AI-era contact center."** Same Rust media core, aimed at a category AI is actively disrupting instead of one Teams Phone/UCaaS already ate. 2. **The competitor stopped being Asterisk.** It became **LiveKit** (horizontal media infra, no contact-center domain), **cloud CCaaS** (Five9/Genesys/NICE/Amazon Connect — un-self-hostable, AI bolted on), **cheap cloud AI-voice** (Vapi/Retell — your calls and data on their infra), and **dated OSS** (Vicidial/FreePBX — Asterisk-era PHP+C). rutster's slot — *self-hostable + AI-native + owns the contact-center domain + memory-safe* — is genuine white space. 3. **The wedge is a coherent combination, not a silver bullet** — no-GC real-time determinism **+** one secure auditable boundary **+** operational simplicity. Strongest for regulated/high-trust phone-agent work (PCI / HIPAA / TCPA). 4. **The architecture tightened** — from pure three-plane microservices to a **fused per-call vertical + composable horizontal platform.** 5. **ADR-0001 reversed** — the Kamailio + rtpengine C shield is dropped in favor of **Rust-native trunk SIP.** 6. **Pillars re-weighted** — memory-safety and security-as-product survive *stronger*; **data-ownership** added; **in-boundary spend control** promoted to constitutive; **WASM demoted** out of the core story. --- ## 1. North star & identity rutster is **the open-source engine for building the modern, AI-era contact center** — the swiss-army-knife toolkit, where "modern" means AI is native, not bolted on. - It is a **framework / engine**, not a turnkey product. Asterisk won because contact centers were *built on it* (Vicidial, GOautodial, a thousand integrator builds) — it never tried to *be* Five9. rutster inherits that position. The moment it chases GUI-complete feature-parity with billion-dollar CCaaS, it dies; as the engine others build on, breadth is a strength and scope stays bounded. - Asterisk's capability map is a **completeness checklist** ("what must a telephony system handle"), explicitly **not** an architecture template. We keep the checklist; we reject the channel/bridge/dialplan model as the spine. ## 2. Target persona The modern equivalent of the 2006 Linux-nerd-who-stood-up-Asterisk-for-an-SMB. Concretely: the **CLI/IDE/AI-comfortable self-hosting technical builder** — the person who runs Claude Code in a terminal, lives in an editor with an AI pair, versions everything in git, and self-hosts on principle. - **Not** the no-code admin clicking a flow-designer canvas. The builder serves the non-technical operator downstream, exactly as integrators did on top of Asterisk. - This narrowing is deliberate and correct **for an engine**. It also liberates the design (see §8): you can make the authoring layer *powerful* because the audience codes and has AI assistance — no "dumb it down for non-programmers" tax. ## 3. The wedge Against each competitor: | Competitor | What they are | rutster's edge | |---|---|---| | **LiveKit** | Horizontal real-time media infra (Go) | rutster owns the **contact-center domain** (ACD, IVR, queues, recording, CDR, dialer, supervisor, agent-state) LiveKit will never ship; fused secure core; self-hostable | | **Cloud CCaaS** (Five9, Genesys, NICE, Amazon Connect, Twilio Flex) | Proprietary, full contact center, AI bolted on | Self-hostable, AI-native, auditable, no per-seat/minute lock-in | | **Cloud AI-voice** (Vapi, Retell, Bland) | Cheap managed voice bots | You own your **calls and training data**; it's a *contact center* (human escalation, queues), not a single bot | | **Dated OSS** (Vicidial, FreePBX) | Self-hostable, Asterisk-era | Modern, AI-native, memory-safe Rust | The **technical wedge** is the coherent combination, not any single capability: 1. **No-GC real-time determinism** — tight turn-taking / barge-in / jitter behavior in a no-GC loop. The one thing a Go SFU + external agent structurally can't match on quality. 2. **One secure auditable boundary** — trunk termination + media + spend/abuse control + audit in a single memory-safe trust domain. One thing to certify, not a 3-vendor chain. 3. **Operational simplicity** — one binary, one bill, one deploy. **Honest caveat (recorded so we don't kid ourselves):** the agent *brain* (STT/LLM/TTS) is necessarily external — audio leaves the box to reach it, same as LiveKit. The real-time edge therefore lives in the **local reflexes that don't need the brain** (VAD killing TTS the instant the caller speaks, jitter, pacing, DTMF), not the brain round-trip. The moat is the *whole*, and it is strongest where self-hosting + audit + data-ownership are buying criteria. ## 4. Architecture identity — fused per-call vertical, composable horizontal platform The core owns the **per-call vertical** end-to-end as one deterministic, auditable trust domain: ``` carrier SIP trunk ─► media termination (RTP/SRTP + local real-time reflexes) │ ├─► clean audio tap ──► external agent brain (STT/LLM/TTS) │ └─► in-boundary spend / abuse gate ``` **Horizontal platform** concerns are services *around* the core, independently scaled: number inventory, billing rollup, analytics, multi-region orchestration, the management API, and the agent **brain** itself. This is tighter than the founding three-plane model: - The **control↔media gRPC hop on the per-call hot path** (founding ARCHITECTURE) is removed. - The **spend gate** and the **agent tap** — which the founding PORT_PLAN externalized (a `☁️ Service` and the app plane respectively) — are pulled **into** the boundary, because they are constitutive of the wedge. - It is neither a monolith nor pure microservices: **fused where fusion buys determinism + security + simplicity; composable where independent scaling matters.** ## 5. SIP — Rust-native trunk SIP (supersedes ADR-0001) Own trunk SIP **and** media termination directly in the Rust core; IP-allowlist the handful of trunk providers. **No Kamailio + rtpengine shield.** - ADR-0001 rented the "20-year device interop tail" via a proven C SBC. Under the AI-voice contact-center scope, that tail **collapses**: you talk to a few documented trunk providers (Telnyx, Bandwidth, Twilio SIP), not thousands of desk-phone/carrier quirks. An inbound/outbound SIP-trunk client against cooperative carriers is tractable in `rsip` / `ezk`. - The C shield put **C at the most exposed seam** (the public internet) and terminated media **twice** — both directly contradicting the wedge. Dropping it makes the memory-safety thesis *literally true*: hostile bytes hit a fuzzed Rust parser first. - **Cost accepted:** we own a (bounded) SIP-trunk client early. **Mitigation:** WebRTC ingress ships first and is unaffected, so first-call never blocks on SIP. ## 6. Pillars (revised) | Pillar | Change | Note | |---|---|---| | Memory-safety | ▲ stronger | Now literally true at the wire (no C edge) | | Security-as-product | ▲ stronger | The single auditable boundary **is** the moat; compliance is a buying criterion | | In-boundary spend/abuse control | ▲ promoted | From `☁️ service / table stakes` to **constitutive** — co-located with trunk termination, structurally impossible for a 3-vendor stack | | **Data ownership** | ✦ new | Calls + training data never leave the operator's infra — the self-host wedge *and* the ML-loop fuel | | WASM plugin sandbox | ▼ demoted | Out of the core story. The agent brain is external (the **tap** is the extension point); ops-simplicity wants one binary. Softly retained as a *candidate* mechanism for community call-flow/routing plugins — but undecided vs. webhooks/scripting | ## 7. Why no hardware (the visceral rationale) Drop TDM / DAHDI / zaptel entirely (PORT_PLAN already ⛔'d it). The rationale, stated so it isn't just a line item: **every kernel-recompile, every `ztdummy`-on-UHCI timing hack, every `HZ=1000` ritual existed because telephony was shackled to a hardware clock living in a kernel module.** rutster is all userspace Rust + commodity trunking. **"Kernel to desk" becomes "container to desk" — never recompile a kernel for a phone call again.** The timing *obsession* survives — it just moves into userspace Rust with **dedicated timing threads** (not the shared tokio pool). The thing that justified the suffering is first-class; the suffering is designed out. ## 8. DX spine — developer-first authoring The engine is **headless and API-complete.** The persona authors via **code + config-as-text**: git-versioned, CLI-driven, IDE-native, AI-assistant-friendly (typed, schema'd, well-documented, LSP-friendly). **Terraform/Rails for call centers, not Squarespace.** - **The AEL lesson** (from the person who wrote the DCAP exam): *better isn't enough.* AEL was superior to `extensions.conf` and still lost — it arrived after the muscle memory had set. An authoring layer must win **on contact** and meet people where their muscle memory already is. In 2026 that muscle memory is **code + an AI pair**, not a config syntax or a visual canvas. - **"Boom" + swiss-army-knife, reconciled:** an opinionated **batteries-included reference distro** (`compose up`, point a trunk at it, start taking calls) on top of a **composable framework** (build anything in code). Home Assistant model, not raw dialplan. - **Call-flow authoring is a first-class design surface** — owned by the DCAP author, designed with the AEL lesson baked in. The AI-era twist: part of the old dialplan **dissolves into the agent** (the model improvises the conversation). The authoring layer becomes the **routing, escalation, and business scaffolding *around* an AI that writes half the flow at runtime** — genuinely new design space, not "dialplan 2.0." ## 9. GUI & extension architecture **The GUI is a pure API client, never an insider** — FreePBX↔Asterisk, modernized. - **Not a plugin in the core.** A web GUI must not share an address space / lifecycle / attack surface with the latency-pinned media engine inside the one secure boundary. - **A separate application.** The **official reference GUI** ships in the batteries-included distro (so "boom" includes a usable UI) but holds **no privilege a third party couldn't get.** The ecosystem can build rival GUIs. - **Discipline:** the official GUI is built **only** on the public API — no backdoors. That guarantees API completeness. (Learn from FreePBX's leaky abstraction: coupling to Asterisk's config *files* caused the "don't hand-edit or it'll clobber you" war.) - **Config-as-code vs. GUI-mutation tension → the Kubernetes model.** Declarative desired-state (config-as-code, git, reconciled by the engine) **plus** an API/CLI/GUI for live operational state and ad-hoc actions, all through **one API**, single source of truth. The GUI is the *dashboard*, not a side-channel. *Manifests + kubectl + dashboard, for call centers.* - **Bonus — scope guard:** the GUI can only surface what the API already does, so it can't drag the engine toward Five9-parity. ## 10. First proof (the spearhead) **The full thin slice:** a real call → core → external STT/LLM/TTS brain → barge-in + spend cap. It proves the *combination* (which is the wedge), and "I called my Rust box and an AI answered the phone" is the momentum fuel a solo multi-year build needs. It is only survivable if built **brutally thin and sequenced so each step is its own proof** — never a big bang: 1. WebRTC media loopback (terminate RTP/SRTP, echo audio to a browser) — proves the media core 2. Add the **tap** (route audio to an external echo process and back) — proves the tap interface 3. Swap echo for the **brain** (ideally a single speech-to-speech API, e.g. OpenAI Realtime, to collapse STT+LLM+TTS into one integration) — proves agent integration 4. Add **barge-in** (VAD-driven playout kill) — proves the reflex 5. Replace WebRTC ingress with a real **PSTN trunk** call — proves the trunk client 6. Add the **spend cap** (hard-stop at threshold) — proves the boundary Steps 1–4 *are* the reflex loop — the hard, most-differentiating part proves itself before trunk integration piles on. Keep the dev loop on WebRTC ingress until step 5. ## 11. Capability ladder (the grand vision, incrementally) Proof that "AI-first contact center" decomposes into shippable, independently-demoable rungs: | Rung | Capability | Reuses | |---|---|---| | 1 | **Self-serve** — AI answers, contains the call | the thin-slice first proof | | 2 | **Escalation** — human agent barges in / takes over when AI breaks down | the audiohook/barge primitive PORT_PLAN already kept | | 3 | **Measurement** — containment rate, where/why AI failed | CDR + analytics on calls *you own* | | 4 | **Self-improvement** — every takeover → auto-labeled training data → loop | rungs 1–3 compounding | **ML "self-train," honestly:** not autonomous magic (the persona has no ML team). The engine **captures the perfect training signal** — every human takeover auto-labeled *"AI failed here → human did this"* — and provides the loop to act on it: containment analytics, eval sets that regression-test against past failures, prompt/KB suggestions, optional fine-tune export. All on the operator's own infra. Uniquely enabled by owning the whole call. ## 12. Out of scope (deliberately) & open decisions - **Adoption / trust / go-to-market** — "why would anyone route real calls through a brand-new Rust platform?" A positioning question, flagged for its own session. - **License** — still undecided (carried over from founding docs). - **Plugin mechanism** — WASM vs. webhooks vs. scripting for community call-flow/routing extensions. - **The agent-tap protocol** — the single most important interface in the system (raw PCM over WebSocket/TCP vs. gRPC streaming vs. SDK-joins-the-call). A design decision for the framework-layer phase. - **Event bus** — NATS vs. Kafka vs. Redis Streams (carried over). --- ## Document impact (what this revision changes in the repo) | Doc | Change | |---|---| | `README.md` | Reframe north star (AI-era contact-center engine, not Asterisk-successor); add the persona; revise pillars (add data-ownership, demote WASM, promote spend-control); update "what it is/isn't"; mark SIP decided | | `docs/ARCHITECTURE.md` | Replace three-plane framing with fused per-call vertical + composable platform; remove control↔media hot-path gRPC hop; make the agent tap the central interface; add DX spine and GUI-as-API-client + k8s declarative/operational model | | `docs/PORT_PLAN.md` | Recharacterize as "the checklist, not the spine"; graduate contact-center capabilities (queues/ACD/IVR/recording/CDR/dialer/supervisor) from peripheral to core domain library; update SIP rows (Rust-native trunk, no Kamailio); update WASM/plugin rows; replace phasing with the capability ladder + thin-slice first proof | | `docs/adr/0001-sip-strategy.md` | Add `Superseded by ADR-0003` header | | **New** `docs/adr/0002-north-star-and-fused-core.md` | The identity reframe: AI-era contact-center engine + fused-vertical architecture | | **New** `docs/adr/0003-sip-rust-native-trunk.md` | Rust-native trunk SIP, no SBC shield (supersedes ADR-0001) |