Tyagi // Engineering Log
← Back to Projects
Telephony & CRM production

Runo Hybrid Telephony — Cloud & GSM Calling

Unifying SIM and cloud calling into one model instead of two parallel features

Contributed to hybrid telephony support at Runo — letting users call via cloud or GSM, with call-medium selection, virtual number assignment, and consistent reporting across logs, exports, and analytics.

Date 2026-04
Reading Time 2 min read
Difficulty
Intermediate
Stack
Flutter,Dart,Telephony UX +2
Reported

49+

Telephony-related commits

Reported

Calls, reports, analytics, permissions

Surfaces touched

How it evolved

  1. 2026-03

    Problem identified

    Hybrid customers got unreliable reporting because nothing modeled SIM-only vs. cloud-only vs. both.

  2. 2026-03

    gsmNCloud model introduced

    A single three-state model propagated through user data, permissions, and UI instead of parallel SIM/cloud code paths.

  3. 2026-04

    Call-medium UI and bulk assignment shipped

    CallMediumSelector and bulk virtual-number assignment rolled out across calling, reports, and analytics.

Sanitized from private commit history. Adoption and support-impact metrics aren’t claimed here since they aren’t independently verifiable — see this site’s evidence policy.

Problem & Context

Before this work, a user with cloud telephony enabled was effectively treated as cloud-only by most of the product. Virtual number assignment didn’t express whether a user should be cloud-only or allowed to use both SIM and cloud calling. Call logs, reports, analytics, and exports had inconsistent ways of separating SIM calls from cloud calls — which made reporting for hybrid customers unreliable.

Solution & Architecture

The core idea was a gsmNCloud model representing three states — SIM-only, cloud-only, or hybrid — propagated consistently through user models, permissions, payloads, call UI, settings, reports, and analytics.

Diagram source (mermaid)
flowchart TD
  U[User / Team config] --> M{Calling mode}
  M -->|SIM only| S[Standard GSM call flow]
  M -->|Cloud only| C[Cloud-only call flow]
  M -->|Hybrid| H[CallMediumSelector]
  H --> S
  H --> C
  S --> L[Call Logs / Reports / Analytics]
  C --> L

Supporting pieces:

  • CallMediumSelector — a reusable UI component (bottom sheet on mobile, popup menu on web) for choosing the calling method when both options are valid.
  • Bulk virtual number assignment — admins could assign virtual numbers to many users in one operation instead of one at a time, including the “Allow both SIM & Cloud calling” choice.
  • Call medium propagation — filtering and request parameters for call medium were threaded through call logs, deleted call logs, scheduled/request reports, analytics exports, and service calls.
  • Terminology cleanup — renamed “Virtual Calls” to “Cloud calls” across call logs UI for clarity.

Key Decisions & Tradeoffs

[!NOTE] Modeling calling mode as one central enum/payload (rather than letting each page infer SIM-vs-cloud locally) meant more upfront design work, but it made every later “does this page support hybrid?” question answerable by passing one value instead of writing new conditional logic per screen.

  • Default calling option settings were added so hybrid users don’t have to re-choose a calling method every time.
  • Call medium filters were added to analytics sections incrementally — first to call logs, then deleted call logs, then reports/exports — reflecting a deliberate decision to ship the core flow before completing reporting parity.

Implementation Details

Tests were added specifically for hybrid telephony behavior and call handling logic, given the cross-cutting risk of this change (it touches call initiation, permissions, admin setup, logs, reports, exports, and several analytics sections simultaneously).

Lessons Learned

A feature like this is only “done” when reporting and exports respect it too — early versions left scheduled reports and analytics exports ignoring call medium, which had to be retrofitted once it became clear hybrid customers needed accurate SIM-vs-cloud breakdowns in their data, not just in the live UI.