Phone Restrictions
Members can only place calls and send messages from phone numbers assigned to them. Organization owners bypass all restrictions and can use any phone. Members with no assignments cannot send messages — the compose bar is hidden until an admin assigns them a phone.
How It Works
Section titled “How It Works”The resolve_member_allowed_phones service determines which phones a member can use:
pub async fn resolve_member_allowed_phones( member_id: Uuid, organization_id: Uuid, is_owner: bool,) -> Result<Vec<phone_number::Model>, AppError>Three resolution paths:
| Member type | Result |
|---|---|
| Owner | All org phones — no restriction checks |
| Member with assignments | Only assigned phones from member_phone_number table |
| Member without assignments | Empty list — no phones available |
API Endpoint
Section titled “API Endpoint”GET /api/member/allowed-phones
Section titled “GET /api/member/allowed-phones”Returns the current member’s allowed phones with default designation.
Response: Vec<MemberPhoneSummary>
[ { "phone_number_id": "123e4567-e89b-12d3-a456-426614174000", "number": "+15551234567", "friendly_name": "Main Line", "is_default": true }, { "phone_number_id": "223e4567-e89b-12d3-a456-426614174000", "number": "+15559876543", "friendly_name": "Support Line", "is_default": false }]Permission: Authenticated session (any role).
Server-Side Enforcement
Section titled “Server-Side Enforcement”Both the call and messaging endpoints validate the selected phone against the allowed list before proceeding.
In initiate_call_api, the server resolves allowed phones and validates:
let allowed = resolve_member_allowed_phones( session.member_id, org_id, session.is_owner).await?;
// If phone_number_id provided, validate it's in the allowed list// If not provided, auto-select from allowed listWhen no phone is specified, the server auto-selects — preferring a phone with voice_webhook_active = true.
Messages
Section titled “Messages”In send_message_api, the server checks the outbound phone:
let allowed_phones = resolve_member_allowed_phones( session.member_id, org_id, session.is_owner).await?;
if !allowed_phones.iter().any(|p| p.id == phone_number_id) { return Err(HttpError::new( StatusCode::FORBIDDEN, "You are not assigned to this phone number", ));}Attempting to send from an unassigned phone returns 403 Forbidden.
UI Integration
Section titled “UI Integration”Both the dial pad and message composer show a “From:” phone selector populated by GET /api/member/allowed-phones.
Dial Pad
Section titled “Dial Pad”The DialPadPanel fetches allowed phones on mount and renders a SearchableSelect when multiple phones are available:
- Multiple phones — searchable dropdown with “From:” label
- Single phone — phone name displayed inline (no dropdown)
- Default selection —
is_defaultphone, or the first available
Message Composer
Section titled “Message Composer”The MessageCompose component receives org_phones as a prop and applies default selection:
- Prefer the member’s default phone (
is_default = true) - Then the first available phone
If the allowed phones list is empty (non-owner with no assignments), the compose bar does not render — the member can view the conversation but cannot send messages.
The dropdown opens upward (side: "top") since the composer sits at the bottom of the viewport.
No-Assignment Behavior
Section titled “No-Assignment Behavior”When a non-owner member has no phone assignments, the service returns an empty list. This means:
- The compose bar does not render — the member cannot send SMS
- The dial pad has no available phones — the member cannot place calls
- The member can still view conversations and call history
This enforces least-privilege access. An admin must assign at least one phone before the member can communicate. Owners bypass this restriction and always have access to all org phones.
Module Structure
Section titled “Module Structure”src/mods/settings/├── services/│ └── resolve_member_phones_service.rs # Core resolution logic├── api/│ └── get_member_allowed_phones_api.rs # GET /api/member/allowed-phones└── types/ └── member_phone_type.rs # MemberPhoneSummary + helpers
# Enforcement points:src/mods/call/api/initiate_call_api.rssrc/mods/messaging/api/send_message_api.rs
# UI components:src/mods/call/components/dial_pad_panel_component.rssrc/mods/messaging/components/message_compose_component.rsRelated Pages
Section titled “Related Pages”- Member Management — assign phones and roles to members
- Phone Numbers — phone number import and Twilio configuration