Skip to content

Fix OTP 28/29 compatibility and modernize the build#197

Open
maennchen wants to merge 11 commits into
potatosalad:mainfrom
maennchen:otp-28-29-compat
Open

Fix OTP 28/29 compatibility and modernize the build#197
maennchen wants to merge 11 commits into
potatosalad:mainfrom
maennchen:otp-28-29-compat

Conversation

@maennchen

Copy link
Copy Markdown
Contributor

Key fixes

PKCS #8 / SubjectPublicKeyInfo compatibility with OTP 28. OTP 28 regenerated the public_key ASN.1 bindings: der_decode('PrivateKeyInfo', ...) now returns the privateKeyAlgorithm field as #'PrivateKeyAlgorithmIdentifier'{} instead of #'PrivateKeyInfo_privateKeyAlgorithm'{}, and der_encode('SubjectPublicKeyInfo', ...) expects decoded EcpkParameters instead of their DER-encoded form. As a result, DER/PEM round-trips were broken on OTP 28: from_der/from_pem failed with {error, {unknown_key, ...}} for EC, X25519, and X448 private keys, and to_der raised badarg for EC public keys. jose_public_key now handles both representations.

Deprecated catch expressions. OTP 29 deprecates the standalone catch Expr form; the capability probes in jose_server and jose_jwa now use try/of/catch, including removal of clauses this makes unreachable.

Build & CI

  • Extract Erlang records in the Elixir modules via a cwd-relative path instead of from_lib, which fails under erlang.mk's Elixir compile step (:code.lib_dir(:jose) cannot resolve during the build).
  • Add a rebar3 test profile so rebar3 ct works (test deps incl. PropEr, recursive test compilation for the *_SUITE_data helpers).
  • Skip the flaky config.guess/config.sub download in libsodium's autogen.sh (DO_NOT_UPDATE_CONFIG_SCRIPTS); a GNU Savannah outage previously saved an HTML error page as the script and broke the build.
  • Update erlang.mk, CI matrix (OTP 27/28/29 with Elixir 1.20.2, rebar3 3.27.0), dialyzer job, Mix dependencies, and documentation URLs.

Known issue

The OTP 29 jobs fail until potatosalad/erlang-libsodium#12 is merged and released: libsodium's port driver references erts_fprintf, which OTP 29 no longer exports, so the driver fails to load.

maennchen and others added 11 commits July 17, 2026 14:45
Running the CT suites previously required erlang.mk (make ct), which
declares the TEST_DEPS and compiles test/ recursively. Mirror that in a
rebar3 test profile so rebar3 ct works: pull in the test-only
dependencies (PropEr for the ct_property_test suites, plus the optional
JSON and crypto backends) and compile the helper modules in
test/*_SUITE_data and test/property_test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… OTP 28

OTP 28 regenerated the public_key ASN.1 bindings:

- der_decode('PrivateKeyInfo', ...) now returns the privateKeyAlgorithm
  field as a #'PrivateKeyAlgorithmIdentifier'{} record instead of
  #'PrivateKeyInfo_privateKeyAlgorithm'{}, so decoding X25519, X448, and
  EC private keys fell through to an unknown_key error. Normalize the
  record tag before matching in i2k/1.
- der_encode('SubjectPublicKeyInfo', ...) now takes the decoded
  EcpkParameters value in AlgorithmIdentifier parameters instead of its
  DER-encoded binary form, so encoding EC public keys raised badarg.
  Pass the decoded value on OTP 28 and later.

Fixes the kty_ec_from_der_and_to_der, kty_okp_x25519_from_der_and_to_der,
kty_okp_x25519_from_pem_and_to_pem, kty_okp_x448_from_der_and_to_der, and
kty_okp_x448_from_pem_and_to_pem property test failures on OTP 28.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
libsodium's autogen.sh re-downloads config.guess/config.sub from GNU
Savannah with curl -sL but without -f, so a Savannah outage saves an HTML
error page as config.sub and the configure step fails with "cannot run
./build-aux/config.sub". autoreconf already installs working copies from
automake, so skip the download via DO_NOT_UPDATE_CONFIG_SCRIPTS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Test on OTP 29.0.3, 28.5.0.3, and 27.3.4.14, all with Elixir 1.20.2 and
rebar3 3.27.0 (Elixir 1.19 does not support OTP 29). Move linting to the
OTP 29 job, pass the previously unused rebar3 matrix version to
setup-beam, and fix the CT log artifact name, which referenced a
nonexistent matrix key.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Record.extract with from_lib requires :code.lib_dir(:jose) to resolve at
compile time, which fails under erlang.mk's Elixir compile step: the
checkout directory is not named "jose" and ebin/jose.app does not exist
yet, so make ct breaks with "lib file jose/include/jose_jwe.hrl could not
be found". Both Mix and erlang.mk compile with the project root as the
current directory, so extract via a relative path instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
OTP 29 deprecates the standalone 'catch Expr' form, and the resulting
compiler warnings fail the rebar3 build under warnings_as_errors. Convert
the 'case catch ... of' capability probes in jose_server and jose_jwa to
equivalent try/of/catch expressions. Unlike 'catch', try does not let
thrown values match the success patterns, but none of the probed
functions throw.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant