The repo already validates provider base URLs during provider CRUD, but
TTS test-connection built ephemeral providers from user-supplied api_base
without reusing that protection. This change applies the same validation
at test time and adds regression coverage for blocked loopback targets.
Constraint: Must preserve current local-provider SSRF policy semantics from provider validation
Rejected: Restrict test-connection to admins only | larger behavior change than needed for the bug
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep TTS test-connection URL validation aligned with validateProviderURL behavior for provider CRUD
Tested: go test ./internal/http -run 'TestTestConnection_(MissingProvider|UnsupportedProvider|MissingAPIKey|BelowOperator|BlockedAPIBase)$' -count=1 -v
Tested: go build ./...
Tested: go build -tags sqliteonly ./...
Not-tested: Full repo race test suite
Co-authored-by: viettranx <viettranx@gmail.com>
The new per-tenant TTS config surface diverged from the established TTS
schema after the audio refactor, dropping UI alias fields and root-level
settings during round-trip. It also returned ok=true even when non-secret
system config writes failed. This patch accepts backward-compatible field
aliases, round-trips timeout and Edge settings, reuses tenant timeout/rate
when building ephemeral providers, and returns errors on failed saves.
Constraint: Must preserve the existing TTS config schema expected by dashboard flows and legacy config docs
Rejected: Fix only the UI payload shape | backend would still break legacy aliases and direct API callers
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: When extending per-tenant config handlers, keep request/response structs aligned with the established config schema and do not ignore store write errors
Related: #935
Related: #936
Tested: go test ./internal/http -run 'Test(TTSConfig|TestConnection_)' -count=1 -v
Tested: go build ./...
Tested: go build -tags sqliteonly ./...
Not-tested: Full repo race test suite
- Add POST /v1/tts/test-connection for testing TTS credentials before saving
- Add UpdateManager() with RWMutex for thread-safe HTTP handler hot-reload
- Add sendVoice() for Telegram voice bubble support via audio_as_voice metadata
- Wire ttsHandler into gateway deps for config reload propagation