Header-only auth for GET endpoints. Query-string api_key parameters are
rejected with a 400: credentials in URLs leak through logs, proxies and
referrers and are a classic SSRF/credential-theft vector.
JSON body extractor whose rejection (missing body, malformed JSON,
wrong content type) is a JSON 400 instead of axum’s defaults. Bodies
larger than the configured server.max_body_bytes are rejected with a
413 before deserialization.
Build the axum router from a PhronaConfig: the search client
(profile / timeout / proxies / concurrency), the API key, the
max_results clamp, the rate limit and the body-size cap all come from
the config.