Proof of concept — demo environment, not production. No SLA, no emergency calling (no 911/112), data may be reset without notice. Calls will drop after ~50s as the app is in testing mode.
T9phone

Under the hood

A plain-language tour of the stack, the protocols, and the cryptography that holds T9phone together. If you don’t trust a system you can’t inspect, this is where to start.

Frontend

  • Next.js 14 (App Router) on Node, served behind Cloudflare.
  • React, Tailwind CSS, Radix UI primitives, Framer Motion for motion.
  • Strict Content-Security-Policy with per-request nonce. No third-party trackers or analytics scripts.
  • Cloudflare Turnstile on the registration form (no captcha on token-gated invite flows).

Backend

  • Express (Node.js) for the portal API.
  • PostgreSQL for users, groups, invites, audit log, and SIP credentials.
  • HTTP-only, Secure, SameSite=Lax session cookies; CSRF token on state-changing requests.
  • Cloudflare may set a __cf_bm bot-management cookie on edge-challenged requests. It is HTTP-only, ~30 minutes, used only to distinguish humans from bots — not for tracking or advertising.
  • Rate limiting on registration, login, password reset, and invite redemption.
  • Transactional email via Resend (verification, password reset, invitations).
  • Services run under systemd (portal-backend, portal-frontend, portal-provisioning) with journald logs.

Voice

  • FreeSWITCH on a dedicated VPS handles SIP registration and call routing.
  • SIP user directory served from the portal (/api/freeswitch/directory) over mutually-authenticated HTTPS — there are no static .xml user files on the SIP box.
  • Dialplan served the same way (/api/freeswitch/dialplan) — the closed-group rule lives in the portal, not the switch.
  • coturn provides ICE/STUN/TURN so calls connect through NAT and carrier-grade firewalls.
  • bypass_media mode: once the call is up, RTP flows endpoint-to-endpoint through TURN — the SIP server never sees the audio.
  • No PSTN trunking, no SIP federation. Calls cannot enter or leave the platform.

Closed-group routing

When a call arrives the dialplan looks up both legs in PostgreSQL. The call is bridged only if caller and callee share at least one group, and an active group is selected with the optional *N*<code> prefix. If no shared group exists the call is rejected at the switch — the destination is never rung.

Cryptography

  • Account passwords: bcrypt at cost 12. Hashed, salted, not recoverable. Compares are constant-time and a dummy hash is verified for unknown users to prevent timing-based account enumeration.
  • SIP credentials: AES-256-GCM with a rotated key set. The plaintext only ever lives in memory long enough to answer a FreeSWITCH directory lookup.
  • Email verification & password reset tokens: 32 bytes of CSPRNG entropy; only their SHA-256 hash is stored. Expire on use and after a short TTL.
  • Invite tokens: single- or multi-use bearer secrets, hashed at rest, redemption gated on the invitee’s email matching the invite when enforced.

Transport

  • Web (t9phone.com): TLS 1.2+, Cloudflare Full (strict) to the origin which presents a Cloudflare Origin cert. HSTS enabled.
  • SIP signalling (sip.t9phone.com:5061): SIP over TLS using a Let’s Encrypt certificate (full chain delivered to clients). Plain UDP SIP is not exposed.
  • Media: ICE/TURN over UDP, with TLS-protected credential exchange. Acrobits clients run with ZRTP enabled where the peer supports it.

What we keep, and what we don’t

  • Kept: account row (email, nickname, bcrypt hash), SIP credential row (AES-GCM ciphertext), group membership, invite state, group audit events (joins, leaves, bans, role changes).
  • Not kept: call detail records, recordings, transcripts, call durations, voicemail, contact lists, message history, presence status, IP geolocation logs.

Self-verification

Everything above can be checked from your own device. Inspect the TLS certificates with openssl s_client, observe traffic flows with Wireshark, or read the deployed JavaScript in your browser’s devtools — there is no obfuscation. T9phone is built on open cryptography because secrecy of design is not security.