# Revision history for acme-not-a-joke
## 0.2.0.0 -- 2026-10-23
The first release since 0.1.0.0. It also contains the changes listed under
0.1.1.0 below, which never was released on its own.
* TLS-ALPN-01 challenges (RFC-8737): `isTLSALPN01` (in
`Acme.NotAJoke.Api.Challenge`), `runAcmeDance_tlsalpn01` (in
`Acme.NotAJoke.Dancer`), and `createTLSALPN01Certificate`,
`acmeIdentifierDigest`, `acmeIdentifierOID` and `acmeTLSALPNProtocol` (in
`Acme.NotAJoke.CertManagement`) to build the self-signed certificate with
the `acmeIdentifier` extension. New dependency: `time-hourglass`.
ACME errors are now returned as values rather than thrown (or printed), which
changes the type of most API calls.
* Replace `wreq` with `http-client` and `http-client-tls`: non-2xx responses
are no longer thrown as exceptions. Network-level failures still are raised
as `HttpException` (from `http-client`).
* Add `AcmeError` (in `Acme.NotAJoke.Api.Endpoint`) with `SigningFailed`,
`ServerRejected` and `UnexpectedResponse`, and the helpers `errorResponse`,
`readProblem`, `problemType` and `problemDetail` to read the RFC-7807
problem document of a rejected request.
* Breaking: the `post*` API calls, `getNonce`, the `Nonce.Fetcher` fields,
`saveNonce` and `AcmePrim` use `Either AcmeError a` where they had `Maybe a`.
Signing errors are returned (as `SigningFailed`) instead of printed on stdout.
* Breaking: `fetchDirectory` and `Endpoint.get` return an `Either AcmeError`.
* Breaking: `prepareAcmeOrder` returns an `Either AcmeError AcmeSingle` instead
of failing with a pattern-match error when a step fails.
* Breaking: `DanceStep` has a new `AcmeFailure` constructor, `runAcmeDance`
reports failed API calls with it instead of crashing.
* Breaking: the response newtypes (`AccountCreated`, `OrderCreated`,
`Certificate` etc.) wrap an `Endpoint.Response` (an `http-client` response)
rather than a `wreq` one.
* Breaking: remove `wrequrl`, `responseNonceWreq` and `responseNonceWreqBS`;
add `rawResponseNonce`, `responseHeader`, `call`, `head_`, `postJose`,
`postJoseWith` and `checkResponse`.
* Nonces from error responses are saved for the next request as well.
* Requests carry a `User-Agent` header, as required by RFC-8555.
* Add `isHTTP01` (in `Acme.NotAJoke.Api.Challenge`) and `runAcmeDance_http01`
(in `Acme.NotAJoke.Dancer`) to validate orders with HTTP-01 challenges. The
new `acme-not-a-joke-wai` package serves these challenges from a wai
application, and hands the certificates to a running warp-tls server.
* Wildcard certificates: orders with several identifiers, such as
`*.example.com` together with `example.com`, are validated with one challenge
per authorization (wildcard authorizations need DNS-01). Add
`dns01RecordName`, `wildcardBase`, `isWildcardDomain` and `pickChallenges`
(in `Acme.NotAJoke.Client`).
* Breaking: `AcmeSingle` has a `pendingAuthorizations :: [AcmeAuthorization]`
field in place of `fetchAuthorization`, `proof`, `replyChallenge` and
`pollChallenge`, which moved to `AcmeAuthorization` (along with the
identifier and wildcard flag of the authorization). `prepareAcmeOrder`
inspects every authorization of the order (emitting one `GotAuthorization`
each) instead of the first one only, and skips the valid ones.
* Breaking: `DanceStep` has a new `Authorizing` constructor, emitted before the
`Validation` step of each authorization; `runAcmeDance` emits all the
`Validation` steps before telling the server to check the challenges.
* Account key rollover (RFC-8555 section 7.3.5): add
`Acme.NotAJoke.Api.KeyChange` with `KeyChange`, `KeyChangeHeader` (the
protected header of the inner JWS, with the new key and no nonce),
`keyChangeInnerSign`, `keyChangeSign` and `postKeyChange`, and
`changeAccountKey` (in `Acme.NotAJoke.Client`), which fetches the directory,
nonce and account before changing its key.
* Certificate revocation (RFC-8555 section 7.6): add
`Acme.NotAJoke.Api.Revocation` with `Revocation`, `RevocationReason`,
`revocation`, `revocationDER`, `postRevokeCertificate` (signed with the
account key) and `postRevokeCertificateWithCertKey` (signed with the key of
the certificate), and `revokeCertificate` and `revokeCertificateWithCertKey`
(in `Acme.NotAJoke.Client`), which fetch the directory, nonce and account.
* JWS algorithms beyond RS256: `jwkSign` and `kidSign` sign with the algorithm
that fits the key (`RS256` for RSA, `ES256`/`ES384`/`ES512`/`ES256K` for EC,
`EdDSA` for Ed25519/Ed448), or with the algorithm pinned in the `alg`
parameter of the JWK. Symmetric keys and the `none`/MAC algorithms are
refused (a `SigningFailed`). Add `acmeJWSAlg`, `acmeProtectedHeader` and
`setAcmeJWSAlg` (in `Acme.NotAJoke.Api.JWS`) and `genJWKecP256`,
`genJWKecP384` and `genJWKed25519` (in `Acme.NotAJoke.KeyManagement`). RSA
keys without a pinned algorithm still sign with `RS256`. New dependency:
`mtl`.
* Account deactivation (RFC-8555 section 7.3.6): add `postDeactivateAccount`,
`deactivateAccountPayload` and `AccountDeactivationResponse` (in
`Acme.NotAJoke.Api.Account`), and `deactivateAccount` (in
`Acme.NotAJoke.Client`), which fetches the directory, nonce and account
before deactivating it.
## 0.1.1.0 -- never released (shipped in 0.2.0.0)
Helpers to create, load and write the PKI formats involved in getting a
certificate, so that `openssl` and `scripts/gen-csr.sh` no longer are required.
Existing functions keep their types.
* `Acme.NotAJoke.KeyManagement`: add `genRSAKey` and `genRSAKey4096` to
generate the key of a certificate; `encodeRSAKeyPEM`, `decodeRSAKeyPEM`,
`encodeRSAKeyDER`, `decodeRSAKeyDER`, `loadRSAKeyPEM` and `writeRSAKeyPEM` to
read and write RSA keys (PKCS#1 is written, PKCS#1 and unencrypted PKCS#8 are
read); `jwkFromRSAKey` and `jwkToRSAKey` to convert between RSA keys and
JWKs; `loadOrCreateJWKFile` and `loadOrCreateRSAKeyPEM` to generate a key on
the first run.
* `Acme.NotAJoke.CertManagement`: add `createCSR` and `createCSRWith` to build
and sign (RSA with SHA-256) a CSR with its subject alternative names;
`loadCSR` (PEM or DER files), `writeCSRDER`, `writeCSRPEM`, `csrFromDER`,
`csrToDER`, `encodeCSRPEM` and `decodeCSRPEM` to read and write CSRs;
`certificateChain`, `decodeCertificateChain`, `encodeCertificateChain`,
`loadCertificateChain` and `writeCertificateChain` to parse and write the
certificates returned by the ACME server.
* Both modules now have an explicit export list (all the functions they had
still are exported).
* New dependencies: `crypton`, `crypton-x509`, `crypton-asn1-encoding`,
`crypton-asn1-types`, `crypton-pem` and `directory`. The `crypton` packages
already were transitive dependencies (via `jose`).
* Add a `pki-formats` test-suite.
## 0.1.0.0 -- 2023
* First version. Released on an unsuspecting world.