A synthesis request with no text returns 400 instead of a provider error

A TTS request whose text field was absent or empty was sent to a provider, rejected, and retried across every candidate before returning 502 all_upstreams_failed. A malformed request now returns 400 and names the field it is missing.

The check runs before any provider is selected, so an incomplete request costs no synthesis and no failover attempts.

The named field matches the route: input on POST /v1/audio/speech and its streaming sibling, text on POST /v1/synthesize and its streaming sibling.

This was reachable by sending the native text field to the OpenAI-shaped route, whose provider body is built from input. The request looked valid, reached a provider with nothing to speak, and the resulting 502 named the provider rather than the request.

Action: No migration is required. A client that was receiving 502 for an incomplete body now receives 400 with the field name.