Sarj · Bulbul Platform · Quality Assurance TEL / SELF-SERVE / 2026-07

Self-Serve TelephonyQA Test Plan

Providers, connections, the six-step wizard, number linking, and live call routing. Work through the suites in order. Mark each check P (pass), F (fail), or B (blocked); your verdicts and notes are saved in this browser automatically.

Scope Full self-serve surface
Environment Preview / staging
Real test calls Yes, with an engineer
Progress 0 / 24
00
Prerequisites & setup
before any suite begins
00.1
A super-admin account on the target environment, plus one non-super-admin account for permission checks.
00.2
The connection wizard must be enabled on the environment (engineering controls this). Quick check: the "New connection" button appears on /admin/telephony/connections. If it is missing, ask engineering to enable the wizard before starting suite 03.
00.3
The Linphone softphone app, installed and ready (its settings are at the top of suite 03). Before starting, open https://ipv4.icanhazip.com in your browser, copy the number it shows (your internet address), and send it to engineering; they must add it to a firewall before your softphone will work. If the softphone suddenly stops working mid-run, for example after switching Wi-Fi, open that page again: if the number changed, send the new one to engineering and wait for their OK before continuing.
00.4
At least one test organization, two is better (call them Org A and Org B).
00.5
At least two provisioned test phone numbers you can place real calls from/to. One of them should be a number that already makes calls successfully today, with no connection linked.
00.6
Details of a test SIP endpoint (an IP address or hostname) to enter in the wizard, plus a second unused IP address for runs that must not collide. Ask engineering to provide both.
00.7
Test data you create should be clearly named (prefix qa-) so it can be cleaned up afterwards.
Reporting For every failure capture: the page URL, a screenshot, the exact text of any popup or error message, and the exact time including timezone (engineering uses the time to find it in the server logs). For anything involving the softphone or a phone call, also note which username you were using and take a screenshot of the /admin/telephony/kamailio page at the moment of failure; those two let engineering pull the matching server logs. Mark the check F (or B if you could not attempt it) and put the detail in its notes field. File one issue per failing test ID. When the run is done, use the "Copy results" button at the top to paste a summary into the ticket or Slack.
Engineering support needed Suite 06 (an engineer must confirm in the server logs which route carried each call), WIZ-5 setup, the optional steps in NUM-2 and PERM-1, and cleanup. Book an engineer for the suite 06 session in advance.
01
Providers
/admin/telephony/providers
IDStepsExpectedP / F / BNotes
PROV-1
Create and edit a provider
  1. Click "Create provider". Name it qa-carrier, type Carrier, submit.
  2. Try creating another provider with the exact same name.
  3. Rename qa-carrier to qa-carrier-2 (try submitting unchanged first).
The first create succeeds: toast "Provider created", row appears with Active status and 0 connections. The duplicate is rejected with an inline error on the name field saying the name is already in use, and no duplicate row appears. The Rename button is disabled while the name is empty or unchanged; after renaming, toast "Provider renamed" and the table updates.
PROV-2
Deprecate and reactivate
  1. Kebab on qa-carrier-2, Deprecate.
  2. Open the wizard (suite 03), step 1, choose "From a provider" and check the provider list.
  3. Back on the providers page, Reactivate.
Toasts "<name> deprecated." then "<name> reactivated."; the status badge flips Deprecated/Active and the kebab shows only the applicable action each time. While deprecated, the provider does NOT appear in the wizard's catalog select (active carriers only).
PROV-3
List and count links
  1. Open the providers page and review the table.
  2. After suite 03 has created a connection, click a non-zero Connections count.
Table shows Name, Type (Carrier / Client endpoint badge), Status badge, Connections count, Actions kebab; empty state "No providers yet" if none exist. A non-zero count is a link that opens the connections list already filtered to that provider; zero counts are plain numbers.
02
Connections list
/admin/telephony/connections
IDStepsExpectedP / F / BNotes
LIST-1
Page and table
  1. Open the connections list and review the table.
  2. Compare status badge colors across rows: active, pending verification, disabled.
  3. Find a connection whose provider was deprecated (deprecate its provider if needed, then undo after).
Header shows "Manage providers" and "New connection" buttons (the latter only while the wizard is enabled). Columns: Organization, Provider, Path badge, Transport, Status badge, Numbers, Created, View. Active is green, pending verification is warning, disabled is gray. A deprecated provider shows a muted "Deprecated provider" sub-label in its cell.
LIST-2
Filters and navigation
  1. Use the Organization filter, then the Provider filter, then both.
  2. Click anywhere on a row, then use the explicit View button on another row.
The page URL updates as filters change (so a filtered view can be bookmarked) and rows filter correctly; a combination with no matches shows "No matching connections" with the clear-filters hint. Both the row click and the View button open the connection detail page.
03
New-connection wizard
/admin/telephony/connections/new

Six steps: Integration type, Endpoint details, Collision check, Credentials, Numbers, Verification. Run WIZ-A as the happy path first; the rest can reuse partial runs. Softphone settings for WIZ-3: Linphone, SIP domain 34.166.223.250, transport UDP, no TLS/SRTP, codecs PCMU/PCMA only. Username and password are whatever you entered in the wizard's credentials step.

IDStepsExpectedP / F / BNotes
WIZ-A
Happy path, custom + IP auth
  1. Step 1: choose "Custom integration".
  2. Step 2: pick Org A, endpoint name qa-acme-pbx, one unused signaling IP, transport UDP, auth "IP allowlist".
  3. Step 3: wait for the collision check.
  4. Step 4: note the platform signaling addresses shown.
  5. Step 5: select one unassigned number.
  6. Step 6: review summary, click "Provision and verify".
Progress shows "Step N of 6". Collision step auto-runs and reports "No collisions found". IP-auth credentials step shows the "IP authentication" info with the platform addresses to whitelist (no username/password fields). Summary matches inputs. Provisioning then verifying phases appear, then per-check icons, then "Connection is active" with a "Go to connections" link. The new connection appears in the list as active with number count 1.
WIZ-1
Validation blocks
  1. Step 1: choose "From a provider" without selecting a provider, click Next.
  2. In a custom-mode run, step 2: leave endpoint name and signaling addresses empty with IP auth selected, click Next.
Both are blocked with field errors: a provider must be selected in catalog mode (if no active carriers exist, the muted "No active carriers in the catalog yet..." hint shows instead of the select); endpoint name is required in custom mode; at least one signaling address is required for IP auth.
WIZ-2
Collision reporting
  1. Enter signaling IPs already claimed by an existing carrier connection and proceed to step 3.
  2. Repeat with IPs claimed by an existing client-endpoint connection (e.g. the WIZ-A endpoint).
  3. Go back, change to an unused address, and re-enter step 3.
Both cases show the warning "These addresses are already in use" and block Next: carrier copy says to edit that connection instead of creating another; client-endpoint copy says the address can only belong to one connection. The client-endpoint case is new in this release (it previously reported no collision, wrongly). Re-entering step 3 with a changed address re-runs the check and clears the warning.
WIZ-3
Digest credentials, register, re-verify
  1. Run a custom wizard with transport UDP and auth "Digest credentials"; leave the signaling addresses box empty (it is not needed for this mode).
  2. Step 4: try a password under 12 characters, then a valid one. Try a username the system already knows (reuse one from an earlier run), then a fresh one. Write the final username and password down; the password is never shown again.
  3. Finish the wizard and click "Provision and verify". Do NOT close this tab.
  4. When the screen says "Not verified yet", put the new username and password into Linphone (settings in the intro above) and wait until Linphone shows it is connected ("Registered").
  5. Back in the still-open wizard tab, click Retry.
A password under 12 characters is rejected. A taken username shows "This username is already in use. Choose another." when you click Next; a fresh one goes through. After "Provision and verify" the connection does NOT turn active right away: a check named digest_registration keeps spinning and the screen shows "Not verified yet" with a Retry button. That is expected, not a bug; the platform is waiting for your softphone to connect. Once Linphone shows "Registered" and you click Retry, every check turns green and "Connection is active" appears. If Linphone never manages to register, mark this F and screenshot Linphone's error message plus the address page from 00.3. If you closed the wizard tab too early there is no other button to finish verification, so mark this B and note it.
WIZ-4
Numbers step and back navigation
  1. With one number dedicated to Org B and one unassigned, open the numbers step in a wizard run for Org A.
  2. From step 4, go back to step 2, change a signaling address, go forward again.
  3. From step 6 (before provisioning), go back and forward once more.
The numbers multi-select offers only unassigned and Org A numbers (the Org B number is absent), and the step is optional. Re-entering step 3 re-runs the collision check against the new address (no stale result). Back is disabled on step 1 and while provisioning/verifying. No duplicate connection is created by back-and-forth.
WIZ-5
Verification failure and retry
  1. Run a wizard against an endpoint address that will not verify (ask engineering for an IP that looks valid but has nothing behind it).
  2. Wait for verification to finish or time out (about 30 seconds).
  3. Click Retry.
Failure state "Not verified yet" (or the timeout message "Verification timed out. The connection stays pending until every check passes."). The connection exists in the list as pending verification. Retry re-verifies the SAME connection: no duplicate row appears.
04
Connection detail
/admin/telephony/connections/[id]
IDStepsExpectedP / F / BNotes
DET-1
Page renders
  1. Open the WIZ-A connection.
  2. Open a made-up connection id in the URL.
Title "{org} via {provider}" with status badge. Connection card shows organization, provider (with type badge), transport, created/updated. The Routing card matches the Path badge: "Platform SIP" connections show "Outbound setid" and "Inbound identity"; "LiveKit direct" connections show "Inbound trunk" and "Outbound trunk" (or "No inbound"/"No outbound" when not set). The made-up id shows a 404 page without errors.
DET-2
Link and unlink numbers
  1. On an Org A connection, click "Link number", review the candidate list, and link one.
  2. In two tabs, open two different connections' link dialogs offering the same number; link it in tab 1, then attempt in tab 2 without refreshing.
  3. Unlink a linked number (read the dialog before confirming).
The dialog offers only numbers with no connection AND (unowned OR owned by Org A); numbers linked elsewhere or dedicated to Org B are absent ("No provisioned numbers are available to link." when none qualify). Linking: toast "Number linked", the number appears in the Linked numbers table, the list page's Numbers count increments. Tab 2 shows the friendly inline error "This number cannot be linked to this connection. It may be dedicated to another organization or already linked elsewhere.", with no double link. Unlinking: the dialog warns the number stops routing until linked again; toast "{number} unlinked."; the row leaves the table.
DET-3
Disable
  1. On a disposable qa connection with a linked number, click "Disable connection", read the dialog, confirm.
  2. If you disabled the WIZ-3 connection (preferred), refresh /admin/telephony/kamailio and check its Registration column; also keep an eye on Linphone.
Dialog warns calls stop routing immediately, linked numbers stay attached but become unroutable, and re-enabling requires verification. After confirming: status flips to Disabled, the Disable button disappears, linked numbers remain listed. For the WIZ-3 connection: its Registration column no longer says "registered", and within a few minutes Linphone shows it is disconnected and cannot reconnect. If it still says "registered" after a refresh, that is a failure: screenshot the page. If an error message appears instead of the status changing, capture it and report.
DET-4
Live phone-server state page
  1. Before starting suite 03, open /admin/telephony/kamailio and screenshot the whole page. This is your "before" picture.
  2. After WIZ-3's connection is active and Linphone shows "Registered", refresh the page.
  3. Find your WIZ-3 connection's row in the "Connections vs live bell state" table (clicking the Connection column takes you back to its detail page), and look at the "Orphans" box below it.
The page shows three boxes: a table called "Connections vs live bell state", a box called "Orphans", and "Raw dumps". Your WIZ-3 row shows Status "active", Registration "registered" with an address under it, and Subscriber "present". Your connection must NOT be mentioned anywhere in the Orphans box (that box lists leftovers that lost their connection; appearing there is a failure, screenshot it). If a warning called "Partial bell data" appears at the top of the page, screenshot and report it, and mark this check B.
05
Phone numbers, Provisioned tab
/admin/phone-numbers?tab=provisioned
IDStepsExpectedP / F / BNotes
NUM-1
Connection column
  1. Open the Provisioned tab and review the Connection column across linked and unlinked numbers.
Unlinked numbers show a muted "Not linked". Linked numbers show a link labeled "{org} via {provider}" that opens the connection detail page; numbers linked to a pending-verification connection additionally show a "Pending" badge.
NUM-2
Register with the connection picker
  1. Click Register, fill in a valid unused number, a provider, and a SIP trunk value (ask engineering what to enter). Pick an active connection in "Connection (optional)" and submit.
  2. Register another number with the picker left on "No connection".
  3. In the form, set Ownership to "Client BYO" with Org A as owner and inspect the picker options; then switch the owner to Org B, then back to "Shared pool".
  4. Optional, with an engineer: stage a conflict so registration succeeds but the link is rejected (e.g. disable the chosen connection just before submitting).
The picker offers "No connection" plus non-disabled connections (pending ones carry a "Pending verification" badge). Success toasts: "{number} registered and linked." with the row showing the connection link, or "{number} registered" with "Not linked". With an owner org set, only that org's connections are offered, and changing ownership kind or owner org resets a previously picked connection. In the staged-conflict case the number IS registered and a message explains the link failed and to link it from the numbers list; mark that step N/A if it cannot be staged.
NUM-3
Row actions
  1. On an unlinked number, open the kebab, choose "Link to connection", link it, then reopen the kebab.
  2. On the now-linked number, verify the existing actions still work: activate/deactivate, assign scenario, change organization, edit trunk configuration.
The kebab shows "Link to connection" only when unlinked and "Unlink from connection" only when linked (never both). The link dialog filters candidates like DET-2 and shows "No eligible connections..." when none. Toasts "{number} linked" / "{number} unlinked.". The other actions behave as before and the Connection column stays correct afterwards.
06
Call routing
real calls · engineer present
Background for this suite Every number has its own built-in outbound route (shown in the "Provider / Trunk" column). The new behavior under test: when a number is linked to a connection whose status is Active and whose Path badge reads "LiveKit direct" with an outbound trunk set, outbound calls should go out through that connection instead. In every other case (no link, Pending verification, Disabled, Path badge "Platform SIP") calls should fall back to the number's own built-in route. You place the calls; the engineer confirms in the server logs which route each call actually took. Run this suite in one sitting with the engineer present.
Call behavior on preview (read before dialing) The test phone network is occasionally flaky. A good call rings within about 5 seconds and is answered within about 10, and you can hear the agent and it can hear you. If nothing has rung after 10 seconds: hang up, wait a few seconds, and dial once more; a second try usually works. If the second try also fails, stop, write down the exact time and which number or username you called from, and report it; do not keep retrying. Remember your softphone only works after engineering has your internet address (00.3). Nobody will call your softphone in this round: receiving calls on it is not being tested, so do not report that as a bug.
IDStepsExpectedP / F / BNotes
CALL-1
Linked active connection wins
  1. Link a test number to a connection that is Active, has the "LiveKit direct" Path badge, and shows an Outbound trunk on its detail page.
  2. Place an outbound call from that number.
The call connects, and the engineer confirms it went through the connection's route, not the number's built-in route.
CALL-2
Fallback cases
  1. Unlink the number, place the same outbound call.
  2. Link it to a pending-verification connection (from WIZ-5), place a call.
  3. Link it to an active connection, disable that connection (DET-3), place a call.
  4. Link it to an Active connection whose Path badge reads "Platform SIP", place a call.
In all four cases the call connects using the number's built-in route (engineer confirms each), and the link causes no errors. Unlinking and disabling take effect immediately, with no restart or waiting period.
CALL-3
Inbound and shared-pool smoke
  1. Call INTO a linked number and into an unlinked number.
  2. Place an outbound call that picks its number from the shared pool automatically (ask the engineer how to trigger this), with at least one linked number in the pool.
Inbound behavior is unchanged for both (this release changes outbound routing; inbound must not regress). The shared-pool call completes and routes by the same rules as above (engineer confirms); a pool mixing linked and unlinked numbers causes no failures.
07
Permissions & access
non-admin account required
IDStepsExpectedP / F / BNotes
PERM-1
Access control
  1. As the non-super-admin user, open each URL directly: /admin/telephony/providers, /admin/telephony/connections, a connection detail URL, /admin/telephony/connections/new, /admin/phone-numbers.
  2. Optional, with an engineer: have them call the underlying telephony API directly using the non-admin user's login session.
  3. Optional, if engineering can toggle it: with the wizard turned off, open /admin/telephony/connections/new directly and check the connections list.
Every page redirects to the home page (or shows "not found" for the wizard); no telephony data is visible. The direct API request is rejected as unauthorized with no telephony data. With the wizard off, the page shows "not found" and the "New connection" button is absent. Mark the optional steps N/A in the notes if they cannot be arranged.
08
Regression smoke
pre-existing flows
IDStepsExpectedP / F / BNotes
REG-1
Register flows unchanged
  1. Register a number the pre-existing way (no connection involved) for each ownership kind: shared pool, Sarj dedicated, Client BYO.
All three register as before; the ownership-specific fields (outbound access options and the organization pickers) look and behave as they did before this release.
REG-2
Everything else still works
  1. Spot-check the other phone-numbers tabs (Call activity, Outbound).
  2. Place one ordinary end-to-end voice call on a number untouched by this QA round.
The tabs are unaffected by this release: they load and paginate normally. The ordinary call works exactly as before the deploy.
09
Cleanup
after all suites complete
09.1
Unlink all qa-linked numbers and restore their original trunk configuration.
09.2
Disable any qa- connections and hand the list to engineering to fully remove them from the routing system.
09.3
Deprecate or delete qa- providers.
09.4
Deactivate test numbers registered during NUM tests.