Skip to main content

BYOC Number Pools Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement task-by-task.
Goal: Restrict all pool behavior to customer-owned telephony while preserving hosted legacy calls. Architecture: Bind each pool to an explicit custom SIP trunk. Keep optional encrypted customer Twilio replacement credentials on the pool; validate account and trunk ownership, and route every purchase/release/recovery through this binding. Never classify BYOC replacement numbers as platform-hosted. Tech Stack: Existing Fastify/Zod/Kysely/PostgreSQL, LiveKit SIP, Twilio SDK, React and generated SDK. Spec: docs/superpowers/specs/2026-10-18-byoc-number-pools.md

Global Constraints

  • Existing worktree and PR; no unrelated changes or production mutations.
  • One backend function per file; derived types; no any/as/nonnull assertions.
  • Additive migration with lock_timeout; no required new API request fields at schema level.
  • Tests use isolated local verification DB and stub vendor boundaries, never live vendors.
  • Credentials encrypted and write-only; no hosted/global fallback for pools.

Review Focus

  • Foreign-org, hosted and stale number/trunk references must reject at save and dialing.
  • Invalid/missing credentials and mismatched provider trunk must fail before purchase/release.
  • Replacement and cancellation races must retain account identity and purchased candidates.
  • Single-number/trunk sequence steps remain single attempt and progress normally.
  • Older clients and pre-existing hosted pool drafts fail safely without invoking hosted replacement.

Task 1: Backend ownership, routing and replacement

Files: backend/src/phone/number-pools/*; backend/src/phone/phone-service/set-agent-outbound-trunk.ts; backend/src/campaign/sender-binding-service/voice-sender-catalog.ts; backend/src/voice-channel/livekit/live-kit-service/make-outbound-call.ts; related exact specs; additive Kysely migration; generated DB types. Interfaces: Pool input gains optional outbound_trunk_id and optional nullable twilio_connection . Pool response exposes outbound_trunk_id and nullable twilio_connection , never auth_token. Backend requires valid custom-trunk binding for pool saves/calls. Add shared scoped pool-route and customer-client helpers, used by all replacement/cancellation paths.
  • Extend nearest regression tests for BYOC eligibility, hosted rejection, no fallback, encrypted credentials and foreign-account/trunk rejection; prove relevant new tests red.
  • Implement migration, validation, safe customer credential storage, pool routing and replacement/recovery/cancellation on customer account.
  • Adapt existing pool fixtures to intended BYOC scope while preserving their original assertions, and run exact affected specs plus backend typecheck/lint.
  • Review backend against the spec before integrating UI.

Task 2: Dashboard and SDK

Files: dashboard phone-number NumberPoolsSection and related components; agent OutboundCallerSelector; generated SDK. Interfaces: Consume Task 1 schema and existing outbound-trunk listing. Select a custom trunk and verified BYOC members; expose optional Twilio credentials only for replacement, including saved-connection state and secure secret refresh/removal.
  • Generate SDK via root pnpm gensdk with pinned local/test env.
  • Implement BYOC pool setup and accurate responsibility copy; exclude hosted members and trunks.
  • Add/run focused UI behavior tests for member/trunk eligibility and replacement credential requirements; typecheck/lint changed dashboard files.
  • Review UI and generated contract against backend.

Task 3: Documentation, integration verification and PR

Files: existing affected docs/phone and sequences guides; PR description.
  • Update guides for BYOC-only eligibility, explicit customer routing, optional Twilio credentials/replacement and unchanged hosted behavior.
  • Run frontmatter/schema binding checks and preview affected UI/docs where available.
  • Run focused regression checks, inspect final diff, obtain independent whole-change review and resolve material findings.
  • Commit/push to existing feature branch and update PR #3714 description; never commit screenshots. Remove or replace obsolete PR screenshots if their claims no longer match.