Folds the 2026-06-26 vision-revision pressure-test into the canonical docs. The spec moves from Proposed to Ratified; the decisions it produced land in the docs it said it would amend, with ADRs recording each load-bearing reversal. - README.md: reframe north star (AI-era contact-center engine, not Asterisk successor); persona; revised pillars (add data-ownership, demote WASM, promote spend-control); update 'what it is/isn't'. - ARCHITECTURE.md: replace three-plane framing with fused per-call vertical + composable horizontal platform; remove control<->media hot-path gRPC hop; make the agent tap the central interface; add DX spine + GUI-as-API-client + k8s declarative/operational model. Also: 'too slow to police' -> 'too slow to enforce' (terminology). - PORT_PLAN.md: recharacterize as capability checklist (not template); graduate contact-center capabilities to first-class domain; Rust-native trunk SIP rows; WASM demoted; thin-slice + capability ladder phasing. - ADR-0001: marked Superseded by ADR-0003. - ADR-0002 (new): north star + fused per-call core. - ADR-0003 (new): Rust-native trunk SIP, no SBC shield. - ADR-0004 (new): GPL-3.0-or-later license. - ADR-0005 (new): Valkey as event bus + state store. - ADR-0006 (new): WebRTC-first ingress; SIP endpoint deferred. - vision-revision spec: status -> Ratified 2026-06-26.
17 KiB
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:
- 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.
- 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.
- 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).
- The architecture tightened — from pure three-plane microservices to a fused per-call vertical + composable horizontal platform.
- ADR-0001 reversed — the Kamailio + rtpengine C shield is dropped in favor of Rust-native trunk SIP.
- 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:
- 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.
- 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.
- 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
☁️ Serviceand 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.confand 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:
- WebRTC media loopback (terminate RTP/SRTP, echo audio to a browser) — proves the media core
- Add the tap (route audio to an external echo process and back) — proves the tap interface
- 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
- Add barge-in (VAD-driven playout kill) — proves the reflex
- Replace WebRTC ingress with a real PSTN trunk call — proves the trunk client
- 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) |