OpenPhn docs

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-flow clarify_on_uncertainty block that has the agent ask callers to repeat instead of guessing. See Analytics → Didn't catch.

Docs

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=prior query 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/calls filter query params: direction, voice_engine, start, end, to_prefix, has_outcome, min_confidence, max_confidence, plus a sort=duration_desc option.
  • 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 /analytics page is URL-driven — ?range=30d&breakdown=voice_engine&compare-volume=1 round-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/*.csv for volume-by-status, latency-percentiles, cost-breakdown, top-failures, outcome-quality. Streaming responses; tenant-scoped via calls:read.
  • carrier_prefix lookup table seeded with ~60 US/CA area-code-to- carrier prefixes. Powers the breakdown=carrier dimension.

Changed

  • The per-chart "Compare to last week" toggle moved from localStorage to URL state. A one-time mount-time migration drains any pre-existing local toggle into the URL.

Migrations

  • a1b5c9d3e6f_carrier_prefix — adds the carrier_prefix lookup 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_engine setting. Each Number can override its voice engine via PATCH /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 accepts voice_ab_disabled as a kill switch.
  • 5% A/B routing. New tenants are deterministically assigned to Grok at a 5% rate (configurable via settings.grok_ab_percent), using sha256(tenant_id) mod 100 < 5 for stable bucketing.
  • Voice-model outcome telemetry at the voice_model_outcomes_daily SQL view. Surfaced via GET /v1/admin/voice-model-stats?days=N (admin-only).
  • Admin dashboard at /admin/voice-models with side-by-side engine comparison, winner highlight per metric, kill-switch panel, and a Promote button to flip the system default via PATCH /v1/admin/system-defaults.
  • Operator runbook at docs/runbooks/voice-engine-promotion.md codifying the 4-gate promotion criteria.
  • PostHog voice_engine property on call_completed events.
  • Sentry voice_engine tag on call-related exceptions.
  • Prometheus openphn_voice_model_duration_seconds{engine} histogram
    • openphn_voice_model_cost_usd_total{engine} counter.

Migrations

  • w7q0r3s4o8p_number_voice_enginenumbers.voice_engine column
  • x8r1s4t5p9q_tenant_voice_engine_defaulttenants.voice_engine_default
    • tenants.voice_ab_disabled
  • y9s2t5u6q0r_voice_model_outcomes_view — backfill + composite index + SQL view
  • z0u4v7w8r2s_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/compliance for 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_yaml actually 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

  • SetupCard CTA on /stage routes to /numbers/new when the user already has a working setup (was opening the wizard unconditionally).
  • /v1/calls list endpoint scopes by tenant_id so inbound rows appear for the owning tenant.
  • CallsTable row 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/flow with 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 /simulations for 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/byo plus disconnect at DELETE /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, /inspector reflow 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_runner after the Call row is created with 30s TTL. 410/404 responses tombstone the subscription at failure_count=5; other errors increment.
  • Server-side PostHog backstop. POST /v1/push/delivered fires the push_delivered event 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_summary now returns greeting_latency_p50_ms. Card shows "—" while the window has no first_audio_ms samples yet (expected right after the x1y5z9a3b0c migration 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. $pageview and 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 jinja2 dep pulled in transitively by sentry-sdk[fastapi]'s Starlette integration.
  • CSP on app.openphn.com and admin.openphn.com was blocking Sentry ingest + PostHog POSTs and Sentry Session Replay blob workers.
  • PostHog SDK was lazy-initialized via ensureInit() inside track()/identify()/reset() — pages without actions never called posthog.init(), so $pageview never fired. Now eagerly initialized from main.tsx at boot.

Changed

  • SENTRY_PROJECT_FRONTEND and SENTRY_PROJECT_ADMIN are now required on the Hetzner host .env for 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.

On this page