# Rutster โ€” Asterisk Capability Checklist This is the **capability checklist**, not the architecture spine. It walks the Asterisk subsystem surface as a completeness audit โ€” *"what must a telephony system handle"* โ€” and assigns every capability a **disposition** in the rutster architecture, with a one-line rationale. We keep the checklist; we **reject** the Asterisk channel/bridge/dialplan model as the architecture (see [ADR-0002](adr/0002-north-star-and-fused-core.md)). The crate/service boundaries fall out of the "Core / Service" rows; the threat model hangs off the "attack surface" of each row. Grounded against the Asterisk 22.10.1 tree (~1.18M LOC C/H). ## Disposition legend | | Disposition | Meaning | |---|---|---| | ๐Ÿฆ€ | **Core** | In the hardened, memory-safe Rust core. Reserved for the hot media path, call model, and signaling glue โ€” fast, always-present, trusted. | | ๐Ÿงฉ | **Plugin (WASM)** | Sandboxed extension. Logic that benefits from isolation and third-party extensibility. Cannot crash the core or cross tenant boundaries. | | โ˜๏ธ | **Service** | Independent microservice. Stateful, independently-scaled, or business/billing logic. Talks over API + event bus. | | ๐Ÿ”Œ | **Edge / FFI** | Wrap mature external C (pjproject/spandsp) or front with an SBC. Used where a pure-Rust rewrite is a tar pit. | | โ›” | **Drop** | Legacy hardware or dead protocol. Gone. | | ๐Ÿ” | **Replace** | Capability survives but the mechanism is entirely redesigned (no 1:1 mapping). | ## Design rules (the heuristics behind every row) 1. Hot media path & the call model โ†’ **Core**. Trusted, fast, always-on. Inside the fused per-call vertical. 2. Anything that benefits from isolation or third-party extension โ†’ **Plugin** *(now softened โ€” WASM demoted out of the core story per [ADR-0002](adr/0002-north-star-and-fused-core.md); the agent **tap** is the primary extension point for in-call logic).* 3. Stateful, independently-scaled, or business/billing logic โ†’ **Service**. Around the core, horizontal platform. 4. Mature C that's a tar pit to rewrite (SIP) โ†’ **rent it, don't own it.** *[ADR-0007](adr/0007-trunk-rented-transport.md) restores this rule's original instinct for the trunk: rutster owns no SIP stack โ€” carrier transport is a rented CPaaS raw-media fork (primary) or an out-of-tree SBC (on-prem graduation); ADR-0003's from-scratch Rust trunk SIP is superseded. FFI retained only for mature codec/DSP/EQ libraries (libopus, speexdsp, WebRTC APM).* 5. Legacy hardware / dead protocols โ†’ **Drop**. 6. Security & multi-tenancy are cross-cutting โ€” never a row, always a property. **Spend / abuse control is constitutive**, pulled into the boundary, not externalized. --- ## 1. Signaling & channel drivers (`channels/`, `res/res_pjsip*`) | Asterisk subsystem | Module(s) | Disp. | Rationale | |---|---|---|---| | SIP signaling (trunk) | `chan_pjsip` + `res_pjsip*` (48 mods) | ๐Ÿ”Œ Rented / out-of-tree | **Re-decided ([ADR-0007](adr/0007-trunk-rented-transport.md), supersedes ADR-0003):** rutster owns **no SIP stack.** PSTN audio arrives as a media-leg ingress from a rented CPaaS raw-media fork (Twilio Media Streams / Telnyx โ€” primary), or an out-of-tree SBC (Kamailio/FreeSWITCH/drachtio + rtpengine) when media must stay on-prem. rutster parses no SIP โ†’ SIP is removed from the attack surface entirely, not rewritten. The from-scratch Rust trunk SIP of ADR-0003 was the highest-cost / lowest-differentiation square on the board, with no production-hardened Rust SIP stack to stand on. | | โ†ณ outbound registration (to carriers) | `res_pjsip_outbound_registration` | ๐Ÿ”Œ Rented / out-of-tree | Handled by the rented transport or the out-of-tree SBC ([ADR-0007](adr/0007-trunk-rented-transport.md)), not by rutster โ€” the provider/SBC owns register-to-carrier. | | โ†ณ **inbound endpoint registration (desk/soft phones)** | `res_pjsip_registrar` | โ›” **Deferred โ€” community edge** | **Split from trunk.** An inbound endpoint server re-imports the *unbounded device interop tail* โ€” it fails all three FOB tests ([ADR-0008](adr/0008-fob-and-green-zone.md)), so it's **green-zone, out-of-tree, never first-party** ([ADR-0007](adr/0007-trunk-rented-transport.md)): Polycom/Yealink/Zoiper `REGISTER`, BLF/MWI, DTMF variants, per-device NAT/provisioning. In an SSO/browser-agent UX, the desk-phone demographic has collapsed. Out-of-tree SBC-style adapter (fronting the public API / B2B-SIP) for anyone who needs it โ€” **outside the trust boundary**, so its tail can't compromise the wedge. See [ADR-0006](adr/0006-ingress-posture.md). | | โ†ณ SDP / media negotiation | `res_pjsip_session`, `_sdp_rtp` | ๐Ÿฆ€ Core | Offer/answer drives the media plane directly. | | โ†ณ auth | `res_pjsip_outbound_authenticator_digest`, etc. | ๐Ÿฆ€ Core | Digest + token auth, deny-by-default, rate-limited. Security-critical. | | โ†ณ NAT / ICE / rtcp | `res_pjsip_nat`, `res_rtp_asterisk` ICE | ๐Ÿฆ€ Core | ICE/STUN/TURN via `str0m`/`webrtc-rs`. | | โ†ณ pub/sub (presence, MWI, BLF) | `res_pjsip_pubsub`, `_exten_state`, `_mwi` | ๐Ÿฆ€ Core + โ˜๏ธ | Signaling in core; presence/MWI state aggregation as a service. | | โ†ณ T.38 fax | `res_pjsip_t38` | โ˜๏ธ Service | Isolate fax entirely (see ยง5). | | WebRTC signaling (agent ingress) | `chan_websocket`, `res_http_websocket` | ๐Ÿฆ€ Core | **First-party human-participant ingress** ([ADR-0006](adr/0006-ingress-posture.md)). The browser is the softphone: SSO in, one peer-connection, DTLS-SRTP + ICE handled by the browser, zero device-provisioning tail. Also the modern hosted UX and the escalation path (rung 2): agent clicks *take this call* โ†’ WebRTC leg + audiohook/barge handoff. WSS + DTLS-SRTP via the media stack. | | External media | `chan_audiosocket` | ๐Ÿฆ€ Core | Modern, relevant pattern (stream media to an external process); keep as a media tap/source API. | | Local console audio | `chan_console` | ๐Ÿงฉ Plugin | Dev/testing convenience; not core. | | RTP-only pseudo-channel | `chan_rtp`, `chan_bridge_media` | ๐Ÿฆ€ Core | Media-plane primitives. | | IAX2 | `chan_iax2` | โ›” Drop | Dead inter-Asterisk protocol. SIP trunks instead. | | TDM / analog / ISDN | `chan_dahdi`, `sig_analog`, `sig_pri`, `sig_ss7` | โ›” Drop | No hardware era. PSTN via SIP trunk / SBC. | | H.323 | `addons/chan_ooh323` | โ›” Drop | Dead protocol. | | SCCP / Skinny, MGCP | (Skinny/MGCP) | โ›” Drop | Dead protocols. | | Unistim | `chan_unistim` | โ›” Drop | Dead vendor protocol. | | XMPP / Jingle | `chan_motif`, `res_xmpp` | โ›” Drop | Dead path. | --- ## 2. Media plane (`main/rtp_engine.c`, `res_rtp_asterisk`, `bridges/`, `main/dsp.c`) | Asterisk subsystem | Module(s) | Disp. | Rationale | |---|---|---|---| | RTP / RTCP engine | `rtp_engine.c`, `res_rtp_asterisk` | ๐Ÿฆ€ Core | **Crown jewel.** Built on `str0m`/`webrtc-rs`, sans-IO, dedicated timing (not the shared tokio pool). | | SRTP / DTLS | `res_srtp` | ๐Ÿฆ€ Core | Mandatory-by-default encryption. | | Bridging framework | `main/bridge.c` | ๐Ÿฆ€ Core | The 2-party + N-party call topology engine. | | โ†ณ softmix conference mixer | `bridges/bridge_softmix` | ๐Ÿฆ€ Core | N-party mixing on the hot path. | | โ†ณ simple / native-RTP bridge | `bridge_simple`, `bridge_native_rtp` | ๐Ÿฆ€ Core | Direct media flow (re-INVITE peers together) when no mixing needed. | | โ†ณ holding bridge | `bridge_holding` | ๐Ÿฆ€ Core | Parking/hold media state. | | โ†ณ native DAHDI bridge | `bridge_native_dahdi` | โ›” Drop | Hardware. | | DSP (DTMF/MF detect, silence, tone) | `main/dsp.c` | ๐Ÿฆ€ Core | Media-plane primitive; exposed to plugins as events. | | Echo cancellation | (hardware / sw) | ๐Ÿ”Œ Edge/FFI | No mature pure-Rust EC; FFI speexdsp / WebRTC APM. | | Audio hooks (tap/inject/volume) | `main/audiohook.c` | ๐Ÿฆ€ Core | Primitive behind recording, ChanSpy, whisper/barge. | | Music on hold | `res_musiconhold` | ๐Ÿฆ€ Core | Just a media source; small, keep in core (asset from object storage). | | Jitter buffer | `func_jitterbuffer`, abstract jb | ๐Ÿฆ€ Core | Quality-critical; part of the RTP path. | --- ## 3. Call model & PBX core (`main/`) | Asterisk subsystem | Module(s) | Disp. | Rationale | |---|---|---|---| | Channel abstraction | `main/channel.c` (`ast_channel`) | ๐Ÿฆ€ Core | The unifying "leg" object (signaling + media state). Reimagined as a `Channel`/leg. | | PBX / dialplan engine | `main/pbx.c` | ๐Ÿ” Replace | โ†’ declarative routing (data) + event-driven apps. No `extensions.conf`. | | Call features (transfer/park/pickup) | `res_features`, `res_parking` | ๐Ÿฆ€ Core | Call-control primitives, exposed via the API. | | Scheduler / taskprocessor / threadpool | `main/sched.c`, `taskprocessor.c`, `threadpool.c` | ๐Ÿฆ€ Core | tokio for control; dedicated timing threads + timer wheel for the 20ms media loop. | | Internal message bus (Stasis) | `main/stasis*.c` | ๐Ÿ” Replace | In-core dispatcher for intra-core; external event bus (NATS/Kafka) for cross-service. | | Module loader | `main/loader.c` | ๐Ÿ” Replace | โ†’ WASM host + service registry. No in-process `.so`. | | ACL / named ACL | `main/acl.c`, `res_named_acl` | ๐Ÿฆ€ Core | Security primitive; policy-driven. | | astdb (internal KV) | `main/db.c` | ๐Ÿ” Replace | โ†’ state store (**Valkey** KV, [ADR-0005](adr/0005-event-bus.md)). | --- ## 4. Dialplan & programmability (`pbx/`, `res_agi`, `res_ari`, `manager`) | Asterisk subsystem | Module(s) | Disp. | Rationale | |---|---|---|---| | `extensions.conf` dialplan | `pbx_config` | ๐Ÿ” Replace | Declarative routing as data (GitOps) for the 90% case. | | AEL / Lua dialplan | `pbx_ael`, `pbx_lua` | โ›” Drop | Replaced by WASM call-flow + routing config. | | Realtime dialplan | `pbx_realtime` | ๐Ÿ” Replace | Routing in the config/state layer. | | Call files / spool | `pbx_spool` | ๐Ÿ” Replace | โ†’ originate via API. | | Macro / Gosub / Stack | `app_stack`, `app_macro` | ๐Ÿ” Replace | โ†’ WASM call-flow logic. | | AGI / FastAGI | `res_agi` | ๐Ÿ” Replace | โ†’ WASM plugins + gRPC. Same "external program controls a call," sandboxed and typed. | | ARI (REST + stasis apps) | `res_ari*`, `res_stasis*` | ๐Ÿฆ€ Core | **Becomes THE API** โ€” the control-plane resource model. `api-docs/*.json` is the reusable spec. | | AMI (manager) | `main/manager*.c` | ๐Ÿ” Replace | Drop the plaintext TCP protocol โ†’ mTLS gRPC + RBAC + audit log. | | CLI | `main/cli.c` | ๐Ÿ” Replace | Thin CLI that's an API client, not an in-process console. | | DUNDi (distributed routing) | `pbx_dundi` | โ›” Drop | Dead/niche. | | ENUM lookup | `func_enum` | ๐Ÿงฉ Plugin | Routing-time lookup; pluggable. | --- ## 5. Applications (`apps/`) โ€” the contact-center domain > **Scope lift** ([vision-revision](superpowers/specs/2026-06-26-vision-revision-design.md) ยง4): the > contact-center capabilities Asterisk kept as apps are **rutster's core domain**, not peripheral. > This is the difference between "Asterisk successor" and "AI-era contact-center engine." Every row > here is load-bearing for the wedge (the thing LiveKit will never ship). | Asterisk app | Module | Disp. | Rationale | |---|---|---|---| | Dial / originate | `app_dial`, `app_originate` | ๐Ÿฆ€ Core | Core call origination, exposed via the API. | | Queues / ACD | `app_queue` | โ˜๏ธ Service (**domain core**) | Stateful, independently scaled. **First-class** โ€” ACD is the beating heart of a contact center, not a peripheral app. The AI self-serve + human-escalation loop (capability ladder) is an ACD-shaped problem. | | Voicemail | `app_voicemail` | โ˜๏ธ Service | Stateful storage + business logic; isolate it. | | Conferencing | `app_confbridge` | ๐Ÿฆ€ Core + โ˜๏ธ | Mixing in core (softmix); orchestration/features as a service. | | MeetMe | `app_meetme` | โ›” Drop | DAHDI-timing legacy; ConfBridge supersedes. | | Recording | `app_mixmonitor`, `app_monitor` | ๐Ÿฆ€ Core + โ˜๏ธ | Audiohook tap in core; storage/lifecycle as a recording service (object-storage-backed, retention policy, tenant-scoped โ€” **durable, not on the bus**). | | ChanSpy / whisper / barge | `app_chanspy` | ๐Ÿฆ€ Core | Audiohook primitive; gated by RBAC. **The escalation primitive** (rung 2). | | Answering-machine detect | `app_amd` | ๐Ÿฆ€ Core + ๐Ÿงฉ | DSP primitive in core; policy/thresholds as a plugin. | | IVR primitives (playback/read/say) | `app_playback`, `app_read`, `app_sayunixtime`, `app_directory` | ๐Ÿฆ€ Core | Media primitives (play/collect-digits/say) exposed via the API/tap. The IVR *flow* dissolves into the agent; these are the primitives left over. | | Echo / test | `app_echo`, `app_milliwatt` | ๐Ÿฆ€ Core | Trivial diagnostics. | | FollowMe | `app_followme` | ๐Ÿงฉ Plugin | Routing policy โ†’ plugin/service. | | Speech recognition | `app_speech_utils`, `res_speech` | โ˜๏ธ Service | Modern ASR is external; expose as a service integration. | | Fax | `res_fax`, `res_fax_spandsp` (T.38) | โ˜๏ธ Service (FFI) | Niche, isolate fully; spandsp via FFI. Optional. | | **Supervisor / agent-state** | (scattered manager/AMI surfaces) | โ˜๏ธ Service (**domain core**) | **First-class.** Agent presence, state, real-time monitoring, coaching/whisper โ€” the contact-center operator surface. Pure API client (the dashboard). | | **Dialer (predictive/progressive)** | (custom/`app_dial`-derived) | โ˜๏ธ Service (**domain core**) | **First-class.** Outbound campaign dialing with pacing โ€” where the in-boundary spend/abuse gate (ยง10) *bites hardest*; structurally co-located. | --- ## 6. Telephony features / subscriptions | Asterisk subsystem | Module(s) | Disp. | Rationale | |---|---|---|---| | Presence / BLF | `res_pjsip_pubsub`, `res_pjsip_exten_state` | ๐Ÿฆ€ Core + โ˜๏ธ | Signaling in core; state aggregation service. | | MWI (message-waiting) | `res_mwi_external`, `app_voicemail` MWI | โ˜๏ธ Service | Tied to the voicemail service. | | STIR/SHAKEN (attestation) | `res_stir_shaken` | โ˜๏ธ Service | **Keep โ€” modern, anti-robocall/fraud.** Core to the security story. | | Call recording lifecycle | `app_mixmonitor` + storage | โ˜๏ธ Service | Object-storage backed, retention policy, tenant-scoped. | | CDR (call detail records) | `cdr/`, `cdr_*` | โ˜๏ธ Service | Event stream โ†’ billing/analytics pipeline. | | CEL (channel event logging) | `cel/`, `cel_*` | โ˜๏ธ Service | Folded into the unified event bus + analytics. | --- ## 7. Codecs & formats (`codecs/`, `formats/`) | Codec / format | Module | Disp. | Rationale | |---|---|---|---| | G.711 a-law / ยต-law | `codec_alaw`, `codec_ulaw`, `codec_a_mu` | ๐Ÿฆ€ Core | Trivial, ubiquitous. Native Rust. | | G.722 (HD) | `codec_g722` | ๐Ÿฆ€ Core | Common wideband. Native Rust. | | Opus | (external `codec_opus`) | ๐Ÿฆ€ Core (FFI) | WebRTC default; libopus via FFI. | | Sample-rate resample | `codec_resample` | ๐Ÿฆ€ Core | Needed for any transcoding/mixing. | | GSM | `codec_gsm` | ๐Ÿงฉ Plugin (FFI) | Optional; FFI libgsm. | | G.726 / G.729 | `codec_g726` / (external) | ๐Ÿงฉ Plugin (FFI) | Optional; G.729 now patent-free. | | Speex / iLBC / LPC10 / ADPCM / codec2 | `codec_speex`, `codec_ilbc`, โ€ฆ | โ›” Drop | Obsolete; drop or community plugin. | | Hardware transcode | `codec_dahdi` | โ›” Drop | Hardware. | | File formats (wav/sln/ogg-opus) | `format_wav`, `format_sln`, โ€ฆ | ๐Ÿฆ€ Core | Small set for prompts/recordings in core; rest as plugins. | | Legacy file formats (gsm/g729/g726 files) | `format_*` | ๐Ÿงฉ Plugin | Optional. | --- ## 8. Config, state & data (`res_config_*`, `res_sorcery*`) | Asterisk subsystem | Module(s) | Disp. | Rationale | |---|---|---|---| | `.conf` files | `main/config.c` | ๐Ÿ” Replace | Config-as-data (declarative, validated, GitOps). | | Sorcery (object config abstraction) | `res_sorcery*` | ๐Ÿ” Replace | Typed config + state-store layer. | | Realtime backends (ODBC/PgSQL/SQLite/cURL/LDAP) | `res_config_*` | ๐Ÿ” Replace | One config/state service with pluggable backends. | | HTTP media cache | `res_http_media_cache` | ๐Ÿฆ€ Core | Prompt/asset fetch โ†’ object storage + cache. | | Security event logging | `res_security_log` | ๐Ÿฆ€ Core | Structured audit log; security-critical. | --- ## 9. Management & APIs | Asterisk surface | Module(s) | Disp. | Rationale | |---|---|---|---| | ARI (REST resource model + event WS) | `res_ari*` | ๐Ÿฆ€ Core | The control-plane API. Reuse the resource model. | | AMI (plaintext TCP admin) | `manager*.c` | ๐Ÿ” Replace | โ†’ mTLS gRPC + RBAC + audit. No plaintext admin channel. | | HTTP server | `res_http*` | ๐Ÿฆ€ Core | TLS-only; axum/hyper. | | CLI | `cli.c` | ๐Ÿ” Replace | API-client CLI. | --- ## 10. New subsystems (no Asterisk equivalent) These are the "modern" deltas โ€” load-bearing, not optional polish. | Subsystem | Disp. | Purpose | |---|---|---| | WASM plugin host | ๐Ÿงฉ **Demoted (candidate)** | **Out of the core story** ([ADR-0002](adr/0002-north-star-and-fused-core.md)). The agent **tap** is the extension point for in-call logic; ops-simplicity wants one binary. Softly retained as a *candidate* mechanism for community call-flow/routing plugins โ€” undecided vs. webhooks/scripting. | | Multi-tenancy / isolation | ๐Ÿฆ€ Core | Per-tenant keys, quotas, media separation, RBAC. | | Toll-fraud / spend / abuse engine | ๐Ÿฆ€ Core (**promoted**) | **Constitutive, not a service** ([ADR-0002](adr/0002-north-star-and-fused-core.md), re-scoped by [ADR-0009](adr/0009-spend-gate-honest-rescope.md)). Spend caps, pacing caps, deny-by-default routing, rate limits, pattern detection โ€” **co-located with the tap + the provider call-control client inside the boundary**: the brain never holds provider credentials, the gate is unskippable on everything rutster mediates (which is everything the brain can do), and pacing/playout are enforced over media the core terminates ([ADR-0007](adr/0007-trunk-rented-transport.md)). Not a physical wire monopoly โ€” deployments pair it with provider-side caps. This is what makes the boundary *auditable* on spend. | | Secrets / KMS | ๐Ÿฆ€ Core | Vault/KMS integration; no plaintext credentials in config. | | Observability (OTel) | ๐Ÿฆ€ Core | Distributed traces that follow a single call across services. | | Event bus | โ˜๏ธ Service | **Valkey** ([ADR-0005](adr/0005-event-bus.md)): streams + consumer groups (CDR/CEL/analytics), pub/sub (presence/MWI/BLF), KV (state store). Pluggable to NATS later at a config seam. The 20ms media loop never rides the bus. | | SBOM / supply chain | โ€” | cargo-deny, SBOM generation, reproducible builds. | | Fuzzing harness | โ€” | Continuous fuzzing of every wire parser (SIP/SDP/RTP). | --- ## Phasing โ†’ the thin-slice first proof + capability ladder The old Phase 0โ€“4 capability-rolldown is **replaced** (see [vision-revision ยง10โ€“11](superpowers/specs/2026-06-26-vision-revision-design.md)) by a **brutally thin vertical slice** that proves the *combination* (the wedge) first, then a **capability ladder** that grows the contact center feature by feature. The spearhead proves the hardest, most-differentiating part before trunk integration piles on. ### The thin-slice first proof (spearhead) 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. - **4ยฝ โ€” Benchmark + simulation harness** ([ADR-0010](adr/0010-spearhead-benchmark-sim-harness.md)): synthetic-caller ingress drives p50/p99 mouth-to-ear + barge-in kill-time under concurrent load, CI-regressed. Proves the reflex *measurably*; seeds `rutster-sim`. 5. **Add a real phone number via rented transport** โ€” a CPaaS raw-media fork (e.g. Twilio Media Streams) lands a PSTN call on the reflex loop; no first-party SIP ([ADR-0007](adr/0007-trunk-rented-transport.md)). 6. **Add the spend cap** โ€” hard-stop at threshold. Proves the boundary. Steps 1โ€“4 *are* the reflex loop. Keep the dev loop on WebRTC ingress until step 5. Post-review re-sequencing ([ADR-0010](adr/0010-spearhead-benchmark-sim-harness.md)): after step 4ยฝ, **rung-2 escalation is pulled forward ahead of steps 5โ€“6**. ### The 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 (ยง5) | | 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 | ## Open decisions - ~~**SIP:** FFI pjproject vs. SBC front vs. pure-Rust.~~ ~~Decided โ€” ADR-0003: Rust-native trunk SIP.~~ **Re-decided โ€” [ADR-0007](adr/0007-trunk-rented-transport.md):** rutster owns no SIP stack; the trunk is rented transport (CPaaS raw-media fork) or an out-of-tree SBC. - ~~**License**~~ **Decided โ€” ADR-0004:** GPL-3.0-or-later. - ~~**Event bus:** NATS vs. Kafka vs. Redis Streams.~~ **Decided โ€” ADR-0005:** Valkey. - ~~**Ingress:** WebRTC vs. inbound SIP endpoint.~~ **Decided โ€” ADR-0006:** WebRTC-first; SIP endpoint deferred. - **WASM runtime** โ€” `wasmtime` component model, *if* WASM is retained at all (demoted to candidate per [ADR-0002](adr/0002-north-star-and-fused-core.md)). Uncoupled from the critical path. - **Plugin mechanism** โ€” WASM vs. webhooks vs. scripting for community call-flow/routing extensions. Deferred. - **Agent-tap protocol** โ€” presumptively WSS + core-as-client + clean PCM + core-authoritative playout (see ARCHITECTURE.md, "Agent tap"). To harden against the thin-slice first proof, *not* a decided ADR yet.