v0.12.0
Added
mount/1on the SSH transport receives the client's username as:ssh_user.:app_optsis static and shared by every connection;:ssh_useris the one opt that differs per client — the username from the SSH handshake, injected by the channel into that connection's mount opts. It arrives underno_auth_needed: trueas well, since the username travels in the protocol handshake rather than in authentication, which makes it a natural per-session identity for public or demo daemons where each client picks a name withssh alice@host. It is user input, not an identity: without authentication anyone can claim any name, and a daemon with one shared account reports the same name for everybody — sanitize before display and never use it for authorization on its own. The key is absent when the connection cannot report a username, so match with a fallback rather thanKeyword.fetch!/2. The SSH transport guide covers the details.
Fixed
-
Precompiled
*-unknown-linux-muslNIFs no longer depend onlibgcc_s.so.1(#83). Withcrt-staticoff — and off it must be, since a NIF is a cdylib and musl cannot produce one with crt-static (rust-lang/rust#59302) — rustc links the panic unwinder via an explicit-lgcc_s, which neither-static-libgccnor-C panic=abortremoves (the reference lives in the prebuilt std, not in our crates). Every published musl artifact therefore carried aNEEDED libgcc_s.so.1entry that stock musl systems (Alpine containers, Burrito's Linux payload, Nerves-style rootfs) cannot satisfy, and the NIF failed to relocate — this affects the wholerustler_precompiledecosystem, not just ex_ratatui. Since no stable rustc switch embeds the unwinder under dynamic musl (-C link-self-contained=+unwindis nightly-only), a newbuild.rsshadows the lookup on musl targets: it copies the C toolchain's staticlibgcc_eh.a(the same unwinder code) into the build directory aslibgcc_s.aand prepends that directory to the link search path, so-lgcc_sresolves statically and the artifact links against musl libc alone. Panics keep unwinding — rustler still catches them and raises on the Elixir side. Verified on stockalpine:3.20: the new artifactdlopens cleanly where the v0.11.2 one reproduces the reported relocation failure. Hardened after downstream validation on both musl arches: a trailing-lgccresolves the outline-atomics helpers that GCC >= 10'slibgcc_eh.areferences on aarch64 (__aarch64_*, defined inlibgcc.aand not exported bylibgcc_s.so.1— without it a leaner crate reusing this pattern links silently and fails todlopen), and the release workflow now fails any musl job whose artifact carries alibgcc_sNEEDED entry or undefined unwinder/outline-atomics symbols, so a future toolchain change cannot silently republish broken artifacts. Forcing a source build from a consumer requires declaring:rustlerexplicitly in the consumer's dependencies (optional dependencies are not fetched transitively) — the README documents it. For already-published artifacts (0.11.2 and earlier),apk add libgccis the workaround. The 0.10.0 entry below claimed-static-libgcchad made the musl artifacts self-contained; it had not, and that entry has been corrected in place. -
config :rustler_precompiled, :force_build, ex_ratatui: truenow actually forces a build from source. The native bridge (lib/ex_ratatui/native.ex) always put a:force_buildkey into the option list (derived fromEX_RATATUI_BUILD) and then tried to apply the per-application config withKeyword.put_new/3, which never overwrites an existing key — so the documentedrustler_precompiledescape hatch was silently ignored and the precompiled NIF was downloaded anyway. The three inputs are now resolved explicitly, highest precedence first::force_build_all(orRUSTLER_PRECOMPILED_FORCE_BUILD_ALL), thenconfig :rustler_precompiled, :force_build, ex_ratatui: true/false, thenEX_RATATUI_BUILD. Behaviour is unchanged when the per-application config is absent. -
Modules declaring
@behaviour ExRatatui.Appwithoutuse ExRatatui.Appno longer crash on the optional callbacks. The server invokedhandle_info/2,subscriptions/1,terminate/2, and the reducer-runtime probe__runtime__/0unconditionally —use ExRatatui.Appinjects defaults for all four, so a bare@behaviourmodule implementing only the required callbacks raisedUndefinedFunctionErrorthe moment any of them fired (first at startup, where__runtime__/0is read). The server now falls back to the same defaults the macro injects whenever a callback is not exported, so both forms behave identically. The reducer runtime remains opt-in throughuse— without the macro there is no__runtime__/0to read — anduse ExRatatui.Appstays the recommended form, since it also providesstart_link/1andchild_spec/1for supervision. -
Corrected the OTP 29 note in the README. It claimed OTP 29 had no precompiled binary and required the Rust toolchain plus
EX_RATATUI_BUILD=true. Not so: the NIF ABI is backward compatible andrustler_precompiledselects the highest available version at or below the current one, so OTP 29 (NIF 2.18) loads the published 2.17 binary with no Rust toolchain. Only publishing a native 2.18 artifact is still pending upstream support. The 0.11.2 entry below carried the same error and has been corrected in place — no behaviour changed, only its description.
Changed
- Vendored Rust dependencies bumped.
time0.3.54 → 0.3.55. As always, these compile into the precompiled NIF, so every consumer picks them up with this release regardless of their own lock.