sasl
The SASL mechanism registry and framing codec, shared by cx-platform/smtp and cx-platform/imap. mechanisms picks the one mechanism to use from what a server advertised and what the credential holds — strongest-first WITHIN the credential's class (OAUTHBEARER over XOAUTH2, PLAIN over LOGIN) and never across it, so a bearer token is never presented as a password and a password is never dressed as a bearer token. initial-response builds the base64 octets that follow AUTH or AUTHENTICATE, with RFC 4616's NUL placement for PLAIN and RFC 7628's gs2 header and %x01 key/value run for OAUTHBEARER, refusing a NUL, CR, LF or kvsep in any identity before it encodes anything. step answers one server challenge and surfaces a token mechanism's own error JSON rather than swallowing it, together with the continuation that mechanism requires the client to send next. Every verb is pure: no socket, no clock, no randomness, no capability and no state that outlives a call, so an entire hostile exchange replays offline. The module is not an OAuth flow — the token comes from cx-stdlib/oidc — and it defines no base64 of its own, because cx-stdlib/bytes already has one.
sasl:initial-response
[$sasl:initial-response] -> bytes — Build the base64 initial client response for the mechanism the credential names; refuses a NUL, CR, LF or kvsep in any identity before it encodes anything. LOGIN has none and yields the absence channel.
[?lib 'cx-stdlib/sasl']
[?lib 'cx-stdlib/bytes']
[?let [= $a [sasl-auth mechanism=:plain authcid="tim" secret="tanstaaftanstaaf"]]
[$bytes:to-hex [$bytes:from-base64 [$bytes:to-string-utf8 [$sasl:initial-response $a]]]]]
'0074696d0074616e737461616674616e7374616166'
sasl:step
[$sasl:step] -> element — Answer one server challenge with the base64 octets to write back, or done=true when the mechanism has nothing further to say; a token mechanism's error JSON is surfaced as CXER5903 with its required continuation, never swallowed.
[?lib 'cx-stdlib/sasl']
[?lib 'cx-stdlib/bytes']
[?let [= $a [sasl-auth mechanism=:login authcid="tim" secret="tanstaaftanstaaf"]]
[= $r [$sasl:step $a [$bytes:from-base64 "VXNlcm5hbWU6"]]]
[probe [response [$string $r@response]] [done [$string $r@done]]]]
[probe [response dGlt] [done 'false']]
sasl:mechanisms
[$sasl:mechanisms] -> string — Choose the one mechanism to use from the advertised names and the credential — strongest-first within the credential's class, never across it, and a pinned mechanism the server did not advertise is CXER5901 rather than a silent fall-back.
[?lib 'cx-stdlib/sasl']
[?let [= $adv ("PLAIN", "LOGIN")]
[$sasl:mechanisms $adv [sasl-auth authcid="tim" secret="tanstaaftanstaaf"]]]
PLAIN