Sign final buffered response bytes in a Plug before_send callback.
Requires all five options: :sign (the signing map described below),
:signer (caller signer or key handle), :signing_timeout (1..300,000 ms),
:clock (arity zero returning Unix seconds), and :on_failure
({:respond, status} with final status in 200..599). req components bind
to the captured request; tr components are unsupported. A covered missing date is added
before signing from the same sampled :clock as created and expires.
Request @request-target, @target-uri, and @query coverage
rejects with :unsupported_component because Plug lacks exact target evidence.
Required body coverage needs conn.state == :set:
file/chunked delivery cannot authenticate unretained bytes. Status-only
streaming signatures are supported without body coverage.
The signing callback runs after other registered callbacks, including callbacks
registered earlier that mutate signed facts. Their changes are included before
signing. Absent or nil callback state means no callbacks; malformed callback
state replaces delivery with a bounded :unsupported_delivery failure.
Plug merges
resp_cookies into headers afterward; if response coverage includes
set-cookie and cookies are pending, signing fails closed with
:unsupported_delivery. This also applies to cookies set by session callbacks.
Explicit final set-cookie response headers can be signed without pending
cookies. Transformations in the server after Plug's callbacks (such as Bandit
compression) must be disabled when covering bytes; no no-transform field
is injected.
On failure the requested status and empty unsigned body replace any delivery,
including file and chunked modes. Later chunk writes return {:error, :closed}.
A redacted request-local transport wrapper enforces that replacement without
starting a process. Private state's error holds the bounded failure.
The signing map contains exactly :label (signature label), :components
(serialized component Inner List without metadata parameters), :algorithm
(exact supported HTTP signature algorithm), :parameters, :digest, and
:field_schemas (explicit field schema map). :parameters contains exactly
:created and :alg (Booleans), :expires_in (positive seconds or nil,
requiring created when present), :nonce (:random or nil), and :keyid
and :tag (bounded strings or nil). The adapter generates selected metadata
for each signing operation. :digest is nil or a nonempty unique selection
of "sha-256" and "sha-512"; present digests must match those algorithms
and the retained response body. Request fields selected with req retain
their captured values and do not establish response content integrity.