Concepts
The mental model
Define the product language clearly, or your AI agent will improvise, confidently, right up until production. These are the objects every SOMVAD client reasons about.
Data hierarchy
structure
Tenant ─────────── an organisation (bank/fund); hard isolation boundary ├── Desk ──────── a trading desk; has a HEAD who supervises its calls │ └── User ─── a per-tenant PROFILE; one person may hold a distinct │ profile in several tenants ├── Conference ── THE voice primitive: ad-hoc call, private call, hoot… │ │ status: created → starting → active ⇄ locked → ended │ │ visibility: tenant | private │ └── Participant ── a user's leg: invited → joining → connected → left ├── Call ──────── a RING pointing at a conference (signaling overlay): │ ringing → accepted | declined | cancelled | missed ├── Entitlement ─ user ⇄ resource permission (conference / line / hoot) └── Hoot / Line / PrivateWire ── always-on rooms, DDI lines, ring-downs Media plane (FreeSWITCH mixers) is reached ONLY via the control plane. /join returns the mixer + room + its own wss:// endpoint. Audio never touches this API.
Glossary
| Object | What it is |
|---|---|
| Tenant | An organisation. The hard isolation boundary: data never crosses it. |
| Desk | A trading desk within a tenant. Its head can supervise (monitor / whisper / barge) any call on the desk. |
| User | A per-tenant profile of a person. One identity can hold profiles in several tenants; the token's tenant_id picks which one you act as. |
| Conference | The single voice primitive. Every call, hoot, private wire, line, and DM rides this one model with different policy. |
| Participant | A user's leg in a conference, with its own lifecycle and an optional role (call admin). |
| Call | A ring pointing at a conference. A signaling overlay: accept turns a ring into a join. |
| Line / Hoot / Private wire | Trader-voice primitives: DDI lines, always-on hoot/squawk rooms, and ring-down wires, all conferences underneath. |
| Entitlement | The permission linking a user to a resource they may see or join. |
| Mixer | A stateful media worker (FreeSWITCH). Conferences are pinned to a home mixer; the pool autoscales. |
| Recording | A captured call, optionally signed for non-repudiation and retained per tenant policy. |
Roles & tenancy
Three roles, strictly ordered:
member: uses voice and creates conferences in their own tenant.tenant_admin: manages users, desks, and lines within their tenant.platform_admin: an environment allow-list, never stored in the database; manages tenants and can impersonate a tenant admin (short-lived, audited).
A desk head is not a role. It is supervision scope over one desk. Tenant isolation is enforced server-side on every list, read, and write; a token scoped to one tenant cannot see another's data.
State machines
Honest state is a platform rule. A client shows "joined" only when the SIP session is actually established, never optimistically.
Conference
created → starting → active ⇄ locked → held → ended
locked = temporary privacy. held = parked, resumable.
Participant
invited → joining → connected → left / removed
A leg's own lifecycle, independent of the room's.
Call (ring)
ringing → accepted | declined | cancelled | missed
accept → the callee joins the conference normally.
Environments
Sandbox, test, production stay separate
Promote a workflow when it is ready, not before. The sandbox gives you seeded data and simulated media so you can build and test conference flows without touching a live desk.