opencode controller 7616878bb1 docs: propagate ADR-0007/0008 to README, ARCHITECTURE, PORT_PLAN, AGENTS
ADR-0007 (rent the trunk) + ADR-0008 (FOB/green-zone doctrine) propagation
into the narrative docs that orient contributors + readers. No code changes.

README:
- Wedge bullet 2: 'one secure auditable boundary' now lists media + local
  reflexes + spend + tap + audit (was: trunk termination + media + spend).
  Adds the honest caveat that PSTN media inside the boundary is the on-prem
  *graduation* (ADR-0007), not a day-one claim.
- 'Is / isn't': 'isn't a TDM/PSTN-hardware PBX — *and not a SIP stack.*'
  No first-party SIP (ADR-0007). PSTN reach is rented transport.
- Memory-safety pillar: 'rutster parses no SIP at all' — entire first-party
  wire surface is WebRTC/RTP/SRTP + WebSocket tap/ingress, all memory-safe
  Rust. The carrier-SIP interop tail lives outside the trust boundary.
- Spearhead step 5: 'Add a real phone number via rented transport' (was:
  'Replace WebRTC ingress with a real PSTN trunk call'). Re-aims at the
  AI-telephony frontier; no first-party SIP stack.
- References: 0007 supersedes 0003 in the highlighted ADR list.

ARCHITECTURE:
- New 'FOB and the green zone' section after the fused-vertical framing —
  names the build-vs-reuse doctrine with the FOB member list + green-zone
  member list, and restates memory-safety precisely ('FOB is 100%
  memory-safe Rust; the green zone is trusted OSS kept outside the
  boundary — not an over-claim that every byte is Rust').
- 'Inside the boundary': 'Carrier trunk — rented transport, not first-party'
  replaces 'Trunk SIP termination — Rust-native.' PSTN audio arrives as
  a media-leg ingress from a rented CPaaS raw-media fork or an out-of-tree
  SBC for on-prem sovereignty.
- Biggest technical risk: 'No longer the SIP stack — because rutster no
  longer builds one.' Retires ADR-0003's named schedule risk; redirects
  to 'the reflex loop itself' (turn-taking, VAD-driven barge-in, jitter,
  pacing) — which is also the differentiator.

PORT_PLAN:
- Design rule 4: 'rent it, don't own it' replaces ADR-0003's 'Rust-native
  trunk SIP, no SBC shield.' ADR-0007 restores the rule's original instinct.
- SIP signaling (trunk) row: disposition flipped to 🔌 Rented / out-of-tree.
- Outbound registration row: disposition flipped to 🔌 Rented / out-of-tree
  (handled by the rented transport or out-of-tree SBC; rutster parses no SIP).
- Spend/abuse engine row: 'co-located with call origination + the tap inside
  the boundary' (was: 'co-located with trunk termination'). rutster mediates
  both the provider call-control API and the brain tap — the brain never
  holds the wire.
- Spearhead step 5: 'Add a real phone number via rented transport.'
- Open decisions: SIP line updated to 'Re-decided — ADR-0007.'

AGENTS.md:
- ADR list: adds 0007 and 0008 with annotations; marks 0003 as superseded
  by 0007.
- Key decisions to respect: prepends the FOB/green-zone doctrine as the
  *the* build-vs-reuse rule. 'When in doubt, default to green zone — the
  FOB earns its members, it doesn't collect them. This is why the trunk is
  rented (ADR-0007) and Valkey reused (ADR-0005), not rebuilt. Don't pull
  green-zone plumbing into the core.'
2026-06-29 20:26:51 -04:00

Rutster

The open-source engine for building the AI-era contact center — self-hostable, AI-native, memory-safe Rust. A spiritual successor to Asterisk's place in the world, not its protocols or its architecture.

Not a port of Asterisk. rutster inherits the role Asterisk held — the self-hostable engine a technical builder uses to stand up a contact center — and re-aims it at a category AI is actively disrupting, instead of a PBX category UCaaS already ate.

Quickstart

# Prereqs: Rust (rustup), libopus dev headers (libopus-dev / opus-devel / brew install opus)
cargo run
# listening on http://0.0.0.0:8080

Open http://localhost:8080/ → click "Start call" → grant mic → hear yourself echo. Full walkthrough + troubleshooting: docs/QUICKSTART.md.

Status: Slice 1 (WebRTC media loopback) is the active build target. The workspace is landing task-by-task on the slice-1-webrtc-loopback branch. Design: docs/superpowers/specs/2026-06-28-slice-1-webrtc-loopback-design.md. Implementation plan: docs/superpowers/plans/2026-06-28-slice-1-webrtc-loopback.md.

Documentation

Doc For when you want to…
docs/QUICKSTART.md Run it in 5 minutes
docs/DEVELOPMENT.md Iterate on the codebase (workspace layout, per-crate testing, dev loop)
docs/ARCHITECTURE.md Understand the fused per-call vertical + composable platform + agent tap
docs/PORT_PLAN.md See every Asterisk subsystem mapped to a disposition (capability checklist, not template)
docs/adr/ Load-bearing architecture decisions
AGENTS.md Project orientation for any agent (human/AI/hybrid) working in the repo
CONTRIBUTING.md Trunk-based dev workflow, CI gates, commit style, review checklist
LEARNING.md Index of "to learn concept X, read file Y" (learner-facing codebase)

Why it exists

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: it is a framework / engine, not a turnkey product.

The white space no incumbent fills:

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) LiveKit will never ship
Cloud CCaaS (Five9, Genesys, NICE, Amazon Connect, Twilio Flex) Proprietary, AI bolted on Self-hostable, AI-native, 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 (escalation, queues), not a single bot
Dated OSS (Vicidial, FreePBX) Self-hostable, Asterisk-era Modern, AI-native, memory-safe Rust

The wedge is a coherent combination, not a silver bullet:

  1. No-GC real-time determinism — tight turn-taking / barge-in / jitter in a no-GC loop.
  2. One secure auditable boundary — media + local reflexes + spend/abuse control + the tap + audit in a single memory-safe trust domain. One thing to certify (strongest for PCI / HIPAA / TCPA). The carrier trunk is rented (or out-of-tree); bringing PSTN media inside the boundary is the on-prem graduation (ADR-0007), not a day-one claim.
  3. Operational simplicity — one binary, one bill, one deploy.

Honest caveat: 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, barge-in, jitter, pacing, DTMF), not the brain round-trip. The moat is the whole.

Who it's for

The modern equivalent of the 2006 Linux-nerd-who-stood-up-Asterisk-for-an-SMB: the CLI/IDE/AI-comfortable self-hosting technical builder — runs Claude Code in a terminal, lives in an editor with an AI pair, versions everything in git, 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.

What it is / isn't

  • Is: a Rust media core owning the per-call vertical (RTP/SRTP media termination + local real-time reflexes + a clean audio tap to an external brain + in-boundary spend/abuse control; the carrier trunk is rented transport, not first-party — ADR-0007); a programmable call model exposed as a REST/gRPC API + event stream; WebRTC-first human ingress; a library of contact-center capabilities (ACD, IVR, queues, recording, CDR, dialer, supervisor) delivered as services around the core.
  • Isn't: a TDM/PSTN-hardware PBX — and not a SIP stack. No DAHDI, no Sangoma/Digium cards, no ISDN/SS7, no IAX2/H.323/SCCP/MGCP/Unistim — and no first-party SIP (ADR-0007). PSTN reach is rented transport (a CPaaS raw-media fork, or an out-of-tree SBC for on-prem media). Inbound SIP endpoint registration (desk phones) likewise stays out-of-tree — not the browser/SSO UX rutster targets.

Core design pillars

  1. Memory-safe by construction — Rust everywhere on the hot path; fuzzed sans-IO protocol parsers. rutster parses no SIP at all (ADR-0007): its entire first-party wire surface is WebRTC/RTP/SRTP + the WebSocket tap/ingress protocol — all memory-safe Rust. The carrier-SIP interop tail lives outside the trust boundary (rented transport or an out-of-tree SBC), so the buffer-overflow/RCE CVE class is designed out of rutster's own surface.
  2. Security-as-product — the single auditable boundary is the moat. TLS/SRTP mandatory, deny-by-default routing, built-in toll-fraud controls, mTLS gRPC admin (no plaintext AMI), hard multi-tenancy. Compliance is a buying criterion, not a row.
  3. In-boundary spend / abuse control — spend caps and abuse/pacing control live inside the trust boundary, co-located with trunk termination. A runaway brain can't exceed pacing or spend because it doesn't hold the wire — structurally impossible for a 3-vendor stack.
  4. Data ownership — calls and training data never leave the operator's infra. The self-host wedge and the fuel for the ML self-improvement loop.
  5. Degradation, deterministic, observable — no-GC real-time loop; OpenTelemetry traces that follow a single call across the boundary; config-as-data, not .conf files edited on a box.
  6. Operational simplicity — one binary, one bus, one deploy (compose up).

Layout

  • docs/ARCHITECTURE.md — the fused per-call vertical + composable horizontal platform; the agent tap as the central interface.
  • docs/PORT_PLAN.md — the capability checklist (what a telephony system must handle), not an architecture template. Every Asterisk subsystem mapped to a disposition with rationale.
  • docs/adr/ — decisions. Highlights:
    • 0002 — north star + fused vertical
    • 0007 — rent the trunk transport; no first-party SIP stack (supersedes 0003)
    • 0004 — GPL-3.0-or-later
    • 0005 — Valkey (bus + state store)
    • 0006 — WebRTC-first ingress; SIP endpoint deferred

Status

Slice 1 (WebRTC media loopback) implemented; spearhead steps 26 pending. The vision revision and ADRs define the architecture; the slice-1 design documents the active build.

First proof (the spearhead)

The full thin slice, 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. Add a real phone number via rented transport (a CPaaS raw-media fork, e.g. Twilio Media Streams) — proves a PSTN call reaches the reflex loop, no first-party SIP (ADR-0007)
  6. Add the spend cap (hard-stop at threshold) — proves the boundary

Steps 14 are the reflex loop — the hard, most-differentiating part proves itself before trunk integration piles on. "I called my Rust box and an AI answered the phone" is the momentum fuel a solo multi-year build needs.

Capability ladder (the grand vision, incrementally)

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
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 13 compounding

License

GPL-3.0-or-later (ADR-0004). Strong copyleft in the Asterisk lineage, modernized one notch. The license is the floor, not the moat — the wedge is.

Description
Terribly-named "spiritual" ancestor to the niche Asterisk PBX filled in 2005, but for AI-first call centers in 2026
Readme 3.8 MiB
Languages
Rust 99.5%
HTML 0.5%