# 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) |
