The Control Plane
The control plane is the brain: an edge runtime that fields decisions from the edge, backed by stateful edge objects, the edge SQL database, the key-value store, and object storage. This page covers what each component owns.
The edge runtime
Section titled “The edge runtime”A single edge runtime is the front door for every decision. Its endpoints (see the Control-Plane API) fall into groups:
- SIP-facing:
/auth(REGISTER/INVITE digest auth),/route(returns routing JSON for the SIP signaling layer),/flow(the call-flow command loop),/presence/event(SIP dialog/register/agent events). - ACD & agents:
/agent(login/logout/pause/available + queue membership),/agent/confirm/*and/agent/claim/*(answer-time hooks). - Concurrency:
/cac(channel-usage view),/cac/reset(ops). - Security:
/security/report,/security/bans,/security/allow(ban reporting + allowlist). - Media:
/media/*(serve prompts/MOH to the edge; receive voicemail uploads). - Admin & future:
/admin/tts/generate(prompt synthesis),/debug(dev monitor), and the roadmap/v1public API and/hooks.
The edge runtime is stateless between requests: all durable state lives in the bindings below.
Bindings
Section titled “Bindings”| Binding | Type | Holds |
|---|---|---|
CONTROL | the edge SQL database | All configuration: accounts, devices, numbers, queues, schedules, trunks, policies. |
PRESENCE | stateful edge object | Per-account presence, ACD, CAC, dashboard deltas. |
CALL_SESSION | stateful edge object | Per-call flow interpreter state. |
BALANCE | stateful edge object | Per-account retail wallet. |
STEERING | the key-value store | Routing keys (e.g. cac:<callId> → account) for stateless BYE handling. |
SECRETS | the key-value store | Encrypted trunk passwords, tokens, PINs (referenced by *_secret_ref). |
MEDIA | object storage | System prompts, MOH, voicemail, TTS cache. |
Stateful edge objects
Section titled “Stateful edge objects”stateful edge objects are the heart of the design. Each is single-threaded (it processes one request at a time), which is exactly what concurrency-sensitive telephony state needs.
PresenceDO (one per account)
Section titled “PresenceDO (one per account)”The per-account PresenceDO does four jobs in one single-threaded object, so that reservation, admission, and distribution are all atomic with no cross-object locking:
- Presence: agent status (
offline/available/on_break) and state (waiting/offering/in_call/wrap_up/idle), plus reachability fed by the SIP signaling layer register/qualify feed. - Queue ACD: picking agents by strategy, and the reserve → confirm → release fence that guarantees no double-dispatch (see Queues & ACD).
- CAC (admission control): account/user concurrency ceilings and sliding-window rate rules, decided in one atomic
admit()(see Concurrency Control). - Dashboard deltas: every mutation emits a delta to a decoupled outbox that fans out to live wallboards over WebSocket.
CallSessionDO (one per active call)
Section titled “CallSessionDO (one per active call)”Each live call walking a flow has its own CallSessionDO. It is the flow interpreter: it holds the current node, the call’s variables, and drives the poll-based command loop. Pure-logic nodes (condition, timeCondition, httpRequest, setVar) resolve inside the session object without an extra edge round-trip. It also buffers the call’s event trace and flushes it in one batch at a terminal step (see Observability).
BalanceDO (one per account)
Section titled “BalanceDO (one per account)”The per-account retail wallet, kept separate from PresenceDO on purpose. Money math uses integer micro-units to avoid float drift. Wholesale balance (carrier termination) is fed externally; the retail wallet gates retail spend.
The edge SQL database: the configuration source of truth
Section titled “The edge SQL database: the configuration source of truth”All queryable, enforceable configuration lives in the edge SQL database (the edge platform’s SQLite). Every tenant row carries an explicit, indexed account_id; enums are CHECK-constrained; JSON is used only for genuinely opaque/variable data (the flow graph, small per-hop transforms, custom SIP headers). See the Data Model.
What is deliberately not in the edge SQL database:
- CDR / call-event trace → the Apache Iceberg data lake (3M+ calls/month would blow the edge SQL database’s size cap).
- SIP registrations / contacts → the registrar's location store.
- Real-time state (online, agent status, live channels, reservations) → PresenceDO.
How they cooperate: one inbound call
Section titled “How they cooperate: one inbound call”INVITE ─▶ the SIP signaling layer ─▶ edge runtime /route │ reads the edge SQL database (did → flow), runs CAC via PresenceDO.admit() ▼ flow directive ─▶ the media engine ─▶ edge runtime /flow (loop) │ CallSessionDO.start()/resume() ▼ enqueue ─▶ PresenceDO (reserve→confirm) │ agent frees → dispatch push ▼ node-agent ─▶ bridge agentEach arrow is a small, well-typed request. The edge runtime is the orchestrator; the stateful edge objects hold the truth; the edge moves the packets.
Next: The Media Edge.