The decision half of the client-configuration fix, as a pure header so every
transition is a host test rather than a hardware run.
`MqttEffectiveConfig` is the complete owned description of what a slot's client
should be configured with — URI (its own copy, because `slot.broker_uri` is
rewritten in place), transport, trust policy, auth mode, credential pointers,
buffer size, keepalive. Two things are deliberate:
- the transport is derived from the URI scheme, and the trust policy is
normalised against it: an unencrypted transport verifies nothing, whatever
certificate material was requested, so a plaintext endpoint can never look
like it retained a verified policy;
- absent credentials are represented as nullptr and written as "", never
omitted. IDF's `esp_mqtt_set_if_config()` treats NULL as "leave unchanged",
so a cleared wrapper pointer cannot erase an SDK-held credential, while an
empty string overwrites it and leaves the CONNECT's username flag clear
(verified on an ESP32-S3 against a local broker on IDF 4.4).
`mqttConfigRecreateDecision()` says whether the existing client can be
reconfigured in place. Reuse covers every credential and auth-mode change and
any endpoint move within one scheme — the cases that matter for reconnect and
token renewal, where a client create/destroy cycle is the fork's documented
internal-heap fragmentation driver. Recreation is reserved for the three fields
that cannot be overwritten safely: a transport (scheme) change, a trust-policy
or CA-certificate change, and growth beyond the allocated buffer capacity,
which IDF 4.4 fixes at client init.
Client certificates are excluded on purpose: `setClientCertificate()` has no
caller in the firmware, so modelling mutual TLS here would be untested
configuration surface. Noted in the header.
Nothing consumes this yet; the bridge is migrated onto it after the result
propagation and generation-guard steps, which it depends on.