# Changelog

## Pending

### Features

- group dashboard navigation and align view layout with dcrouter (ui)
  - replace flat SipRouter dashboard tabs with grouped Overview, Telephony, Configuration, and System sections
  - move dashboard URLs to grouped route paths such as `/telephony/calls` and `/configuration/providers`
  - add consistent view headings and shared layout spacing across dashboard views
- group dashboard navigation into sectioned routes and align view layouts with dcrouter (ui)
  - replace flat dashboard tabs with grouped Overview, Telephony, Configuration, and System navigation
  - move routing to nested view/subview paths such as /telephony/calls and /configuration/providers
  - add consistent headings and shared spacing across dashboard views
  - update contact actions and app navigation syncing to use grouped routes
  - switch restartBackground to the populate helper for loading local SmartData and SmartBucket config before restarting

### Fixes

- load local SmartData/SmartBucket config before restarting the development background server (dev)

## 2026-05-22 - 1.27.1

### Fixes

- install fax build and runtime libraries for Docker images and update release tooling dependencies (docker)
  - add libclang, libjpeg, and libtiff development packages required for Rust bindgen and fax-related native builds
  - add libjpeg-turbo and tiff runtime libraries to the Alpine production image for the fax engine
  - bump build and release tooling packages including @git.zone/tsbundle, @git.zone/tsdocker, @git.zone/tsrust, @git.zone/tswatch, and esbuild

## 2026-05-21 - 1.27.0

### Features

- persist siprouter config and media through SmartData and SmartBucket (storage)
  - store runtime config, voicemail metadata, fax jobs, and fax inbox metadata in SmartData
  - store voicemail audio, custom greetings, and fax payloads in SmartBucket while keeping local cache paths for Rust media access
  - migrate legacy local voicemail and fax metadata/media into SmartData and SmartBucket on startup
  - enable gitzone Docker release publishing through the configured tsdocker target

## 2026-04-20 - 1.26.0 - feat(fax)
add fax routing, job tracking, inbox management, and T.38/UDPTL media support

- adds outbound fax origination through the proxy engine with provider codec validation and a new send_fax command
- introduces fax box configuration, inbox storage, and dashboard/API endpoints for listing, downloading, and deleting received fax messages
- tracks fax lifecycle events and persisted fax jobs in the runtime layer
- extends SIP SDP parsing and rewriting to support non-audio media, including T.38 over UDPTL
- records leg media protocol details and bridge state to distinguish RTP, WebRTC, internal, and fax media paths

## 2026-04-14 - 1.25.2 - fix(proxy-engine)
improve inbound SIP routing diagnostics and enrich leg media state reporting

- Extract inbound called numbers from DID-related SIP headers when the request URI contains a provider account username.
- Emit detailed sip_unhandled diagnostics for inbound route misses, missing devices, and RTP allocation failures.
- Include codec, RTP port, remote media, and metadata in leg state change events and preserve those fields in runtime status/history views.
- Match hostname-based providers against resolved inbound source IPs to accept provider traffic sent from resolved addresses.
- Invalidate cached TTS WAV metadata across engine restarts and vendor the kokoro-tts crate via a local patch.

## 2026-04-14 - 1.25.1 - fix(proxy-engine)
respect explicit inbound route targets and store voicemail in the configured mailbox

- Prevent inbound routes with an explicit empty target list from ringing arbitrary registered devices by distinguishing omitted targets from empty targets.
- Route unrouted or no-target inbound calls to voicemail with a generated unrouted greeting instead of falling back to random devices.
- Pass voicemail box identifiers through proxy events and runtime handling so recordings are saved and indexed under the correct mailbox instead of always using default.

## 2026-04-14 - 1.25.0 - feat(proxy-engine)
add live TTS streaming interactions and incoming number range support

- add a new start_tts_interaction command and bridge API to begin IVR or leg interactions before full TTS rendering completes
- stream synthesized TTS chunks into the mixer with cancellation handling so prompts can stop cleanly on digit match, leg removal, or shutdown
- extract PCM-to-mixer frame conversion for reusable live prompt processing
- extend routing pattern matching to support numeric number ranges like start..end, including + prefixed values
- add incomingNumbers config typing and frontend config update support for single, range, and regex number modes

## 2026-04-14 - 1.24.0 - feat(routing)
require explicit inbound DID routes and normalize SIP identities for provider-based number matching

- Inbound route resolution now returns no match unless a configured inbound route explicitly matches the provider and called number.
- Normalized routing identities were added for SIP/TEL URIs so inbound DIDs and outbound dialed numbers match consistently across provider-specific formats.
- Call handling and incoming call events now use normalized numbers, improving routing accuracy for shared trunk providers.
- Route configuration docs and the web route editor were updated to support explicit inbound DID ownership, voicemail fallback, and IVR selection.
- Mixer RTP handling was enhanced to better support variable packet durations, timestamp-based gap fill, and non-blocking output drop reporting.

## 2026-04-14 - 1.23.0 - feat(runtime)
refactor runtime state and proxy event handling for typed WebRTC linking and shared status models

- extract proxy event handling into dedicated runtime modules for status tracking and WebRTC session-to-call linking
- introduce shared typed proxy event and status interfaces used by both backend and web UI
- update web UI server initialization to use structured options and await async config save hooks
- simplify browser signaling by routing WebRTC offer/ICE handling through frontend-to-Rust integration
- align device status rendering with the new address/port fields in dashboard views

## 2026-04-12 - 1.22.0 - feat(proxy-engine)
add on-demand TTS caching for voicemail and IVR prompts

- Route inbound calls directly to configured IVR menus and track them with a dedicated IVR call state
- Generate voicemail greetings and IVR menu prompts inside the Rust proxy engine on demand instead of precomputing prompts in TypeScript
- Add cacheable TTS output with sidecar metadata and enable Kokoro CMUdict support for improved prompt generation
- Extend proxy configuration to include voiceboxes and IVR menus, and update documentation to reflect Kokoro-only prompt generation

## 2026-04-11 - 1.21.0 - feat(providers)
replace provider creation modal with a guided multi-step setup flow

- Adds a stepper-based provider creation flow with provider type selection, connection, credentials, advanced settings, and review steps.
- Applies built-in templates for Sipgate and O2/Alice from the selected provider type instead of separate add actions.
- Adds a final review step with generated provider ID preview and duplicate ID collision handling before saving.

## 2026-04-11 - 1.20.5 - fix(readme)
improve architecture and call flow documentation with Mermaid diagrams

- Replace ASCII architecture and audio pipeline diagrams with Mermaid diagrams for better readability
- Document the WebRTC browser call setup sequence, including offer handling and session-to-call linking

## 2026-04-11 - 1.20.4 - fix(deps)
bump @design.estate/dees-catalog to ^3.71.1

- Updates the @design.estate/dees-catalog dependency from ^3.70.0 to ^3.71.1 in package.json.

## 2026-04-11 - 1.20.3 - fix(ts-config,proxybridge,voicebox)
align voicebox config types and add missing proxy bridge command definitions

- Reuses the canonical IVoiceboxConfig type from voicebox.ts in config.ts to eliminate duplicated type definitions and optionality mismatches.
- Makes voicemail timing and limits optional in voicebox config so defaults can be applied consistently during initialization.
- Adds VoiceboxManager.addMessage and updates recording handling to use it directly for persisted voicemail metadata.
- Extends proxy bridge command typings with add_leg, remove_leg, and WebRTC signaling commands, and tightens sendCommand typing.

## 2026-04-11 - 1.20.2 - fix(proxy-engine)
fix inbound route browser ringing and provider-facing SDP advertisement while preventing RTP port exhaustion

- Honor inbound routing `ringBrowsers` when emitting incoming call events so browser toast notifications can be suppressed per route.
- Rewrite SDP and Record-Route using the destination leg's routable address, using `public_ip` for provider legs and LAN IP for device and internal legs.
- Store provider leg public IP metadata on legs to support correct per-destination SIP message rewriting.
- Change the RTP port pool to track sockets with `Weak<UdpSocket>` so ports are reclaimed automatically after calls end, avoiding leaked allocations and eventual 503 failures on new calls.
- Remove unused dashboard/status, DTMF, relay, and transport helper code paths as part of engine cleanup. 

## 2026-04-11 - 1.20.1 - fix(docker)
install required native build tools for Rust dependencies in the build image

- Add cmake and pkg-config to the Docker build stage so Rust native dependencies can compile successfully in the container
- Document why these tools are needed for transitive Rust crates that build or detect native libraries

## 2026-04-11 - 1.20.0 - feat(docker)
add multi-arch Docker build and tagged release pipeline

- Add a production Dockerfile for building and running the SIP router with the Rust proxy engine and web bundle
- Configure tsdocker and tsrust for linux/amd64 and linux/arm64 image builds and registry mapping
- Add a tag-triggered Gitea workflow to build and push Docker images
- Update runtime binary resolution to load architecture-specific Rust artifacts in Docker and CI environments
- Add Docker-related package scripts, dependency updates, and ignore rules for container builds

## 2026-04-11 - 1.19.2 - fix(web-ui)
normalize lucide icon names across SIP proxy views

- Updates icon identifiers to the expected PascalCase lucide format in app navigation, calls, IVR, overview, providers, and voicemail views.
- Fixes UI icon rendering for stats cards and action menus such as transfer, delete, status, and call direction indicators.

## 2026-04-10 - 1.19.1 - fix(readme)
refresh documentation for jitter buffering, voicemail, and WebSocket signaling details

- Add adaptive jitter buffer and packet loss concealment details to the audio pipeline documentation
- Document voicemail unheard count and heard-state API endpoints
- Update WebSocket event and browser signaling examples to reflect current message types

## 2026-04-10 - 1.19.0 - feat(proxy-engine,codec-lib)
add adaptive RTP jitter buffering with Opus packet loss concealment and stable 20ms resampling

- introduces a per-leg adaptive jitter buffer in the mixer to reorder RTP packets, gate initial playout, and deliver one frame per 20ms tick
- adds Opus PLC support to synthesize missing audio frames when packets are lost, with fade-based fallback handling for non-Opus codecs
- updates i16 and f32 resamplers to use canonical 20ms chunks so cached resamplers preserve filter state and avoid variable-size cache thrashing

## 2026-04-10 - 1.18.0 - feat(readme)
expand documentation for voicemail, IVR, audio engine, and API capabilities

- Updates the feature overview to document voicemail, IVR menus, call recording, enhanced TTS, and the 48kHz float audio engine
- Refreshes the architecture section to describe the TypeScript control plane, Rust proxy-engine data plane, and JSON-over-stdio IPC
- Clarifies REST API and WebSocket coverage with voicemail endpoints, incoming call events, and refined endpoint descriptions

## 2026-04-10 - 1.17.2 - fix(proxy-engine)
use negotiated SDP payload types when wiring SIP legs and enable default nnnoiseless features for telephony denoising

- Select the negotiated codec payload type from SDP answers instead of always using the first offered codec
- Preserve the device leg's preferred payload type from its own INVITE SDP when attaching it to the mixer
- Enable default nnnoiseless features in codec-lib and proxy-engine dependencies

## 2026-04-10 - 1.17.1 - fix(proxy-engine,codec-lib,sip-proto,ts)
preserve negotiated media details and improve RTP audio handling across call legs

- Use native Opus float encode/decode to avoid unnecessary i16 quantization in the f32 audio path.
- Parse full RTP headers including extensions and sequence numbers, then sort inbound packets before decoding to keep codec state stable for out-of-order audio.
- Capture negotiated codec payload types from SDP offers and answers and include codec, RTP port, remote media, and metadata in leg_added events.
- Emit leg_state_changed and leg_removed events more consistently so the dashboard reflects leg lifecycle updates accurately.

## 2026-04-10 - 1.17.0 - feat(proxy-engine)
upgrade the internal audio bus to 48kHz f32 with per-leg denoising and improve SIP leg routing

- switch mixer, prompt playback, and tool leg audio handling from 16kHz i16 to 48kHz f32 for higher-quality internal processing
- add f32 decode/encode and resampling support plus standalone RNNoise denoiser creation in codec-lib
- apply per-leg inbound noise suppression in the mixer before mix-minus generation
- fix passthrough call routing by matching the actual leg from the signaling source address when Call-IDs are shared
- correct dialed number extraction from bare SIP request URIs by parsing the user part directly

## 2026-04-10 - 1.16.0 - feat(proxy-engine)
integrate Kokoro TTS generation into proxy-engine and simplify TypeScript prompt handling to use cached WAV files

- adds a generate_tts command to proxy-engine with lazy-loaded Kokoro model support and WAV output generation
- removes standalone opus-codec and tts-engine workspace binaries by consolidating TTS generation into proxy-engine
- updates announcement and prompt cache flows to generate and cache WAV files on disk instead of pre-encoding RTP frames in TypeScript

## 2026-04-10 - 1.15.0 - feat(proxy-engine)
add device leg, leg transfer, and leg replacement call controls

- adds proxy-engine commands and call manager support for inviting a registered SIP device into an active call
- supports transferring an existing leg between calls while preserving the active connection and updating mixer routing
- supports replacing a call leg by removing the current leg and dialing a new outbound destination
- wires the frontend add-leg API and TypeScript bridge to the new device leg and leg control commands

## 2026-04-10 - 1.14.0 - feat(proxy-engine)
add multiparty call mixing with dynamic SIP and WebRTC leg management

- replace passthrough call handling with a mixer-backed call model that tracks multiple legs and exposes leg status in call state output
- add mixer and leg I/O infrastructure to bridge SIP RTP and WebRTC audio through channel-based mix-minus processing
- introduce add_leg and remove_leg proxy commands and wire frontend bridge APIs to manage external call legs
- emit leg lifecycle events for observability and mark unimplemented device-leg and transfer HTTP endpoints with 501 responses

## 2026-04-10 - 1.13.0 - feat(proxy-engine,webrtc)
add B2BUA SIP leg handling and WebRTC call bridging for outbound calls

- introduce a new SipLeg module to manage outbound provider dialogs, including INVITE lifecycle, digest auth retries, ACK handling, media endpoint tracking, and termination
- store outbound dashboard calls as B2BUA calls in the call manager and emit provider media details on call_answered for bridge setup
- separate SIP and WebRTC engine locking to avoid contention and deadlocks while linking sessions to call RTP sockets
- add bidirectional RTP bridging between provider SIP media and browser WebRTC audio using the allocated RTP socket
- wire browser webrtc-accept events in the frontend and sipproxy so session-to-call linking can occur when media and acceptance arrive in either order

## 2026-04-10 - 1.12.0 - feat(proxy-engine)
add Rust-based outbound calling, WebRTC bridging, and voicemail handling

- adds outbound call origination through the Rust proxy engine with dashboard make_call support
- routes unanswered inbound calls to voicemail, including greeting playback, beep generation, and WAV message recording
- introduces Rust WebRTC session handling and SIP audio bridging, replacing the previous TypeScript WebRTC path
- moves SIP registration and routing responsibilities further into the Rust proxy engine and removes legacy TypeScript call/SIP modules

## 2026-04-10 - 1.11.0 - feat(rust-proxy-engine)
add a Rust SIP proxy engine with shared SIP and codec libraries

- add new Rust workspace crates for proxy-engine, sip-proto, and codec-lib
- move transcoding logic out of opus-codec into reusable codec-lib and keep opus-codec as a thin CLI wrapper
- implement SIP message parsing, dialog handling, SDP/URI rewriting, provider registration, device registration, call management, RTP relay, and DTMF detection in Rust
- add a TypeScript proxy bridge and update the SIP proxy entrypoint to spawn and configure the Rust engine as the SIP data plane

## 2026-04-10 - 1.10.0 - feat(call, voicemail, ivr)
add voicemail and IVR call flows with DTMF handling, prompt playback, recording, and dashboard management

- introduces system call legs, DTMF detection, prompt caching, and audio recording to support automated call handling
- adds configurable voiceboxes and IVR menus to routing, including voicemail fallback on busy or no-answer flows
- exposes voicemail message APIs, message waiting counts, and new dashboard views for voicemail and IVR management

## 2026-04-10 - 1.9.0 - feat(routing)
add rule-based SIP routing for inbound and outbound calls with dashboard route management

- Replaces provider/device routing config with prioritized match/action routes for inbound and outbound call handling
- Adds outbound route resolution with provider failover and number transformation, and applies it in the call manager and SIP proxy
- Adds a dashboard Routes view and updates provider editing to manage inbound routing through route definitions
- Improves announcement generation by preferring espeak-ng, falling back to Kokoro, and detecting WAV sample rates dynamically

## 2026-04-09 - 1.8.0 - feat(providerstate)
sync provider registrations when config is reloaded after save

- Adds provider state synchronization to create registrations for new providers, remove deleted providers, and re-register providers whose configuration changed.
- Preserves detected public IP when rebuilding provider state for updated provider configs.
- Triggers registration status broadcasts after config reload so runtime state stays aligned with saved provider settings.

## 2026-04-09 - 1.7.0 - feat(audio)
add directional RNNoise suppression to transcoding and preserve RTP continuity during announcement handoff

- adds per-direction RNNoise denoising in the Rust opus transcoder with 48kHz frame processing
- passes transcoder direction through the TypeScript bridge so browser-bound and SIP-bound audio use separate suppression state
- shares RTP sequence and timestamp counters between announcements and live provider audio to avoid browser jitter buffer discontinuities
- updates the background restart script to rebuild the Rust codec before bundling

## 2026-04-09 - 1.6.0 - feat(codec,call,web-ui)
add isolated codec sessions for concurrent call transcoding and fix form input event handling

- adds per-session Rust codec state with create_session and destroy_session support to prevent concurrent calls from corrupting Opus and G.722 state
- updates WebRTC call setup to await transcoder initialization and clean up codec sessions on teardown
- improves codec robustness with safer PCM handling, larger Opus decode buffers, auto-reinit after bridge exit, and telephony tuning for Opus encoding
- switches multiple web UI forms from changeValue to input/newValue events so text fields and checkboxes update reliably

## 2026-04-09 - 1.5.1 - fix(call,opus-codec)
improve SIP/WebRTC RTP routing and use cached FFT resampling for transcoding

- route browser-to-provider RTP through the SIP leg socket to avoid symmetric RTP double-path issues
- preserve active calls when a WebRTC leg disconnects by removing only the terminated leg and updating call state correctly
- set dynamic SIP From URIs and display names for mediated and conference invites
- replace the custom resampler with rubato FFT resampling and cache resamplers by rate pair and chunk size for continuous audio streams

## 2026-04-09 - 1.5.0 - feat(contacts,phone)
add starred contacts quick dial flow and improve call/media handling

- Add starred contacts to config and app state, with sorting and contact stats support in the contacts view.
- Let contact actions open the phone view with a selected contact and show starred contacts as quick-dial entries.
- Update the phone and contacts UI to use dees input components and show all devices with online/offline status.
- Prevent raw codec passthrough on transcode failure and forward RTP using the parsed payload instead of slicing serialized packets.
- Adjust the 3x Opus downsampling lowpass filter coefficients for improved resampling behavior.

## 2026-04-09 - 1.4.0 - feat(calling)
add cached TTS announcements, external participant dialing, and call history support

- pre-generate Piper-based announcements and cache encoded G.722 and Opus RTP frames for SIP and WebRTC playback
- add encode_pcm support in the Rust codec bridge with anti-aliased PCM resampling for direct PCM-to-codec encoding
- add API and UI support for dialing external participants into an existing call
- record completed calls in bounded call history and expose them in the web UI
- improve RTP handling with stable SSRC usage, codec-specific silence payloads, and safer async transcoding sequencing

## 2026-04-09 - 1.3.1 - fix(router)
prevent duplicate app navigation callbacks when syncing tab selection with URL updates

- add an optional skipCallback flag to router navigation so URL changes do not re-trigger view loading
- update sipproxy app tab selection handling to push browser history without causing navigation loops
- limit router-driven appdash view loading to browser back/forward navigation

## 2026-04-09 - 1.3.0 - feat(webrtc-ui)
add routed dashboard views with contacts and provider management, and fix browser WebRTC call linking and audio forwarding

- Defers browser WebRTC leg creation until the offer arrives, links the standalone session on accept, and routes SIP-to-browser audio through the WebRTC peer connection to prevent one-way audio
- Adds URL-routed app views for overview, calls, phone, contacts, providers, and log, replacing the previous dashboard-only layout
- Introduces contacts support in config and app state, exposes contacts in status payloads, and adds UI to create, edit, delete, and call contacts
- Expands provider configuration management to support editing full provider settings plus adding and removing providers
- Makes outbound provider selection tolerant of deployments with no configured providers to avoid forwarding errors

## 2026-04-09 - 1.2.0 - feat(call)
introduce a hub-based call manager with SIP and WebRTC legs, unified RTP port pooling, and expanded call control APIs

- Adds a new call hub model with Call, Leg, SipLeg, WebRtcLeg, shared types, and centralized RTP forwarding/transcoding.
- Replaces the legacy call originator flow with CallManager-driven call handling in the SIP proxy bootstrap.
- Extends the web API and dashboard to support provider selection, richer call status, adding/removing legs, transfers, and WebRTC call control.
- Refactors WebRTC bridge responsibilities to signaling only while moving media handling into the new call layer.

## 2026-04-09 - 1.1.1 - fix(calloriginator)
handle 200 OK retransmits without rebuilding the bridge and always start RTP keepalive silence when remote media is available

- Resend ACK for repeated 200 OK responses and return early once the call is already connected.
- Prevent duplicate bridge setup and repeated state transitions on SIP response retransmits.
- Start the silence stream for all calls with remote media to keep the provider media path alive and help open the RTP NAT path.

## 2026-04-09 - 1.1.0 - feat(webrtc)
add browser audio device controls and improve WebRTC audio bridging

- add microphone and speaker selection to the browser softphone
- show local and remote audio level meters during active WebRTC calls
- ensure the WebRTC answer negotiates sendrecv audio so the server can send RTP to the browser
- extract and use sender SSRC for browser-bound RTP and add diagnostics for SIP-to-WebRTC media flow
- avoid starting the SIP silence stream for browser calls to prevent media path issues with easybell

## 2026-04-09 - 1.0.0 - platform
Major 1.0.0 release delivering a configurable multi-provider SIP router with web UI, browser softphone support, and Rust-based media transcoding.

- Introduced a generic multi-provider SIP proxy/router architecture with local registrar, per-provider upstream registration, digest auth handling, configurable routing, device status, quick-dials, and provider-specific call quirks
- Added a full web dashboard and later migrated it to a component-based frontend using `@design.estate/dees-element`, with provider/device/call/log views, status APIs, WebSocket updates, hot reload behavior, and improved app shell/modals
- Added configuration APIs and settings UI for editing providers, devices, inbound routing, quick-dials, and browser ringing behavior, persisted to `.nogit/config.json`
- Renamed the project from `grandstream-sip-proxy` to `SipRouter`, including binary naming and updated user-agent branding
- Added WebRTC softphone support for browsers, including browser device registration, incoming-call notifications, accept/reject handling, targeted WebSocket messaging, and device-aware call routing
- Improved browser device UX with automatic registration, browser-specific naming, `(this browser)` labeling, duplicate/stale registration cleanup, IP display, and always-visible configured devices with connection state
- Added HTTPS support for browser audio flows, including inbound browser ringing, single-port HTTP/HTTPS serving, and re-enabled `getUserMedia` once TLS was available
- Refined call routing so calls go to the selected device instead of a hardcoded endpoint, including explicit device selection requirements and defaulting outbound origin to the first SIP device instead of the browser
- Improved call stability by starting a silence stream when leg B connects to prevent provider teardown before media is flowing
- Migrated runtime/server infrastructure from Deno to Node.js/tsx, replacing Deno-specific APIs with Node.js HTTP/HTTPS and WebSocket implementations
- Completed media handling in Rust, replacing buggy TypeScript G.722 processing with a single IPC transcoding path covering Opus, G.722, PCMU, PCMA, resampling, and verified browser-to-mobile audio bridging
- Included prior build/runtime work such as TypeScript migration, Deno support with single-binary compilation, and related setup as part of the path to the final 1.0.0 architecture

## 2026-04-08 - unknown - initial
Initial SIP-aware proxy for Grandstream HT801 ↔ easybell connectivity.

- Added SIP message parsing with binary passthrough to avoid corrupting STUN keep-alives and RTP
- Implemented Contact and Request-URI rewriting between LAN and public addresses
- Added SDP rewriting and per-call RTP relay sockets
- Added NAT priming and G.722 silence streaming after `200 OK` so easybell detects inbound media promptly
- Inserted `Record-Route` so in-dialog ACK/BYE/re-INVITE continue through the proxy
- Included captured device setting snapshots and setup documentation for diagnosing registration issues
