-module(acumen@nonce). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/acumen/nonce.gleam"). -export([build/1, response/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " Nonce fetching for ACME replay protection.\n" "\n" " ACME uses nonces to prevent replay attacks. Every request to the ACME server\n" " must include a fresh nonce, and every response includes a new nonce for the\n" " next request.\n" "\n" " ## Usage\n" "\n" " You need to fetch an initial nonce before making your first ACME request:\n" "\n" " ```gleam\n" " import acumen\n" " import acumen/nonce\n" " import gleam/httpc\n" "\n" " // After fetching the directory...\n" " let assert Ok(nonce_req) = nonce.build(directory)\n" " let assert Ok(resp) = httpc.send(nonce_req)\n" " let assert Ok(initial_nonce) = nonce.response(resp)\n" "\n" " let ctx = acumen.Context(directory:, nonce: initial_nonce)\n" " ```\n" "\n" " After the initial nonce, subsequent nonces are handled automatically by\n" " `acumen.execute`, which extracts nonces from response headers and updates\n" " the context.\n" "\n" " ## Extracting Nonces from Any Response\n" "\n" " The `response` function can extract a nonce from any ACME response, not\n" " just dedicated nonce responses. This is useful if you need to manually\n" " manage nonces outside of the `execute` flow.\n" ). -file("src/acumen/nonce.gleam", 42). ?DOC(" Builds an HTTP HEAD request to the directory's `newNonce` endpoint.\n"). -spec build(acumen:directory()) -> gleam@http@request:request(binary()). build(Directory) -> _pipe = acumen@internal@utils:request_from_url(erlang:element(2, Directory)), gleam@http@request:set_method(_pipe, head). -file("src/acumen/nonce.gleam", 50). ?DOC( " Extracts a nonce from any ACME response's `Replay-Nonce` header.\n" "\n" " When using `acumen.execute`, nonce extraction is handled automatically.\n" ). -spec response(gleam@http@response:response(any())) -> {ok, binary()} | {error, acumen:acme_error()}. response(Resp) -> _pipe = gleam@http@response:get_header(Resp, <<"replay-nonce"/utf8>>), gleam@result:replace_error( _pipe, {invalid_response, <<"missing Replay-Nonce header"/utf8>>} ).