Repository navigation
feat: call ordinary phones from qrypt.chat, 10 free minutes a day (0.14.0) - #335
Conversation
…14.0) Anthony: "rebuild so it works like skype used to" (after Suparelay), and "let people make ten minutes of phone calls a day for free". /phone (Navbar "Phone"): a dialer for US and Canadian numbers on Telnyx. - The browser's line is a per-user Telnyx telephony credential on a credential connection with NO outbound voice profile: a WebRTC token cannot dial the phone network. POST /api/phone/call checks the number and the allowance, rings that line through a Call Control app, and on call.answered transfers it to the number with time_limit_secs = the allowance, so Telnyx itself ends the call. - call.answered / call.hangup on the phone leg (signed Ed25519 webhooks at /api/phone/webhook, raw 32-byte or PEM key) bill answer -> hang-up seconds. - 10 free minutes a day (UTC) for signed-in accounts, none for anonymous ones, operators (PHONE_OPERATOR_IDS) an hour a call. 911/N11, 900/976 and fictional 555-01XX numbers are refused; one live call per person. - Caller ID is forced to PHONE_CALLER_ID by the connection's ANI override. The outbound profile allows US/CA only with a $10/day spend cap. - The page says plainly that calls to phones are not end-to-end encrypted. Tables phone_lines and phone_calls (service role only), migration applied on dev2. Tested against the real phone network before building: browser rang, server transferred to NIST's time line (+1 303-499-7111), audio transcribed as "At the tone, 12 hours, 43 minutes, coordinated universal time", and Telnyx ended the call at the time limit (hangup_cause time_limit). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
ThreatCrush Security Scan16 finding(s) MEDIUM: 12 | LOW: 4
Snippets are redacted; ThreatCrush never prints matched credential material. |
| const result = await handleEvent({ ...phoneContext(), event }); | ||
| return NextResponse.json({ ok: true, ...result }); | ||
| } catch (error) { | ||
| console.error('[phone/webhook]', event?.event_type, error?.message); |
Anthony: "rebuild so it works like skype used to" (after looking at Suparelay), then "let people make ten minutes of phone calls a day for free".
What:
/phone(and a "Phone" link in the navbar) is a dialer for US and Canadian numbers: a keypad, the minutes left today, mute, keypad tones during the call, hang up, and recent calls. Signed-in accounts get 10 free minutes a day. Calls to phones aren't end-to-end encrypted, and the page says so.How (Telnyx, all on the existing account)
POST /api/phone/callchecks the number and the allowance, saves aphone_callsrow, and rings the user's line through the qrypt.chat call control app (carryingclient_state {c: callId}). Oncall.answeredit transfers that leg to the number withtime_limit_secs= the allowance, so Telnyx ends the call itself when the minutes run out.call.answered/call.hangupon the phone leg give answer → hang-up seconds./api/phone/webhookverifies Ed25519 signatures with a 5-minute replay window, and accepts the bare 32-byte key we have as well as PEM.src/lib/phone/rules.js): 911/N11, 900/976 and fictional 555-01XX are refused. Anonymous accounts get no free minutes. Operators (PHONE_OPERATOR_IDS: Anthony and the agents) get an hour per call. One live call per person.Verified against the real phone network before writing the app:
hangup_cause: time_limit).phone.test.jsreplays that exact event sequence (including the extra internal leg Telnyx reports) and checks 33 billed seconds.Server setup already done on dev2: migration
20261026120000_phone_calls.sqlapplied.TELNYX_CALL_APP_ID,TELNYX_CREDENTIAL_CONNECTION_ID,PHONE_CALLER_IDandPHONE_OPERATOR_IDSadded to app.env (backup bak-009) and to vaultqryptchat-web--prod.Tests:
bun run test:cipasses, apart from the known-flaky exit test. The localnext buildfails on dev2 even on plain master, because the box's Bun is 1.4.4 and the repo pins 1.4.0. CI builds with the pinned version.Found along the way, not fixed here:
src/app/api/webhooks/telnyx/sms/route.jsverifies withformat: 'pem', but the storedTELNYX_PUBLIC_KEYis the bare 32-byte key, so inbound SMS webhooks there probably always fail verification.🤖 Generated with Claude Code