Changelog
Releases, breaking changes, and fixes — newest first.
Format follows Keep a Changelog. Version
tags correspond to the git SHA on phase1-build at the time of deploy.
2026-05-30 — Voice reliability, keypad & speech quality
Added
- Keypad (DTMF) capture (PR #263). Flows can collect touch-tone input with terminator / fixed-length / timeout ending modes; digits are masked in the transcript by default. See Keypad (DTMF).
- Connect-time voice-engine failover (PR #257). If the chosen engine can't establish the live audio session, OpenPhn retries the next healthy engine on the same call before any audio starts; a background probe restores engines as they recover. See Voice → Failover & reliability.
- "Didn't catch" low-confidence metric (PR #261). Per-call low-confidence
STT count + an analytics KPI (denominator = STT-measured calls;
—when unmeasured), plus a per-flowclarify_on_uncertaintyblock that has the agent ask callers to repeat instead of guessing. See Analytics → Didn't catch.
Docs
- New concept pages: Templates,
Voice cloning, and
HIPAA & BAA. Corrected the
Voice page — the
gemini_25default key runs Gemini 3.1 Flash Live (it predates the 3.1 rename).
2026-05-27 — 0a0faf3 (Win 15 — analytics depth)
Added
- Period-over-period deltas on every KPI and chart on
/analytics. KPI cards read as sentences ("Up 18% from 1,053 last week"), with color polarity that always means the change is good for this metric — cost going down is green; volume going up is green. A one-line headline insight above the KPI row picks one of six templates based on the delta signs. ?compare=priorquery param on every/v1/analytics/*endpoint. When set, the response wraps in{current, prior, delta_pct}. Default off — existing clients unchanged.- Drilldown from charts to filtered /calls. Every chart bar / heatmap
cell / failure row navigates to
/calls?status=…&range=…&source=…pre-filtered. A pill bar above the table renders each active filter in English ("Failed calls", "Inbound", "Grok engine") with × to clear. - Eight new
/v1/callsfilter query params:direction,voice_engine,start,end,to_prefix,has_outcome,min_confidence,max_confidence, plus asort=duration_descoption. - Breakdown by 5 dimensions on
/analytics: voice engine, hour of day, day of week, carrier, phone number. Charts render as small multiples when set. Top-8 cap with "Other" overflow. - Shareable URL state. The
/analyticspage is URL-driven —?range=30d&breakdown=voice_engine&compare-volume=1round-trips perfectly. A new Share button copies the current URL to the clipboard. - CSV export per chart. Each chart toolbar gains a Download icon.
Endpoints under
/v1/analytics/*.csvfor volume-by-status, latency-percentiles, cost-breakdown, top-failures, outcome-quality. Streaming responses; tenant-scoped viacalls:read. carrier_prefixlookup table seeded with ~60 US/CA area-code-to- carrier prefixes. Powers thebreakdown=carrierdimension.
Changed
- The per-chart "Compare to last week" toggle moved from
localStorageto URL state. A one-time mount-time migration drains any pre-existing local toggle into the URL.
Migrations
a1b5c9d3e6f_carrier_prefix— adds thecarrier_prefixlookup table- seed.
2026-05-23 — 1227738 (Win 14 — always-on-best-model framework)
Added
- Grok Voice Think Fast 1.0 as a third voice-engine option alongside Gemini 2.5 (default) and Gemini 3.1 Flash Live.
- Per-Number
voice_enginesetting. Each Number can override its voice engine viaPATCH /v1/numbers/{id} { "voice_engine": "grok_think_fast" }. - Per-Tenant
voice_engine_default. Owners pick the default engine via a Settings panel (PATCH /v1/tenants/me { "voice_engine_default": "grok_think_fast" }). Also acceptsvoice_ab_disabledas a kill switch. - 5% A/B routing. New tenants are deterministically assigned to Grok
at a 5% rate (configurable via
settings.grok_ab_percent), usingsha256(tenant_id) mod 100 < 5for stable bucketing. - Voice-model outcome telemetry at the
voice_model_outcomes_dailySQL view. Surfaced viaGET /v1/admin/voice-model-stats?days=N(admin-only). - Admin dashboard at
/admin/voice-modelswith side-by-side engine comparison, winner highlight per metric, kill-switch panel, and a Promote button to flip the system default viaPATCH /v1/admin/system-defaults. - Operator runbook at
docs/runbooks/voice-engine-promotion.mdcodifying the 4-gate promotion criteria. - PostHog
voice_engineproperty oncall_completedevents. - Sentry
voice_enginetag on call-related exceptions. - Prometheus
openphn_voice_model_duration_seconds{engine}histogramopenphn_voice_model_cost_usd_total{engine}counter.
Migrations
w7q0r3s4o8p_number_voice_engine—numbers.voice_enginecolumnx8r1s4t5p9q_tenant_voice_engine_default—tenants.voice_engine_defaulttenants.voice_ab_disabled
y9s2t5u6q0r_voice_model_outcomes_view— backfill + composite index + SQL viewz0u4v7w8r2s_system_defaults— singleton table for the process-wide default voice engine, audit-logged on promotion
Notes
- The 30-day A/B accrual window opened 2026-05-23. First eligible promotion review: 2026-06-22.
2026-05-22 — c33965f (Tier 9b — deferred follow-ups + onboarding polish)
Added
- HIPAA dashboard config UI under
/settings/compliancefor owners to toggle BAA mode + view the PHI-enforcement banner state (Win 39b). - Webhook secondary-secret auto-retire cron: secrets older than 7 days drop out of the verifier rotation automatically (Win 42b).
- YAML flow engine wired into outbound dispatch so flows defined in
templates.flow_yamlactually drive call behavior (Win 38b). - Mid-call provider fallback with a per-call swap counter — if the primary TTS/STT provider degrades during a call, the runtime swaps without dropping the call (Win 41b).
Fixed
SetupCardCTA on/stageroutes to/numbers/newwhen the user already has a working setup (was opening the wizard unconditionally)./v1/callslist endpoint scopes bytenant_idso inbound rows appear for the owning tenant.CallsTablerow limit dropped from 500 to 200 to match the server cap.- 7 onboarding gaps closed across PRs #233 / #234 / #235: email
verification gate, sidebar pre-tenant gating, cell-verify in the setup
card, track-aware SetupCard, sandbox key auto-issue, per-call
disclosure-certificate download in
/inspector, status link in sidebar, zero-state polish, voice-chain UI in/settings, HIPAA banner CTA.
2026-05-21 — f805bc9 (Tier 9 — revenue + GTM enablement)
Added
- Stripe metered billing wired to per-call pulses with a Stripe
customer-portal redirect from
/billing(Win 36). - Voice cloning v1 with biometric-consent attestation (Win 37).
- YAML flow builder at
/templates/:id/flowwith compliance-aware nodes (every node enforces DNC + consent + AI-disclosure checks) (Win 38). - HIPAA BAA mode. When the tenant flips
hipaa_baa_enabled=true, PHI gets mechanically redacted in transcripts, recordings, and webhook payloads (Win 39). - Sandbox / test API keys that route to a dry-run dispatcher and return synthetic outcomes (Win 40).
- Provider fallback chain for voice/TTS/STT with health-aware routing (Win 41).
- Replay-resistant webhook signing v2 with per-tenant key rotation and 5-minute timestamp window (Win 42).
- Public status page at openphn.com/status driven by Sentry incidents + provider-health rollups, with a subscribe form for email updates (Win 43).
2026-05-19/20 — efb42c0 (Tier 8 — beat-the-pack feature parity)
Added
- OpenPhn MCP server — Model Context Protocol server exposing call dispatch + transcript retrieval to Claude/ChatGPT/Gemini clients (Win 28).
- Agent-vs-agent simulation harness at
/simulationsfor testing flows against scripted personas (Win 29). - Knowledge base v1 with per-call retrieval audit + Postgres-backed full-text search (Win 30).
- Voicemail drop with disclosure-compliance enforcement (Win 31).
- Real-time alerts for compliance violations + provider degradation via webhook + email (Win 32).
- PII redaction + legal-hold key escrow (Win 33).
- Per-second pulse + in-call cost cap. Pulses cleared every 15s during the call; the cap fires if a call's running cost exceeds the per-call ceiling (Win 34).
- Per-call disclosure certificate — every outbound call's AI-
disclosure utterance is fingerprinted + attested; certificate downloadable
from
/inspector/:call_id. (Win 35).
2026-05-13/18 — 5f6c87e (Win 26 — managed outbound + UX-sweep marathon)
Added
- Carrier-of-record managed outbound with STIR/SHAKEN attestation applied at dispatch time. Four-phase rollout (Win 26 Phase 1a–d).
- AUP v2 + re-attestation banner for tenants whose attestation version trails the current published version (Win 23).
- BYO inbound number registration at
POST /v1/numbers/byoplus disconnect atDELETE /v1/numbers/byo/{id}and the UI on/numbers(Win 24a-d). - Append-only consent ledger with a Postgres trigger enforcing
insert-only on
consent_records(Win 20). - Per-item consent_record_id on
/v1/calls/batch(Win 20b). - Outbound circuit breaker with rate-slice + time-of-day anomaly detectors that auto-flip the breaker on a sustained spike (Wins 22, 22b, 22c).
- External DNC scrubbing hook for tenants who maintain their own DNC lists outside OpenPhn (Win 19a).
Marathon (2026-05-18)
- 53-PR sweep (#114-#166) closing 22 frontend a11y + UX issues plus 23 backend bugs surfaced by a new-user UX audit. Highlights: UUID-parse panics, pagination-DoS gaps, suppression dedup, signup/resend rate-limits, JWT-survives-reset, tenant TOCTOU, Twilio orphans, test calls billed, login timing oracle, 22 sync-on-event-loop offloads.
2026-04-22 — c026bff (§8 mobile + Web Push)
Added
- Mobile-first responsive layouts.
/stage,/numbers,/numbers/:id,/calls,/inspectorreflow cleanly at 375 / 768 / 1440. The mobile topbar + Sheet drawer nav handles<768px; desktop sidebar pinned at≥768px. - Playwright viewport-matrix CI. Every PR runs a 15-test responsive smoke across the three breakpoints against a seeded e2e user. Catches regressions before they reach review.
- Web Push notifications for live inbound calls. Per-device, per-number
opt-in on
/numbers/:id. iOS 16.4+ installed-PWA + Android Chrome. iOS Safari users see a dismissible Add-to-Home-Screen banner (90-day TTL on the dismissal) since iOS only allows Push API from home-screen-installed PWAs. - Backend endpoints for push subscription management:
GET /v1/push/vapid-key,POST /v1/push/subscribe,POST /v1/push/unsubscribe,POST /v1/push/delivered,GET /v1/push/subscriptions. - Emit hook fires on
inbound_runnerafter the Call row is created with 30s TTL. 410/404 responses tombstone the subscription atfailure_count=5; other errors increment. - Server-side PostHog backstop.
POST /v1/push/deliveredfires thepush_deliveredevent from the backend in addition to the SW's client-side capture, so adoption metrics don't silently miss ad-blocked / corp-proxy'd sessions.
Changed
- Gated by
VITE_FEATURE_PUSH_NOTIFICATIONS=1. Until the flag flips on Hetzner, no SW registers, no toggle UI renders, no banner appears. Merging is safe without key provisioning.
Also on 2026-04-22
- Greeting p50 overview card on Stage. Measures carrier-WS-connect →
first bot audio frame per call;
compute_summarynow returnsgreeting_latency_p50_ms. Card shows "—" while the window has nofirst_audio_mssamples yet (expected right after thex1y5z9a3b0cmigration lands), then settles into the steady-state sub-1s number. GET /v1/admin/users/{user_id}now returns a user detail row (was 404). Admin UserDetailPage no longer falls through to null.
2026-04-21 — 1575f86
Added
- Docs site. This site launched at
docs.openphn.com. - PostHog analytics.
$pageviewand the explicit event taxonomy (signup_completed,call_created, etc.) now fire from both app and admin surfaces. - Sentry. Backend + frontend + admin error capture, with source-map resolution on the SPA bundles.
Fixed
- Backend crash-loop on startup caused by a missing
jinja2dep pulled in transitively bysentry-sdk[fastapi]'s Starlette integration. - CSP on
app.openphn.comandadmin.openphn.comwas blocking Sentry ingest + PostHog POSTs and Sentry Session Replay blob workers. - PostHog SDK was lazy-initialized via
ensureInit()insidetrack()/identify()/reset()— pages without actions never calledposthog.init(), so$pageviewnever fired. Now eagerly initialized frommain.tsxat boot.
Changed
SENTRY_PROJECT_FRONTENDandSENTRY_PROJECT_ADMINare now required on the Hetzner host.envfor source-map upload to complete.- Docker-compose build-arg defaults for
SENTRY_ORG/SENTRY_PROJECT_*changed from the string"openphn"/"openphn-*"to empty string, so partial-config fail-fast doesn't trip when an auth token isn't set.
Earlier
Earlier changes predate this changelog. See the git log on phase1-build for full history.