Scope note, 2026-08-17. Retitled from "neither TLS stream". The comment below
extends this to SolidSyslogLwipRawTcpStream_Create and
SolidSyslogLwipRawDnsResolver_Create, so the issue covers four classes across
two platform packs, and the fix is one decision about what Create owes the
caller across all four. The sections below describe the two TLS adapters only;
read them with the comment.
docs/tls.md requires a TLS Stream given an unusable configuration to report a
bad configuration and return the Null object, rather than accepting it and
failing later. Neither adapter does this.
What happens today
Create in both adapters takes a pool slot, copies the config, and validates
nothing:
Sleep is documented "required — there is no fallback" in both headers, and
both call self->Config.Sleep(...) unguarded on the first WANT_READ /
WANT_WRITE poll. That is every real handshake, so a NULL Sleep is a NULL
function-pointer call on the first connection attempt.
SolidSyslogMbedTlsStream additionally passes Rng and CaChain straight to
mbedtls_ssl_conf_rng and mbedtls_ssl_conf_ca_chain, neither of which
returns a status. A NULL there surfaces later as a handshake failure rather
than as the configuration error it is.
No test covers a NULL in any of these fields; every test in both suites wires
them.
Why this is not a new rule
The library already holds Create to this contract elsewhere.
SolidSyslogMetaSd_Create reports NULL_CONFIG and NULL_COUNTER as WARNING
and returns the Null structured data rather than proceeding. The TLS adapters are
not following a rule the codebase already demonstrates.
Acceptance
- A NULL
Sleep is reported at Create and the Null stream returned, in both
adapters
SolidSyslogMbedTlsStream does the same for a NULL Rng and a NULL CaChain
- Severity follows
docs/error-severity.md — a Create that falls back to the
Null object cannot deliver, which is the CRITICAL case
- Tests cover each field's NULL, since none do today
Not in scope
Whether other classes share the lapse. This was found in the two TLS adapters
while writing their contract; a sweep across every Create is separate work.
Scope note, 2026-08-17. Retitled from "neither TLS stream". The comment below
extends this to
SolidSyslogLwipRawTcpStream_CreateandSolidSyslogLwipRawDnsResolver_Create, so the issue covers four classes acrosstwo platform packs, and the fix is one decision about what
Createowes thecaller across all four. The sections below describe the two TLS adapters only;
read them with the comment.
docs/tls.mdrequires a TLSStreamgiven an unusable configuration to report abad configuration and return the Null object, rather than accepting it and
failing later. Neither adapter does this.
What happens today
Createin both adapters takes a pool slot, copies the config, and validatesnothing:
Sleepis documented "required — there is no fallback" in both headers, andboth call
self->Config.Sleep(...)unguarded on the firstWANT_READ/WANT_WRITEpoll. That is every real handshake, so a NULLSleepis a NULLfunction-pointer call on the first connection attempt.
SolidSyslogMbedTlsStreamadditionally passesRngandCaChainstraight tombedtls_ssl_conf_rngandmbedtls_ssl_conf_ca_chain, neither of whichreturns a status. A NULL there surfaces later as a handshake failure rather
than as the configuration error it is.
No test covers a NULL in any of these fields; every test in both suites wires
them.
Why this is not a new rule
The library already holds
Createto this contract elsewhere.SolidSyslogMetaSd_CreatereportsNULL_CONFIGandNULL_COUNTERasWARNINGand returns the Null structured data rather than proceeding. The TLS adapters are
not following a rule the codebase already demonstrates.
Acceptance
Sleepis reported atCreateand the Null stream returned, in bothadapters
SolidSyslogMbedTlsStreamdoes the same for a NULLRngand a NULLCaChaindocs/error-severity.md— aCreatethat falls back to theNull object cannot deliver, which is the
CRITICALcaseNot in scope
Whether other classes share the lapse. This was found in the two TLS adapters
while writing their contract; a sweep across every
Createis separate work.