Skip to content

feat: updating plivo imports - #122

Open
TEJASNARAYANS wants to merge 6 commits into
mainfrom
plivo-integration
Open

feat: updating plivo imports#122
TEJASNARAYANS wants to merge 6 commits into
mainfrom
plivo-integration

Conversation

@TEJASNARAYANS

Copy link
Copy Markdown
Contributor

What Changed?

Briefly describe what this PR changes.

Why?

Explain the problem this solves and why this approach was chosen.

How to Test?

List clear steps for reviewers to verify the change.

Release Label

Select one semantic version bump intent for this PR:

  • major - breaking change, next release bumps major version
  • minor - backward-compatible feature, next release bumps minor version
  • fix - backward-compatible bug fix, next release bumps patch version
  • No label (defaults to patch release)

If you do not have permission to apply labels, mention the intended release label here and a maintainer will set it.

Checklist

  • I have read the CONTRIBUTING.md guide.
  • My code follows the project's style guidelines.
  • I have added tests that prove my fix is effective or my feature works.
  • I have updated documentation where needed.

@TEJASNARAYANS TEJASNARAYANS added the fix Fix version release label Sep 1, 2026
@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR expands native Plivo support across call imports, webhook routing, inbound media streaming, recording downloads, and carrier-aware call control.

  • Adds dedicated Plivo webhook URLs while retaining legacy callback routes.
  • Persists carrier and integration identity so the shared media endpoint can select the appropriate serializer and hangup credentials.
  • Adds credentialed Plivo recording imports with stricter URL validation and per-credential rate limiting.
  • Updates phone-number metadata normalization, voice-provider configuration, frontend Plivo controls, documentation, and tests.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
app/services/telephony/recording_download.py Separates credentialed carrier hosts from general recording hosts and validates literal IPs, DNS results, and redirects.
app/workers/tasks/process_call_import_row.py Adds credentialed Plivo recording acquisition while preserving provider-specific concurrency and error handling.
app/services/telephony/carrier_media_serializer.py Selects Plivo or Vobiz media serialization and resolves the selected Plivo integration鈥檚 call-control credentials.
app/services/telephony/inbound_stream_answer.py Creates provider-tagged inbound call sessions and records the routing integration used by native Plivo calls.
app/services/telephony/call_recording_lifecycle.py Replaces bounded in-memory call-record scans with dialect-aware JSON lookups and persists carrier metadata.
app/api/v1/routes/vobiz_telephony.py Moves media streaming to the shared carrier endpoint and selects its serializer from the matched call record.
app/services/telephony/telephony_service.py Routes native Plivo calls into streaming media callbacks and persists the selected integration for later call control.
app/services/telephony/number_import_service.py Registers provider-specific webhook URLs and normalizes imported country and application metadata.

Reviews (6): Last reviewed commit: "feat: updating telephony integration" | Re-trigger Greptile

Comment on lines +226 to +233
_CREDENTIALED_RECORDING_IMPORT_PROVIDERS = frozenset({"exotel", "plivo"})


def _use_credentialed_recording_download(call_import, client) -> bool:
"""True when CSV recording URLs should be fetched with provider auth."""
if client is None or not hasattr(client, "download_recording"):
return False
return (call_import.provider or "").lower() == "exotel"
return (call_import.provider or "").lower() in _CREDENTIALED_RECORDING_IMPORT_PROVIDERS

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Plivo credentials reach untrusted hosts

When a credentialed Plivo import contains a recording URL hosted on an attacker-controlled public IP address, the worker passes that URL to PlivoClient.download_recording, which attaches the account ID and token as HTTP Basic authentication. Literal public IP addresses bypass the carrier hostname-suffix allowlist, exposing the organization's Plivo credentials to the destination server. How this was verified: The imported row URL reaches the authenticated Plivo download helper, while URL validation accepts non-blocked literal public IP hosts without applying the carrier-host suffix allowlist.

Knowledge Base Used: Telephony provider workflows

Comment thread pytest_out1.txt Outdated
return None


_CREDENTIALED_RECORDING_IMPORT_PROVIDERS = frozenset({"exotel", "plivo"})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Plivo credentials reach shared hosts

When a credentialed Plivo import contains a recording URL for an attacker-controlled S3 bucket or CloudFront distribution, the worker sends the organization's Plivo Basic-auth credentials because every subdomain of amazonaws.com and cloudfront.net is allowlisted, exposing those credentials to the destination. How this was verified: The CSV recording URL reaches the authenticated Plivo downloader, while the hostname validator accepts all subdomains beneath the shared Amazon and CloudFront suffixes.

Knowledge Base Used:

Comment thread app/services/telephony/carrier_media_serializer.py Outdated
Comment on lines +688 to +694
serializer = build_carrier_frame_serializer(
provider_platform=getattr(call_row, "provider_platform", None),
stream_id=stream_id,
call_id=call_id,
auth_id=settings.VOBIZ_AUTH_ID,
auth_token=settings.VOBIZ_AUTH_TOKEN,
params=VobizFrameSerializer.InputParams(
sample_rate=8000,
api_base=settings.VOBIZ_API_BASE,
),
organization_id=UUID(session.organization_id),
db=db,
telephony_integration_id=telephony_integration_id_from_call_row(call_row),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Plivo streams fall back to Vobiz

If more than 200 newer call records exist when a Plivo media WebSocket starts, the bounded call-reference lookup returns no row and this code passes None as the provider. The serializer factory then selects Vobiz, causing automatic hangups to target Vobiz while the Plivo call remains connected.

Knowledge Base Used:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Fix version release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant